NIM 跨平台 C++ SDK
载入中...
搜索中...
未找到
phmap_utils.h
浏览该文件的文档.
1#if !defined(phmap_utils_h_guard_)
2#define phmap_utils_h_guard_
3
4// ---------------------------------------------------------------------------
5// Copyright (c) 2019, Gregory Popovitch - greg7mdp@gmail.com
6//
7// minimal header providing phmap::HashState
8//
9// use as: phmap::HashState().combine(0, _first_name, _last_name, _age);
10//
11// Licensed under the Apache License, Version 2.0 (the "License");
12// you may not use this file except in compliance with the License.
13// You may obtain a copy of the License at
14//
15// https://www.apache.org/licenses/LICENSE-2.0
16//
17// Unless required by applicable law or agreed to in writing, software
18// distributed under the License is distributed on an "AS IS" BASIS,
19// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20// See the License for the specific language governing permissions and
21// limitations under the License.
22// ---------------------------------------------------------------------------
23
24#ifdef _MSC_VER
25#pragma warning(push)
26#pragma warning(disable : 4514) // unreferenced inline function has been removed
27#pragma warning(disable : 4710) // function not inlined
28#pragma warning(disable : 4711) // selected for automatic inline expansion
29#endif
30
31#include <cstdint>
32#include <functional>
33#include <tuple>
34#include "phmap_bits.h"
35#ifdef _MSC_VER
36#include "ne_stl_string.h"
37#endif
38
39// ---------------------------------------------------------------
40// Absl forward declaration requires global scope.
41// ---------------------------------------------------------------
42#if defined(PHMAP_USE_ABSL_HASH) && !defined(phmap_fwd_decl_h_guard_) && !defined(ABSL_HASH_HASH_H_)
43namespace absl {
44template <class T>
45struct Hash;
46};
47#endif
48
49namespace phmap {
50
51// ---------------------------------------------------------------
52// ---------------------------------------------------------------
53template <int n>
54struct phmap_mix {
55 inline size_t operator()(size_t) const;
56};
57
58template <>
59struct phmap_mix<4> {
60 inline size_t operator()(size_t a) const {
61 static constexpr uint64_t kmul = 0xcc9e2d51UL;
62 // static constexpr uint64_t kmul = 0x3B9ACB93UL; // [greg] my own random prime
63 uint64_t l = a * kmul;
64 return static_cast<size_t>(l ^ (l >> 32));
65 }
66};
67
68#if defined(PHMAP_HAS_UMUL128)
69template <>
70struct phmap_mix<8> {
71 // Very fast mixing (similar to Abseil)
72 inline size_t operator()(size_t a) const {
73 static constexpr uint64_t k = 0xde5fb9d2630458e9ULL;
74 // static constexpr uint64_t k = 0x7C9D0BF0567102A5ULL; // [greg] my own random prime
75 uint64_t h;
76 uint64_t l = umul128(a, k, &h);
77 return static_cast<size_t>(h + l);
78 }
79};
80#else
81template <>
82struct phmap_mix<8> {
83 inline size_t operator()(size_t a) const {
84 a = (~a) + (a << 21); // a = (a << 21) - a - 1;
85 a = a ^ (a >> 24);
86 a = (a + (a << 3)) + (a << 8); // a * 265
87 a = a ^ (a >> 14);
88 a = (a + (a << 2)) + (a << 4); // a * 21
89 a = a ^ (a >> 28);
90 a = a + (a << 31);
91 return static_cast<size_t>(a);
92 }
93};
94#endif
95
96// --------------------------------------------
97template <int n>
99 inline size_t operator()(uint64_t) const;
100};
101
102template <>
103struct fold_if_needed<4> {
104 inline size_t operator()(uint64_t a) const { return static_cast<size_t>(a ^ (a >> 32)); }
105};
106
107template <>
108struct fold_if_needed<8> {
109 inline size_t operator()(uint64_t a) const { return static_cast<size_t>(a); }
110};
111
112// ---------------------------------------------------------------
113// see if class T has a hash_value() friend method
114// ---------------------------------------------------------------
115template <typename T>
117private:
118 typedef std::true_type yes;
119 typedef std::false_type no;
120
121 template <typename U>
122 static auto test(int) -> decltype(hash_value(std::declval<const U&>()) == 1, yes());
123
124 template <typename>
125 static no test(...);
126
127public:
128 static constexpr bool value = std::is_same<decltype(test<T>(0)), yes>::value;
129};
130
131#if defined(PHMAP_USE_ABSL_HASH) && !defined(phmap_fwd_decl_h_guard_)
132template <class T>
133using Hash = ::absl::Hash<T>;
134#elif !defined(PHMAP_USE_ABSL_HASH)
135// ---------------------------------------------------------------
136// phmap::Hash
137// ---------------------------------------------------------------
138template <class T>
139struct Hash {
140 template <class U, typename std::enable_if<has_hash_value<U>::value, int>::type = 0>
141 size_t _hash(const T& val) const {
142 return hash_value(val);
143 }
144
145 template <class U, typename std::enable_if<!has_hash_value<U>::value, int>::type = 0>
146 size_t _hash(const T& val) const {
147 return std::hash<T>()(val);
148 }
149
150 inline size_t operator()(const T& val) const { return _hash<T>(val); }
151};
152
153template <class T>
154struct Hash<T*> {
155 inline size_t operator()(const T* val) const noexcept { return static_cast<size_t>(reinterpret_cast<const uintptr_t>(val)); }
156};
157
158template <class ArgumentType, class ResultType>
160 typedef ArgumentType argument_type;
161 typedef ResultType result_type;
162};
163
164template <>
165struct Hash<bool> : public phmap_unary_function<bool, size_t> {
166 inline size_t operator()(bool val) const noexcept { return static_cast<size_t>(val); }
167};
168
169template <>
170struct Hash<char> : public phmap_unary_function<char, size_t> {
171 inline size_t operator()(char val) const noexcept { return static_cast<size_t>(val); }
172};
173
174template <>
175struct Hash<signed char> : public phmap_unary_function<signed char, size_t> {
176 inline size_t operator()(signed char val) const noexcept { return static_cast<size_t>(val); }
177};
178
179template <>
180struct Hash<unsigned char> : public phmap_unary_function<unsigned char, size_t> {
181 inline size_t operator()(unsigned char val) const noexcept { return static_cast<size_t>(val); }
182};
183
184#ifdef PHMAP_HAS_NATIVE_WCHAR_T
185template <>
186struct Hash<wchar_t> : public phmap_unary_function<wchar_t, size_t> {
187 inline size_t operator()(wchar_t val) const noexcept { return static_cast<size_t>(val); }
188};
189#endif
190
191template <>
192struct Hash<int16_t> : public phmap_unary_function<int16_t, size_t> {
193 inline size_t operator()(int16_t val) const noexcept { return static_cast<size_t>(val); }
194};
195
196template <>
197struct Hash<uint16_t> : public phmap_unary_function<uint16_t, size_t> {
198 inline size_t operator()(uint16_t val) const noexcept { return static_cast<size_t>(val); }
199};
200
201template <>
202struct Hash<int32_t> : public phmap_unary_function<int32_t, size_t> {
203 inline size_t operator()(int32_t val) const noexcept { return static_cast<size_t>(val); }
204};
205
206template <>
207struct Hash<uint32_t> : public phmap_unary_function<uint32_t, size_t> {
208 inline size_t operator()(uint32_t val) const noexcept { return static_cast<size_t>(val); }
209};
210
211template <>
212struct Hash<int64_t> : public phmap_unary_function<int64_t, size_t> {
213 inline size_t operator()(int64_t val) const noexcept { return fold_if_needed<sizeof(size_t)>()(static_cast<uint64_t>(val)); }
214};
215
216template <>
217struct Hash<uint64_t> : public phmap_unary_function<uint64_t, size_t> {
218 inline size_t operator()(uint64_t val) const noexcept { return fold_if_needed<sizeof(size_t)>()(val); }
219};
220
221template <>
222struct Hash<float> : public phmap_unary_function<float, size_t> {
223 inline size_t operator()(float val) const noexcept {
224 // -0.0 and 0.0 should return same hash
225 uint32_t* as_int = reinterpret_cast<uint32_t*>(&val);
226 return (val == 0) ? static_cast<size_t>(0) : static_cast<size_t>(*as_int);
227 }
228};
229
230template <>
231struct Hash<double> : public phmap_unary_function<double, size_t> {
232 inline size_t operator()(double val) const noexcept {
233 // -0.0 and 0.0 should return same hash
234 uint64_t* as_int = reinterpret_cast<uint64_t*>(&val);
235 return (val == 0) ? static_cast<size_t>(0) : fold_if_needed<sizeof(size_t)>()(*as_int);
236 }
237};
238
239#if defined(_MSC_VER)
240template <>
241struct Hash<nstd::string> : public phmap_unary_function<nstd::string, size_t> {
242 inline size_t operator()(const nstd::string& val) const noexcept {
243 return (val.empty() ? static_cast<size_t>(0) : std::hash<std::string>{}(val.c_str()));
244 }
245};
246#endif // _MSC_VER
247
248#endif // defined(PHMAP_USE_ABSL_HASH) && !defined(phmap_fwd_decl_h_guard_)
249
250#if defined(_MSC_VER)
251#define PHMAP_HASH_ROTL32(x, r) _rotl(x, r)
252#else
253#define PHMAP_HASH_ROTL32(x, r) (x << r) | (x >> (32 - r))
254#endif
255
256template <class H, int sz>
257struct Combiner {
258 H operator()(H seed, size_t value);
259};
260
261template <class H>
262struct Combiner<H, 4> {
263 H operator()(H h1, size_t k1) {
264#if 1
265 // Copyright 2005-2014 Daniel James.
266 // Distributed under the Boost Software License, Version 1.0. (See accompanying
267 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
268
269 const uint32_t c1 = 0xcc9e2d51;
270 const uint32_t c2 = 0x1b873593;
271
272 k1 *= c1;
273 k1 = PHMAP_HASH_ROTL32(k1, 15);
274 k1 *= c2;
275
276 h1 ^= k1;
277 h1 = PHMAP_HASH_ROTL32(h1, 13);
278 h1 = h1 * 5 + 0xe6546b64;
279
280 return h1;
281#else
282 return h1 ^ (k1 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2));
283#endif
284 }
285};
286
287template <class H>
288struct Combiner<H, 8> {
289 H operator()(H h, size_t k) {
290#if 1
291 // Copyright 2005-2014 Daniel James.
292 // Distributed under the Boost Software License, Version 1.0. (See accompanying
293 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
294 const uint64_t m = (uint64_t(0xc6a4a793) << 32) + 0x5bd1e995;
295 const int r = 47;
296
297 k *= m;
298 k ^= k >> r;
299 k *= m;
300
301 h ^= k;
302 h *= m;
303
304 // Completely arbitrary number, to prevent 0's
305 // from hashing to 0.
306 h += 0xe6546b64;
307
308 return h;
309#else
310 return h ^ (k + size_t(0xc6a4a7935bd1e995) + (h << 6) + (h >> 2));
311#endif
312 }
313};
314
315// define HashState to combine member hashes... see example below
316// -----------------------------------------------------------------------------
317template <typename H>
319public:
320 template <typename T, typename... Ts>
321 static H combine(H state, const T& value, const Ts&... values);
322
323 static H combine(H state) { return state; }
324};
325
326template <typename H>
327template <typename T, typename... Ts>
328H HashStateBase<H>::combine(H seed, const T& v, const Ts&... vs) {
329 return HashStateBase<H>::combine(Combiner<H, sizeof(H)>()(seed, phmap::Hash<T>()(v)), vs...);
330}
331
333
334// -----------------------------------------------------------------------------
335
336#if !defined(PHMAP_USE_ABSL_HASH)
337
338// define Hash for std::pair
339// -------------------------
340template <class T1, class T2>
341struct Hash<std::pair<T1, T2>> {
342 size_t operator()(std::pair<T1, T2> const& p) const noexcept { return phmap::HashState().combine(phmap::Hash<T1>()(p.first), p.second); }
343};
344
345// define Hash for std::tuple
346// --------------------------
347template <class... T>
348struct Hash<std::tuple<T...>> {
349 size_t operator()(std::tuple<T...> const& t) const noexcept {
350 size_t seed = 0;
351 return _hash_helper(seed, t);
352 }
353
354private:
355 template <size_t I = 0, class TUP>
356 typename std::enable_if<I == std::tuple_size<TUP>::value, size_t>::type _hash_helper(size_t seed, const TUP&) const noexcept {
357 return seed;
358 }
359
360 template <size_t I = 0, class TUP>
361 typename std::enable_if < I<std::tuple_size<TUP>::value, size_t>::type _hash_helper(size_t seed, const TUP& t) const noexcept {
362 const auto& el = std::get<I>(t);
363 using el_type = typename std::remove_cv<typename std::remove_reference<decltype(el)>::type>::type;
365 return _hash_helper<I + 1>(seed, t);
366 }
367};
368
369#endif
370
371} // namespace phmap
372
373#ifdef _MSC_VER
374#pragma warning(pop)
375#endif
376
377#endif // phmap_utils_h_guard_
Definition: ne_stl_string.h:19
Definition: phmap_utils.h:318
static H combine(H state)
Definition: phmap_utils.h:323
static H combine(H state, const T &value, const Ts &... values)
Definition: phmap_utils.h:328
Definition: ne_stl_any.h:7
Definition: btree.h:77
HashStateBase< size_t > HashState
Definition: phmap_utils.h:332
STL namespace
#define PHMAP_HASH_ROTL32(x, r)
Definition: phmap_utils.h:253
unsigned char bool
Definition: stdbool.h:25
H operator()(H h1, size_t k1)
Definition: phmap_utils.h:263
H operator()(H h, size_t k)
Definition: phmap_utils.h:289
Definition: phmap_utils.h:257
H operator()(H seed, size_t value)
size_t operator()(const T *val) const noexcept
Definition: phmap_utils.h:155
size_t operator()(bool val) const noexcept
Definition: phmap_utils.h:166
size_t operator()(char val) const noexcept
Definition: phmap_utils.h:171
size_t operator()(double val) const noexcept
Definition: phmap_utils.h:232
size_t operator()(float val) const noexcept
Definition: phmap_utils.h:223
size_t operator()(int16_t val) const noexcept
Definition: phmap_utils.h:193
size_t operator()(int32_t val) const noexcept
Definition: phmap_utils.h:203
size_t operator()(int64_t val) const noexcept
Definition: phmap_utils.h:213
size_t operator()(signed char val) const noexcept
Definition: phmap_utils.h:176
size_t operator()(std::pair< T1, T2 > const &p) const noexcept
Definition: phmap_utils.h:342
size_t operator()(std::tuple< T... > const &t) const noexcept
Definition: phmap_utils.h:349
std::enable_if< I==std::tuple_size< TUP >::value, size_t >::type _hash_helper(size_t seed, const TUP &) const noexcept
Definition: phmap_utils.h:356
size_t operator()(uint16_t val) const noexcept
Definition: phmap_utils.h:198
size_t operator()(uint32_t val) const noexcept
Definition: phmap_utils.h:208
size_t operator()(uint64_t val) const noexcept
Definition: phmap_utils.h:218
size_t operator()(unsigned char val) const noexcept
Definition: phmap_utils.h:181
size_t operator()(wchar_t val) const noexcept
Definition: phmap_utils.h:187
Definition: phmap_utils.h:139
size_t operator()(const T &val) const
Definition: phmap_utils.h:150
size_t _hash(const T &val) const
Definition: phmap_utils.h:141
size_t operator()(uint64_t a) const
Definition: phmap_utils.h:104
size_t operator()(uint64_t a) const
Definition: phmap_utils.h:109
Definition: phmap_utils.h:98
size_t operator()(uint64_t) const
Definition: phmap_utils.h:116
static no test(...)
static auto test(int) -> decltype(hash_value(std::declval< const U & >())==1, yes())
std::true_type yes
Definition: phmap_utils.h:118
std::false_type no
Definition: phmap_utils.h:119
static constexpr bool value
Definition: phmap_utils.h:128
size_t operator()(size_t a) const
Definition: phmap_utils.h:60
size_t operator()(size_t a) const
Definition: phmap_utils.h:83
Definition: phmap_utils.h:54
size_t operator()(size_t) const
Definition: phmap_utils.h:159
ArgumentType argument_type
Definition: phmap_utils.h:160
ResultType result_type
Definition: phmap_utils.h:161