| 347 | } |
| 348 | |
| 349 | uint64 CityHash64(const char *s, size_t len) { |
| 350 | if (len <= 32) { |
| 351 | if (len <= 16) { |
| 352 | return HashLen0to16(s, len); |
| 353 | } else { |
| 354 | return HashLen17to32(s, len); |
| 355 | } |
| 356 | } else if (len <= 64) { |
| 357 | return HashLen33to64(s, len); |
| 358 | } |
| 359 | |
| 360 | // For strings over 64 bytes we hash the end first, and then as we |
| 361 | // loop we keep 56 bytes of state: v, w, x, y, and z. |
| 362 | uint64 x = Fetch64(s + len - 40); |
| 363 | uint64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56); |
| 364 | uint64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24)); |
| 365 | pair<uint64, uint64> v = WeakHashLen32WithSeeds(s + len - 64, len, z); |
| 366 | pair<uint64, uint64> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x); |
| 367 | x = x * k1 + Fetch64(s); |
| 368 | |
| 369 | // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks. |
| 370 | len = (len - 1) & ~static_cast<size_t>(63); |
| 371 | do { |
| 372 | x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1; |
| 373 | y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; |
| 374 | x ^= w.second; |
| 375 | y += v.first + Fetch64(s + 40); |
| 376 | z = Rotate(z + w.first, 33) * k1; |
| 377 | v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); |
| 378 | w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16)); |
| 379 | std::swap(z, x); |
| 380 | s += 64; |
| 381 | len -= 64; |
| 382 | } while (len != 0); |
| 383 | return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z, |
| 384 | HashLen16(v.second, w.second) + x); |
| 385 | } |
| 386 | |
| 387 | uint64 CityHash64WithSeed(const char *s, size_t len, uint64 seed) { |
| 388 | return CityHash64WithSeeds(s, len, k2, seed); |
no test coverage detected