OLD | NEW |
---|---|
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 | 5 |
6 // | 6 // |
7 // Deal with the differences between Microsoft and GNU implemenations | 7 // Deal with the differences between Microsoft and GNU implemenations |
8 // of hash_map. Allows all platforms to use |base::hash_map| and | 8 // of hash_map. Allows all platforms to use |base::hash_map| and |
9 // |base::hash_set|. | 9 // |base::hash_set|. |
10 // eg: | 10 // eg: |
(...skipping 13 matching lines...) Expand all Loading... | |
24 #include "build/build_config.h" | 24 #include "build/build_config.h" |
25 | 25 |
26 #include "base/string16.h" | 26 #include "base/string16.h" |
27 | 27 |
28 #if defined(COMPILER_MSVC) | 28 #if defined(COMPILER_MSVC) |
29 #include <hash_map> | 29 #include <hash_map> |
30 #include <hash_set> | 30 #include <hash_set> |
31 | 31 |
32 #define BASE_HASH_NAMESPACE stdext | 32 #define BASE_HASH_NAMESPACE stdext |
33 | 33 |
34 template <typename Key> | |
35 struct hash : public BASE_HASH_NAMESPACE::hash_compare<Key> { | |
36 }; | |
37 | |
34 #elif defined(COMPILER_GCC) | 38 #elif defined(COMPILER_GCC) |
35 #if defined(OS_ANDROID) | 39 #if defined(OS_ANDROID) |
36 #define BASE_HASH_NAMESPACE std | 40 #define BASE_HASH_NAMESPACE std |
37 #else | 41 #else |
38 #define BASE_HASH_NAMESPACE __gnu_cxx | 42 #define BASE_HASH_NAMESPACE __gnu_cxx |
39 #endif | 43 #endif |
40 | 44 |
41 // This is a hack to disable the gcc 4.4 warning about hash_map and hash_set | 45 // This is a hack to disable the gcc 4.4 warning about hash_map and hash_set |
42 // being deprecated. We can get rid of this when we upgrade to VS2008 and we | 46 // being deprecated. We can get rid of this when we upgrade to VS2008 and we |
43 // can use <tr1/unordered_map> and <tr1/unordered_set>. | 47 // can use <tr1/unordered_map> and <tr1/unordered_set>. |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
98 result = (result * 131) + *i; \ | 102 result = (result * 131) + *i; \ |
99 return result; \ | 103 return result; \ |
100 } \ | 104 } \ |
101 } | 105 } |
102 | 106 |
103 DEFINE_STRING_HASH(std::string); | 107 DEFINE_STRING_HASH(std::string); |
104 DEFINE_STRING_HASH(string16); | 108 DEFINE_STRING_HASH(string16); |
105 | 109 |
106 #undef DEFINE_STRING_HASH | 110 #undef DEFINE_STRING_HASH |
107 | 111 |
112 // Implement hashing for pairs of at-most 32 bit integer values. | |
113 // We use randomly-generated 32-bit and 64-bit values to produce a hash code. | |
114 // If the hash code is 64-bit then we can be very efficient to produce a | |
115 // universal hash function. When size_t is 64 bits, the algorithm, as described | |
116 // in Section 4 of "UMAC: Fast and Secure Message Authentication" by Black, | |
117 // Halevi, Krawczyk, Krovetz, and Rogaway, is: | |
118 // | |
119 // h64(x32, y32) = ((x32 + rand32) % 2^32)((y32 + rand32) % 2^32) % 2^64 | |
jar (doing other things)
2012/09/17 22:01:13
a) It appears that the second modulus operator (mo
| |
120 // | |
121 // When size_t is 32 bits, we turn the 64-bit hash code above back into | |
122 // 32 bits by using multiply-add hashing. This algorithm, as described in | |
123 // Theorem 6 of "Efficient Strongly Universal and Optimally Universal Hashing" | |
124 // by Woelfel, is: | |
125 // | |
126 // h32(x32, y32) = (h64(x32, y32) * randOdd64 + rand32 * 2^32) % 2^64 / 2^32 | |
jar (doing other things)
2012/09/17 22:01:13
Here, the addition of rand32 * 2^32 is useless, fo
| |
127 | |
128 #define DEFINE_32BIT_PAIR_HASH(type1, type2) \ | |
129 template<> \ | |
130 struct hash<std::pair<type1, type2> > { \ | |
131 std::size_t operator()(std::pair<type1, type2> value) const { \ | |
132 uint32 shortRandom1 = 698340900U; \ | |
133 uint32 shortRandom2 = 2638093458U; \ | |
134 \ | |
135 uint32 sum1 = value.first + shortRandom1; \ | |
136 uint32 sum2 = value.second + shortRandom2; \ | |
137 uint64 hash64 = static_cast<uint64>(sum1) * sum2; \ | |
138 \ | |
139 if (sizeof(std::size_t) >= sizeof(uint64)) \ | |
140 return static_cast<std::size_t>(hash64); \ | |
141 \ | |
142 uint64 longRandom1 = 885644242649267641LL; \ | |
143 uint64 longRandom2 = 1614045628LL << 32; \ | |
144 \ | |
145 hash64 = hash64 * longRandom1 + longRandom2; \ | |
146 std::size_t highBits = static_cast<std::size_t>( \ | |
147 hash64 >> (sizeof(uint64) - sizeof(std::size_t))); \ | |
148 return highBits; \ | |
149 } \ | |
150 \ | |
151 size_t operator()(const std::pair<type1, type2>& a, \ | |
152 const std::pair<type1, type2>& b) const { \ | |
153 return a < b; \ | |
154 } \ | |
155 }; \ | |
156 | |
157 DEFINE_32BIT_PAIR_HASH(short, short); | |
158 DEFINE_32BIT_PAIR_HASH(short, unsigned short); | |
159 DEFINE_32BIT_PAIR_HASH(short, int); | |
160 DEFINE_32BIT_PAIR_HASH(short, unsigned); | |
161 DEFINE_32BIT_PAIR_HASH(unsigned short, short); | |
162 DEFINE_32BIT_PAIR_HASH(unsigned short, unsigned short); | |
163 DEFINE_32BIT_PAIR_HASH(unsigned short, int); | |
164 DEFINE_32BIT_PAIR_HASH(unsigned short, unsigned); | |
165 DEFINE_32BIT_PAIR_HASH(int, short); | |
166 DEFINE_32BIT_PAIR_HASH(int, unsigned short); | |
167 DEFINE_32BIT_PAIR_HASH(int, int); | |
168 DEFINE_32BIT_PAIR_HASH(int, unsigned); | |
169 DEFINE_32BIT_PAIR_HASH(unsigned, short); | |
170 DEFINE_32BIT_PAIR_HASH(unsigned, unsigned short); | |
171 DEFINE_32BIT_PAIR_HASH(unsigned, int); | |
172 DEFINE_32BIT_PAIR_HASH(unsigned, unsigned); | |
173 | |
174 #undef DEFINE_32BIT_PAIR_HASH | |
175 | |
176 // Implement hashing for pairs of up-to 64-bit integer values. | |
177 // We use the above algorithms for 32-bit integers, but treat each 64-bit | |
178 // value as 2 32-bit values. | |
179 | |
180 #define DEFINE_64BIT_PAIR_HASH(type1, type2) \ | |
181 template<> \ | |
182 struct hash<std::pair<type1, type2> > { \ | |
183 std::size_t operator()(std::pair<type1, type2> value) const { \ | |
184 uint32 shortRandom1 = 673537332U; \ | |
185 uint32 shortRandom2 = 2309950629U; \ | |
186 uint32 shortRandom3 = 29379286U; \ | |
187 uint32 shortRandom4 = 2611985739U; \ | |
188 \ | |
189 uint64 value1 = value.first; \ | |
190 uint64 value2 = value.second; \ | |
191 uint32 value1a = static_cast<uint32>(value1 & 0xffffffff); \ | |
192 uint32 value1b = static_cast<uint32>((value1 >> 32) & 0xffffffff); \ | |
193 uint32 value2a = static_cast<uint32>(value2 & 0xffffffff); \ | |
194 uint32 value2b = static_cast<uint32>((value2 >> 32) & 0xffffffff); \ | |
195 \ | |
196 uint32 sum1 = value1a + shortRandom1; \ | |
197 uint32 sum2 = value1b + shortRandom2; \ | |
198 uint32 sum3 = value2a + shortRandom3; \ | |
199 uint32 sum4 = value2b + shortRandom4; \ | |
200 uint64 hash64 = static_cast<uint64>(sum1) * sum2 + \ | |
201 static_cast<uint64>(sum3) * sum4; \ | |
202 \ | |
203 if (sizeof(std::size_t) >= sizeof(uint64)) \ | |
204 return static_cast<std::size_t>(hash64); \ | |
205 \ | |
206 uint64 longRandom1 = 629146275505555501LL; \ | |
207 uint64 longRandom2 = 45557137LL << 32; \ | |
208 \ | |
209 hash64 = hash64 * longRandom1 + longRandom2; \ | |
210 std::size_t highBits = static_cast<std::size_t>( \ | |
211 hash64 >> (sizeof(uint64) - sizeof(std::size_t))); \ | |
212 return highBits; \ | |
213 } \ | |
214 size_t operator()(const std::pair<type1, type2>& a, \ | |
215 const std::pair<type1, type2>& b) const { \ | |
216 return a < b; \ | |
217 } \ | |
218 }; | |
219 | |
220 DEFINE_64BIT_PAIR_HASH(short, int64); | |
221 DEFINE_64BIT_PAIR_HASH(short, uint64); | |
222 DEFINE_64BIT_PAIR_HASH(unsigned short, int64); | |
223 DEFINE_64BIT_PAIR_HASH(unsigned short, uint64); | |
224 DEFINE_64BIT_PAIR_HASH(int, int64); | |
225 DEFINE_64BIT_PAIR_HASH(int, uint64); | |
226 DEFINE_64BIT_PAIR_HASH(unsigned, int64); | |
227 DEFINE_64BIT_PAIR_HASH(unsigned, uint64); | |
228 DEFINE_64BIT_PAIR_HASH(int64, short); | |
229 DEFINE_64BIT_PAIR_HASH(int64, unsigned short); | |
230 DEFINE_64BIT_PAIR_HASH(int64, int); | |
231 DEFINE_64BIT_PAIR_HASH(int64, unsigned); | |
232 DEFINE_64BIT_PAIR_HASH(int64, int64); | |
233 DEFINE_64BIT_PAIR_HASH(int64, uint64); | |
234 DEFINE_64BIT_PAIR_HASH(uint64, short); | |
235 DEFINE_64BIT_PAIR_HASH(uint64, unsigned short); | |
236 DEFINE_64BIT_PAIR_HASH(uint64, int); | |
237 DEFINE_64BIT_PAIR_HASH(uint64, unsigned); | |
238 DEFINE_64BIT_PAIR_HASH(uint64, int64); | |
239 DEFINE_64BIT_PAIR_HASH(uint64, uint64); | |
240 | |
241 #undef DEFINE_64BIT_PAIR_HASH | |
242 | |
108 } // namespace BASE_HASH_NAMESPACE | 243 } // namespace BASE_HASH_NAMESPACE |
109 | 244 |
110 #else // COMPILER | 245 #else // COMPILER |
111 #error define BASE_HASH_NAMESPACE for your compiler | 246 #error define BASE_HASH_NAMESPACE for your compiler |
112 #endif // COMPILER | 247 #endif // COMPILER |
113 | 248 |
114 namespace base { | 249 namespace base { |
115 using BASE_HASH_NAMESPACE::hash_map; | 250 using BASE_HASH_NAMESPACE::hash_map; |
116 using BASE_HASH_NAMESPACE::hash_set; | 251 using BASE_HASH_NAMESPACE::hash_set; |
117 } | 252 } |
118 | 253 |
119 #endif // BASE_HASH_TABLES_H_ | 254 #endif // BASE_HASH_TABLES_H_ |
OLD | NEW |