NexusForce 1.0.0
A rigorously engineered full-stack C++ backend library.
载入中...
搜索中...
未找到
hash.hpp
浏览该文件的文档.
1#ifndef NEFORCE_CORE_FUNCTIONAL_HASH_HPP__
2#define NEFORCE_CORE_FUNCTIONAL_HASH_HPP__
3
13
16NEFORCE_BEGIN_NAMESPACE__
17
84
94template <typename Key, typename Dummy = void>
95struct hash;
96
101template <typename T>
102struct hash<T*> {
103 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_t operator()(const T* ptr) const noexcept {
104 return static_cast<size_t>(reinterpret_cast<uintptr_t>(ptr));
105 }
106};
107 // HashPrimary
109
110NEFORCE_BEGIN_CONSTANTS__
111
116
122NEFORCE_INLINE17 constexpr size_t FNV_OFFSET_BASIS =
123#ifdef NEFORCE_ARCH_BITS_64
124 14695981039346656037ULL;
125#else
126 2166136261U;
127#endif
128
134NEFORCE_INLINE17 constexpr size_t FNV_PRIME
135#ifdef NEFORCE_ARCH_BITS_64
136 = 1099511628211ULL;
137#else
138 = 16777619U;
139#endif
140 // HashPrimary
142
143NEFORCE_END_CONSTANTS__
144
149
163NEFORCE_CONSTEXPR14 size_t FNV_hash(const byte_t* first, const size_t count) noexcept {
164 size_t result = constants::FNV_OFFSET_BASIS;
165 for (size_t i = 0; i < count; i++) {
166 result ^= static_cast<size_t>(first[i]);
167 result *= constants::FNV_PRIME;
168 }
169 return result;
170}
171
178template <typename T>
179NEFORCE_CONSTEXPR14 size_t FNV_hash_integer(const T value) noexcept {
180 static_assert(is_integral<T>::value, "T must be integral");
181
182 size_t result = constants::FNV_OFFSET_BASIS;
183 for (size_t i = 0; i < sizeof(T); ++i) {
184 const auto byte_val = static_cast<byte_t>((value >> (i * 8)) & 0xFF);
185 result ^= static_cast<size_t>(byte_val);
186 result *= constants::FNV_PRIME;
187 }
188 return result;
189}
190
198template <typename CharT>
199NEFORCE_CONSTEXPR14 size_t FNV_hash_string(const CharT* str, const size_t len) noexcept {
200 static_assert(is_character<CharT>::value, "CharT must be character types");
201
202 size_t result = constants::FNV_OFFSET_BASIS;
203 for (size_t i = 0; i < len; ++i) {
204 result ^= static_cast<size_t>(static_cast<byte_t>(str[i]));
205 result *= constants::FNV_PRIME;
206 }
207 return result;
208}
209
219NEFORCE_CONSTEXPR14 size_t low_level_hash(size_t x) noexcept {
220#ifdef NEFORCE_ARCH_BITS_64
221 x += 0x9e3779b97f4a7c15ULL;
222 x ^= x >> 33;
223 x *= 0xff51afd7ed558ccdULL;
224 x ^= x >> 33;
225 x *= 0xc4ceb9fe1a85ec53ULL;
226 x ^= x >> 33;
227 return x;
228#else
229 x += 0x9e3779b9U;
230 x ^= x >> 16;
231 x *= 0x85ebca6bU;
232 x ^= x >> 13;
233 x *= 0xc2b2ae35U;
234 x ^= x >> 16;
235 return x;
236#endif
237}
238 // HashPrimary
240
242
243template <>
244struct hash<bool> {
245 NEFORCE_NODISCARD constexpr size_t operator()(const bool x) const noexcept { return x ? 0x9e3779b9 : 0x7f4a7c15; }
246};
247
248#define __NEFORCE_BUILD_INTEGER_HASH_STRUCT(OPT) \
249 template <> \
250 struct hash<OPT> { \
251 NEFORCE_NODISCARD constexpr size_t operator()(const OPT x) const noexcept { \
252 return low_level_hash(static_cast<size_t>(x)); \
253 } \
254 };
255
256NEFORCE_MACRO_RANGE_CHARS(__NEFORCE_BUILD_INTEGER_HASH_STRUCT)
257NEFORCE_MACRO_RANGE_INT(__NEFORCE_BUILD_INTEGER_HASH_STRUCT)
258#undef __NEFORCE_BUILD_INTEGER_HASH_STRUCT
259
260#define __NEFORCE_BUILD_FLOAT_HASH_STRUCT(OPT) \
261 template <> \
262 struct hash<OPT> { \
263 private: \
264 union __float_converter { \
265 OPT f; \
266 uint64_t i; \
267 }; \
268 \
269 public: \
270 NEFORCE_NODISCARD NEFORCE_CONSTEXPR14 size_t operator()(const OPT x) const noexcept { \
271 if (x == 0.0f) \
272 return 0; \
273 __float_converter converter{}; \
274 converter.f = x; \
275 return low_level_hash(static_cast<size_t>(converter.i)); \
276 } \
277 };
278
279NEFORCE_MACRO_RANGE_FLOAT(__NEFORCE_BUILD_FLOAT_HASH_STRUCT)
280#undef __NEFORCE_BUILD_FLOAT_HASH_STRUCT
281
283
294template <typename T>
295NEFORCE_CONSTEXPR14 void hash_combine(size_t& seed, const T& value) noexcept {
296 seed ^= hash<T>()(value) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
297}
298
307template <typename... Types>
308NEFORCE_CONSTEXPR14 size_t hash_combine_all(const Types&... values) noexcept {
309 size_t seed = 0;
310 int dummy[] = {(_NEFORCE hash_combine(seed, values), 0)...};
311 ignore = dummy;
312 return seed;
313}
314
319
324template <typename T>
325struct hash<T, enable_if_t<is_enum_v<T>>> {
326 NEFORCE_NODISCARD NEFORCE_CONSTEXPR14 size_t operator()(const T e) const {
327 using UT = underlying_type_t<T>;
328 return hash<UT>()(static_cast<UT>(e));
329 }
330};
331
345NEFORCE_CONSTEXPR14 size_t DJB2_hash(const char* str, const size_t len) noexcept {
346 size_t hash = 5381;
347 for (size_t i = 0; i < len; ++i) {
348 hash = (hash << 5) + hash + static_cast<byte_t>(str[i]);
349 }
350 return hash;
351}
352
353
354#ifdef NEFORCE_ARCH_BITS_64
355
362struct murmur_hash {
363 size_t low = 0;
364 size_t high = 0;
365
366 murmur_hash() noexcept = default;
367 ~murmur_hash() noexcept = default;
368
374 murmur_hash(const size_t l, const size_t h) noexcept :
375 low(l),
376 high(h) {}
377};
378
395murmur_hash NEFORCE_API murmur_hash64(const void* key, size_t len, uint32_t seed) noexcept;
396#endif
397
408uint32_t NEFORCE_API murmur_hash32(const void* key, size_t len, uint32_t seed) noexcept;
409
410
411#ifdef NEFORCE_COMPILER_MSVC
412// use switch penetrate
413# pragma warning(push)
414# pragma warning(disable : 26819)
415#endif
416
417
428NEFORCE_CONSTEXPR14 uint32_t XXH32(const void* input, size_t len, uint32_t seed = 0) noexcept {
429 constexpr uint32_t PRIME32_1 = 0x9E3779B1U;
430 constexpr uint32_t PRIME32_2 = 0x85EBCA77U;
431 constexpr uint32_t PRIME32_3 = 0xC2B2AE3DU;
432 constexpr uint32_t PRIME32_4 = 0x27D4EB2FU;
433 constexpr uint32_t PRIME32_5 = 0x165667B1U;
434
435 const auto* p = static_cast<const byte_t*>(input);
436 uint32_t hash = 0;
437
438 if (len >= 16) {
439 uint32_t acc1 = seed + PRIME32_1 + PRIME32_2;
440 uint32_t acc2 = seed + PRIME32_2;
441 uint32_t acc3 = seed + 0;
442 uint32_t acc4 = seed - PRIME32_1;
443
444 const byte_t* limit = p + (len & ~static_cast<size_t>(15));
445 for (; p < limit; p += 16) {
446 acc1 = rotate_l32(acc1 + endian::read_le32(p + 0) * PRIME32_2, 13) * PRIME32_1;
447 acc2 = rotate_l32(acc2 + endian::read_le32(p + 4) * PRIME32_2, 13) * PRIME32_1;
448 acc3 = rotate_l32(acc3 + endian::read_le32(p + 8) * PRIME32_2, 13) * PRIME32_1;
449 acc4 = rotate_l32(acc4 + endian::read_le32(p + 12) * PRIME32_2, 13) * PRIME32_1;
450 }
451
452 hash = rotate_l32(acc1, 1) + rotate_l32(acc2, 7) + rotate_l32(acc3, 12) + rotate_l32(acc4, 18);
453 } else {
454 hash = seed + PRIME32_5;
455 }
456
457 hash += static_cast<uint32_t>(len);
458
459 const byte_t* end = static_cast<const byte_t*>(input) + len;
460 for (; p + 4 <= end; p += 4) {
461 hash += endian::read_le32(p) * PRIME32_3;
462 hash = rotate_l32(hash, 17) * PRIME32_4;
463 }
464 switch (len & 3) {
465 case 3:
466 hash += static_cast<uint32_t>(p[2]) * PRIME32_5;
467 hash = rotate_l32(hash, 11) * PRIME32_1;
468 case 2:
469 hash += static_cast<uint32_t>(p[1]) * PRIME32_5;
470 hash = rotate_l32(hash, 11) * PRIME32_1;
471 case 1:
472 hash += static_cast<uint32_t>(p[0]) * PRIME32_5;
473 hash = rotate_l32(hash, 11) * PRIME32_1;
474 default:
475 break;
476 }
477
478 hash ^= hash >> 15;
479 hash *= PRIME32_2;
480 hash ^= hash >> 13;
481 hash *= PRIME32_3;
482 hash ^= hash >> 16;
483
484 return hash;
485}
486
487#ifdef NEFORCE_ARCH_BITS_64
488
499NEFORCE_CONSTEXPR14 uint64_t XXH64(const void* input, size_t len, uint64_t seed = 0) noexcept {
500 constexpr uint64_t PRIME64_1 = 0x9E3779B185EBCA87ULL;
501 constexpr uint64_t PRIME64_2 = 0xC2B2AE3D27D4EB4FULL;
502 constexpr uint64_t PRIME64_3 = 0x165667B19E3779F9ULL;
503 constexpr uint64_t PRIME64_4 = 0x85EBCA77C2B2AE63ULL;
504 constexpr uint64_t PRIME64_5 = 0x27D4EB2F165667C5ULL;
505
506 const auto* p = static_cast<const byte_t*>(input);
507 uint64_t hash = 0;
508
509 if (len >= 32) {
510 uint64_t acc1 = seed + PRIME64_1 + PRIME64_2;
511 uint64_t acc2 = seed + PRIME64_2;
512 uint64_t acc3 = seed + 0;
513 uint64_t acc4 = seed - PRIME64_1;
514
515 const byte_t* limit = p + (len & ~static_cast<size_t>(31));
516 for (; p < limit; p += 32) {
517 acc1 = rotate_l64(acc1 + endian::read_le64(p + 0) * PRIME64_2, 31) * PRIME64_1;
518 acc2 = rotate_l64(acc2 + endian::read_le64(p + 8) * PRIME64_2, 31) * PRIME64_1;
519 acc3 = rotate_l64(acc3 + endian::read_le64(p + 16) * PRIME64_2, 31) * PRIME64_1;
520 acc4 = rotate_l64(acc4 + endian::read_le64(p + 24) * PRIME64_2, 31) * PRIME64_1;
521 }
522
523 hash = rotate_l64(acc1, 1) + rotate_l64(acc2, 7) + rotate_l64(acc3, 12) + rotate_l64(acc4, 18);
524
525 hash ^= rotate_l64(acc1 * PRIME64_2, 31) * PRIME64_1;
526 hash = hash * PRIME64_1 + PRIME64_4;
527 hash ^= rotate_l64(acc2 * PRIME64_2, 31) * PRIME64_1;
528 hash = hash * PRIME64_1 + PRIME64_4;
529 hash ^= rotate_l64(acc3 * PRIME64_2, 31) * PRIME64_1;
530 hash = hash * PRIME64_1 + PRIME64_4;
531 hash ^= rotate_l64(acc4 * PRIME64_2, 31) * PRIME64_1;
532 hash = hash * PRIME64_1 + PRIME64_4;
533 } else {
534 hash = seed + PRIME64_5;
535 }
536
537 hash += static_cast<uint64_t>(len);
538
539 const byte_t* end = static_cast<const byte_t*>(input) + len;
540 for (; p + 8 <= end; p += 8) {
542 k1 *= PRIME64_2;
543 k1 = rotate_l64(k1, 31);
544 k1 *= PRIME64_1;
545 hash ^= k1;
546 hash = rotate_l64(hash, 27) * PRIME64_1 + PRIME64_4;
547 }
548 for (; p + 4 <= end; p += 4) {
549 hash ^= static_cast<uint64_t>(endian::read_le32(p)) * PRIME64_1;
550 hash = rotate_l64(hash, 23) * PRIME64_2 + PRIME64_3;
551 }
552 switch (len & 3) {
553 case 3:
554 hash ^= static_cast<uint64_t>(p[2]) * PRIME64_5;
555 hash = rotate_l64(hash, 11) * PRIME64_1;
556 case 2:
557 hash ^= static_cast<uint64_t>(p[1]) * PRIME64_5;
558 hash = rotate_l64(hash, 11) * PRIME64_1;
559 case 1:
560 hash ^= static_cast<uint64_t>(p[0]) * PRIME64_5;
561 hash = rotate_l64(hash, 11) * PRIME64_1;
562 default:
563 break;
564 }
565
566 hash ^= hash >> 33;
567 hash *= PRIME64_2;
568 hash ^= hash >> 29;
569 hash *= PRIME64_3;
570 hash ^= hash >> 32;
571
572 return hash;
573}
574
575
576# ifdef NEFORCE_COMPILER_MSVC
577# pragma warning(pop)
578# endif
579
580
591uint64_t NEFORCE_API wyhash(const void* key, size_t len, uint64_t seed) noexcept;
592
593#endif
594
595
605size_t NEFORCE_API city_hash64(const void* key, size_t len) noexcept;
606
607
617uint64_t NEFORCE_API XXH3_64(const void* data, size_t len) noexcept;
618
619
626template <typename Key, typename Dummy = void>
628
630template <typename Key>
631struct is_nothrow_hashable<Key, void_t<decltype(_NEFORCE hash<Key>{}(_NEFORCE declval<const Key&>()))>>
632: bool_constant<noexcept(_NEFORCE hash<Key>{}(_NEFORCE declval<const Key&>()))> {};
634
635#ifdef NEFORCE_STANDARD_14
640template <typename Key>
642#endif
643
644
654template <typename Func, typename Arg, typename Dummy = void>
655struct is_hash : false_type {};
656
658template <typename Func, typename Arg>
659struct is_hash<Func, Arg,
660 enable_if_t<is_convertible<decltype(_NEFORCE declval<Func>()(_NEFORCE declval<Arg>())), size_t>::value>>
661: true_type {};
663
664#ifdef NEFORCE_STANDARD_14
669template <typename Func, typename Arg>
671#endif
672 // HashPrimary
674
675NEFORCE_END_NAMESPACE__
676#endif // NEFORCE_CORE_FUNCTIONAL_HASH_HPP__
位操作函数
端序转换工具
constexpr bool is_enum_v
is_enum的便捷变量模板
typename underlying_type< T >::type underlying_type_t
underlying_type的便捷别名
constexpr uint32_t rotate_l32(const uint32_t x, const int s) noexcept
32位整数循环左移
constexpr uint64_t rotate_l64(const uint64_t x, const int s) noexcept
64位整数循环左移
unsigned char byte_t
字节类型,定义为无符号字符
unsigned int uint32_t
32位无符号整数类型
unsigned long uint64_t
64位无符号整数类型
constexpr iter_difference_t< Iterator > count(Iterator first, Iterator last, const T &value)
统计范围内等于指定值的元素数量
add_rvalue_reference_t< T > declval() noexcept
获取类型的右值引用,仅用于非求值上下文
constexpr size_t FNV_hash_string(const CharT *str, const size_t len) noexcept
字符串类型的FNV哈希
constexpr size_t FNV_OFFSET_BASIS
FNV哈希算法的偏移基础值
size_t city_hash64(const void *key, size_t len) noexcept
CityHash64 哈希算法
constexpr size_t FNV_hash(const byte_t *first, const size_t count) noexcept
FNV-1a哈希算法
uint32_t murmur_hash32(const void *key, size_t len, uint32_t seed) noexcept
MurmurHash3_x86_32算法
murmur_hash murmur_hash64(const void *key, size_t len, uint32_t seed) noexcept
MurmurHash3_x64_128算法
constexpr uint32_t XXH32(const void *input, size_t len, uint32_t seed=0) noexcept
XXH32 哈希算法
constexpr size_t FNV_hash_integer(const T value) noexcept
整数类型的FNV哈希
constexpr uint64_t XXH64(const void *input, size_t len, uint64_t seed=0) noexcept
XXH64 哈希算法
constexpr bool is_nothrow_hashable_v
is_nothrow_hashable的便捷变量模板
uint64_t wyhash(const void *key, size_t len, uint64_t seed) noexcept
wyhash 哈希算法
constexpr bool is_hash_v
is_hash的便捷变量模板
uint64_t XXH3_64(const void *data, size_t len) noexcept
XXH3_64bits 哈希算法
constexpr size_t DJB2_hash(const char *str, const size_t len) noexcept
DJB2哈希算法
constexpr size_t low_level_hash(size_t x) noexcept
快速位混合哈希函数
constexpr size_t FNV_PRIME
FNV哈希算法的质数乘数
uint64_t size_t
无符号大小类型
uint64_t uintptr_t
可容纳指针的无符号整数类型
constexpr decltype(auto) end(Container &cont) noexcept(noexcept(cont.end()))
获取容器的结束迭代器
constexpr decltype(auto) data(Container &cont) noexcept(noexcept(cont.data()))
获取容器的底层数据指针
#define NEFORCE_MACRO_RANGE_INT(MAC)
所有整数类型列表宏
#define NEFORCE_MACRO_RANGE_CHARS(MAC)
所有字符类型列表宏
#define NEFORCE_MACRO_RANGE_FLOAT(MAC)
浮点类型列表宏
void void_t
将任意类型映射为void
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名
bool_constant< false > false_type
表示false的类型
bool_constant< true > true_type
表示true的类型
constexpr void hash_combine(size_t &seed, const T &value) noexcept
混合两个哈希值
constexpr size_t hash_combine_all(const Types &... values) noexcept
混合多个哈希值
static constexpr uint32_t read_le32(const byte_t *data) noexcept
读取32位小端整数
static constexpr uint64_t read_le64(const byte_t *data) noexcept
读取64位小端整数
哈希函数的主模板
判断类型From是否可以隐式转换为类型To
判断类型是否为有效的哈希函数
判断类型是否可无异常哈希
MurmurHash_x64的128位哈希结果容器
size_t low
哈希值的低64位
size_t high
哈希值的高64位