diff options
| author | [email protected] <[email protected]> | 2021-11-02 12:34:05 +0800 |
|---|---|---|
| committer | [email protected] <[email protected]> | 2021-11-02 12:34:05 +0800 |
| commit | 31f55f0b88d4af34a8a36497f5e49c69b88b2fbf (patch) | |
| tree | 63515b3ceb361369cdc88ae6db1a808fc80e5b42 /src/nirvana_murmurhash.cpp | |
Diffstat (limited to 'src/nirvana_murmurhash.cpp')
| -rw-r--r-- | src/nirvana_murmurhash.cpp | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/src/nirvana_murmurhash.cpp b/src/nirvana_murmurhash.cpp new file mode 100644 index 0000000..193bde9 --- /dev/null +++ b/src/nirvana_murmurhash.cpp @@ -0,0 +1,99 @@ +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> + +#include "nirvana_murmurhash.h" + +unsigned int murmurhash2(const void * key, int len, const unsigned int seed) +{ + // 'm' and 'r' are mixing constants generated offline. + // They're not really 'magic', they just happen to work well. + + const unsigned int m = 0x5bd1e995; + const int r = 24; + + // Initialize the hash to a 'random' value + + unsigned int h = seed ^ len; + + // Mix 4 bytes at a time into the hash + + const unsigned char * data = (const unsigned char *)key; + + while(len >= 4) + { + unsigned int k = *(unsigned int *)data; + + k *= m; + k ^= k >> r; + k *= m; + + h *= m; + h ^= k; + + data += 4; + len -= 4; + } + + // Handle the last few bytes of the input array + + switch(len) + { + case 3: h ^= data[2] << 16; + case 2: h ^= data[1] << 8; + case 1: h ^= data[0]; + h *= m; + default:break; + }; + + // Do a few final mixes of the hash to ensure the last few + // bytes are well-incorporated. + + h ^= h >> 13; + h *= m; + h ^= h >> 15; + return h; +} + +/*64-bit hash for 64-bit platforms*/ +u_int64_t MurmurHash64A(const void * key, int len, unsigned int seed) +{ + const uint64_t m = 0xc6a4a7935bd1e995; + const int r = 47; + uint64_t k, h = seed ^ (len * m); + const uint64_t * data = (const uint64_t *)key; + const uint64_t * end = data + (len/8); + + while (data != end) + { + 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; +} + + |
