Chromium Code Reviews| 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 |