| // Copyright 2014 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // This also contains public domain code from MurmurHash. From the |
| // MurmurHash header: |
| // |
| // MurmurHash3 was written by Austin Appleby, and is placed in the public |
| // domain. The author hereby disclaims copyright to this source code. |
| |
| #include "src/base/functional.h" |
| |
| #include <limits> |
| |
| #include "src/base/bits.h" |
| |
| namespace v8 { |
| namespace base { |
| |
| namespace { |
| |
| // Thomas Wang, Integer Hash Functions. |
| // https://gist.github.com/badboy/6267743 |
| template <typename T> |
| V8_INLINE size_t hash_value_unsigned(T v) { |
| switch (sizeof(T)) { |
| case 4: { |
| // "32 bit Mix Functions" |
| v = ~v + (v << 15); // v = (v << 15) - v - 1; |
| v = v ^ (v >> 12); |
| v = v + (v << 2); |
| v = v ^ (v >> 4); |
| v = v * 2057; // v = (v + (v << 3)) + (v << 11); |
| v = v ^ (v >> 16); |
| return static_cast<size_t>(v); |
| } |
| case 8: { |
| switch (sizeof(size_t)) { |
| case 4: { |
| // "64 bit to 32 bit Hash Functions" |
| v = ~v + (v << 18); // v = (v << 18) - v - 1; |
| v = v ^ (v >> 31); |
| v = v * 21; // v = (v + (v << 2)) + (v << 4); |
| v = v ^ (v >> 11); |
| v = v + (v << 6); |
| v = v ^ (v >> 22); |
| return static_cast<size_t>(v); |
| } |
| case 8: { |
| // "64 bit Mix Functions" |
| v = ~v + (v << 21); // v = (v << 21) - v - 1; |
| v = v ^ (v >> 24); |
| v = (v + (v << 3)) + (v << 8); // v * 265 |
| v = v ^ (v >> 14); |
| v = (v + (v << 2)) + (v << 4); // v * 21 |
| v = v ^ (v >> 28); |
| v = v + (v << 31); |
| return static_cast<size_t>(v); |
| } |
| } |
| } |
| } |
| UNREACHABLE(); |
| } |
| |
| } // namespace |
| |
| |
| // This code was taken from MurmurHash. |
| size_t hash_combine(size_t seed, size_t value) { |
| #if V8_HOST_ARCH_32_BIT |
| const uint32_t c1 = 0xCC9E2D51; |
| const uint32_t c2 = 0x1B873593; |
| |
| value *= c1; |
| value = bits::RotateRight32(value, 15); |
| value *= c2; |
| |
| seed ^= value; |
| seed = bits::RotateRight32(seed, 13); |
| seed = seed * 5 + 0xE6546B64; |
| #else |
| const uint64_t m = uint64_t{0xC6A4A7935BD1E995}; |
| const uint32_t r = 47; |
| |
| value *= m; |
| value ^= value >> r; |
| value *= m; |
| |
| seed ^= value; |
| seed *= m; |
| #endif // V8_HOST_ARCH_32_BIT |
| return seed; |
| } |
| |
| |
| size_t hash_value(unsigned int v) { return hash_value_unsigned(v); } |
| |
| |
| size_t hash_value(unsigned long v) { // NOLINT(runtime/int) |
| return hash_value_unsigned(v); |
| } |
| |
| |
| size_t hash_value(unsigned long long v) { // NOLINT(runtime/int) |
| return hash_value_unsigned(v); |
| } |
| |
| } // namespace base |
| } // namespace v8 |