aboutsummaryrefslogtreecommitdiff
path: root/util/hash.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/hash.c')
-rw-r--r--util/hash.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/util/hash.c b/util/hash.c
new file mode 100644
index 0000000..5f9b482
--- /dev/null
+++ b/util/hash.c
@@ -0,0 +1,46 @@
+#include "hash.h"
+
+uint64_t murmur_hash_64a(void const * key, int len, unsigned int seed)
+{
+ const uint64_t m = 0xc6a4a7935bd1e995;
+ const int r = 47;
+
+ uint64_t h = seed ^ (len * m);
+
+ const uint64_t * data = (const uint64_t *)key;
+ const uint64_t * end = data + (len/8);
+
+ while(data != end)
+ {
+ uint64_t k = *data++;
+
+ k *= m;
+ k ^= k >> r;
+ k *= m;
+
+ h ^= k;
+ h *= m;
+ }
+
+ const unsigned char * data2 = (const unsigned char*)data;
+
+ switch(len & 7)
+ {
+ case 7: h ^= (uint64_t)(data2[6]) << 48;
+ case 6: h ^= (uint64_t)(data2[5]) << 40;
+ case 5: h ^= (uint64_t)(data2[4]) << 32;
+ case 4: h ^= (uint64_t)(data2[3]) << 24;
+ case 3: h ^= (uint64_t)(data2[2]) << 16;
+ case 2: h ^= (uint64_t)(data2[1]) << 8;
+ case 1: h ^= (uint64_t)(data2[0]);
+ h *= m;
+ };
+
+ h ^= h >> r;
+ h *= m;
+ h ^= h >> r;
+
+ return h;
+}
+
+