Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(179)

Side by Side Diff: base/hash.h

Issue 1502373009: Allow std::unordered_*. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: danakj comments, adjust IntPairHash silghtly Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium 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 #ifndef BASE_HASH_H_ 5 #ifndef BASE_HASH_H_
6 #define BASE_HASH_H_ 6 #define BASE_HASH_H_
7 7
8 #include <stddef.h> 8 #include <stddef.h>
9 #include <stdint.h> 9 #include <stdint.h>
10 10
11 #include <limits> 11 #include <limits>
12 #include <string> 12 #include <string>
13 #include <utility>
13 14
14 #include "base/base_export.h" 15 #include "base/base_export.h"
15 #include "base/logging.h" 16 #include "base/logging.h"
16 17
17 namespace base { 18 namespace base {
18 19
19 // WARNING: This hash function should not be used for any cryptographic purpose. 20 // WARNING: This hash function should not be used for any cryptographic purpose.
20 BASE_EXPORT uint32_t SuperFastHash(const char* data, int len); 21 BASE_EXPORT uint32_t SuperFastHash(const char* data, int len);
21 22
22 // Computes a hash of a memory buffer |data| of a given |length|. 23 // Computes a hash of a memory buffer |data| of a given |length|.
23 // WARNING: This hash function should not be used for any cryptographic purpose. 24 // WARNING: This hash function should not be used for any cryptographic purpose.
24 inline uint32_t Hash(const char* data, size_t length) { 25 inline uint32_t Hash(const char* data, size_t length) {
25 if (length > static_cast<size_t>(std::numeric_limits<int>::max())) { 26 if (length > static_cast<size_t>(std::numeric_limits<int>::max())) {
26 NOTREACHED(); 27 NOTREACHED();
27 return 0; 28 return 0;
28 } 29 }
29 return SuperFastHash(data, static_cast<int>(length)); 30 return SuperFastHash(data, static_cast<int>(length));
30 } 31 }
31 32
32 // Computes a hash of a string |str|. 33 // Computes a hash of a string |str|.
33 // WARNING: This hash function should not be used for any cryptographic purpose. 34 // WARNING: This hash function should not be used for any cryptographic purpose.
34 inline uint32_t Hash(const std::string& str) { 35 inline uint32_t Hash(const std::string& str) {
35 return Hash(str.data(), str.size()); 36 return Hash(str.data(), str.size());
36 } 37 }
37 38
39 // Implement hashing for pairs of at-most 32 bit integer values.
40 // When size_t is 32 bits, we turn the 64-bit hash code into 32 bits by using
41 // multiply-add hashing. This algorithm, as described in
42 // Theorem 4.3.3 of the thesis "Über die Komplexität der Multiplikation in
43 // eingeschränkten Branchingprogrammmodellen" by Woelfel, is:
44 //
45 // h32(x32, y32) = (h64(x32, y32) * rand_odd64 + rand16 * 2^16) % 2^64 / 2^32
46 //
47 // Contact danakj@chromium.org for any questions.
48 inline size_t HashInts32(uint32_t value1, uint32_t value2) {
davidben 2016/01/16 00:22:23 I switched std::size_t to size_t to avoid having t
danakj 2016/01/19 21:21:55 Ya they will, cool.
49 uint64_t value1_64 = value1;
50 uint64_t hash64 = (value1_64 << 32) | value2;
51
52 if (sizeof(size_t) >= sizeof(uint64_t))
53 return static_cast<size_t>(hash64);
54
55 uint64_t odd_random = 481046412LL << 32 | 1025306955LL;
56 uint32_t shift_random = 10121U << 16;
57
58 hash64 = hash64 * odd_random + shift_random;
59 size_t high_bits = static_cast<size_t>(
60 hash64 >> (8 * (sizeof(uint64_t) - sizeof(size_t))));
61 return high_bits;
62 }
63
64 // Implement hashing for pairs of up-to 64-bit integer values.
65 // We use the compound integer hash method to produce a 64-bit hash code, by
66 // breaking the two 64-bit inputs into 4 32-bit values:
67 // http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECT ION00832000000000000000
68 // Then we reduce our result to 32 bits if required, similar to above.
69 inline size_t HashInts64(uint64_t value1, uint64_t value2) {
70 uint32_t short_random1 = 842304669U;
71 uint32_t short_random2 = 619063811U;
72 uint32_t short_random3 = 937041849U;
73 uint32_t short_random4 = 3309708029U;
74
75 uint32_t value1a = static_cast<uint32_t>(value1 & 0xffffffff);
76 uint32_t value1b = static_cast<uint32_t>((value1 >> 32) & 0xffffffff);
77 uint32_t value2a = static_cast<uint32_t>(value2 & 0xffffffff);
78 uint32_t value2b = static_cast<uint32_t>((value2 >> 32) & 0xffffffff);
79
80 uint64_t product1 = static_cast<uint64_t>(value1a) * short_random1;
81 uint64_t product2 = static_cast<uint64_t>(value1b) * short_random2;
82 uint64_t product3 = static_cast<uint64_t>(value2a) * short_random3;
83 uint64_t product4 = static_cast<uint64_t>(value2b) * short_random4;
84
85 uint64_t hash64 = product1 + product2 + product3 + product4;
86
87 if (sizeof(size_t) >= sizeof(uint64_t))
88 return static_cast<size_t>(hash64);
89
90 uint64_t odd_random = 1578233944LL << 32 | 194370989LL;
91 uint32_t shift_random = 20591U << 16;
92
93 hash64 = hash64 * odd_random + shift_random;
94 size_t high_bits = static_cast<size_t>(
95 hash64 >> (8 * (sizeof(uint64_t) - sizeof(size_t))));
96 return high_bits;
97 }
98
99 template<typename T1, typename T2>
100 inline size_t HashInts(T1 value1, T2 value2) {
101 // This condition is expected to be compile-time evaluated and optimised away
102 // in release builds.
103 if (sizeof(T1) > sizeof(uint32_t) || (sizeof(T2) > sizeof(uint32_t)))
104 return HashInts64(value1, value2);
105
106 return HashInts32(value1, value2);
107 }
108
109 // A templated hasher for pairs of integer types.
110 template<typename T> struct IntPairHash;
111
112 template<typename Type1, typename Type2>
113 struct IntPairHash<std::pair<Type1, Type2>> {
davidben 2016/01/16 00:22:23 Is there a better way to do this? / Should I be do
danakj 2016/01/19 21:21:54 I'm uh.. staring at this pretending I know C++ but
davidben 2016/01/19 22:30:28 Oh, sorry, that was ambiguous. By "the old one", I
114 size_t operator()(std::pair<Type1, Type2> value) const {
115 return HashInts(value.first, value.second);
116 }
117 };
118
38 } // namespace base 119 } // namespace base
39 120
40 #endif // BASE_HASH_H_ 121 #endif // BASE_HASH_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698