blob: cc94f79acdb20d57eb7672eff522fd9196aaaac3 [file] [log] [blame]
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +00001#include "MurmurHash2.h"
2
3//-----------------------------------------------------------------------------
4// MurmurHash2, by Austin Appleby
5
6// Note - This code makes a few assumptions about how your machine behaves -
7
8// 1. We can read a 4-byte value from any address without crashing
9// 2. sizeof(int) == 4
10
11// And it has a few limitations -
12
13// 1. It will not work incrementally.
14// 2. It will not produce the same results on little-endian and big-endian
15// machines.
16
17uint32_t MurmurHash2 ( const void * key, int len, uint32_t seed )
18{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000019 // 'm' and 'r' are mixing constants generated offline.
20 // They're not really 'magic', they just happen to work well.
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000021
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000022 const uint32_t m = 0x5bd1e995;
23 const int r = 24;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000024
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000025 // Initialize the hash to a 'random' value
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000026
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000027 uint32_t h = seed ^ len;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000028
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000029 // Mix 4 bytes at a time into the hash
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000030
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000031 const unsigned char * data = (const unsigned char *)key;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000032
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000033 while(len >= 4)
34 {
35 uint32_t k = *(uint32_t*)data;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000036
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000037 k *= m;
38 k ^= k >> r;
39 k *= m;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000040
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000041 h *= m;
42 h ^= k;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000043
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000044 data += 4;
45 len -= 4;
46 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000047
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000048 // Handle the last few bytes of the input array
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000049
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000050 switch(len)
51 {
52 case 3: h ^= data[2] << 16;
53 case 2: h ^= data[1] << 8;
54 case 1: h ^= data[0];
55 h *= m;
56 };
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000057
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000058 // Do a few final mixes of the hash to ensure the last few
59 // bytes are well-incorporated.
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000060
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000061 h ^= h >> 13;
62 h *= m;
63 h ^= h >> 15;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000064
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000065 return h;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000066}
67
68//-----------------------------------------------------------------------------
69// MurmurHash2, 64-bit versions, by Austin Appleby
70
71// The same caveats as 32-bit MurmurHash2 apply here - beware of alignment
72// and endian-ness issues if used across multiple platforms.
73
74// 64-bit hash for 64-bit platforms
75
76uint64_t MurmurHash64A ( const void * key, int len, uint64_t seed )
77{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000078 const uint64_t m = BIG_CONSTANT(0xc6a4a7935bd1e995);
79 const int r = 47;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000080
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000081 uint64_t h = seed ^ (len * m);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000082
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000083 const uint64_t * data = (const uint64_t *)key;
84 const uint64_t * end = data + (len/8);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000085
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000086 while(data != end)
87 {
88 uint64_t k = *data++;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000089
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000090 k *= m;
91 k ^= k >> r;
92 k *= m;
93
94 h ^= k;
95 h *= m;
96 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000097
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000098 const unsigned char * data2 = (const unsigned char*)data;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000099
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000100 switch(len & 7)
101 {
102 case 7: h ^= uint64_t(data2[6]) << 48;
103 case 6: h ^= uint64_t(data2[5]) << 40;
104 case 5: h ^= uint64_t(data2[4]) << 32;
105 case 4: h ^= uint64_t(data2[3]) << 24;
106 case 3: h ^= uint64_t(data2[2]) << 16;
107 case 2: h ^= uint64_t(data2[1]) << 8;
108 case 1: h ^= uint64_t(data2[0]);
109 h *= m;
110 };
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000111
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000112 h ^= h >> r;
113 h *= m;
114 h ^= h >> r;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000115
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000116 return h;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000117}
118
119
120// 64-bit hash for 32-bit platforms
121
122uint64_t MurmurHash64B ( const void * key, int len, uint64_t seed )
123{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000124 const uint32_t m = 0x5bd1e995;
125 const int r = 24;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000126
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000127 uint32_t h1 = uint32_t(seed) ^ len;
128 uint32_t h2 = uint32_t(seed >> 32);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000129
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000130 const uint32_t * data = (const uint32_t *)key;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000131
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000132 while(len >= 8)
133 {
134 uint32_t k1 = *data++;
135 k1 *= m; k1 ^= k1 >> r; k1 *= m;
136 h1 *= m; h1 ^= k1;
137 len -= 4;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000138
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000139 uint32_t k2 = *data++;
140 k2 *= m; k2 ^= k2 >> r; k2 *= m;
141 h2 *= m; h2 ^= k2;
142 len -= 4;
143 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000144
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000145 if(len >= 4)
146 {
147 uint32_t k1 = *data++;
148 k1 *= m; k1 ^= k1 >> r; k1 *= m;
149 h1 *= m; h1 ^= k1;
150 len -= 4;
151 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000152
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000153 switch(len)
154 {
155 case 3: h2 ^= ((unsigned char*)data)[2] << 16;
156 case 2: h2 ^= ((unsigned char*)data)[1] << 8;
157 case 1: h2 ^= ((unsigned char*)data)[0];
158 h2 *= m;
159 };
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000160
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000161 h1 ^= h2 >> 18; h1 *= m;
162 h2 ^= h1 >> 22; h2 *= m;
163 h1 ^= h2 >> 17; h1 *= m;
164 h2 ^= h1 >> 19; h2 *= m;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000165
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000166 uint64_t h = h1;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000167
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000168 h = (h << 32) | h2;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000169
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000170 return h;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000171}
172
173//-----------------------------------------------------------------------------
174// MurmurHash2A, by Austin Appleby
175
176// This is a variant of MurmurHash2 modified to use the Merkle-Damgard
177// construction. Bulk speed should be identical to Murmur2, small-key speed
178// will be 10%-20% slower due to the added overhead at the end of the hash.
179
180// This variant fixes a minor issue where null keys were more likely to
181// collide with each other than expected, and also makes the function
182// more amenable to incremental implementations.
183
184#define mmix(h,k) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; }
185
186uint32_t MurmurHash2A ( const void * key, int len, uint32_t seed )
187{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000188 const uint32_t m = 0x5bd1e995;
189 const int r = 24;
190 uint32_t l = len;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000191
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000192 const unsigned char * data = (const unsigned char *)key;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000193
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000194 uint32_t h = seed;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000195
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000196 while(len >= 4)
197 {
198 uint32_t k = *(uint32_t*)data;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000199
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000200 mmix(h,k);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000201
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000202 data += 4;
203 len -= 4;
204 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000205
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000206 uint32_t t = 0;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000207
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000208 switch(len)
209 {
210 case 3: t ^= data[2] << 16;
211 case 2: t ^= data[1] << 8;
212 case 1: t ^= data[0];
213 };
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000214
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000215 mmix(h,t);
216 mmix(h,l);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000217
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000218 h ^= h >> 13;
219 h *= m;
220 h ^= h >> 15;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000221
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000222 return h;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000223}
224
225//-----------------------------------------------------------------------------
226// CMurmurHash2A, by Austin Appleby
227
228// This is a sample implementation of MurmurHash2A designed to work
229// incrementally.
230
231// Usage -
232
233// CMurmurHash2A hasher
234// hasher.Begin(seed);
235// hasher.Add(data1,size1);
236// hasher.Add(data2,size2);
237// ...
238// hasher.Add(dataN,sizeN);
239// uint32_t hash = hasher.End()
240
241class CMurmurHash2A
242{
243public:
244
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000245 void Begin ( uint32_t seed = 0 )
246 {
247 m_hash = seed;
248 m_tail = 0;
249 m_count = 0;
250 m_size = 0;
251 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000252
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000253 void Add ( const unsigned char * data, int len )
254 {
255 m_size += len;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000256
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000257 MixTail(data,len);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000258
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000259 while(len >= 4)
260 {
261 uint32_t k = *(uint32_t*)data;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000262
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000263 mmix(m_hash,k);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000264
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000265 data += 4;
266 len -= 4;
267 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000268
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000269 MixTail(data,len);
270 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000271
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000272 uint32_t End ( void )
273 {
274 mmix(m_hash,m_tail);
275 mmix(m_hash,m_size);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000276
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000277 m_hash ^= m_hash >> 13;
278 m_hash *= m;
279 m_hash ^= m_hash >> 15;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000280
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000281 return m_hash;
282 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000283
284private:
285
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000286 static const uint32_t m = 0x5bd1e995;
287 static const int r = 24;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000288
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000289 void MixTail ( const unsigned char * & data, int & len )
290 {
291 while( len && ((len<4) || m_count) )
292 {
293 m_tail |= (*data++) << (m_count * 8);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000294
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000295 m_count++;
296 len--;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000297
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000298 if(m_count == 4)
299 {
300 mmix(m_hash,m_tail);
301 m_tail = 0;
302 m_count = 0;
303 }
304 }
305 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000306
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000307 uint32_t m_hash;
308 uint32_t m_tail;
309 uint32_t m_count;
310 uint32_t m_size;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000311};
312
313//-----------------------------------------------------------------------------
314// MurmurHashNeutral2, by Austin Appleby
315
316// Same as MurmurHash2, but endian- and alignment-neutral.
317// Half the speed though, alas.
318
319uint32_t MurmurHashNeutral2 ( const void * key, int len, uint32_t seed )
320{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000321 const uint32_t m = 0x5bd1e995;
322 const int r = 24;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000323
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000324 uint32_t h = seed ^ len;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000325
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000326 const unsigned char * data = (const unsigned char *)key;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000327
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000328 while(len >= 4)
329 {
330 uint32_t k;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000331
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000332 k = data[0];
333 k |= data[1] << 8;
334 k |= data[2] << 16;
335 k |= data[3] << 24;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000336
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000337 k *= m;
338 k ^= k >> r;
339 k *= m;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000340
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000341 h *= m;
342 h ^= k;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000343
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000344 data += 4;
345 len -= 4;
346 }
347
348 switch(len)
349 {
350 case 3: h ^= data[2] << 16;
351 case 2: h ^= data[1] << 8;
352 case 1: h ^= data[0];
353 h *= m;
354 };
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000355
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000356 h ^= h >> 13;
357 h *= m;
358 h ^= h >> 15;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000359
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000360 return h;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000361}
362
363//-----------------------------------------------------------------------------
364// MurmurHashAligned2, by Austin Appleby
365
366// Same algorithm as MurmurHash2, but only does aligned reads - should be safer
367// on certain platforms.
368
369// Performance will be lower than MurmurHash2
370
371#define MIX(h,k,m) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; }
372
373uint32_t MurmurHashAligned2 ( const void * key, int len, uint32_t seed )
374{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000375 const uint32_t m = 0x5bd1e995;
376 const int r = 24;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000377
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000378 const unsigned char * data = (const unsigned char *)key;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000379
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000380 uint32_t h = seed ^ len;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000381
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000382 int align = (uint64_t)data & 3;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000383
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000384 if(align && (len >= 4))
385 {
386 // Pre-load the temp registers
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000387
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000388 uint32_t t = 0, d = 0;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000389
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000390 switch(align)
391 {
392 case 1: t |= data[2] << 16;
393 case 2: t |= data[1] << 8;
394 case 3: t |= data[0];
395 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000396
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000397 t <<= (8 * align);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000398
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000399 data += 4-align;
400 len -= 4-align;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000401
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000402 int sl = 8 * (4-align);
403 int sr = 8 * align;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000404
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000405 // Mix
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000406
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000407 while(len >= 4)
408 {
409 d = *(uint32_t *)data;
410 t = (t >> sr) | (d << sl);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000411
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000412 uint32_t k = t;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000413
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000414 MIX(h,k,m);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000415
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000416 t = d;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000417
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000418 data += 4;
419 len -= 4;
420 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000421
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000422 // Handle leftover data in temp registers
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000423
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000424 d = 0;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000425
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000426 if(len >= align)
427 {
428 switch(align)
429 {
430 case 3: d |= data[2] << 16;
431 case 2: d |= data[1] << 8;
432 case 1: d |= data[0];
433 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000434
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000435 uint32_t k = (t >> sr) | (d << sl);
436 MIX(h,k,m);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000437
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000438 data += align;
439 len -= align;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000440
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000441 //----------
442 // Handle tail bytes
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000443
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000444 switch(len)
445 {
446 case 3: h ^= data[2] << 16;
447 case 2: h ^= data[1] << 8;
448 case 1: h ^= data[0];
449 h *= m;
450 };
451 }
452 else
453 {
454 switch(len)
455 {
456 case 3: d |= data[2] << 16;
457 case 2: d |= data[1] << 8;
458 case 1: d |= data[0];
459 case 0: h ^= (t >> sr) | (d << sl);
460 h *= m;
461 }
462 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000463
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000464 h ^= h >> 13;
465 h *= m;
466 h ^= h >> 15;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000467
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000468 return h;
469 }
470 else
471 {
472 while(len >= 4)
473 {
474 uint32_t k = *(uint32_t *)data;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000475
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000476 MIX(h,k,m);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000477
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000478 data += 4;
479 len -= 4;
480 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000481
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000482 //----------
483 // Handle tail bytes
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000484
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000485 switch(len)
486 {
487 case 3: h ^= data[2] << 16;
488 case 2: h ^= data[1] << 8;
489 case 1: h ^= data[0];
490 h *= m;
491 };
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000492
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000493 h ^= h >> 13;
494 h *= m;
495 h ^= h >> 15;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000496
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000497 return h;
498 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000499}
500
501//-----------------------------------------------------------------------------
502