Gaia-ECS v0.9.3
A simple and powerful entity component system
Loading...
Searching...
No Matches
hashing_policy.h
1#pragma once
2#include "gaia/config/config.h"
3
4#include <cstdint>
5#include <type_traits>
6
7namespace gaia {
8 namespace core {
9
10 namespace detail {
11 template <typename, typename = void>
12 struct is_direct_hash_key: std::false_type {};
13 template <typename T>
14 struct is_direct_hash_key<T, std::void_t<decltype(T::IsDirectHashKey)>>: std::true_type {};
15
16 //-----------------------------------------------------------------------------------
17
18 constexpr void hash_combine2_out(uint32_t& lhs, uint32_t rhs) {
19 lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2);
20 }
21 constexpr void hash_combine2_out(uint64_t& lhs, uint64_t rhs) {
22 lhs ^= rhs + 0x9e3779B97f4a7c15ULL + (lhs << 6) + (lhs >> 2);
23 }
24
25 template <typename T>
26 GAIA_NODISCARD constexpr T hash_combine2(T lhs, T rhs) {
27 hash_combine2_out(lhs, rhs);
28 return lhs;
29 }
30 } // namespace detail
31
32 template <typename T>
33 inline constexpr bool is_direct_hash_key_v = detail::is_direct_hash_key<T>::value;
34
35 template <typename T>
37 using Type = T;
38
39 static_assert(std::is_integral_v<T>);
40 static constexpr bool IsDirectHashKey = true;
41
42 T hash;
43 bool operator==(direct_hash_key other) const {
44 return hash == other.hash;
45 }
46 bool operator!=(direct_hash_key other) const {
47 return hash != other.hash;
48 }
49 };
50
52 template <typename... T>
53 constexpr auto combine_or([[maybe_unused]] T... t) {
54 return (... | t);
55 }
56
58 template <typename T, typename... Rest>
59 constexpr T hash_combine(T first, T next, Rest... rest) {
60 auto h = detail::hash_combine2(first, next);
61 (detail::hash_combine2_out(h, rest), ...);
62 return h;
63 }
64
65#if GAIA_ECS_HASH == GAIA_ECS_HASH_FNV1A
66
67 namespace detail {
68 namespace fnv1a {
69 constexpr uint64_t val_64_const = 0xcbf29ce484222325;
70 constexpr uint64_t prime_64_const = 0x100000001b3;
71 } // namespace fnv1a
72 } // namespace detail
73
74 constexpr uint64_t calculate_hash64(const char* const str) noexcept {
75 uint64_t hash = detail::fnv1a::val_64_const;
76
77 uint64_t i = 0;
78 while (str[i] != '\0') {
79 hash = (hash ^ uint64_t(str[i])) * detail::fnv1a::prime_64_const;
80 ++i;
81 }
82
83 return hash;
84 }
85
86 constexpr uint64_t calculate_hash64(const char* const str, const uint64_t length) noexcept {
87 uint64_t hash = detail::fnv1a::val_64_const;
88
89 for (uint64_t i = 0; i < length; ++i)
90 hash = (hash ^ uint64_t(str[i])) * detail::fnv1a::prime_64_const;
91
92 return hash;
93 }
94
95#elif GAIA_ECS_HASH == GAIA_ECS_HASH_MURMUR2A
96
97 // Thank you https://gist.github.com/oteguro/10538695
98
99 GAIA_MSVC_WARNING_PUSH()
100 GAIA_MSVC_WARNING_DISABLE(4592)
101
102 namespace detail {
103 namespace murmur2a {
104 constexpr uint64_t seed_64_const = 0xe17a1465ULL;
105 constexpr uint64_t m = 0xc6a4a7935bd1e995ULL;
106 constexpr uint64_t r = 47;
107
108 constexpr uint64_t Load8(const char* data) {
109 return (uint64_t(data[7]) << 56) | (uint64_t(data[6]) << 48) | (uint64_t(data[5]) << 40) |
110 (uint64_t(data[4]) << 32) | (uint64_t(data[3]) << 24) | (uint64_t(data[2]) << 16) |
111 (uint64_t(data[1]) << 8) | (uint64_t(data[0]) << 0);
112 }
113
114 constexpr uint64_t StaticHashValueLast64(uint64_t h) {
115 return (((h * m) ^ ((h * m) >> r)) * m) ^ ((((h * m) ^ ((h * m) >> r)) * m) >> r);
116 }
117
118 constexpr uint64_t StaticHashValueLast64_(uint64_t h) {
119 return (((h) ^ ((h) >> r)) * m) ^ ((((h) ^ ((h) >> r)) * m) >> r);
120 }
121
122 constexpr uint64_t StaticHashValue64Tail1(uint64_t h, const char* data) {
123 return StaticHashValueLast64((h ^ uint64_t(data[0])));
124 }
125
126 constexpr uint64_t StaticHashValue64Tail2(uint64_t h, const char* data) {
127 return StaticHashValue64Tail1((h ^ uint64_t(data[1]) << 8), data);
128 }
129
130 constexpr uint64_t StaticHashValue64Tail3(uint64_t h, const char* data) {
131 return StaticHashValue64Tail2((h ^ uint64_t(data[2]) << 16), data);
132 }
133
134 constexpr uint64_t StaticHashValue64Tail4(uint64_t h, const char* data) {
135 return StaticHashValue64Tail3((h ^ uint64_t(data[3]) << 24), data);
136 }
137
138 constexpr uint64_t StaticHashValue64Tail5(uint64_t h, const char* data) {
139 return StaticHashValue64Tail4((h ^ uint64_t(data[4]) << 32), data);
140 }
141
142 constexpr uint64_t StaticHashValue64Tail6(uint64_t h, const char* data) {
143 return StaticHashValue64Tail5((h ^ uint64_t(data[5]) << 40), data);
144 }
145
146 constexpr uint64_t StaticHashValue64Tail7(uint64_t h, const char* data) {
147 return StaticHashValue64Tail6((h ^ uint64_t(data[6]) << 48), data);
148 }
149
150 constexpr uint64_t StaticHashValueRest64(uint64_t h, uint64_t len, const char* data) {
151 return ((len & 7) == 7) ? StaticHashValue64Tail7(h, data)
152 : ((len & 7) == 6) ? StaticHashValue64Tail6(h, data)
153 : ((len & 7) == 5) ? StaticHashValue64Tail5(h, data)
154 : ((len & 7) == 4) ? StaticHashValue64Tail4(h, data)
155 : ((len & 7) == 3) ? StaticHashValue64Tail3(h, data)
156 : ((len & 7) == 2) ? StaticHashValue64Tail2(h, data)
157 : ((len & 7) == 1) ? StaticHashValue64Tail1(h, data)
158 : StaticHashValueLast64_(h);
159 }
160
161 constexpr uint64_t StaticHashValueLoop64(uint64_t i, uint64_t h, uint64_t len, const char* data) {
162 return (
163 i == 0 ? StaticHashValueRest64(h, len, data)
164 : StaticHashValueLoop64(
165 i - 1, (h ^ (((Load8(data) * m) ^ ((Load8(data) * m) >> r)) * m)) * m, len, data + 8));
166 }
167
168 constexpr uint64_t hash_murmur2a_64_ct(const char* key, uint64_t len, uint64_t seed) {
169 return StaticHashValueLoop64(len / 8, seed ^ (len * m), (len), key);
170 }
171 } // namespace murmur2a
172 } // namespace detail
173
174 constexpr uint64_t calculate_hash64(uint64_t value) {
175 value ^= value >> 33U;
176 value *= 0xff51afd7ed558ccdULL;
177 value ^= value >> 33U;
178
179 value *= 0xc4ceb9fe1a85ec53ULL;
180 value ^= value >> 33U;
181 return value;
182 }
183
184 constexpr uint64_t calculate_hash64(const char* str) {
185 uint64_t length = 0;
186 while (str[length] != '\0')
187 ++length;
188
189 return detail::murmur2a::hash_murmur2a_64_ct(str, length, detail::murmur2a::seed_64_const);
190 }
191
192 constexpr uint64_t calculate_hash64(const char* str, uint64_t length) {
193 return detail::murmur2a::hash_murmur2a_64_ct(str, length, detail::murmur2a::seed_64_const);
194 }
195
196 GAIA_MSVC_WARNING_POP()
197
198#else
199 #error "Unknown hashing type defined"
200#endif
201
202 } // namespace core
203} // namespace gaia
Checks if endianess was detected correctly at compile-time.
Definition bitset.h:9
Definition hashing_policy.h:12
Definition hashing_policy.h:36