30 #include "../interface/city.h"
37 static uint64 UNALIGNED_LOAD64(
const char *p) {
39 memcpy(&result, p,
sizeof(result));
43 static uint32 UNALIGNED_LOAD32(
const char *p) {
45 memcpy(&result, p,
sizeof(result));
49 #if !defined(WORDS_BIGENDIAN)
51 #define uint32_in_expected_order(x) (x)
52 #define uint64_in_expected_order(x) (x)
58 #define bswap_32(x) _byteswap_ulong(x)
59 #define bswap_64(x) _byteswap_uint64(x)
61 #elif defined(__APPLE__)
63 #include <libkern/OSByteOrder.h>
64 #define bswap_32(x) OSSwapInt32(x)
65 #define bswap_64(x) OSSwapInt64(x)
71 #define uint32_in_expected_order(x) (bswap_32(x))
72 #define uint64_in_expected_order(x) (bswap_64(x))
74 #endif // WORDS_BIGENDIAN
77 #if HAVE_BUILTIN_EXPECT
78 #define LIKELY(x) (__builtin_expect(!!(x), 1))
84 static uint64 Fetch64(
const char *p) {
88 static uint32 Fetch32(
const char *p) {
93 static const uint64 k0 = 0xc3a5c85c97cb3127ULL;
94 static const uint64 k1 = 0xb492b66fbe98f273ULL;
95 static const uint64 k2 = 0x9ae16a3b2f90404fULL;
96 static const uint64 k3 = 0xc949d7c7509e6557ULL;
102 return shift == 0 ? val : ((val >> shift) | (val << (64 - shift)));
109 return (val >> shift) | (val << (64 - shift));
113 return val ^ (val >> 47);
120 static uint64 HashLen0to16(
const char *s,
size_t len) {
123 uint64 b = Fetch64(s + len - 8);
124 return HashLen16(a, RotateByAtLeast1(b + len, len)) ^ b;
128 return HashLen16(len + (a << 3), Fetch32(s + len - 4));
132 uint8 b = s[len >> 1];
133 uint8 c = s[len - 1];
134 uint32 y =
static_cast<uint32>(a) + (static_cast<uint32>(b) << 8);
136 return ShiftMix(y * k2 ^ z * k3) * k2;
143 static uint64 HashLen17to32(
const char *s,
size_t len) {
144 uint64 a = Fetch64(s) * k1;
145 uint64 b = Fetch64(s + 8);
146 uint64 c = Fetch64(s + len - 8) * k2;
147 uint64 d = Fetch64(s + len - 16) * k0;
148 return HashLen16(Rotate(a - b, 43) + Rotate(c, 30) + d,
149 a + Rotate(b ^ k3, 20) - c + len);
154 static pair<uint64, uint64> WeakHashLen32WithSeeds(
157 b = Rotate(b + a + z, 21);
162 return make_pair(a + z, b + c);
166 static pair<uint64, uint64> WeakHashLen32WithSeeds(
168 return WeakHashLen32WithSeeds(Fetch64(s),
177 static uint64 HashLen33to64(
const char *s,
size_t len) {
178 uint64 z = Fetch64(s + 24);
179 uint64 a = Fetch64(s) + (len + Fetch64(s + len - 16)) * k0;
180 uint64 b = Rotate(a + z, 52);
184 a += Fetch64(s + 16);
186 uint64 vs = b + Rotate(a, 31) + c;
187 a = Fetch64(s + 16) + Fetch64(s + len - 32);
188 z = Fetch64(s + len - 8);
189 b = Rotate(a + z, 52);
191 a += Fetch64(s + len - 24);
193 a += Fetch64(s + len - 16);
195 uint64 ws = b + Rotate(a, 31) + c;
196 uint64 r = ShiftMix((vf + ws) * k2 + (wf + vs) * k0);
197 return ShiftMix(r * k0 + vs) * k2;
203 return HashLen0to16(s, len);
205 return HashLen17to32(s, len);
207 }
else if (len <= 64) {
208 return HashLen33to64(s, len);
213 uint64 x = Fetch64(s + len - 40);
214 uint64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56);
215 uint64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));
216 pair<uint64, uint64> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
217 pair<uint64, uint64> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
218 x = x * k1 + Fetch64(s);
221 len = (len - 1) & ~static_cast<size_t>(63);
223 x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
224 y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
226 y += v.first + Fetch64(s + 40);
227 z = Rotate(z + w.first, 33) * k1;
228 v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
229 w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
234 return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z,
235 HashLen16(v.second, w.second) + x);
248 return HashLen16(
CityHash64(s, len) - seed0, seed1);
253 static uint128 CityMurmur(
const char *s,
size_t len,
uint128 seed) {
258 signed long l = len - 16;
260 a = ShiftMix(a * k1) * k1;
261 c = b * k1 + HashLen0to16(s, len);
262 d = ShiftMix(a + (len >= 8 ? Fetch64(s) : c));
264 c = HashLen16(Fetch64(s + len - 8) + k1, a);
265 d = HashLen16(b + len, c + Fetch64(s + len - 16));
268 a ^= ShiftMix(Fetch64(s) * k1) * k1;
271 c ^= ShiftMix(Fetch64(s + 8) * k1) * k1;
280 return uint128(a ^ b, HashLen16(b, a));
285 return CityMurmur(s, len, seed);
290 pair<uint64, uint64> v, w;
294 v.first = Rotate(y ^ k1, 49) * k1 + Fetch64(s);
295 v.second = Rotate(v.first, 42) * k1 + Fetch64(s + 8);
296 w.first = Rotate(y + z, 35) * k1 + x;
297 w.second = Rotate(x + Fetch64(s + 88), 53) * k1;
301 x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
302 y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
304 y += v.first + Fetch64(s + 40);
305 z = Rotate(z + w.first, 33) * k1;
306 v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
307 w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
310 x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
311 y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
313 y += v.first + Fetch64(s + 40);
314 z = Rotate(z + w.first, 33) * k1;
315 v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
316 w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
320 }
while (
LIKELY(len >= 128));
321 x += Rotate(v.first + z, 49) * k0;
322 z += Rotate(w.first, 37) * k0;
324 for (
size_t tail_done = 0; tail_done < len; ) {
326 y = Rotate(x + y, 42) * k0 + v.second;
327 w.first += Fetch64(s + len - tail_done + 16);
328 x = x * k0 + w.first;
329 z += w.second + Fetch64(s + len - tail_done);
331 v = WeakHashLen32WithSeeds(s + len - tail_done, v.first + z, v.second);
336 x = HashLen16(x, v.first);
337 y = HashLen16(y + z, w.first);
338 return uint128(HashLen16(x + v.second, w.second) + y,
339 HashLen16(x + w.second, y + v.second));
348 }
else if (len >= 8) {
351 uint128(Fetch64(s) ^ (len * k0),
352 Fetch64(s + len - 8) ^ k1));
360 #include <nmmintrin.h>
363 static void CityHashCrc256Long(
const char *s,
size_t len,
365 uint64 a = Fetch64(s + 56) + k0;
366 uint64 b = Fetch64(s + 96) + k0;
367 uint64 c = result[0] = HashLen16(b, len);
368 uint64 d = result[1] = Fetch64(s + 120) * k0 + len;
369 uint64 e = Fetch64(s + 184) + seed;
378 size_t iters = len / 240;
381 #define CHUNK(multiplier, z) \
384 a = Rotate(b, 41 ^ z) * multiplier + Fetch64(s); \
385 b = Rotate(c, 27 ^ z) * multiplier + Fetch64(s + 8); \
386 c = Rotate(d, 41 ^ z) * multiplier + Fetch64(s + 16); \
387 d = Rotate(e, 33 ^ z) * multiplier + Fetch64(s + 24); \
388 e = Rotate(t, 25 ^ z) * multiplier + Fetch64(s + 32); \
391 f = _mm_crc32_u64(f, a); \
392 g = _mm_crc32_u64(g, b); \
393 h = _mm_crc32_u64(h, c); \
394 i = _mm_crc32_u64(i, d); \
395 j = _mm_crc32_u64(j, e); \
398 CHUNK(1, 1); CHUNK(k0, 0);
399 CHUNK(1, 1); CHUNK(k0, 0);
400 CHUNK(1, 1); CHUNK(k0, 0);
401 }
while (--iters > 0);
415 c = HashLen16(c, f) + i;
416 d = HashLen16(d, e + result[0]);
418 i += HashLen16(h, t);
419 e = HashLen16(a, d) + j;
420 f = HashLen16(b, c) + a;
421 g = HashLen16(j, i) + c;
422 result[0] = e + f + g +
h;
423 a = ShiftMix((a + g) * k0) * k0 + b;
424 result[1] += a + result[0];
425 a = ShiftMix(a * k0) * k0 + c;
426 result[2] = a + result[1];
427 a = ShiftMix((a + e) * k0) * k0;
428 result[3] = a + result[2];
432 static void CityHashCrc256Short(
const char *s,
size_t len,
uint64 *result) {
435 memset(buf + len, 0, 240 - len);
436 CityHashCrc256Long(buf, 240, ~static_cast<uint32>(len), result);
439 void CityHashCrc256(
const char *s,
size_t len,
uint64 *result) {
441 CityHashCrc256Long(s, len, 0, result);
443 CityHashCrc256Short(s, len, result);
447 uint128 CityHashCrc128WithSeed(
const char *s,
size_t len,
uint128 seed) {
452 CityHashCrc256(s, len, result);
455 return uint128(HashLen16(u, v + result[2]),
456 HashLen16(Rotate(v, 32), u * k0 + result[3]));
460 uint128 CityHashCrc128(
const char *s,
size_t len) {
465 CityHashCrc256(s, len, result);
466 return uint128(result[2], result[3]);
uint64 Uint128High64(const uint128 &x)
uint64 Hash128to64(const uint128 &x)
uint64 Uint128Low64(const uint128 &x)
#define uint64_in_expected_order(x)
uint64 CityHash64WithSeeds(const char *s, size_t len, uint64 seed0, uint64 seed1)
uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed)
uint64 CityHash64(const char *s, size_t len)
uint128 CityHash128(const char *s, size_t len)
uint64 CityHash64WithSeed(const char *s, size_t len, uint64 seed)
std::pair< uint64, uint64 > uint128
#define uint32_in_expected_order(x)