OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 // | 4 // |
5 // This also contains public domain code from MurmurHash. From the | 5 // This also contains public domain code from MurmurHash. From the |
6 // MurmurHash header: | 6 // MurmurHash header: |
7 // | 7 // |
8 // MurmurHash3 was written by Austin Appleby, and is placed in the public | 8 // MurmurHash3 was written by Austin Appleby, and is placed in the public |
9 // domain. The author hereby disclaims copyright to this source code. | 9 // domain. The author hereby disclaims copyright to this source code. |
10 | 10 |
11 #include "src/base/functional.h" | 11 #include "src/base/functional.h" |
12 | 12 |
13 #include <limits> | 13 #include <limits> |
14 | 14 |
15 #include "src/base/bits.h" | 15 #include "src/base/bits.h" |
16 | 16 |
17 namespace v8 { | 17 namespace v8 { |
18 namespace base { | 18 namespace base { |
19 | 19 |
20 namespace { | 20 namespace { |
21 | 21 |
| 22 // Thomas Wang, Integer Hash Functions. |
| 23 // https://gist.github.com/badboy/6267743 |
22 template <typename T> | 24 template <typename T> |
23 inline size_t hash_value_unsigned(T value) { | 25 V8_INLINE size_t hash_value_unsigned(T v) { |
24 const unsigned size_t_bits = std::numeric_limits<size_t>::digits; | 26 switch (sizeof(T)) { |
25 // ceiling(std::numeric_limits<T>::digits / size_t_bits) - 1 | 27 case 4: { |
26 const unsigned length = (std::numeric_limits<T>::digits - 1) / size_t_bits; | 28 // "32 bit Mix Functions" |
27 size_t seed = 0; | 29 v = ~v + (v << 15); // v = (v << 15) - v - 1; |
28 // Hopefully, this loop can be unrolled. | 30 v = v ^ (v >> 12); |
29 for (unsigned i = length * size_t_bits; i > 0; i -= size_t_bits) { | 31 v = v + (v << 2); |
30 seed ^= static_cast<size_t>(value >> i) + (seed << 6) + (seed >> 2); | 32 v = v ^ (v >> 4); |
| 33 v = v * 2057; // v = (v + (v << 3)) + (v << 11); |
| 34 v = v ^ (v >> 16); |
| 35 return static_cast<size_t>(v); |
| 36 } |
| 37 case 8: { |
| 38 switch (sizeof(size_t)) { |
| 39 case 4: { |
| 40 // "64 bit to 32 bit Hash Functions" |
| 41 v = ~v + (v << 18); // v = (v << 18) - v - 1; |
| 42 v = v ^ (v >> 31); |
| 43 v = v * 21; // v = (v + (v << 2)) + (v << 4); |
| 44 v = v ^ (v >> 11); |
| 45 v = v + (v << 6); |
| 46 v = v ^ (v >> 22); |
| 47 return static_cast<size_t>(v); |
| 48 } |
| 49 case 8: { |
| 50 // "64 bit Mix Functions" |
| 51 v = ~v + (v << 21); // v = (v << 21) - v - 1; |
| 52 v = v ^ (v >> 24); |
| 53 v = (v + (v << 3)) + (v << 8); // v * 265 |
| 54 v = v ^ (v >> 14); |
| 55 v = (v + (v << 2)) + (v << 4); // v * 21 |
| 56 v = v ^ (v >> 28); |
| 57 v = v + (v << 31); |
| 58 return static_cast<size_t>(v); |
| 59 } |
| 60 } |
| 61 } |
31 } | 62 } |
32 seed ^= static_cast<size_t>(value) + (seed << 6) + (seed >> 2); | 63 UNREACHABLE(); |
33 return seed; | 64 return static_cast<size_t>(v); |
34 } | 65 } |
35 | 66 |
36 } // namespace | 67 } // namespace |
37 | 68 |
38 | 69 |
39 // This code was taken from MurmurHash. | 70 // This code was taken from MurmurHash. |
40 size_t hash_combine(size_t seed, size_t value) { | 71 size_t hash_combine(size_t seed, size_t value) { |
41 #if V8_HOST_ARCH_32_BIT | 72 #if V8_HOST_ARCH_32_BIT |
42 const uint32_t c1 = 0xcc9e2d51; | 73 const uint32_t c1 = 0xcc9e2d51; |
43 const uint32_t c2 = 0x1b873593; | 74 const uint32_t c2 = 0x1b873593; |
(...skipping 13 matching lines...) Expand all Loading... |
57 value ^= value >> r; | 88 value ^= value >> r; |
58 value *= m; | 89 value *= m; |
59 | 90 |
60 seed ^= value; | 91 seed ^= value; |
61 seed *= m; | 92 seed *= m; |
62 #endif // V8_HOST_ARCH_32_BIT | 93 #endif // V8_HOST_ARCH_32_BIT |
63 return seed; | 94 return seed; |
64 } | 95 } |
65 | 96 |
66 | 97 |
67 // Thomas Wang, Integer Hash Functions. | 98 size_t hash_value(unsigned int v) { return hash_value_unsigned(v); } |
68 // http://www.concentric.net/~Ttwang/tech/inthash.htm | |
69 size_t hash_value(unsigned int v) { | |
70 v = ~v + (v << 15); // v = (v << 15) - v - 1; | |
71 v = v ^ (v >> 12); | |
72 v = v + (v << 2); | |
73 v = v ^ (v >> 4); | |
74 v = v * 2057; // v = (v + (v << 3)) + (v << 11); | |
75 v = v ^ (v >> 16); | |
76 return v; | |
77 } | |
78 | 99 |
79 | 100 |
80 size_t hash_value(unsigned long v) { // NOLINT(runtime/int) | 101 size_t hash_value(unsigned long v) { // NOLINT(runtime/int) |
81 return hash_value_unsigned(v); | 102 return hash_value_unsigned(v); |
82 } | 103 } |
83 | 104 |
84 | 105 |
85 size_t hash_value(unsigned long long v) { // NOLINT(runtime/int) | 106 size_t hash_value(unsigned long long v) { // NOLINT(runtime/int) |
86 return hash_value_unsigned(v); | 107 return hash_value_unsigned(v); |
87 } | 108 } |
88 | 109 |
89 | |
90 size_t hash_value(float v) { | |
91 // 0 and -0 both hash to zero. | |
92 return v != 0.0f ? hash_value_unsigned(bit_cast<uint32_t>(v)) : 0; | |
93 } | |
94 | |
95 | |
96 size_t hash_value(double v) { | |
97 // 0 and -0 both hash to zero. | |
98 return v != 0.0 ? hash_value_unsigned(bit_cast<uint64_t>(v)) : 0; | |
99 } | |
100 | |
101 } // namespace base | 110 } // namespace base |
102 } // namespace v8 | 111 } // namespace v8 |
OLD | NEW |