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), ...);
89#if GAIA_ECS_HASH == GAIA_ECS_HASH_FNV1A
94 constexpr uint64_t val_64_const = 0xcbf29ce484222325;
95 constexpr uint64_t prime_64_const = 0x100000001b3;
103 constexpr uint64_t calculate_hash64(
const char*
const str)
noexcept {
104 uint64_t hash = detail::fnv1a::val_64_const;
107 while (str[i] !=
'\0') {
108 hash = (hash ^ uint64_t(str[i])) * detail::fnv1a::prime_64_const;
119 constexpr uint64_t calculate_hash64(
const char*
const str,
const uint64_t length)
noexcept {
120 uint64_t hash = detail::fnv1a::val_64_const;
122 for (uint64_t i = 0; i < length; ++i)
123 hash = (hash ^ uint64_t(str[i])) * detail::fnv1a::prime_64_const;
128#elif GAIA_ECS_HASH == GAIA_ECS_HASH_MURMUR2A
132 GAIA_MSVC_WARNING_PUSH()
133 GAIA_MSVC_WARNING_DISABLE(4592)
138 constexpr uint64_t seed_64_const = 0xe17a1465ULL;
139 constexpr uint64_t m = 0xc6a4a7935bd1e995ULL;
140 constexpr uint64_t r = 47;
142 constexpr uint64_t Load8(
const char* data) {
143 return (uint64_t(data[7]) << 56) | (uint64_t(data[6]) << 48) | (uint64_t(data[5]) << 40) |
144 (uint64_t(data[4]) << 32) | (uint64_t(data[3]) << 24) | (uint64_t(data[2]) << 16) |
145 (uint64_t(data[1]) << 8) | (uint64_t(data[0]) << 0);
148 constexpr uint64_t StaticHashValueLast64(uint64_t h) {
149 return (((h * m) ^ ((h * m) >> r)) * m) ^ ((((h * m) ^ ((h * m) >> r)) * m) >> r);
152 constexpr uint64_t StaticHashValueLast64_(uint64_t h) {
153 return (((h) ^ ((h) >> r)) * m) ^ ((((h) ^ ((h) >> r)) * m) >> r);
156 constexpr uint64_t StaticHashValue64Tail1(uint64_t h,
const char* data) {
157 return StaticHashValueLast64((h ^ uint64_t(data[0])));
160 constexpr uint64_t StaticHashValue64Tail2(uint64_t h,
const char* data) {
161 return StaticHashValue64Tail1((h ^ uint64_t(data[1]) << 8), data);
164 constexpr uint64_t StaticHashValue64Tail3(uint64_t h,
const char* data) {
165 return StaticHashValue64Tail2((h ^ uint64_t(data[2]) << 16), data);
168 constexpr uint64_t StaticHashValue64Tail4(uint64_t h,
const char* data) {
169 return StaticHashValue64Tail3((h ^ uint64_t(data[3]) << 24), data);
172 constexpr uint64_t StaticHashValue64Tail5(uint64_t h,
const char* data) {
173 return StaticHashValue64Tail4((h ^ uint64_t(data[4]) << 32), data);
176 constexpr uint64_t StaticHashValue64Tail6(uint64_t h,
const char* data) {
177 return StaticHashValue64Tail5((h ^ uint64_t(data[5]) << 40), data);
180 constexpr uint64_t StaticHashValue64Tail7(uint64_t h,
const char* data) {
181 return StaticHashValue64Tail6((h ^ uint64_t(data[6]) << 48), data);
184 constexpr uint64_t StaticHashValueRest64(uint64_t h, uint64_t len,
const char* data) {
185 return ((len & 7) == 7) ? StaticHashValue64Tail7(h, data)
186 : ((len & 7) == 6) ? StaticHashValue64Tail6(h, data)
187 : ((len & 7) == 5) ? StaticHashValue64Tail5(h, data)
188 : ((len & 7) == 4) ? StaticHashValue64Tail4(h, data)
189 : ((len & 7) == 3) ? StaticHashValue64Tail3(h, data)
190 : ((len & 7) == 2) ? StaticHashValue64Tail2(h, data)
191 : ((len & 7) == 1) ? StaticHashValue64Tail1(h, data)
192 : StaticHashValueLast64_(h);
195 constexpr uint64_t StaticHashValueLoop64(uint64_t i, uint64_t h, uint64_t len,
const char* data) {
197 i == 0 ? StaticHashValueRest64(h, len, data)
198 : StaticHashValueLoop64(
199 i - 1, (h ^ (((Load8(data) * m) ^ ((Load8(data) * m) >> r)) * m)) * m, len, data + 8));
202 constexpr uint64_t hash_murmur2a_64_ct(
const char* key, uint64_t len, uint64_t seed) {
203 return StaticHashValueLoop64(len / 8, seed ^ (len * m), (len), key);
212 constexpr uint64_t calculate_hash64(uint64_t value) {
213 value ^= value >> 33U;
214 value *= 0xff51afd7ed558ccdULL;
215 value ^= value >> 33U;
217 value *= 0xc4ceb9fe1a85ec53ULL;
218 value ^= value >> 33U;
225 constexpr uint64_t calculate_hash64(
const char* str) {
227 while (str[length] !=
'\0')
230 return detail::murmur2a::hash_murmur2a_64_ct(str, length, detail::murmur2a::seed_64_const);
237 constexpr uint64_t calculate_hash64(
const char* str, uint64_t length) {
238 return detail::murmur2a::hash_murmur2a_64_ct(str, length, detail::murmur2a::seed_64_const);
241 GAIA_MSVC_WARNING_POP()
244 #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