1 #ifndef EAGINE_INTEGER_HASH_HPP
9 #define EAGINE_INTEGER_HASH_HPP
17 template <std::
size_t N,
typename I>
19 integer_rotate_right(I x, type_identity<I> = {}, size_constant<N> = {}) noexcept
21 static_assert(N <
sizeof(I) * 8);
22 return I(x << N) | I(x >> (-N & (
sizeof(I) * 8U - 1U)));
27 integer_hash_init(H x, type_identity<H> = {}, type_identity<H> = {}) noexcept
32 template <
typename H,
typename I>
33 constexpr
auto integer_hash_init(
35 type_identity<H> hid = {},
36 type_identity<I> = {}) noexcept -> H {
39 if constexpr(is_same_v<I, std::uint16_t>) {
40 if constexpr(is_same_v<H, std::uint32_t>) {
41 return H(x) ^ (H(x) << 16U);
43 if constexpr(is_same_v<H, std::uint64_t>) {
44 return H(x) ^ (H(x) << 16U) ^ (H(x) << 32U) ^ (H(x) << 48U);
47 if constexpr(is_same_v<I, std::uint32_t>) {
48 if constexpr(is_same_v<H, std::uint16_t>) {
49 return H(x ^ (x >> 16U));
51 if constexpr(is_same_v<H, std::uint64_t>) {
52 return H(x) ^ (H(x) << 32U);
55 if constexpr(is_same_v<I, std::uint64_t>) {
56 if constexpr(is_same_v<H, std::uint16_t>) {
57 return H(x ^ (x >> 16U) ^ (x >> 32U) ^ (x >> 48U));
59 if constexpr(is_same_v<H, std::uint32_t>) {
60 return H(x ^ (x >> 32U));
64 using UI = std::make_unsigned_t<I>;
65 return integer_hash_init(UI(x), hid, type_identity<UI>());
70 template <
typename H,
typename I>
74 if constexpr(std::is_unsigned_v<H>) {
75 auto h = integer_hash_init(x, hid, iid);
76 if constexpr(is_same_v<H, std::uint16_t>) {
77 h ^= integer_rotate_right<9U>(h, hid);
79 h ^= integer_rotate_right<9U>(h, hid);
81 h ^= integer_rotate_right<9U>(h, hid);
83 h ^= integer_rotate_right<9U>(h, hid);
85 h ^= integer_rotate_right<9U>(h, hid);
87 h ^= integer_rotate_right<9U>(h, hid);
89 h ^= integer_rotate_right<9U>(h, hid);
91 h ^= integer_rotate_right<9U>(h, hid);
93 h ^= integer_rotate_right<9U>(h, hid);
95 if constexpr(is_same_v<H, std::uint32_t>) {
96 h ^= integer_rotate_right<17U>(h, hid);
98 h ^= integer_rotate_right<17U>(h, hid);
100 h ^= integer_rotate_right<17U>(h, hid);
102 h ^= integer_rotate_right<17U>(h, hid);
104 h ^= integer_rotate_right<17U>(h, hid);
106 if constexpr(is_same_v<H, std::uint64_t>) {
107 h ^= integer_rotate_right<33U>(h, hid);
108 h *= 0xff51afd7ed558ccd;
109 h ^= integer_rotate_right<33U>(h, hid);
110 h *= 0xed558ccdff51afd7;
111 h ^= integer_rotate_right<33U>(h, hid);
112 h *= 0xc4ceb9fe1a85ec53;
113 h ^= integer_rotate_right<33U>(h, hid);
114 h *= 0x1a85ec53c4ceb9fe;
115 h ^= integer_rotate_right<33U>(h, hid);
120 using UH = std::make_unsigned_t<H>;
121 return H(integer_hash<UH>(x));
126 #endif // EAGINE_INTEGER_HASH_HPP