OGLplus  (0.59.0) a C++ wrapper for rendering APIs

integer_hash.hpp
Go to the documentation of this file.
1 #ifndef EAGINE_INTEGER_HASH_HPP
9 #define EAGINE_INTEGER_HASH_HPP
10 
11 #include "int_constant.hpp"
12 #include "type_identity.hpp"
13 #include <cstdint>
14 
15 namespace eagine {
16 //------------------------------------------------------------------------------
17 template <std::size_t N, typename I>
18 constexpr auto
19 integer_rotate_right(I x, type_identity<I> = {}, size_constant<N> = {}) noexcept
20  -> I {
21  static_assert(N < sizeof(I) * 8);
22  return I(x << N) | I(x >> (-N & (sizeof(I) * 8U - 1U)));
23 }
24 //------------------------------------------------------------------------------
25 template <typename H>
26 constexpr auto
27 integer_hash_init(H x, type_identity<H> = {}, type_identity<H> = {}) noexcept
28  -> H {
29  return x;
30 }
31 //------------------------------------------------------------------------------
32 template <typename H, typename I>
33 constexpr auto integer_hash_init(
34  I x,
35  type_identity<H> hid = {},
36  type_identity<I> = {}) noexcept -> H {
37  using std::is_same_v;
38 
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);
42  }
43  if constexpr(is_same_v<H, std::uint64_t>) {
44  return H(x) ^ (H(x) << 16U) ^ (H(x) << 32U) ^ (H(x) << 48U);
45  }
46  }
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));
50  }
51  if constexpr(is_same_v<H, std::uint64_t>) {
52  return H(x) ^ (H(x) << 32U);
53  }
54  }
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));
58  }
59  if constexpr(is_same_v<H, std::uint32_t>) {
60  return H(x ^ (x >> 32U));
61  }
62  }
63 
64  using UI = std::make_unsigned_t<I>;
65  return integer_hash_init(UI(x), hid, type_identity<UI>());
66 }
67 //------------------------------------------------------------------------------
70 template <typename H, typename I>
71 inline auto
72 integer_hash(I x, type_identity<H> hid = {}, type_identity<I> iid = {}) -> H {
73  using std::is_same_v;
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);
78  h *= 0xff51;
79  h ^= integer_rotate_right<9U>(h, hid);
80  h *= 0xafd7;
81  h ^= integer_rotate_right<9U>(h, hid);
82  h *= 0xed55;
83  h ^= integer_rotate_right<9U>(h, hid);
84  h *= 0x8ccd;
85  h ^= integer_rotate_right<9U>(h, hid);
86  h *= 0xc4ce;
87  h ^= integer_rotate_right<9U>(h, hid);
88  h *= 0xb9fe;
89  h ^= integer_rotate_right<9U>(h, hid);
90  h *= 0x1a85;
91  h ^= integer_rotate_right<9U>(h, hid);
92  h *= 0xec53;
93  h ^= integer_rotate_right<9U>(h, hid);
94  }
95  if constexpr(is_same_v<H, std::uint32_t>) {
96  h ^= integer_rotate_right<17U>(h, hid);
97  h *= 0xff51afd7;
98  h ^= integer_rotate_right<17U>(h, hid);
99  h *= 0xed558ccd;
100  h ^= integer_rotate_right<17U>(h, hid);
101  h *= 0xc4ceb9fe;
102  h ^= integer_rotate_right<17U>(h, hid);
103  h *= 0x1a85ec53;
104  h ^= integer_rotate_right<17U>(h, hid);
105  }
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);
116  }
117  return h;
118  }
119 
120  using UH = std::make_unsigned_t<H>;
121  return H(integer_hash<UH>(x));
122 }
123 //------------------------------------------------------------------------------
124 } // namespace eagine
125 
126 #endif // EAGINE_INTEGER_HASH_HPP
auto integer_hash(I x, type_identity< H > hid={}, type_identity< I > iid={}) -> H
Creates a hash value with type H from an integer value of type I.
Definition: integer_hash.hpp:72
Common code is placed in this namespace.
Definition: eagine.hpp:21
Template type used mostly for function type-tag dispatching.
Definition: type_identity.hpp:19

Copyright © 2015-2021 Matúš Chochlík.
<chochlik -at -gmail.com>
Documentation generated on Tue Apr 13 2021 by Doxygen (version 1.8.17).