1 /* This is MurmurHash3. The original C++ code was placed in the public domain
2  * by its author, Austin Appleby.
3  *
4  * SPDX-License-Identifier: CC0-1.0
5  * Source: https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp */
6 
7 #include "murmurhash3.h"
8 #include "string.h"
9 
fmix(uint32_t h)10 static inline uint32_t fmix(uint32_t h)
11 {
12     h ^= h >> 16;
13     h *= 0x85ebca6b;
14     h ^= h >> 13;
15     h *= 0xc2b2ae35;
16     h ^= h >> 16;
17 
18     return h;
19 }
20 
rotl32(uint32_t x,int8_t r)21 static inline uint32_t rotl32(uint32_t x, int8_t r)
22 {
23     return (x << r) | (x >> (32 - r));
24 }
25 
hash(const char * data,size_t len_)26 uint32_t hash(const char* data, size_t len_)
27 {
28     const int len = (int) len_;
29     const int nblocks = len / 4;
30 
31     uint32_t h1 = 0xc062fb4a;
32 
33     uint32_t c1 = 0xcc9e2d51;
34     uint32_t c2 = 0x1b873593;
35 
36     //----------
37     // body
38 
39     for(int i = 0; i < nblocks; ++i)
40     {
41         uint32_t k1;
42         memcpy(&k1, data + i * sizeof(k1), sizeof(k1));
43 
44         k1 *= c1;
45         k1 = rotl32(k1, 15);
46         k1 *= c2;
47 
48         h1 ^= k1;
49         h1 = rotl32(h1, 13);
50         h1 = h1*5+0xe6546b64;
51     }
52 
53     //----------
54     // tail
55 
56     const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
57 
58     uint32_t k1 = 0;
59 
60     switch(len & 3)
61     {
62         case 3: k1 ^= tail[2] << 16;
63         case 2: k1 ^= tail[1] << 8;
64         case 1: k1 ^= tail[0];
65               k1 *= c1; k1 = rotl32(k1,15); k1 *= c2; h1 ^= k1;
66     }
67 
68     //----------
69     // finalization
70 
71     h1 ^= len;
72 
73     h1 = fmix(h1);
74 
75     return h1;
76 }
77