1 // MurmurHash3 was written by Austin Appleby, and is placed in the public
2 // domain. The author hereby disclaims copyright to this source code.
3 
4 #include <mgba-util/hash.h>
5 
6 #if defined(_MSC_VER)
7 
8 #define FORCE_INLINE	__forceinline
9 
10 #include <stdlib.h>
11 
12 #define ROTL32(x,y)	_rotl(x,y)
13 
14 #else
15 
16 #define	FORCE_INLINE inline __attribute__((always_inline))
17 
rotl32(uint32_t x,int8_t r)18 static inline uint32_t rotl32 ( uint32_t x, int8_t r ) {
19   return (x << r) | (x >> (32 - r));
20 }
21 
22 #define	ROTL32(x,y)	rotl32(x,y)
23 
24 #endif
25 
26 //-----------------------------------------------------------------------------
27 // Block read - if your platform needs to do endian-swapping or can only
28 // handle aligned reads, do the conversion here
29 
getblock32(const uint32_t * p,int i)30 static FORCE_INLINE uint32_t getblock32 ( const uint32_t * p, int i ) {
31   uint32_t ret;
32   LOAD_32LE(ret, i << 2, p);
33   return ret;
34 }
35 
36 //-----------------------------------------------------------------------------
37 // Finalization mix - force all bits of a hash block to avalanche
38 
fmix32(uint32_t h)39 static FORCE_INLINE uint32_t fmix32 (uint32_t h) {
40   h ^= h >> 16;
41   h *= 0x85ebca6b;
42   h ^= h >> 13;
43   h *= 0xc2b2ae35;
44   h ^= h >> 16;
45 
46   return h;
47 }
48 
49 //-----------------------------------------------------------------------------
50 
hash32(const void * key,int len,uint32_t seed)51 uint32_t hash32(const void* key, int len, uint32_t seed) {
52   const uint8_t * data = (const uint8_t*)key;
53   const int nblocks = len / 4;
54 
55   uint32_t h1 = seed;
56 
57   const uint32_t c1 = 0xcc9e2d51;
58   const uint32_t c2 = 0x1b873593;
59 
60   //----------
61   // body
62 
63   const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
64 
65   int i;
66   for(i = -nblocks; i; i++)
67   {
68     uint32_t k1 = getblock32(blocks,i);
69 
70     k1 *= c1;
71     k1 = ROTL32(k1,15);
72     k1 *= c2;
73 
74     h1 ^= k1;
75     h1 = ROTL32(h1,13);
76     h1 = h1*5+0xe6546b64;
77   }
78 
79   //----------
80   // tail
81 
82   const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
83 
84   uint32_t k1 = 0;
85 
86   switch(len & 3)
87   {
88   case 3:
89     k1 ^= tail[2] << 16;
90     // Fall through
91   case 2:
92     k1 ^= tail[1] << 8;
93     // Fall through
94   case 1:
95     k1 ^= tail[0];
96     k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
97   };
98 
99   //----------
100   // finalization
101 
102   h1 ^= len;
103 
104   h1 = fmix32(h1);
105 
106   return h1;
107 }
108