summaryrefslogtreecommitdiff
path: root/src/common/cityhash.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/cityhash.cpp')
-rw-r--r--src/common/cityhash.cpp340
1 files changed, 340 insertions, 0 deletions
diff --git a/src/common/cityhash.cpp b/src/common/cityhash.cpp
new file mode 100644
index 000000000..de31ffbd8
--- /dev/null
+++ b/src/common/cityhash.cpp
@@ -0,0 +1,340 @@
1// Copyright (c) 2011 Google, Inc.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19// THE SOFTWARE.
20//
21// CityHash, by Geoff Pike and Jyrki Alakuijala
22//
23// This file provides CityHash64() and related functions.
24//
25// It's probably possible to create even faster hash functions by
26// writing a program that systematically explores some of the space of
27// possible hash functions, by using SIMD instructions, or by
28// compromising on hash quality.
29
30#include <algorithm>
31#include <string.h> // for memcpy and memset
32#include "cityhash.h"
33#include "common/swap.h"
34
35// #include "config.h"
36#ifdef __GNUC__
37#define HAVE_BUILTIN_EXPECT 1
38#endif
39#ifdef COMMON_BIG_ENDIAN
40#define WORDS_BIGENDIAN 1
41#endif
42
43using namespace std;
44
45typedef uint8_t uint8;
46typedef uint32_t uint32;
47typedef uint64_t uint64;
48
49namespace Common {
50
51static uint64 UNALIGNED_LOAD64(const char* p) {
52 uint64 result;
53 memcpy(&result, p, sizeof(result));
54 return result;
55}
56
57static uint32 UNALIGNED_LOAD32(const char* p) {
58 uint32 result;
59 memcpy(&result, p, sizeof(result));
60 return result;
61}
62
63#ifdef WORDS_BIGENDIAN
64#define uint32_in_expected_order(x) (swap32(x))
65#define uint64_in_expected_order(x) (swap64(x))
66#else
67#define uint32_in_expected_order(x) (x)
68#define uint64_in_expected_order(x) (x)
69#endif
70
71#if !defined(LIKELY)
72#if HAVE_BUILTIN_EXPECT
73#define LIKELY(x) (__builtin_expect(!!(x), 1))
74#else
75#define LIKELY(x) (x)
76#endif
77#endif
78
79static uint64 Fetch64(const char* p) {
80 return uint64_in_expected_order(UNALIGNED_LOAD64(p));
81}
82
83static uint32 Fetch32(const char* p) {
84 return uint32_in_expected_order(UNALIGNED_LOAD32(p));
85}
86
87// Some primes between 2^63 and 2^64 for various uses.
88static const uint64 k0 = 0xc3a5c85c97cb3127ULL;
89static const uint64 k1 = 0xb492b66fbe98f273ULL;
90static const uint64 k2 = 0x9ae16a3b2f90404fULL;
91
92// Bitwise right rotate. Normally this will compile to a single
93// instruction, especially if the shift is a manifest constant.
94static uint64 Rotate(uint64 val, int shift) {
95 // Avoid shifting by 64: doing so yields an undefined result.
96 return shift == 0 ? val : ((val >> shift) | (val << (64 - shift)));
97}
98
99static uint64 ShiftMix(uint64 val) {
100 return val ^ (val >> 47);
101}
102
103static uint64 HashLen16(uint64 u, uint64 v) {
104 return Hash128to64(uint128(u, v));
105}
106
107static uint64 HashLen16(uint64 u, uint64 v, uint64 mul) {
108 // Murmur-inspired hashing.
109 uint64 a = (u ^ v) * mul;
110 a ^= (a >> 47);
111 uint64 b = (v ^ a) * mul;
112 b ^= (b >> 47);
113 b *= mul;
114 return b;
115}
116
117static uint64 HashLen0to16(const char* s, size_t len) {
118 if (len >= 8) {
119 uint64 mul = k2 + len * 2;
120 uint64 a = Fetch64(s) + k2;
121 uint64 b = Fetch64(s + len - 8);
122 uint64 c = Rotate(b, 37) * mul + a;
123 uint64 d = (Rotate(a, 25) + b) * mul;
124 return HashLen16(c, d, mul);
125 }
126 if (len >= 4) {
127 uint64 mul = k2 + len * 2;
128 uint64 a = Fetch32(s);
129 return HashLen16(len + (a << 3), Fetch32(s + len - 4), mul);
130 }
131 if (len > 0) {
132 uint8 a = s[0];
133 uint8 b = s[len >> 1];
134 uint8 c = s[len - 1];
135 uint32 y = static_cast<uint32>(a) + (static_cast<uint32>(b) << 8);
136 uint32 z = static_cast<uint32>(len) + (static_cast<uint32>(c) << 2);
137 return ShiftMix(y * k2 ^ z * k0) * k2;
138 }
139 return k2;
140}
141
142// This probably works well for 16-byte strings as well, but it may be overkill
143// in that case.
144static uint64 HashLen17to32(const char* s, size_t len) {
145 uint64 mul = k2 + len * 2;
146 uint64 a = Fetch64(s) * k1;
147 uint64 b = Fetch64(s + 8);
148 uint64 c = Fetch64(s + len - 8) * mul;
149 uint64 d = Fetch64(s + len - 16) * k2;
150 return HashLen16(Rotate(a + b, 43) + Rotate(c, 30) + d, a + Rotate(b + k2, 18) + c, mul);
151}
152
153// Return a 16-byte hash for 48 bytes. Quick and dirty.
154// Callers do best to use "random-looking" values for a and b.
155static pair<uint64, uint64> WeakHashLen32WithSeeds(uint64 w, uint64 x, uint64 y, uint64 z, uint64 a,
156 uint64 b) {
157 a += w;
158 b = Rotate(b + a + z, 21);
159 uint64 c = a;
160 a += x;
161 a += y;
162 b += Rotate(a, 44);
163 return make_pair(a + z, b + c);
164}
165
166// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty.
167static pair<uint64, uint64> WeakHashLen32WithSeeds(const char* s, uint64 a, uint64 b) {
168 return WeakHashLen32WithSeeds(Fetch64(s), Fetch64(s + 8), Fetch64(s + 16), Fetch64(s + 24), a,
169 b);
170}
171
172// Return an 8-byte hash for 33 to 64 bytes.
173static uint64 HashLen33to64(const char* s, size_t len) {
174 uint64 mul = k2 + len * 2;
175 uint64 a = Fetch64(s) * k2;
176 uint64 b = Fetch64(s + 8);
177 uint64 c = Fetch64(s + len - 24);
178 uint64 d = Fetch64(s + len - 32);
179 uint64 e = Fetch64(s + 16) * k2;
180 uint64 f = Fetch64(s + 24) * 9;
181 uint64 g = Fetch64(s + len - 8);
182 uint64 h = Fetch64(s + len - 16) * mul;
183 uint64 u = Rotate(a + g, 43) + (Rotate(b, 30) + c) * 9;
184 uint64 v = ((a + g) ^ d) + f + 1;
185 uint64 w = swap64((u + v) * mul) + h;
186 uint64 x = Rotate(e + f, 42) + c;
187 uint64 y = (swap64((v + w) * mul) + g) * mul;
188 uint64 z = e + f + c;
189 a = swap64((x + z) * mul + y) + b;
190 b = ShiftMix((z + a) * mul + d + h) * mul;
191 return b + x;
192}
193
194uint64 CityHash64(const char* s, size_t len) {
195 if (len <= 32) {
196 if (len <= 16) {
197 return HashLen0to16(s, len);
198 } else {
199 return HashLen17to32(s, len);
200 }
201 } else if (len <= 64) {
202 return HashLen33to64(s, len);
203 }
204
205 // For strings over 64 bytes we hash the end first, and then as we
206 // loop we keep 56 bytes of state: v, w, x, y, and z.
207 uint64 x = Fetch64(s + len - 40);
208 uint64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56);
209 uint64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));
210 pair<uint64, uint64> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
211 pair<uint64, uint64> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
212 x = x * k1 + Fetch64(s);
213
214 // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
215 len = (len - 1) & ~static_cast<size_t>(63);
216 do {
217 x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
218 y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
219 x ^= w.second;
220 y += v.first + Fetch64(s + 40);
221 z = Rotate(z + w.first, 33) * k1;
222 v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
223 w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
224 std::swap(z, x);
225 s += 64;
226 len -= 64;
227 } while (len != 0);
228 return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z,
229 HashLen16(v.second, w.second) + x);
230}
231
232uint64 CityHash64WithSeed(const char* s, size_t len, uint64 seed) {
233 return CityHash64WithSeeds(s, len, k2, seed);
234}
235
236uint64 CityHash64WithSeeds(const char* s, size_t len, uint64 seed0, uint64 seed1) {
237 return HashLen16(CityHash64(s, len) - seed0, seed1);
238}
239
240// A subroutine for CityHash128(). Returns a decent 128-bit hash for strings
241// of any length representable in signed long. Based on City and Murmur.
242static uint128 CityMurmur(const char* s, size_t len, uint128 seed) {
243 uint64 a = Uint128Low64(seed);
244 uint64 b = Uint128High64(seed);
245 uint64 c = 0;
246 uint64 d = 0;
247 signed long l = static_cast<long>(len) - 16;
248 if (l <= 0) { // len <= 16
249 a = ShiftMix(a * k1) * k1;
250 c = b * k1 + HashLen0to16(s, len);
251 d = ShiftMix(a + (len >= 8 ? Fetch64(s) : c));
252 } else { // len > 16
253 c = HashLen16(Fetch64(s + len - 8) + k1, a);
254 d = HashLen16(b + len, c + Fetch64(s + len - 16));
255 a += d;
256 do {
257 a ^= ShiftMix(Fetch64(s) * k1) * k1;
258 a *= k1;
259 b ^= a;
260 c ^= ShiftMix(Fetch64(s + 8) * k1) * k1;
261 c *= k1;
262 d ^= c;
263 s += 16;
264 l -= 16;
265 } while (l > 0);
266 }
267 a = HashLen16(a, c);
268 b = HashLen16(d, b);
269 return uint128(a ^ b, HashLen16(b, a));
270}
271
272uint128 CityHash128WithSeed(const char* s, size_t len, uint128 seed) {
273 if (len < 128) {
274 return CityMurmur(s, len, seed);
275 }
276
277 // We expect len >= 128 to be the common case. Keep 56 bytes of state:
278 // v, w, x, y, and z.
279 pair<uint64, uint64> v, w;
280 uint64 x = Uint128Low64(seed);
281 uint64 y = Uint128High64(seed);
282 uint64 z = len * k1;
283 v.first = Rotate(y ^ k1, 49) * k1 + Fetch64(s);
284 v.second = Rotate(v.first, 42) * k1 + Fetch64(s + 8);
285 w.first = Rotate(y + z, 35) * k1 + x;
286 w.second = Rotate(x + Fetch64(s + 88), 53) * k1;
287
288 // This is the same inner loop as CityHash64(), manually unrolled.
289 do {
290 x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
291 y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
292 x ^= w.second;
293 y += v.first + Fetch64(s + 40);
294 z = Rotate(z + w.first, 33) * k1;
295 v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
296 w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
297 std::swap(z, x);
298 s += 64;
299 x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
300 y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
301 x ^= w.second;
302 y += v.first + Fetch64(s + 40);
303 z = Rotate(z + w.first, 33) * k1;
304 v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
305 w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
306 std::swap(z, x);
307 s += 64;
308 len -= 128;
309 } while (LIKELY(len >= 128));
310 x += Rotate(v.first + z, 49) * k0;
311 y = y * k0 + Rotate(w.second, 37);
312 z = z * k0 + Rotate(w.first, 27);
313 w.first *= 9;
314 v.first *= k0;
315 // If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s.
316 for (size_t tail_done = 0; tail_done < len;) {
317 tail_done += 32;
318 y = Rotate(x + y, 42) * k0 + v.second;
319 w.first += Fetch64(s + len - tail_done + 16);
320 x = x * k0 + w.first;
321 z += w.second + Fetch64(s + len - tail_done);
322 w.second += v.first;
323 v = WeakHashLen32WithSeeds(s + len - tail_done, v.first + z, v.second);
324 v.first *= k0;
325 }
326 // At this point our 56 bytes of state should contain more than
327 // enough information for a strong 128-bit hash. We use two
328 // different 56-byte-to-8-byte hashes to get a 16-byte final result.
329 x = HashLen16(x, v.first);
330 y = HashLen16(y + z, w.first);
331 return uint128(HashLen16(x + v.second, w.second) + y, HashLen16(x + w.second, y + v.second));
332}
333
334uint128 CityHash128(const char* s, size_t len) {
335 return len >= 16
336 ? CityHash128WithSeed(s + 16, len - 16, uint128(Fetch64(s), Fetch64(s + 8) + k0))
337 : CityHash128WithSeed(s, len, uint128(k0, k1));
338}
339
340} // namespace Common