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