123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- //-----------------------------------------------------------------------------
- // 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;
- }
|