MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
hash.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, 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#include "hash.hpp"
13
14#ifdef MFEM_USE_GNUTLS
15#include <gnutls/gnutls.h>
16#include <gnutls/crypto.h>
17#if GNUTLS_VERSION_NUMBER >= 0x020a00
18#define HAVE_GNUTLS_HASH_FUNCTIONS
19#endif
20#endif
21
22namespace mfem
23{
24
25#ifdef HAVE_GNUTLS_HASH_FUNCTIONS
26constexpr gnutls_digest_algorithm_t HASH_ALGORITHM = GNUTLS_DIG_SHA256;
27#endif
28
30{
31#ifndef HAVE_GNUTLS_HASH_FUNCTIONS
32 hash_data = nullptr;
33#else
34 gnutls_hash_init((gnutls_hash_hd_t*)(&hash_data), HASH_ALGORITHM);
35#endif
36}
37
39{
40#ifdef HAVE_GNUTLS_HASH_FUNCTIONS
41 gnutls_hash_deinit((gnutls_hash_hd_t)hash_data, nullptr);
42#endif
43}
44
45void HashFunction::HashBuffer(const void *buffer, size_t num_bytes)
46{
47#ifndef HAVE_GNUTLS_HASH_FUNCTIONS
48 MFEM_CONTRACT_VAR(buffer);
49 MFEM_CONTRACT_VAR(num_bytes);
50#else
51 gnutls_hash((gnutls_hash_hd_t)hash_data, buffer, num_bytes);
52#endif
53}
54
55inline constexpr char to_hex(unsigned char u)
56{
57 return (u < 10) ? '0' + u : (u < 16) ? 'a' + (u - 10) : '?';
58}
59
60std::string HashFunction::GetHash() const
61{
62 std::string hash;
63#ifndef MFEM_USE_GNUTLS
64 hash = "(GnuTLS is required for hashing)";
65#elif !defined (HAVE_GNUTLS_HASH_FUNCTIONS)
66 hash = "(Old GnuTLS version: does not support hashing)";
67#else
68 constexpr unsigned max_hash_len = 64;
69 unsigned char hash_bytes[max_hash_len];
70 unsigned hash_len = gnutls_hash_get_len(HASH_ALGORITHM);
71 MFEM_VERIFY(hash_len <= max_hash_len, "internal error");
72 hash.reserve(2*hash_len);
73 gnutls_hash_output((gnutls_hash_hd_t)hash_data, hash_bytes);
74 for (unsigned i = 0; i < hash_len; i++)
75 {
76 hash += to_hex(hash_bytes[i]/16);
77 hash += to_hex(hash_bytes[i]%16);
78 }
79#endif
80 return hash;
81}
82
83constexpr static uint64_t rotl64(uint64_t x, int r)
84{
85 return (x << r) | (x >> (64 - r));
86}
87
88void Hasher::init(uint64_t seed)
89{
90 data[0] = seed;
91 data[1] = seed;
92 nbytes = 0;
93}
94
95void Hasher::add_block(uint64_t k1, uint64_t k2)
96{
97 constexpr uint64_t c1 = 0x87c37b91114253d5ull;
98 constexpr uint64_t c2 = 0x4cf5ad432745937full;
99
100 k1 *= c1;
101 k1 = rotl64(k1, 31);
102 k1 *= c2;
103 data[0] ^= k1;
104
105 data[0] = rotl64(data[0], 27);
106 data[0] += data[1];
107 data[0] = data[0] * 5 + 0x52dce729ull;
108
109 k2 *= c2;
110 k2 = rotl64(k2, 33);
111 k2 *= c1;
112 data[1] ^= k2;
113
114 data[1] = rotl64(data[1], 31);
115 data[1] += data[0];
116 data[1] = data[1] * 5 + 0x38495ab5ull;
117}
118
119static uint64_t fmix64(uint64_t k)
120{
121 // http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html
122 // mix13
123 k ^= k >> 30;
124 k *= 0xbf58476d1ce4e5b9ull;
125 k ^= k >> 27;
126 k *= 0x94d049bb133111ebull;
127 k ^= k >> 31;
128 return k;
129}
130
131void Hasher::append(const uint8_t *vs, uint64_t bytes)
132{
133 if (bytes == 0)
134 {
135 return;
136 }
137 auto rem = nbytes % 16;
138 nbytes += bytes;
139 uint8_t *tmp = reinterpret_cast<uint8_t *>(buf_);
140 while (true)
141 {
142 if (bytes + rem >= 16)
143 {
144 std::copy(vs, vs + 16 - rem, tmp + rem);
145 add_block(buf_[0], buf_[1]);
146 vs += (16 - rem);
147 bytes -= (16 - rem);
148 rem = 0;
149 }
150 else
151 {
152 std::copy(vs, vs + bytes, tmp + rem);
153 return;
154 }
155 }
156}
157
159{
160 auto rem = nbytes % 16;
161 if (rem > 0)
162 {
163 nbytes -= rem;
164 if (rem <= 8)
165 {
166 finalize(buf_[0], rem);
167 }
168 else
169 {
170 finalize(buf_[0], buf_[1], rem);
171 }
172 return;
173 }
174 data[0] ^= nbytes;
175 data[1] ^= nbytes;
176
177 data[0] += data[1];
178 data[1] += data[0];
179
180 data[0] = fmix64(data[0]);
181 data[1] = fmix64(data[1]);
182
183 data[0] += data[1];
184 data[1] += data[0];
185}
186
187void Hasher::finalize(uint64_t k1, int num)
188{
189 constexpr uint64_t c1 = 0x87c37b91114253d5ull;
190 constexpr uint64_t c2 = 0x4cf5ad432745937full;
191 nbytes += num;
192 k1 *= c1;
193 k1 = rotl64(k1, 31);
194 k1 *= c2;
195 data[0] ^= k1;
196
197 data[0] ^= nbytes;
198 data[1] ^= nbytes;
199
200 data[0] += data[1];
201 data[1] += data[0];
202
203 data[0] = fmix64(data[0]);
204 data[1] = fmix64(data[1]);
205
206 data[0] += data[1];
207 data[1] += data[0];
208}
209
210void Hasher::finalize(uint64_t k1, uint64_t k2, int num)
211{
212 constexpr uint64_t c1 = 0x87c37b91114253d5ull;
213 constexpr uint64_t c2 = 0x4cf5ad432745937full;
214 nbytes += num;
215 k2 *= c2;
216 k2 = rotl64(k2, 33);
217 k2 *= c1;
218 data[1] ^= k2;
219
220 k1 *= c1;
221 k1 = rotl64(k1, 31);
222 k1 *= c2;
223 data[0] ^= k1;
224
225 data[0] ^= nbytes;
226 data[1] ^= nbytes;
227
228 data[0] += data[1];
229 data[1] += data[0];
230
231 data[0] = fmix64(data[0]);
232 data[1] = fmix64(data[1]);
233
234 data[0] += data[1];
235 data[1] += data[0];
236}
237
238} // namespace mfem
HashFunction()
Default constructor: initialize the hash function.
Definition hash.cpp:29
std::string GetHash() const
Return the hash string for the current sequence and reset (clear) the sequence.
Definition hash.cpp:60
~HashFunction()
Destructor.
Definition hash.cpp:38
void HashBuffer(const void *buffer, size_t num_bytes)
Add a sequence of bytes for hashing.
Definition hash.cpp:45
real_t u(const Vector &xvec)
Definition lor_mms.hpp:22
constexpr gnutls_digest_algorithm_t HASH_ALGORITHM
Definition hash.cpp:26
constexpr char to_hex(unsigned char u)
Definition hash.cpp:55
void init(uint64_t seed=0)
resets this hasher back to an initial seed
Definition hash.cpp:88
uint64_t data[2]
Definition hash.hpp:466
void finalize()
Definition hash.cpp:158
void append(const uint8_t *vs, uint64_t bytes)
Definition hash.cpp:131