MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
hash_util.cpp
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#include "hash_util.hpp"
13
14namespace mfem
15{
16
17constexpr static uint64_t rotl64(uint64_t x, int r)
18{
19 return (x << r) | (x >> (64 - r));
20}
21
22void Hasher::init(uint64_t seed)
23{
24 data[0] = seed;
25 data[1] = seed;
26 nbytes = 0;
27}
28
29void Hasher::add_block(uint64_t k1, uint64_t k2)
30{
31 constexpr uint64_t c1 = 0x87c37b91114253d5ull;
32 constexpr uint64_t c2 = 0x4cf5ad432745937full;
33
34 k1 *= c1;
35 k1 = rotl64(k1, 31);
36 k1 *= c2;
37 data[0] ^= k1;
38
39 data[0] = rotl64(data[0], 27);
40 data[0] += data[1];
41 data[0] = data[0] * 5 + 0x52dce729ull;
42
43 k2 *= c2;
44 k2 = rotl64(k2, 33);
45 k2 *= c1;
46 data[1] ^= k2;
47
48 data[1] = rotl64(data[1], 31);
49 data[1] += data[0];
50 data[1] = data[1] * 5 + 0x38495ab5ull;
51}
52
53static uint64_t fmix64(uint64_t k)
54{
55 // http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html
56 // mix13
57 k ^= k >> 30;
58 k *= 0xbf58476d1ce4e5b9ull;
59 k ^= k >> 27;
60 k *= 0x94d049bb133111ebull;
61 k ^= k >> 31;
62 return k;
63}
64
65void Hasher::append(const std::byte *vs, uint64_t bytes)
66{
67 if (bytes == 0)
68 {
69 return;
70 }
71 auto rem = nbytes % 16;
72 nbytes += bytes;
73 std::byte *tmp = reinterpret_cast<std::byte *>(buf_);
74 while (true)
75 {
76 if (bytes + rem >= 16)
77 {
78 std::copy(vs, vs + 16 - rem, tmp + rem);
79 add_block(buf_[0], buf_[1]);
80 vs += (16 - rem);
81 bytes -= (16 - rem);
82 rem = 0;
83 }
84 else
85 {
86 std::copy(vs, vs + bytes, tmp + rem);
87 return;
88 }
89 }
90}
91
93{
94 auto rem = nbytes % 16;
95 if (rem > 0)
96 {
97 nbytes -= rem;
98 if (rem <= 8)
99 {
100 finalize(buf_[0], rem);
101 }
102 else
103 {
104 finalize(buf_[0], buf_[1], rem);
105 }
106 return;
107 }
108 data[0] ^= nbytes;
109 data[1] ^= nbytes;
110
111 data[0] += data[1];
112 data[1] += data[0];
113
114 data[0] = fmix64(data[0]);
115 data[1] = fmix64(data[1]);
116
117 data[0] += data[1];
118 data[1] += data[0];
119}
120
121void Hasher::finalize(uint64_t k1, int num)
122{
123 constexpr uint64_t c1 = 0x87c37b91114253d5ull;
124 constexpr uint64_t c2 = 0x4cf5ad432745937full;
125 nbytes += num;
126 k1 *= c1;
127 k1 = rotl64(k1, 31);
128 k1 *= c2;
129 data[0] ^= k1;
130
131 data[0] ^= nbytes;
132 data[1] ^= nbytes;
133
134 data[0] += data[1];
135 data[1] += data[0];
136
137 data[0] = fmix64(data[0]);
138 data[1] = fmix64(data[1]);
139
140 data[0] += data[1];
141 data[1] += data[0];
142}
143
144void Hasher::finalize(uint64_t k1, uint64_t k2, int num)
145{
146 constexpr uint64_t c1 = 0x87c37b91114253d5ull;
147 constexpr uint64_t c2 = 0x4cf5ad432745937full;
148 nbytes += num;
149 k2 *= c2;
150 k2 = rotl64(k2, 33);
151 k2 *= c1;
152 data[1] ^= k2;
153
154 k1 *= c1;
155 k1 = rotl64(k1, 31);
156 k1 *= c2;
157 data[0] ^= k1;
158
159 data[0] ^= nbytes;
160 data[1] ^= nbytes;
161
162 data[0] += data[1];
163 data[1] += data[0];
164
165 data[0] = fmix64(data[0]);
166 data[1] = fmix64(data[1]);
167
168 data[0] += data[1];
169 data[1] += data[0];
170}
171
172}
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