// Copyright (c) 2011 Google, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // CityHash Version 1, by Geoff Pike and Jyrki Alakuijala // // This file provides CityHash64() and related functions. // // It's probably possible to create even faster hash functions by // writing a program that systematically explores some of the space of // possible hash functions, by using SIMD instructions, or by // compromising on hash quality. #include "city.h" #include using namespace std; #define UNALIGNED_LOAD64(p) (*(const uint64*)(p)) #define UNALIGNED_LOAD32(p) (*(const uint32*)(p)) #if !defined(LIKELY) #if defined(__GNUC__) #define LIKELY(x) (__builtin_expect(!!(x), 1)) #else #define LIKELY(x) (x) #endif #endif // Some primes between 2^63 and 2^64 for various uses. static const uint64 k0 = 0xc3a5c85c97cb3127; static const uint64 k1 = 0xb492b66fbe98f273; static const uint64 k2 = 0x9ae16a3b2f90404f; static const uint64 k3 = 0xc949d7c7509e6557; // Bitwise right rotate. Normally this will compile to a single // instruction, especially if the shift is a manifest constant. static uint64 Rotate(uint64 val, int shift) { // Avoid shifting by 64: doing so yields an undefined result. return shift == 0 ? val : ((val >> shift) | (val << (64 - shift))); } // Equivalent to Rotate(), but requires the second arg to be non-zero. // On x86-64, and probably others, it's possible for this to compile // to a single instruction if both args are already in registers. static uint64 RotateByAtLeast1(uint64 val, int shift) { return (val >> shift) | (val << (64 - shift)); } static uint64 ShiftMix(uint64 val) { return val ^ (val >> 47); } static uint64 HashLen16(uint64 u, uint64 v) { return Hash128to64(uint128(u, v)); } static uint64 HashLen0to16(const char *s, size_t len) { if (len > 8) { uint64 a = UNALIGNED_LOAD64(s); uint64 b = UNALIGNED_LOAD64(s + len - 8); return HashLen16(a, RotateByAtLeast1(b + len, len)) ^ b; } if (len >= 4) { uint64 a = UNALIGNED_LOAD32(s); return HashLen16(len + (a << 3), UNALIGNED_LOAD32(s + len - 4)); } if (len > 0) { uint8 a = s[0]; uint8 b = s[len >> 1]; uint8 c = s[len - 1]; uint32 y = static_cast(a) + (static_cast(b) << 8); uint32 z = len + (static_cast(c) << 2); return ShiftMix(y * k2 ^ z * k3) * k2; } return k2; } // This probably works well for 16-byte strings as well, but it may be overkill // in that case. static uint64 HashLen17to32(const char *s, size_t len) { uint64 a = UNALIGNED_LOAD64(s) * k1; uint64 b = UNALIGNED_LOAD64(s + 8); uint64 c = UNALIGNED_LOAD64(s + len - 8) * k2; uint64 d = UNALIGNED_LOAD64(s + len - 16) * k0; return HashLen16(Rotate(a - b, 43) + Rotate(c, 30) + d, a + Rotate(b ^ k3, 20) - c + len); } // Return a 16-byte hash for 48 bytes. Quick and dirty. // Callers do best to use "random-looking" values for a and b. static pair WeakHashLen32WithSeeds( uint64 w, uint64 x, uint64 y, uint64 z, uint64 a, uint64 b) { a += w; b = Rotate(b + a + z, 21); uint64 c = a; a += x; a += y; b += Rotate(a, 44); return make_pair(a + z, b + c); } // Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty. static pair WeakHashLen32WithSeeds( const char* s, uint64 a, uint64 b) { return WeakHashLen32WithSeeds(UNALIGNED_LOAD64(s), UNALIGNED_LOAD64(s + 8), UNALIGNED_LOAD64(s + 16), UNALIGNED_LOAD64(s + 24), a, b); } // Return an 8-byte hash for 33 to 64 bytes. static uint64 HashLen33to64(const char *s, size_t len) { uint64 z = UNALIGNED_LOAD64(s + 24); uint64 a = UNALIGNED_LOAD64(s) + (len + UNALIGNED_LOAD64(s + len - 16)) * k0; uint64 b = Rotate(a + z, 52); uint64 c = Rotate(a, 37); a += UNALIGNED_LOAD64(s + 8); c += Rotate(a, 7); a += UNALIGNED_LOAD64(s + 16); uint64 vf = a + z; uint64 vs = b + Rotate(a, 31) + c; a = UNALIGNED_LOAD64(s + 16) + UNALIGNED_LOAD64(s + len - 32); z = UNALIGNED_LOAD64(s + len - 8); b = Rotate(a + z, 52); c = Rotate(a, 37); a += UNALIGNED_LOAD64(s + len - 24); c += Rotate(a, 7); a += UNALIGNED_LOAD64(s + len - 16); uint64 wf = a + z; uint64 ws = b + Rotate(a, 31) + c; uint64 r = ShiftMix((vf + ws) * k2 + (wf + vs) * k0); return ShiftMix(r * k0 + vs) * k2; } uint64 CityHash64(const char *s, size_t len) { if (len <= 32) { if (len <= 16) { return HashLen0to16(s, len); } else { return HashLen17to32(s, len); } } else if (len <= 64) { return HashLen33to64(s, len); } // For strings over 64 bytes we hash the end first, and then as we // loop we keep 56 bytes of state: v, w, x, y, and z. uint64 x = UNALIGNED_LOAD64(s); uint64 y = UNALIGNED_LOAD64(s + len - 16) ^ k1; uint64 z = UNALIGNED_LOAD64(s + len - 56) ^ k0; pair v = WeakHashLen32WithSeeds(s + len - 64, len, y); pair w = WeakHashLen32WithSeeds(s + len - 32, len * k1, k0); z += ShiftMix(v.second) * k1; x = Rotate(z + x, 39) * k1; y = Rotate(y, 33) * k1; // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks. len = (len - 1) & ~static_cast(63); do { x = Rotate(x + y + v.first + UNALIGNED_LOAD64(s + 16), 37) * k1; y = Rotate(y + v.second + UNALIGNED_LOAD64(s + 48), 42) * k1; x ^= w.second; y ^= v.first; z = Rotate(z ^ w.first, 33); v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); w = WeakHashLen32WithSeeds(s + 32, z + w.second, y); std::swap(z, x); s += 64; len -= 64; } while (len != 0); return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z, HashLen16(v.second, w.second) + x); } uint64 CityHash64WithSeed(const char *s, size_t len, uint64 seed) { return CityHash64WithSeeds(s, len, k2, seed); } uint64 CityHash64WithSeeds(const char *s, size_t len, uint64 seed0, uint64 seed1) { return HashLen16(CityHash64(s, len) - seed0, seed1); } // A subroutine for CityHash128(). Returns a decent 128-bit hash for strings // of any length representable in ssize_t. Based on City and Murmur. static uint128 CityMurmur(const char *s, size_t len, uint128 seed) { uint64 a = Uint128Low64(seed); uint64 b = Uint128High64(seed); uint64 c = 0; uint64 d = 0; ssize_t l = len - 16; if (l <= 0) { // len <= 16 c = b * k1 + HashLen0to16(s, len); d = Rotate(a + (len >= 8 ? UNALIGNED_LOAD64(s) : c), 32); } else { // len > 16 c = HashLen16(UNALIGNED_LOAD64(s + len - 8) + k1, a); d = HashLen16(b + len, c + UNALIGNED_LOAD64(s + len - 16)); a += d; do { a ^= ShiftMix(UNALIGNED_LOAD64(s) * k1) * k1; a *= k1; b ^= a; c ^= ShiftMix(UNALIGNED_LOAD64(s + 8) * k1) * k1; c *= k1; d ^= c; s += 16; l -= 16; } while (l > 0); } a = HashLen16(a, c); b = HashLen16(d, b); return uint128(a ^ b, HashLen16(b, a)); } uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) { if (len < 128) { return CityMurmur(s, len, seed); } // We expect len >= 128 to be the common case. Keep 56 bytes of state: // v, w, x, y, and z. pair v, w; uint64 x = Uint128Low64(seed); uint64 y = Uint128High64(seed); uint64 z = len * k1; v.first = Rotate(y ^ k1, 49) * k1 + UNALIGNED_LOAD64(s); v.second = Rotate(v.first, 42) * k1 + UNALIGNED_LOAD64(s + 8); w.first = Rotate(y + z, 35) * k1 + x; w.second = Rotate(x + UNALIGNED_LOAD64(s + 88), 53) * k1; // This is the same inner loop as CityHash64(), manually unrolled. do { x = Rotate(x + y + v.first + UNALIGNED_LOAD64(s + 16), 37) * k1; y = Rotate(y + v.second + UNALIGNED_LOAD64(s + 48), 42) * k1; x ^= w.second; y ^= v.first; z = Rotate(z ^ w.first, 33); v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); w = WeakHashLen32WithSeeds(s + 32, z + w.second, y); std::swap(z, x); s += 64; x = Rotate(x + y + v.first + UNALIGNED_LOAD64(s + 16), 37) * k1; y = Rotate(y + v.second + UNALIGNED_LOAD64(s + 48), 42) * k1; x ^= w.second; y ^= v.first; z = Rotate(z ^ w.first, 33); v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); w = WeakHashLen32WithSeeds(s + 32, z + w.second, y); std::swap(z, x); s += 64; len -= 128; } while (LIKELY(len >= 128)); y += Rotate(w.first, 37) * k0 + z; x += Rotate(v.first + z, 49) * k0; // If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s. for (size_t tail_done = 0; tail_done < len; ) { tail_done += 32; y = Rotate(y - x, 42) * k0 + v.second; w.first += UNALIGNED_LOAD64(s + len - tail_done + 16); x = Rotate(x, 49) * k0 + w.first; w.first += v.first; v = WeakHashLen32WithSeeds(s + len - tail_done, v.first, v.second); } // At this point our 48 bytes of state should contain more than // enough information for a strong 128-bit hash. We use two // different 48-byte-to-8-byte hashes to get a 16-byte final result. x = HashLen16(x, v.first); y = HashLen16(y, w.first); return uint128(HashLen16(x + v.second, w.second) + y, HashLen16(x + w.second, y + v.second)); } uint128 CityHash128(const char *s, size_t len) { if (len >= 16) { return CityHash128WithSeed(s + 16, len - 16, uint128(UNALIGNED_LOAD64(s) ^ k3, UNALIGNED_LOAD64(s + 8))); } else if (len >= 8) { return CityHash128WithSeed(NULL, 0, uint128(UNALIGNED_LOAD64(s) ^ (len * k0), UNALIGNED_LOAD64(s + len - 8) ^ k1)); } else { return CityHash128WithSeed(s, len, uint128(k0, k1)); } }