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