Add faster and better-quality hash function hash_lookup3().
authorBen Pfaff <blp@nicira.com>
Tue, 23 Dec 2008 23:01:25 +0000 (15:01 -0800)
committerBen Pfaff <blp@nicira.com>
Tue, 23 Dec 2008 23:06:14 +0000 (15:06 -0800)
lib/hash.c
lib/hash.h

index 8e87216b8a9dee863a38510dfdce36f25c2722c6..22caa9232405921d4cf0eb11afdf426e79772f92 100644 (file)
@@ -44,3 +44,65 @@ hash_fnv(const void *p_, size_t n, uint32_t basis)
     }
     return hash;
 }
+
+/* This is the public domain lookup3 hash by Bob Jenkins from
+ * http://burtleburtle.net/bob/c/lookup3.c, modified for style. */
+#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
+
+#define mix(a, b, c)                            \
+    do {                                        \
+      a -= c; a ^= rot(c,  4); c += b;          \
+      b -= a; b ^= rot(a,  6); a += c;          \
+      c -= b; c ^= rot(b,  8); b += a;          \
+      a -= c; a ^= rot(c, 16); c += b;          \
+      b -= a; b ^= rot(a, 19); a += c;          \
+      c -= b; c ^= rot(b,  4); b += a;          \
+    } while (0)
+
+#define final(a, b, c)                          \
+    do {                                        \
+      c ^= b; c -= rot(b, 14);                  \
+      a ^= c; a -= rot(c, 11);                  \
+      b ^= a; b -= rot(a, 25);                  \
+      c ^= b; c -= rot(b, 16);                  \
+      a ^= c; a -= rot(c,  4);                  \
+      b ^= a; b -= rot(a, 14);                  \
+      c ^= b; c -= rot(b, 24);                  \
+    } while (0)
+
+/* Returns the hash of the 'n' uint32_t values at 'p', starting from 'basis'.
+ * Note especially that 'n' is a count of 32-bit words, not bytes, and that
+ * 'p' must be properly aligned. */
+uint32_t
+hash_lookup3(const uint32_t *p, size_t n, uint32_t basis)
+{
+    uint32_t a, b, c;
+
+    a = b = c = 0xdeadbeef + (((uint32_t) n) << 2) + basis;
+
+    while (n > 3) {
+        a += p[0];
+        b += p[1];
+        c += p[2];
+        mix(a, b, c);
+        n -= 3;
+        p += 3;
+    }
+
+    switch (n) {
+    case 3:
+        c += p[2];
+        /* fall through */
+    case 2:
+        b += p[1];
+        /* fall through */
+    case 1:
+        a += p[0];
+        final(a, b, c);
+        /* fall through */
+    case 0:
+        break;
+    }
+    return c;
+}
+
index 6fce347187a71db9e2c832ebe5d7714d05dd9729..44d7b054dbd6d6c9d63bc8653aad100477db89f0 100644 (file)
@@ -40,5 +40,6 @@
 #define HASH_FNV_PRIME UINT32_C(16777619)
 
 uint32_t hash_fnv(const void *, size_t, uint32_t basis);
+uint32_t hash_lookup3(const uint32_t *, size_t n, uint32_t basis);
 
 #endif /* hash.h */