2#include "gaia/config/config.h"
12 template <
typename,
typename =
void>
13 struct is_direct_hash_key: std::false_type {};
15 struct is_direct_hash_key<T, std::void_t<decltype(T::IsDirectHashKey)>>: std::true_type {};
19 constexpr void hash_combine2_out(uint32_t& lhs, uint32_t rhs) {
20 lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2);
22 constexpr void hash_combine2_out(uint64_t& lhs, uint64_t rhs) {
23 lhs ^= rhs + 0x9e3779B97f4a7c15ULL + (lhs << 6) + (lhs >> 2);
27 GAIA_NODISCARD
constexpr T hash_combine2(T lhs, T rhs) {
28 hash_combine2_out(lhs, rhs);
37 inline constexpr bool is_direct_hash_key_v = detail::is_direct_hash_key<T>::value;
46 static_assert(std::is_integral_v<T>);
70 template <
typename... T>
71 constexpr auto combine_or([[maybe_unused]] T... t) {
82 template <
typename T,
typename... Rest>
83 constexpr T hash_combine(T first, T next, Rest... rest) {
84 auto h = detail::hash_combine2(first, next);
85 (detail::hash_combine2_out(h, rest), ...);
92 constexpr uint64_t calculate_hash64(uint64_t value) {
93 value ^= value >> 33U;
94 value *= 0xff51afd7ed558ccdULL;
95 value ^= value >> 33U;
97 value *= 0xc4ceb9fe1a85ec53ULL;
98 value ^= value >> 33U;
102#if GAIA_ECS_HASH == GAIA_ECS_HASH_FNV1A
107 constexpr uint64_t val_64_const = 0xcbf29ce484222325;
108 constexpr uint64_t prime_64_const = 0x100000001b3;
116 constexpr uint64_t calculate_hash64(
const char*
const str)
noexcept {
117 uint64_t hash = detail::fnv1a::val_64_const;
120 while (str[i] !=
'\0') {
121 hash = (hash ^ uint64_t(uint8_t(str[i]))) * detail::fnv1a::prime_64_const;
133 constexpr uint64_t calculate_hash64(
const char*
const str,
const uint64_t length)
noexcept {
134 uint64_t hash = detail::fnv1a::val_64_const;
136 for (uint64_t i = 0; i < length; ++i)
137 hash = (hash ^ uint64_t(uint8_t(str[i]))) * detail::fnv1a::prime_64_const;
142#elif GAIA_ECS_HASH == GAIA_ECS_HASH_MURMUR2A
146 GAIA_MSVC_WARNING_PUSH()
147 GAIA_MSVC_WARNING_DISABLE(4592)
152 constexpr uint64_t seed_64_const = 0xe17a1465ULL;
153 constexpr uint64_t m = 0xc6a4a7935bd1e995ULL;
154 constexpr uint64_t r = 47;
156 constexpr uint64_t Load8(
const char* data) {
157 return (uint64_t(uint8_t(data[7])) << 56) | (uint64_t(uint8_t(data[6])) << 48) |
158 (uint64_t(uint8_t(data[5])) << 40) | (uint64_t(uint8_t(data[4])) << 32) |
159 (uint64_t(uint8_t(data[3])) << 24) | (uint64_t(uint8_t(data[2])) << 16) |
160 (uint64_t(uint8_t(data[1])) << 8) | (uint64_t(uint8_t(data[0])) << 0);
163 constexpr uint64_t StaticHashValueLast64(uint64_t h) {
164 return (((h * m) ^ ((h * m) >> r)) * m) ^ ((((h * m) ^ ((h * m) >> r)) * m) >> r);
167 constexpr uint64_t StaticHashValueLast64_(uint64_t h) {
168 return (((h) ^ ((h) >> r)) * m) ^ ((((h) ^ ((h) >> r)) * m) >> r);
171 constexpr uint64_t StaticHashValue64Tail1(uint64_t h,
const char* data) {
172 return StaticHashValueLast64((h ^ uint64_t(uint8_t(data[0]))));
175 constexpr uint64_t StaticHashValue64Tail2(uint64_t h,
const char* data) {
176 return StaticHashValue64Tail1((h ^ uint64_t(uint8_t(data[1])) << 8), data);
179 constexpr uint64_t StaticHashValue64Tail3(uint64_t h,
const char* data) {
180 return StaticHashValue64Tail2((h ^ uint64_t(uint8_t(data[2])) << 16), data);
183 constexpr uint64_t StaticHashValue64Tail4(uint64_t h,
const char* data) {
184 return StaticHashValue64Tail3((h ^ uint64_t(uint8_t(data[3])) << 24), data);
187 constexpr uint64_t StaticHashValue64Tail5(uint64_t h,
const char* data) {
188 return StaticHashValue64Tail4((h ^ uint64_t(uint8_t(data[4])) << 32), data);
191 constexpr uint64_t StaticHashValue64Tail6(uint64_t h,
const char* data) {
192 return StaticHashValue64Tail5((h ^ uint64_t(uint8_t(data[5])) << 40), data);
195 constexpr uint64_t StaticHashValue64Tail7(uint64_t h,
const char* data) {
196 return StaticHashValue64Tail6((h ^ uint64_t(uint8_t(data[6])) << 48), data);
199 constexpr uint64_t StaticHashValueRest64(uint64_t h, uint64_t len,
const char* data) {
200 return ((len & 7) == 7) ? StaticHashValue64Tail7(h, data)
201 : ((len & 7) == 6) ? StaticHashValue64Tail6(h, data)
202 : ((len & 7) == 5) ? StaticHashValue64Tail5(h, data)
203 : ((len & 7) == 4) ? StaticHashValue64Tail4(h, data)
204 : ((len & 7) == 3) ? StaticHashValue64Tail3(h, data)
205 : ((len & 7) == 2) ? StaticHashValue64Tail2(h, data)
206 : ((len & 7) == 1) ? StaticHashValue64Tail1(h, data)
207 : StaticHashValueLast64_(h);
210 constexpr uint64_t StaticHashValueLoop64(uint64_t i, uint64_t h, uint64_t len,
const char* data) {
212 i == 0 ? StaticHashValueRest64(h, len, data)
213 : StaticHashValueLoop64(
214 i - 1, (h ^ (((Load8(data) * m) ^ ((Load8(data) * m) >> r)) * m)) * m, len, data + 8));
217 constexpr uint64_t hash_murmur2a_64_ct(
const char* key, uint64_t len, uint64_t seed) {
218 return StaticHashValueLoop64(len / 8, seed ^ (len * m), (len), key);
227 constexpr uint64_t calculate_hash64(
const char* str) {
229 while (str[length] !=
'\0')
232 return detail::murmur2a::hash_murmur2a_64_ct(str, length, detail::murmur2a::seed_64_const);
240 constexpr uint64_t calculate_hash64(
const char* str, uint64_t length) {
241 return detail::murmur2a::hash_murmur2a_64_ct(str, length, detail::murmur2a::seed_64_const);
244 GAIA_MSVC_WARNING_POP()
247 #error "Unknown hashing type defined"
Wraps an integral value that is already a hash key.
Definition hashing_policy.h:42
T Type
Underlying hash storage type.
Definition hashing_policy.h:44
T hash
Precomputed hash value.
Definition hashing_policy.h:51
static constexpr bool IsDirectHashKey
Marker used by Gaia-ECS hash containers to bypass rehashing.
Definition hashing_policy.h:48
bool operator==(direct_hash_key other) const
Compares two direct hash keys.
Definition hashing_policy.h:55
bool operator!=(direct_hash_key other) const
Compares two direct hash keys for inequality.
Definition hashing_policy.h:61