diff options
Diffstat (limited to 'MurmurHash1.cpp')
-rw-r--r-- | MurmurHash1.cpp | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/MurmurHash1.cpp b/MurmurHash1.cpp new file mode 100644 index 0000000..8225566 --- /dev/null +++ b/MurmurHash1.cpp @@ -0,0 +1,174 @@ +//----------------------------------------------------------------------------- +// MurmurHash was written by Austin Appleby, and is placed in the public +// domain. The author hereby disclaims copyright to this source code. + +// Note - This code makes a few assumptions about how your machine behaves - + +// 1. We can read a 4-byte value from any address without crashing +// 2. sizeof(int) == 4 + +// And it has a few limitations - + +// 1. It will not work incrementally. +// 2. It will not produce the same results on little-endian and big-endian +// machines. + +#include "MurmurHash1.h" + +//----------------------------------------------------------------------------- + +uint32_t MurmurHash1 ( const void * key, int len, uint32_t seed ) +{ + const unsigned int m = 0xc6a4a793; + + const int r = 16; + + unsigned int h = seed ^ (len * m); + + //---------- + + const unsigned char * data = (const unsigned char *)key; + + while(len >= 4) + { + unsigned int k = *(unsigned int *)data; + + h += k; + h *= m; + h ^= h >> 16; + + data += 4; + len -= 4; + } + + //---------- + + switch(len) + { + case 3: + h += data[2] << 16; + case 2: + h += data[1] << 8; + case 1: + h += data[0]; + h *= m; + h ^= h >> r; + }; + + //---------- + + h *= m; + h ^= h >> 10; + h *= m; + h ^= h >> 17; + + return h; +} + +//----------------------------------------------------------------------------- +// MurmurHash1Aligned, by Austin Appleby + +// Same algorithm as MurmurHash1, but only does aligned reads - should be safer +// on certain platforms. + +// Performance should be equal to or better than the simple version. + +unsigned int MurmurHash1Aligned ( const void * key, int len, unsigned int seed ) +{ + const unsigned int m = 0xc6a4a793; + const int r = 16; + + const unsigned char * data = (const unsigned char *)key; + + unsigned int h = seed ^ (len * m); + + int align = (uint64_t)data & 3; + + if(align && (len >= 4)) + { + // Pre-load the temp registers + + unsigned int t = 0, d = 0; + + switch(align) + { + case 1: t |= data[2] << 16; + case 2: t |= data[1] << 8; + case 3: t |= data[0]; + } + + t <<= (8 * align); + + data += 4-align; + len -= 4-align; + + int sl = 8 * (4-align); + int sr = 8 * align; + + // Mix + + while(len >= 4) + { + d = *(unsigned int *)data; + t = (t >> sr) | (d << sl); + h += t; + h *= m; + h ^= h >> r; + t = d; + + data += 4; + len -= 4; + } + + // Handle leftover data in temp registers + + int pack = len < align ? len : align; + + d = 0; + + switch(pack) + { + case 3: d |= data[2] << 16; + case 2: d |= data[1] << 8; + case 1: d |= data[0]; + case 0: h += (t >> sr) | (d << sl); + h *= m; + h ^= h >> r; + } + + data += pack; + len -= pack; + } + else + { + while(len >= 4) + { + h += *(unsigned int *)data; + h *= m; + h ^= h >> r; + + data += 4; + len -= 4; + } + } + + //---------- + // Handle tail bytes + + switch(len) + { + case 3: h += data[2] << 16; + case 2: h += data[1] << 8; + case 1: h += data[0]; + h *= m; + h ^= h >> r; + }; + + h *= m; + h ^= h >> 10; + h *= m; + h ^= h >> 17; + + return h; +} + |