gem5 v24.0.0.0
Loading...
Searching...
No Matches
hash_helpers.hh
Go to the documentation of this file.
1/*
2 * Copyright (c) 2023 Arteris, Inc. and its applicable licensors and
3 * affiliates.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#ifndef BASE_STL_HELPERS_HASH_HELPERS_HH
31#define BASE_STL_HELPERS_HASH_HELPERS_HH
32
33#include <functional>
34#include <numeric>
35#include <tuple>
36#include <type_traits>
37#include <unordered_map>
38#include <unordered_set>
39#include <utility>
40
41#include "base/type_traits.hh"
42
43#include <functional>
44#include <tuple>
45#include <type_traits>
46#include <utility>
47
49{
50
51namespace hash_impl
52{
53// The math in hash_combine and hash_refine functions are inspired from Jon
54// Maiga's work hosted at https://github.com/jonmaiga/mx3 under the CC0
55// license. It makes use of two components: a stream mixer for combination and
56// a scalar mixer for refinement.
57// The stream mixer is a lighter weight function with lower entropy used to
58// combine hash values while the scalar mixer is a high entropy function that
59// increases the overall hashing quality.
60// The tradeoff of not using hash_refine has not been thoroughtly tested and is
61// only done based on Maiga's return on exprerience.
62static constexpr uint64_t C = 0xbea225f9eb34556d;
63template<typename... T>
64constexpr size_t hash_combine(T... hashes) {
65 // gcc reports unused variable if T is the empty pack
66 [[maybe_unused]] auto combine = [](uint64_t a, uint64_t b) {
67 b *= C;
68 b ^= b >> 39;
69 a += b * C;
70 a *= C;
71 return a;
72 };
73 // The following couple of expressions is equivalent to a hypothetical
74 // functional "acc = hashes.fold_left(0, combine)". The comma operator
75 // effectively repeats the expression in the second level parenthesis for
76 // each argument in the parameter pack hashes, in order. Thus, final value
77 // of acc is the recursive combination of all hashes.
78 uint64_t acc{0};
79 ((acc = combine(acc, static_cast<uint64_t>(hashes))), ...);
80 return static_cast<size_t>(acc);
81}
82
83constexpr size_t hash_refine(size_t x) {
84 x ^= x >> 32;
85 x *= C;
86 x ^= x >> 29;
87 x *= C;
88 x ^= x >> 32;
89 x *= C;
90 x ^= x >> 29;
91 return static_cast<size_t>(x);
92}
93
94// SFINAE-enabled hash functor
95template<typename T, typename = void>
96struct hash;
97
98// Reuse std::hash whenever possible
99template<typename T>
100struct hash<T, std::enable_if_t<is_std_hash_enabled_v<T>>>: std::hash<T>
101{};
102
103// Enable type deduction for hash object construction
104template<typename T>
105constexpr auto make_hash_for(const T&) {
106 return hash<T>();
107}
108
109// Compute a hash without the hassle of constructing a hash functor
110template<typename T>
111constexpr auto hash_value(const T& v) {
112 return make_hash_for(v)(v);
113}
114
115// Hash for tuple
116template<typename... T>
117struct hash<std::tuple<T...>>
118{
119 constexpr size_t operator()(const std::tuple<T...>& t) const {
120 if constexpr (sizeof...(T) == 0) {
121 return 0;
122 } else {
123 return std::apply([](const auto&... e){
125 }, t);
126 }
127 }
128};
129
130// Hash for pairs (based on hash for 2-uple)
131template<typename T, typename U>
132struct hash<std::pair<T, U>>
133{
134 constexpr size_t operator()(const std::pair<T, U>& p) const {
135 return hash_value(std::tie(p.first, p.second));
136 }
137};
138
139// Hash for any iterable of stl_helpers::hash-enabled types.
140template<typename T>
141struct hash<T, std::enable_if_t<
142 !is_std_hash_enabled_v<T> && is_iterable_v<T>>>
143{
144 constexpr size_t operator()(const T& t) const {
145 auto b = begin(t);
146 auto e = end(t);
147 if (b == e) return 0;
148 // Equivalent to hypothetical functional style
149 // return t.map(hash_value).reduce(hash_combine)
150 auto h = std::accumulate(next(b), e, hash_value(*b),
151 [](const auto& acc, const auto& val) {
152 return hash_combine(acc, hash_value(val));
153 });
154 return hash_refine(h);
155 }
156};
157
158template<typename, typename = void>
159constexpr bool is_hash_enabled = false;
160
161template <typename T>
162constexpr bool is_hash_enabled<T,
163 std::void_t<decltype(hash<T>()(std::declval<T>()))>> = true;
164
165} // namespace hash_impl
166
167// Export useful hash_impl functions
168using hash_impl::hash;
172
173/*
174 * Provide unordered_map and unordered_set with stl_helpers::hash functions.
175 * These aliases enable clean use of stl_helpers::hash as default Hash template
176 * parameter. The reason for not using an alias is that template type aliases
177 * with default template arguments do not behave well with template parameter
178 * deductions in certain situations. One must remember that std::unordered_X
179 * is not a polymorphic type and as such, gem5::stl_helpers::unordered_X shall
180 * never be owned as a std::unordered_X.
181 */
182template<
183 typename Key,
184 typename T,
185 typename Hash = hash<Key>,
186 typename KeyEqual = std::equal_to<Key>,
187 typename Allocator = std::allocator< std::pair<const Key, T> >>
188struct unordered_map: std::unordered_map<Key, T, Hash, KeyEqual, Allocator>
189{};
190
191template<
192 typename Key,
193 typename Hash = hash<Key>,
194 typename KeyEqual = std::equal_to<Key>,
195 typename Allocator = std::allocator<Key>>
196struct unordered_set: std::unordered_set<Key, Hash, KeyEqual, Allocator>
197{};
198
199} // namespace gem5::stl_helpers
200
201#endif // BASE_STL_HELPERS_HASH_HELPERS_HH
STL pair class.
Definition stl.hh:58
Bitfield< 28 > v
Definition misc_types.hh:54
Bitfield< 5 > t
Definition misc_types.hh:71
Bitfield< 7 > b
Bitfield< 9 > e
Definition misc_types.hh:65
Bitfield< 8 > a
Definition misc_types.hh:66
Bitfield< 0 > p
Bitfield< 3 > x
Definition pagetable.hh:73
Bitfield< 63 > val
Definition misc.hh:804
constexpr auto hash_value(const T &v)
constexpr size_t hash_combine(T... hashes)
constexpr size_t hash_refine(size_t x)
constexpr auto make_hash_for(const T &)
static constexpr uint64_t C
Overload hash function for BasicBlockRange type.
Definition binary32.hh:81
constexpr size_t operator()(const std::pair< T, U > &p) const
constexpr size_t operator()(const std::tuple< T... > &t) const

Generated on Tue Jun 18 2024 16:24:01 for gem5 by doxygen 1.11.0