MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
hash_util.hpp
Go to the documentation of this file.
1// Copyright (c) 2010-2026, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#ifndef MFEM_HASH_UTIL_HPP
13#define MFEM_HASH_UTIL_HPP
14
15#include <array>
16#include <cstddef>
17#include <tuple>
18#include <functional>
19#include <utility>
20#include <cstdint>
21#include <type_traits>
22
23namespace mfem
24{
25
26/// @brief Streaming implementation of MurmurHash3 128 (x64).
27///
28/// Constructs the hash in 3 stages: init, append, finalize.
29struct Hasher
30{
31 /// @brief Storage for the final hash result after finalize() is called.
32 ///
33 /// Use data[1] when only 64 bits are required.
34 uint64_t data[2] = {0, 0};
35
36private:
37 uint64_t nbytes = 0;
38 uint64_t buf_[2] = {0, 0};
39
40public:
41
42 /// Resets the Hasher back to an initial seed
43 void init(uint64_t seed = 0);
44
45 /// Append data @a vs of size @a bytes.
46 void append(const std::byte *vs, uint64_t bytes);
47
48 void finalize();
49
50private:
51 /// Add a block of 16 bytes.
52 void add_block(uint64_t k1, uint64_t k2);
53
54 /// @brief Add [1-8] more bytes, then finalize.
55 ///
56 /// @a num must satisfy 0 < num < 9.
57 void finalize(uint64_t k1, int num);
58
59 /// @brief Add [1-15] more bytes, then finalize.
60 ///
61 /// @a num must satisfy 0 < num < 16.
62 void finalize(uint64_t k1, uint64_t k2, int num);
63};
64
65template <class T> struct ChainedHasher
66{
67 static void Append(Hasher &hasher, const T &value)
68 {
69 if constexpr (std::is_fundamental_v<T> || std::is_pointer_v<T>)
70 {
71 hasher.append(reinterpret_cast<const std::byte *>(&value), sizeof(T));
72 }
73 else
74 {
75 std::hash<T> h;
76 auto v = h(value);
77 hasher.append(reinterpret_cast<std::byte *>(&v), sizeof(v));
78 }
79 }
80};
81
82template <class T, class V> struct ChainedHasher<std::pair<T, V>>
83{
84 static void Append(Hasher &hasher, const std::pair<T, V> &value)
85 {
86 ChainedHasher<T>::Append(hasher, value.first);
87 ChainedHasher<V>::Append(hasher, value.second);
88 }
89};
90
91template <class T, size_t N> struct ChainedHasher<std::array<T, N>>
92{
93 static void Append(Hasher &hasher, const std::array<T, N> &value)
94 {
95 for (size_t i = 0; i < N; ++i)
96 {
97 ChainedHasher<T>::Append(hasher, value[i]);
98 }
99 }
100};
101
102template<class... Ts> struct ChainedHasher<std::tuple<Ts...>>
103{
104private:
105 template <size_t N>
106 static void AppendImpl(Hasher &hasher, const std::tuple<Ts...> &value)
107 {
109 hasher, std::get<N>(value));
110 if constexpr (N + 1 < sizeof...(Ts))
111 {
112 AppendImpl<N + 1>(hasher, value);
113 }
114 }
115
116public:
117 static void Append(Hasher &hasher, const std::tuple<Ts...> &value)
118 {
119 if constexpr (sizeof...(Ts))
120 {
121 AppendImpl<0>(hasher, value);
122 }
123 }
124};
125
126/// Helper class for hashing std::pair of hashable types.
128{
129 template <class T, class V>
130 size_t operator()(const std::pair<T, V> &v) const noexcept
131 {
132 Hasher hash;
133 // chosen randomly with a 2^64-sided dice
134 hash.init(0xfebd1fe69813c14full);
135 ChainedHasher<std::pair<T, V>>::Append(hash, v);
136 hash.finalize();
137 return hash.data[1];
138 }
139};
140
141/// Helper class for hashing std::array of a hashable type.
143{
144 template <class T, size_t N>
145 size_t operator()(const std::array<T, N> &v) const noexcept
146 {
147 Hasher hash;
148 // chosen randomly with a 2^64-sided dice
149 hash.init(0xfebd1fe69813c14full);
150 ChainedHasher<std::array<T, N>>::Append(hash, v);
151 hash.finalize();
152 return hash.data[1];
153 }
154};
155
156/// Helper class for hashing std::tuple of hashable types.
158{
159 template <class T>
160 size_t operator()(const T &v) const noexcept
161 {
162 Hasher hash;
163 // chosen randomly with a 2^64-sided dice
164 hash.init(0xfebd1fe69813c14full);
166 hash.finalize();
167 return hash.data[1];
168 }
169};
170
171} // namespace mfem
172
173#endif
STL namespace.
Helper class for hashing std::array of a hashable type.
size_t operator()(const std::array< T, N > &v) const noexcept
static void Append(Hasher &hasher, const std::array< T, N > &value)
Definition hash_util.hpp:93
static void Append(Hasher &hasher, const std::pair< T, V > &value)
Definition hash_util.hpp:84
static void Append(Hasher &hasher, const std::tuple< Ts... > &value)
static void Append(Hasher &hasher, const T &value)
Definition hash_util.hpp:67
Streaming implementation of MurmurHash3 128 (x64).
Definition hash_util.hpp:30
void init(uint64_t seed=0)
Resets the Hasher back to an initial seed.
Definition hash_util.cpp:22
uint64_t data[2]
Storage for the final hash result after finalize() is called.
Definition hash_util.hpp:34
void finalize()
Definition hash_util.cpp:92
void append(const std::byte *vs, uint64_t bytes)
Append data vs of size bytes.
Definition hash_util.cpp:65
Helper class for hashing std::pair of hashable types.
size_t operator()(const std::pair< T, V > &v) const noexcept
Helper class for hashing std::tuple of hashable types.
size_t operator()(const T &v) const noexcept