blob: 82255667c376b064e7c813b7a5422d515a3f17ba [file] [log] [blame]
tanjent@gmail.comf3b78972012-03-01 03:38:55 +00001//-----------------------------------------------------------------------------
2// MurmurHash was written by Austin Appleby, and is placed in the public
3// domain. The author hereby disclaims copyright to this source code.
4
5// Note - This code makes a few assumptions about how your machine behaves -
6
7// 1. We can read a 4-byte value from any address without crashing
8// 2. sizeof(int) == 4
9
10// And it has a few limitations -
11
12// 1. It will not work incrementally.
13// 2. It will not produce the same results on little-endian and big-endian
14// machines.
15
16#include "MurmurHash1.h"
17
18//-----------------------------------------------------------------------------
19
20uint32_t MurmurHash1 ( const void * key, int len, uint32_t seed )
21{
22 const unsigned int m = 0xc6a4a793;
23
24 const int r = 16;
25
26 unsigned int h = seed ^ (len * m);
27
28 //----------
29
30 const unsigned char * data = (const unsigned char *)key;
31
32 while(len >= 4)
33 {
34 unsigned int k = *(unsigned int *)data;
35
36 h += k;
37 h *= m;
38 h ^= h >> 16;
39
40 data += 4;
41 len -= 4;
42 }
43
44 //----------
45
46 switch(len)
47 {
48 case 3:
49 h += data[2] << 16;
50 case 2:
51 h += data[1] << 8;
52 case 1:
53 h += data[0];
54 h *= m;
55 h ^= h >> r;
56 };
57
58 //----------
59
60 h *= m;
61 h ^= h >> 10;
62 h *= m;
63 h ^= h >> 17;
64
65 return h;
66}
67
68//-----------------------------------------------------------------------------
69// MurmurHash1Aligned, by Austin Appleby
70
71// Same algorithm as MurmurHash1, but only does aligned reads - should be safer
72// on certain platforms.
73
74// Performance should be equal to or better than the simple version.
75
76unsigned int MurmurHash1Aligned ( const void * key, int len, unsigned int seed )
77{
78 const unsigned int m = 0xc6a4a793;
79 const int r = 16;
80
81 const unsigned char * data = (const unsigned char *)key;
82
83 unsigned int h = seed ^ (len * m);
84
85 int align = (uint64_t)data & 3;
86
87 if(align && (len >= 4))
88 {
89 // Pre-load the temp registers
90
91 unsigned int t = 0, d = 0;
92
93 switch(align)
94 {
95 case 1: t |= data[2] << 16;
96 case 2: t |= data[1] << 8;
97 case 3: t |= data[0];
98 }
99
100 t <<= (8 * align);
101
102 data += 4-align;
103 len -= 4-align;
104
105 int sl = 8 * (4-align);
106 int sr = 8 * align;
107
108 // Mix
109
110 while(len >= 4)
111 {
112 d = *(unsigned int *)data;
113 t = (t >> sr) | (d << sl);
114 h += t;
115 h *= m;
116 h ^= h >> r;
117 t = d;
118
119 data += 4;
120 len -= 4;
121 }
122
123 // Handle leftover data in temp registers
124
125 int pack = len < align ? len : align;
126
127 d = 0;
128
129 switch(pack)
130 {
131 case 3: d |= data[2] << 16;
132 case 2: d |= data[1] << 8;
133 case 1: d |= data[0];
134 case 0: h += (t >> sr) | (d << sl);
135 h *= m;
136 h ^= h >> r;
137 }
138
139 data += pack;
140 len -= pack;
141 }
142 else
143 {
144 while(len >= 4)
145 {
146 h += *(unsigned int *)data;
147 h *= m;
148 h ^= h >> r;
149
150 data += 4;
151 len -= 4;
152 }
153 }
154
155 //----------
156 // Handle tail bytes
157
158 switch(len)
159 {
160 case 3: h += data[2] << 16;
161 case 2: h += data[1] << 8;
162 case 1: h += data[0];
163 h *= m;
164 h ^= h >> r;
165 };
166
167 h *= m;
168 h ^= h >> 10;
169 h *= m;
170 h ^= h >> 17;
171
172 return h;
173}
174