summaryrefslogtreecommitdiff
path: root/src/common/container_hash.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/container_hash.h')
-rw-r--r--src/common/container_hash.h92
1 files changed, 92 insertions, 0 deletions
diff --git a/src/common/container_hash.h b/src/common/container_hash.h
new file mode 100644
index 000000000..a5e357745
--- /dev/null
+++ b/src/common/container_hash.h
@@ -0,0 +1,92 @@
1// SPDX-FileCopyrightText: 2005-2014 Daniel James
2// SPDX-FileCopyrightText: 2016 Austin Appleby
3// SPDX-License-Identifier: BSL-1.0
4
5#include <array>
6#include <climits>
7#include <cstdint>
8#include <limits>
9#include <type_traits>
10#include <vector>
11
12namespace Common {
13
14namespace detail {
15
16template <typename T>
17 requires std::is_unsigned_v<T>
18inline std::size_t HashValue(T val) {
19 const unsigned int size_t_bits = std::numeric_limits<std::size_t>::digits;
20 const unsigned int length =
21 (std::numeric_limits<T>::digits - 1) / static_cast<unsigned int>(size_t_bits);
22
23 std::size_t seed = 0;
24
25 for (unsigned int i = length * size_t_bits; i > 0; i -= size_t_bits) {
26 seed ^= static_cast<size_t>(val >> i) + (seed << 6) + (seed >> 2);
27 }
28
29 seed ^= static_cast<size_t>(val) + (seed << 6) + (seed >> 2);
30
31 return seed;
32}
33
34template <size_t Bits>
35struct HashCombineImpl {
36 template <typename T>
37 static inline T fn(T seed, T value) {
38 seed ^= value + 0x9e3779b9 + (seed << 6) + (seed >> 2);
39 return seed;
40 }
41};
42
43template <>
44struct HashCombineImpl<64> {
45 static inline std::uint64_t fn(std::uint64_t h, std::uint64_t k) {
46 const std::uint64_t m = (std::uint64_t(0xc6a4a793) << 32) + 0x5bd1e995;
47 const int r = 47;
48
49 k *= m;
50 k ^= k >> r;
51 k *= m;
52
53 h ^= k;
54 h *= m;
55
56 // Completely arbitrary number, to prevent 0's
57 // from hashing to 0.
58 h += 0xe6546b64;
59
60 return h;
61 }
62};
63
64} // namespace detail
65
66template <typename T>
67inline void HashCombine(std::size_t& seed, const T& v) {
68 seed = detail::HashCombineImpl<sizeof(std::size_t) * CHAR_BIT>::fn(seed, detail::HashValue(v));
69}
70
71template <typename It>
72inline std::size_t HashRange(It first, It last) {
73 std::size_t seed = 0;
74
75 for (; first != last; ++first) {
76 HashCombine<typename std::iterator_traits<It>::value_type>(seed, *first);
77 }
78
79 return seed;
80}
81
82template <typename T, size_t Size>
83std::size_t HashValue(const std::array<T, Size>& v) {
84 return HashRange(v.cbegin(), v.cend());
85}
86
87template <typename T, typename Allocator>
88std::size_t HashValue(const std::vector<T, Allocator>& v) {
89 return HashRange(v.cbegin(), v.cend());
90}
91
92} // namespace Common