| 380 | } |
| 381 | |
| 382 | std::uint64_t CityHash64(const char* s, std::size_t len) |
| 383 | { |
| 384 | if (len <= 32) { |
| 385 | if (len <= 16) { |
| 386 | return HashLen0to16(s, len); |
| 387 | } else { |
| 388 | return HashLen17to32(s, len); |
| 389 | } |
| 390 | } else if (len <= 64) { |
| 391 | return HashLen33to64(s, len); |
| 392 | } |
| 393 | |
| 394 | // For strings over 64 bytes we hash the end first, and then as we |
| 395 | // loop we keep 56 bytes of state: v, w, x, y, and z. |
| 396 | std::uint64_t x = Fetch64(s + len - 40); |
| 397 | std::uint64_t y = Fetch64(s + len - 16) + Fetch64(s + len - 56); |
| 398 | std::uint64_t z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24)); |
| 399 | std::pair<std::uint64_t, std::uint64_t> v = WeakHashLen32WithSeeds(s + len - 64, len, z); |
| 400 | std::pair<std::uint64_t, std::uint64_t> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x); |
| 401 | x = x * k1 + Fetch64(s); |
| 402 | |
| 403 | // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks. |
| 404 | len = (len - 1) & ~static_cast<std::size_t>(63); |
| 405 | do { |
| 406 | x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1; |
| 407 | y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; |
| 408 | x ^= w.second; |
| 409 | y += v.first + Fetch64(s + 40); |
| 410 | z = Rotate(z + w.first, 33) * k1; |
| 411 | v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); |
| 412 | w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16)); |
| 413 | std::swap(z, x); |
| 414 | s += 64; |
| 415 | len -= 64; |
| 416 | } while (len != 0); |
| 417 | return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z, HashLen16(v.second, w.second) + x); |
| 418 | } |
| 419 | |
| 420 | std::uint64_t CityHash64WithSeeds(const char* s, std::size_t len, std::uint64_t seed0, uint64_t seed1) |
| 421 | { |
no test coverage detected