@@@ fltfmt mess
[mLib] / hash / t / hash-test.c
index 57a6ce8..f587c30 100644 (file)
 
 /*----- Header files ------------------------------------------------------*/
 
+#include "tvec.h"
+#include "tvec-bench.h"
+#include "tvec-types.h"
+
 #include "crc32.h"
+#include "siphash.h"
 #include "unihash.h"
-#include "tvec.h"
 
-/*----- Main code ---------------------------------------------------------*/
+/*----- Register allocation -----------------------------------------------*/
 
 enum {
   RH, NROUT,
   RK = NROUT, RM, NREG
 };
 
+/*----- Testing utilities -------------------------------------------------*/
+
 struct step { size_t s; };
 
+static void run_step(struct tvec_state *tv, tvec_testfn *fn, void *ctx)
+{
+  static const size_t steps[] = { 1, 5, 6, 7, 8, 23 };
+  struct step step;
+  size_t i;
+
+  fn(tv->in, tv->out, 0);
+  tvec_check(tv, "whole buffer");
+
+  for (i = 0; i < N(steps); i++) {
+    step.s = steps[i];
+    fn(tv->in, tv->out, &step);
+    tvec_check(tv, "step = %lu", (unsigned long)steps[i]);
+  }
+}
+
+static const struct tvec_env step_testenv = { 0, 0, 0, 0, run_step, 0, 0 };
+
+static void before_hash(struct tvec_state *tv, void *ctx)
+  { tvec_allocbuffer(&tv->in[RM].v); }
+
+/*----- CRC32 -------------------------------------------------------------*/
+
+static const struct tvec_regdef bench_regs[] = {
+  { "msz", &tvty_buffer, RM, TVRF_ID },
+  TVEC_ENDREGS
+};
+
+static const struct tvec_regdef crc32_regs[] = {
+  { "m", &tvty_bytes, RM, 0 },
+  { "h", &tvty_uint, RH, 0, { &tvrange_u32 } },
+  TVEC_ENDREGS
+};
+
 static void test_crc32(const struct tvec_reg *in, struct tvec_reg *out,
                       void *ctx)
 {
@@ -56,59 +96,77 @@ static void test_crc32(const struct tvec_reg *in, struct tvec_reg *out,
   }
 }
 
-static void before_hash(struct tvec_state *tv, void *ctx)
-  { tvec_allocbuffer(&tv->in[RM].v); }
+static const struct tvec_test crc32_test =
+  { "crc32", crc32_regs, &step_testenv, test_crc32 };
 
 static void bench_crc32(const struct tvec_reg *in, struct tvec_reg *out,
                        void *ctx)
   { crc32(0, in[RM].v.bytes.p, in[RM].v.bytes.sz); }
+
 static const struct tvec_env crc32_benchenv =
   { 0, 0, 0, before_hash };
+static const struct tvec_benchenv crc32_bench =
+  { TVEC_BENCHINIT, 1, -1, RM, &crc32_benchenv };
+static const struct tvec_test crc32_benchtest =
+  { "crc32-bench", bench_regs, &crc32_bench._env, bench_crc32 };
 
-static void test_unihash(const struct tvec_reg *in, struct tvec_reg *out,
+/*----- SipHash -----------------------------------------------------------*/
+
+static const struct tvec_urange
+  siphash_keyrange = { SIPHASH_KEYSZ, SIPHASH_KEYSZ },
+  siphash_hashrange = { 8, 8 };
+
+static const struct tvec_regdef siphash_regs[] = {
+  { "k", &tvty_bytes, RK, 0, { &siphash_keyrange } },
+  { "m", &tvty_bytes, RM, 0 },
+  { "h", &tvty_bytes, RH, 0, { &siphash_hashrange } },
+  TVEC_ENDREGS
+};
+
+static void test_siphash(const struct tvec_reg *in, struct tvec_reg *out,
                         void *ctx)
 {
   const struct step *step = ctx;
-  unihash_info ui;
   const unsigned char *p = in[RM].v.bytes.p; size_t sz = in[RM].v.bytes.sz;
-  uint32 h;
+  struct siphash_key k;
+  struct siphash s;
+  kludge64 h;
 
-  unihash_setkey(&ui, in[RK].v.u);
+  siphash_setkey(&k, in[RK].v.bytes.p);
   if (!step)
-    out[RH].v.u = unihash(&ui, p, sz);
+    h = siphash(&k, p, sz);
   else {
-    for (h = UNIHASH_INIT(&ui); sz > step->s; p += step->s, sz -= step->s)
-      h = unihash_hash(&ui, h, p, step->s);
-    out[RH].v.u = unihash_hash(&ui, h, p, sz);
+    siphash_init(&s, &k);
+    for (; sz > step->s; p += step->s, sz -= step->s)
+      siphash_hash(&s, p, step->s);
+    siphash_hash(&s, p, sz);
+    h = siphash_done(&s);
   }
+  tvec_allocbytes(&out[RH].v, 8); STORE64_L_(out[RH].v.bytes.p, h);
 }
 
-static void bench_unihash(const struct tvec_reg *in, struct tvec_reg *out,
-                         void *ctx)
-  { unihash_hash(ctx, 0, in[RM].v.bytes.p, in[RM].v.bytes.sz); }
-static void setup_unihash(struct tvec_state *tv,
-                         const struct tvec_env *env, void *pctx, void *ctx)
-  { tvec_allocbuffer(&tv->in[RM].v); unihash_setkey(ctx, 0); }
-static const struct tvec_env unihash_benchenv =
-  { sizeof(unihash_info), setup_unihash, 0, before_hash };
+static const struct tvec_test siphash_test =
+  { "siphash", siphash_regs, &step_testenv, test_siphash };
 
-static void run_step(struct tvec_state *tv, tvec_testfn *fn, void *ctx)
+static void setup_siphash(struct tvec_state *tv,
+                         const struct tvec_env *env, void *pctx, void *ctx)
 {
-  static const size_t steps[] = { 1, 5, 6, 7, 8, 23 };
-  struct step step;
-  size_t i;
+  struct siphash_key *k = ctx;
+  ASSIGN64(k->k0, 0); ASSIGN64(k->k1, 0);
+}
 
-  fn(tv->in, tv->out, 0);
-  tvec_check(tv, "whole buffer");
+static void bench_siphash(const struct tvec_reg *in, struct tvec_reg *out,
+                         void *ctx)
+  { siphash(ctx, in[RM].v.bytes.p, in[RM].v.bytes.sz); }
 
-  for (i = 0; i < N(steps); i++) {
-    step.s = steps[i];
-    fn(tv->in, tv->out, &step);
-    tvec_check(tv, "step = %lu", (unsigned long)steps[i]);
-  }
-}
+static const struct tvec_env siphash_benchenv =
+  { sizeof(struct siphash_key), setup_siphash, 0, before_hash };
+static const struct tvec_benchenv siphash_bench =
+  { TVEC_BENCHINIT, 1, -1, RM, &siphash_benchenv };
+static const struct tvec_test siphash_benchtest =
+  { "siphash-bench", bench_regs, &siphash_bench._env, bench_siphash };
 
-static const struct tvec_env step_testenv = { 0, 0, 0, 0, run_step, 0, 0 };
+/*----- Unihash -----------------------------------------------------------*/
 
 static const struct tvec_regdef unihash_regs[] = {
   { "k", &tvty_uint, RK, 0, { &tvrange_u32 } },
@@ -117,28 +175,49 @@ static const struct tvec_regdef unihash_regs[] = {
   TVEC_ENDREGS
 };
 
-static const struct tvec_regdef crc32_regs[] = {
-  { "m", &tvty_bytes, RM, 0 },
-  { "h", &tvty_uint, RH, 0, { &tvrange_u32 } },
-  TVEC_ENDREGS
-};
+static void test_unihash(const struct tvec_reg *in, struct tvec_reg *out,
+                        void *ctx)
+{
+  const struct step *step = ctx;
+  unihash_info ui;
+  const unsigned char *p = in[RM].v.bytes.p; size_t sz = in[RM].v.bytes.sz;
+  uint32 h;
 
-static const struct tvec_regdef bench_regs[] = {
-  { "msz", &tvty_buffer, RM, TVRF_ID },
-  TVEC_ENDREGS
-};
+  unihash_setkey(&ui, in[RK].v.u);
+  if (!step)
+    out[RH].v.u = unihash(&ui, p, sz);
+  else {
+    for (h = UNIHASH_INIT(&ui); sz > step->s; p += step->s, sz -= step->s)
+      h = unihash_hash(&ui, h, p, step->s);
+    out[RH].v.u = unihash_hash(&ui, h, p, sz);
+  }
+}
 
-static const struct tvec_benchenv crc32_bench =
-  { TVEC_BENCHINIT, 1, -1, RM, &crc32_benchenv };
+static const struct tvec_test unihash_test =
+  { "unihash", unihash_regs, &step_testenv, test_unihash };
+
+static void setup_unihash(struct tvec_state *tv,
+                         const struct tvec_env *env, void *pctx, void *ctx)
+  { unihash_setkey(ctx, 0); }
+
+static void bench_unihash(const struct tvec_reg *in, struct tvec_reg *out,
+                         void *ctx)
+  { unihash_hash(ctx, 0, in[RM].v.bytes.p, in[RM].v.bytes.sz); }
+
+static const struct tvec_env unihash_benchenv =
+  { sizeof(unihash_info), setup_unihash, 0, before_hash };
 static const struct tvec_benchenv unihash_bench =
   { TVEC_BENCHINIT, 1, -1, RM, &unihash_benchenv };
+static const struct tvec_test unihash_benchtest =
+  { "unihash-bench", bench_regs, &unihash_bench._env, bench_unihash };
+
+/*----- Main program ------------------------------------------------------*/
 
-static const struct tvec_test tests[] = {
-  { "crc32", crc32_regs, &step_testenv, test_crc32 },
-  { "unihash", unihash_regs, &step_testenv, test_unihash },
-  { "crc32-bench", bench_regs, &crc32_bench._env, bench_crc32 },
-  { "unihash-bench", bench_regs, &unihash_bench._env, bench_unihash },
-  TVEC_ENDTESTS
+static const struct tvec_test *const tests[] = {
+  &crc32_test, &crc32_benchtest,
+  &siphash_test, &siphash_benchtest,
+  &unihash_test, &unihash_benchtest,
+  0
 };
 
 static const struct tvec_config testconfig =