other-licenses/nsis/Contrib/CityHash/cityhash/city.cpp

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

     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 Version 1, 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.
    30 #include "city.h"
    32 #include <algorithm>
    34 using namespace std;
    36 #define UNALIGNED_LOAD64(p) (*(const uint64*)(p))
    37 #define UNALIGNED_LOAD32(p) (*(const uint32*)(p))
    39 #if !defined(LIKELY)
    40 #if defined(__GNUC__)
    41 #define LIKELY(x) (__builtin_expect(!!(x), 1))
    42 #else
    43 #define LIKELY(x) (x)
    44 #endif
    45 #endif
    47 // Some primes between 2^63 and 2^64 for various uses.
    48 static const uint64 k0 = 0xc3a5c85c97cb3127;
    49 static const uint64 k1 = 0xb492b66fbe98f273;
    50 static const uint64 k2 = 0x9ae16a3b2f90404f;
    51 static const uint64 k3 = 0xc949d7c7509e6557;
    53 // Bitwise right rotate.  Normally this will compile to a single
    54 // instruction, especially if the shift is a manifest constant.
    55 static uint64 Rotate(uint64 val, int shift) {
    56   // Avoid shifting by 64: doing so yields an undefined result.
    57   return shift == 0 ? val : ((val >> shift) | (val << (64 - shift)));
    58 }
    60 // Equivalent to Rotate(), but requires the second arg to be non-zero.
    61 // On x86-64, and probably others, it's possible for this to compile
    62 // to a single instruction if both args are already in registers.
    63 static uint64 RotateByAtLeast1(uint64 val, int shift) {
    64   return (val >> shift) | (val << (64 - shift));
    65 }
    67 static uint64 ShiftMix(uint64 val) {
    68   return val ^ (val >> 47);
    69 }
    71 static uint64 HashLen16(uint64 u, uint64 v) {
    72   return Hash128to64(uint128(u, v));
    73 }
    75 static uint64 HashLen0to16(const char *s, size_t len) {
    76   if (len > 8) {
    77     uint64 a = UNALIGNED_LOAD64(s);
    78     uint64 b = UNALIGNED_LOAD64(s + len - 8);
    79     return HashLen16(a, RotateByAtLeast1(b + len, len)) ^ b;
    80   }
    81   if (len >= 4) {
    82     uint64 a = UNALIGNED_LOAD32(s);
    83     return HashLen16(len + (a << 3), UNALIGNED_LOAD32(s + len - 4));
    84   }
    85   if (len > 0) {
    86     uint8 a = s[0];
    87     uint8 b = s[len >> 1];
    88     uint8 c = s[len - 1];
    89     uint32 y = static_cast<uint32>(a) + (static_cast<uint32>(b) << 8);
    90     uint32 z = len + (static_cast<uint32>(c) << 2);
    91     return ShiftMix(y * k2 ^ z * k3) * k2;
    92   }
    93   return k2;
    94 }
    96 // This probably works well for 16-byte strings as well, but it may be overkill
    97 // in that case.
    98 static uint64 HashLen17to32(const char *s, size_t len) {
    99   uint64 a = UNALIGNED_LOAD64(s) * k1;
   100   uint64 b = UNALIGNED_LOAD64(s + 8);
   101   uint64 c = UNALIGNED_LOAD64(s + len - 8) * k2;
   102   uint64 d = UNALIGNED_LOAD64(s + len - 16) * k0;
   103   return HashLen16(Rotate(a - b, 43) + Rotate(c, 30) + d,
   104                    a + Rotate(b ^ k3, 20) - c + len);
   105 }
   107 // Return a 16-byte hash for 48 bytes.  Quick and dirty.
   108 // Callers do best to use "random-looking" values for a and b.
   109 static pair<uint64, uint64> WeakHashLen32WithSeeds(
   110     uint64 w, uint64 x, uint64 y, uint64 z, uint64 a, uint64 b) {
   111   a += w;
   112   b = Rotate(b + a + z, 21);
   113   uint64 c = a;
   114   a += x;
   115   a += y;
   116   b += Rotate(a, 44);
   117   return make_pair(a + z, b + c);
   118 }
   120 // Return a 16-byte hash for s[0] ... s[31], a, and b.  Quick and dirty.
   121 static pair<uint64, uint64> WeakHashLen32WithSeeds(
   122     const char* s, uint64 a, uint64 b) {
   123   return WeakHashLen32WithSeeds(UNALIGNED_LOAD64(s),
   124                                 UNALIGNED_LOAD64(s + 8),
   125                                 UNALIGNED_LOAD64(s + 16),
   126                                 UNALIGNED_LOAD64(s + 24),
   127                                 a,
   128                                 b);
   129 }
   131 // Return an 8-byte hash for 33 to 64 bytes.
   132 static uint64 HashLen33to64(const char *s, size_t len) {
   133   uint64 z = UNALIGNED_LOAD64(s + 24);
   134   uint64 a = UNALIGNED_LOAD64(s) + (len + UNALIGNED_LOAD64(s + len - 16)) * k0;
   135   uint64 b = Rotate(a + z, 52);
   136   uint64 c = Rotate(a, 37);
   137   a += UNALIGNED_LOAD64(s + 8);
   138   c += Rotate(a, 7);
   139   a += UNALIGNED_LOAD64(s + 16);
   140   uint64 vf = a + z;
   141   uint64 vs = b + Rotate(a, 31) + c;
   142   a = UNALIGNED_LOAD64(s + 16) + UNALIGNED_LOAD64(s + len - 32);
   143   z = UNALIGNED_LOAD64(s + len - 8);
   144   b = Rotate(a + z, 52);
   145   c = Rotate(a, 37);
   146   a += UNALIGNED_LOAD64(s + len - 24);
   147   c += Rotate(a, 7);
   148   a += UNALIGNED_LOAD64(s + len - 16);
   149   uint64 wf = a + z;
   150   uint64 ws = b + Rotate(a, 31) + c;
   151   uint64 r = ShiftMix((vf + ws) * k2 + (wf + vs) * k0);
   152   return ShiftMix(r * k0 + vs) * k2;
   153 }
   155 uint64 CityHash64(const char *s, size_t len) {
   156   if (len <= 32) {
   157     if (len <= 16) {
   158       return HashLen0to16(s, len);
   159     } else {
   160       return HashLen17to32(s, len);
   161     }
   162   } else if (len <= 64) {
   163     return HashLen33to64(s, len);
   164   }
   166   // For strings over 64 bytes we hash the end first, and then as we
   167   // loop we keep 56 bytes of state: v, w, x, y, and z.
   168   uint64 x = UNALIGNED_LOAD64(s);
   169   uint64 y = UNALIGNED_LOAD64(s + len - 16) ^ k1;
   170   uint64 z = UNALIGNED_LOAD64(s + len - 56) ^ k0;
   171   pair<uint64, uint64> v = WeakHashLen32WithSeeds(s + len - 64, len, y);
   172   pair<uint64, uint64> w = WeakHashLen32WithSeeds(s + len - 32, len * k1, k0);
   173   z += ShiftMix(v.second) * k1;
   174   x = Rotate(z + x, 39) * k1;
   175   y = Rotate(y, 33) * k1;
   177   // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
   178   len = (len - 1) & ~static_cast<size_t>(63);
   179   do {
   180     x = Rotate(x + y + v.first + UNALIGNED_LOAD64(s + 16), 37) * k1;
   181     y = Rotate(y + v.second + UNALIGNED_LOAD64(s + 48), 42) * k1;
   182     x ^= w.second;
   183     y ^= v.first;
   184     z = Rotate(z ^ w.first, 33);
   185     v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
   186     w = WeakHashLen32WithSeeds(s + 32, z + w.second, y);
   187     std::swap(z, x);
   188     s += 64;
   189     len -= 64;
   190   } while (len != 0);
   191   return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z,
   192                    HashLen16(v.second, w.second) + x);
   193 }
   195 uint64 CityHash64WithSeed(const char *s, size_t len, uint64 seed) {
   196   return CityHash64WithSeeds(s, len, k2, seed);
   197 }
   199 uint64 CityHash64WithSeeds(const char *s, size_t len,
   200                            uint64 seed0, uint64 seed1) {
   201   return HashLen16(CityHash64(s, len) - seed0, seed1);
   202 }
   204 // A subroutine for CityHash128().  Returns a decent 128-bit hash for strings
   205 // of any length representable in ssize_t.  Based on City and Murmur.
   206 static uint128 CityMurmur(const char *s, size_t len, uint128 seed) {
   207   uint64 a = Uint128Low64(seed);
   208   uint64 b = Uint128High64(seed);
   209   uint64 c = 0;
   210   uint64 d = 0;
   211   ssize_t l = len - 16;
   212   if (l <= 0) {  // len <= 16
   213     c = b * k1 + HashLen0to16(s, len);
   214     d = Rotate(a + (len >= 8 ? UNALIGNED_LOAD64(s) : c), 32);
   215   } else {  // len > 16
   216     c = HashLen16(UNALIGNED_LOAD64(s + len - 8) + k1, a);
   217     d = HashLen16(b + len, c + UNALIGNED_LOAD64(s + len - 16));
   218     a += d;
   219     do {
   220       a ^= ShiftMix(UNALIGNED_LOAD64(s) * k1) * k1;
   221       a *= k1;
   222       b ^= a;
   223       c ^= ShiftMix(UNALIGNED_LOAD64(s + 8) * k1) * k1;
   224       c *= k1;
   225       d ^= c;
   226       s += 16;
   227       l -= 16;
   228     } while (l > 0);
   229   }
   230   a = HashLen16(a, c);
   231   b = HashLen16(d, b);
   232   return uint128(a ^ b, HashLen16(b, a));
   233 }
   235 uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) {
   236   if (len < 128) {
   237     return CityMurmur(s, len, seed);
   238   }
   240   // We expect len >= 128 to be the common case.  Keep 56 bytes of state:
   241   // v, w, x, y, and z.
   242   pair<uint64, uint64> v, w;
   243   uint64 x = Uint128Low64(seed);
   244   uint64 y = Uint128High64(seed);
   245   uint64 z = len * k1;
   246   v.first = Rotate(y ^ k1, 49) * k1 + UNALIGNED_LOAD64(s);
   247   v.second = Rotate(v.first, 42) * k1 + UNALIGNED_LOAD64(s + 8);
   248   w.first = Rotate(y + z, 35) * k1 + x;
   249   w.second = Rotate(x + UNALIGNED_LOAD64(s + 88), 53) * k1;
   251   // This is the same inner loop as CityHash64(), manually unrolled.
   252   do {
   253     x = Rotate(x + y + v.first + UNALIGNED_LOAD64(s + 16), 37) * k1;
   254     y = Rotate(y + v.second + UNALIGNED_LOAD64(s + 48), 42) * k1;
   255     x ^= w.second;
   256     y ^= v.first;
   257     z = Rotate(z ^ w.first, 33);
   258     v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
   259     w = WeakHashLen32WithSeeds(s + 32, z + w.second, y);
   260     std::swap(z, x);
   261     s += 64;
   262     x = Rotate(x + y + v.first + UNALIGNED_LOAD64(s + 16), 37) * k1;
   263     y = Rotate(y + v.second + UNALIGNED_LOAD64(s + 48), 42) * k1;
   264     x ^= w.second;
   265     y ^= v.first;
   266     z = Rotate(z ^ w.first, 33);
   267     v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
   268     w = WeakHashLen32WithSeeds(s + 32, z + w.second, y);
   269     std::swap(z, x);
   270     s += 64;
   271     len -= 128;
   272   } while (LIKELY(len >= 128));
   273   y += Rotate(w.first, 37) * k0 + z;
   274   x += Rotate(v.first + z, 49) * k0;
   275   // If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s.
   276   for (size_t tail_done = 0; tail_done < len; ) {
   277     tail_done += 32;
   278     y = Rotate(y - x, 42) * k0 + v.second;
   279     w.first += UNALIGNED_LOAD64(s + len - tail_done + 16);
   280     x = Rotate(x, 49) * k0 + w.first;
   281     w.first += v.first;
   282     v = WeakHashLen32WithSeeds(s + len - tail_done, v.first, v.second);
   283   }
   284   // At this point our 48 bytes of state should contain more than
   285   // enough information for a strong 128-bit hash.  We use two
   286   // different 48-byte-to-8-byte hashes to get a 16-byte final result.
   287   x = HashLen16(x, v.first);
   288   y = HashLen16(y, w.first);
   289   return uint128(HashLen16(x + v.second, w.second) + y,
   290                  HashLen16(x + w.second, y + v.second));
   291 }
   293 uint128 CityHash128(const char *s, size_t len) {
   294   if (len >= 16) {
   295     return CityHash128WithSeed(s + 16,
   296                                len - 16,
   297                                uint128(UNALIGNED_LOAD64(s) ^ k3,
   298                                        UNALIGNED_LOAD64(s + 8)));
   299   } else if (len >= 8) {
   300     return CityHash128WithSeed(NULL,
   301                                0,
   302                                uint128(UNALIGNED_LOAD64(s) ^ (len * k0),
   303                                        UNALIGNED_LOAD64(s + len - 8) ^ k1));
   304   } else {
   305     return CityHash128WithSeed(s, len, uint128(k0, k1));
   306   }
   307 }

mercurial