dice-hash
Hash function for stl types and container
Loading...
Searching...
No Matches
DiceHashPolicies.hpp
1#ifndef DICE_HASH_DICEHASHPOLICIES_HPP
2#define DICE_HASH_DICEHASHPOLICIES_HPP
3
4#include "martinus_robinhood_hash.hpp"
5#include "wyhash.h"
6#ifdef __x86_64__
7#include "xxhash.hpp"
8#endif
9#include <type_traits>
10
11namespace dice::hash::Policies {
12 template<typename T>
13 concept HashPolicy =
14 std::is_convertible_v<decltype(T::ErrorValue), std::size_t>
15 &&std::is_nothrow_invocable_r_v<std::size_t, decltype(T::template hash_fundamental<int>), int>
16 &&std::is_nothrow_invocable_r_v<std::size_t, decltype(T::template hash_fundamental<long>), long>
17 &&std::is_nothrow_invocable_r_v<std::size_t, decltype(T::template hash_fundamental<std::size_t>), std::size_t>
18 &&std::is_nothrow_invocable_r_v<std::size_t, decltype(T::hash_bytes), void const *, std::size_t>
19 &&std::is_nothrow_invocable_r_v<std::size_t, decltype(T::hash_combine), std::initializer_list<std::size_t>>
20 &&std::is_nothrow_invocable_r_v<std::size_t, decltype(T::hash_invertible_combine), std::initializer_list<std::size_t>>
21 &&std::is_nothrow_constructible_v<typename T::HashState, std::size_t>
22 &&std::is_nothrow_invocable_r_v<void, decltype(&T::HashState::add), typename T::HashState &, std::size_t>
23 &&std::is_nothrow_invocable_r_v<std::size_t, decltype(&T::HashState::digest), typename T::HashState &>;
24
25 struct wyhash {
26 inline static constexpr uint64_t kSeed = 0xe17a1465UL;
27 inline static constexpr uint64_t kWyhashSalt[4] = {
28 dice::hash::wyhash::_wyp[0],
29 dice::hash::wyhash::_wyp[1],
30 dice::hash::wyhash::_wyp[2],
31 dice::hash::wyhash::_wyp[3]
32 };
33 inline static constexpr std::size_t ErrorValue = kSeed;
34
35 template<typename T>
36 static std::size_t hash_fundamental(T x) noexcept {
37 if constexpr (std::is_integral_v<T>) {
38 return static_cast<std::size_t>(dice::hash::wyhash::wyhash64(kSeed, x));
39 }
40 return static_cast<std::size_t>(dice::hash::wyhash::wyhash(&x, sizeof(T), kSeed, kWyhashSalt));
41 }
42
43 static std::size_t hash_bytes(void const *ptr, std::size_t len) noexcept {
44 return static_cast<std::size_t>(dice::hash::wyhash::wyhash(ptr, len, kSeed, kWyhashSalt));
45 }
46
47 static std::size_t hash_combine(std::initializer_list<size_t> hashes) noexcept {
48 uint64_t state = kSeed;
49 for (auto hash : hashes) {
50 state = dice::hash::wyhash::_wymix(state, hash);
51 }
52 return static_cast<std::size_t>(state);
53 }
54
55 static std::size_t hash_invertible_combine(std::initializer_list<size_t> hashes) noexcept {
56 std::size_t result = 0;
57 for (auto hash : hashes) {
58 result = result xor hash;
59 }
60 return result;
61 }
62
63 class HashState {
64 private:
65 uint64_t state = kSeed;
66 public:
67 explicit HashState(std::size_t) noexcept {}
68 void add (std::size_t hash) noexcept {
69 state = dice::hash::wyhash::_wymix(state, static_cast<uint64_t>(hash));
70 }
71 [[nodiscard]] std::size_t digest() noexcept {
72 return static_cast<std::size_t>(state);
73 }
74 };
75 };
76
77#ifdef __x86_64__
78 struct xxh3 {
79 inline static constexpr std::size_t size_t_bits = 8 * sizeof(std::size_t);
80 inline static constexpr std::size_t seed = std::size_t(0xA24BAED4963EE407UL);
81 inline static constexpr std::size_t ErrorValue = seed;
82
83 template<typename T>
84 static std::size_t hash_fundamental(T x) noexcept {
85 return hash_bytes(&x, sizeof(x));
86 }
87 static std::size_t hash_bytes(void const *ptr, std::size_t len) noexcept {
88 return xxh::xxhash3<size_t_bits>(ptr, len, seed);
89 }
90 static std::size_t hash_combine(std::initializer_list<std::size_t> hashes) noexcept {
91 return xxh::xxhash3<size_t_bits>(hashes, seed);
92 }
93 static std::size_t hash_invertible_combine(std::initializer_list<size_t> hashes) noexcept {
94 std::size_t result = 0;
95 for (auto hash : hashes) {
96 result = result xor hash;
97 }
98 return result;
99 }
100 class HashState {
101 private:
102 xxh::hash3_state64_t hash_state{seed};
103
104 public:
105 explicit HashState(std::size_t) noexcept {}
106
107 void add(std::size_t hash) noexcept {
108 hash_state.update(&hash, sizeof(std::size_t));
109 }
110 [[nodiscard]] std::size_t digest() noexcept {
111 return hash_state.digest();
112 }
113 };
114 };
115#endif
116
117 struct Martinus {
118 static constexpr std::size_t ErrorValue = dice::hash::martinus::seed;
119 template<typename T>
120 static std::size_t hash_fundamental(T x) noexcept {
121 if constexpr (sizeof(std::decay_t<T>) == sizeof(size_t)) {
122 return dice::hash::martinus::hash_int(*reinterpret_cast<size_t const *>(&x));
123 } else if constexpr (sizeof(std::decay_t<T>) > sizeof(size_t) or std::is_floating_point_v<std::decay_t<T>>) {
124 return hash_bytes(&x, sizeof(x));
125 } else {
126 return dice::hash::martinus::hash_int(static_cast<size_t>(x));
127 }
128 }
129 static std::size_t hash_bytes(void const *ptr, std::size_t len) noexcept {
130 return dice::hash::martinus::hash_bytes(ptr, len);
131 }
132 static std::size_t hash_combine(std::initializer_list<size_t> hashes) noexcept {
133 return dice::hash::martinus::hash_combine(hashes);
134 }
135 static std::size_t hash_invertible_combine(std::initializer_list<size_t> hashes) noexcept {
136 std::size_t result = 0;
137 for (auto hash : hashes) {
138 result = result xor hash;
139 }
140 return result;
141 }
142 class HashState {
143 private:
145
146 public:
147 explicit HashState(std::size_t size) noexcept : state(size) {}
148 void add(std::size_t hash) noexcept {
149 state.add(hash);
150 }
151 [[nodiscard]] std::size_t digest() noexcept {
152 return state.digest();
153 }
154 };
155 };
156}// namespace dice::hash::Policies
157#endif//DICE_HASH_DICEHASHPOLICIES_HPP
Definition DiceHashPolicies.hpp:142
Definition DiceHashPolicies.hpp:63
Definition martinus_robinhood_hash.hpp:136
Definition xxhash.hpp:1744
Definition DiceHashPolicies.hpp:13
Definition DiceHashPolicies.hpp:117
Definition DiceHashPolicies.hpp:25