summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2018-04-07 00:48:22 -0400
committerGravatar bunnei2018-04-13 23:48:22 -0400
commit45fd7c4a37d4b890f98f8a0a9373e57c0830cc8d (patch)
treec8407755365316b1316407d5aee6871c0007ba85
parentrenderer_opengl: Use OGLProgram instead of OGLShader. (diff)
downloadyuzu-45fd7c4a37d4b890f98f8a0a9373e57c0830cc8d.tar.gz
yuzu-45fd7c4a37d4b890f98f8a0a9373e57c0830cc8d.tar.xz
yuzu-45fd7c4a37d4b890f98f8a0a9373e57c0830cc8d.zip
common: Port cityhash code from Citra.
-rw-r--r--src/common/CMakeLists.txt3
-rw-r--r--src/common/cityhash.cpp340
-rw-r--r--src/common/cityhash.h110
-rw-r--r--src/common/hash.cpp141
-rw-r--r--src/common/hash.h55
5 files changed, 502 insertions, 147 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 2ba1da195..d6eb9055b 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -32,6 +32,8 @@ add_library(common STATIC
32 break_points.cpp 32 break_points.cpp
33 break_points.h 33 break_points.h
34 chunk_file.h 34 chunk_file.h
35 cityhash.cpp
36 cityhash.h
35 code_block.h 37 code_block.h
36 color.h 38 color.h
37 common_funcs.h 39 common_funcs.h
@@ -39,7 +41,6 @@ add_library(common STATIC
39 common_types.h 41 common_types.h
40 file_util.cpp 42 file_util.cpp
41 file_util.h 43 file_util.h
42 hash.cpp
43 hash.h 44 hash.h
44 linear_disk_cache.h 45 linear_disk_cache.h
45 logging/backend.cpp 46 logging/backend.cpp
diff --git a/src/common/cityhash.cpp b/src/common/cityhash.cpp
new file mode 100644
index 000000000..de31ffbd8
--- /dev/null
+++ b/src/common/cityhash.cpp
@@ -0,0 +1,340 @@
1// Copyright (c) 2011 Google, Inc.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19// THE SOFTWARE.
20//
21// CityHash, by Geoff Pike and Jyrki Alakuijala
22//
23// This file provides CityHash64() and related functions.
24//
25// It's probably possible to create even faster hash functions by
26// writing a program that systematically explores some of the space of
27// possible hash functions, by using SIMD instructions, or by
28// compromising on hash quality.
29
30#include <algorithm>
31#include <string.h> // for memcpy and memset
32#include "cityhash.h"
33#include "common/swap.h"
34
35// #include "config.h"
36#ifdef __GNUC__
37#define HAVE_BUILTIN_EXPECT 1
38#endif
39#ifdef COMMON_BIG_ENDIAN
40#define WORDS_BIGENDIAN 1
41#endif
42
43using namespace std;
44
45typedef uint8_t uint8;
46typedef uint32_t uint32;
47typedef uint64_t uint64;
48
49namespace Common {
50
51static uint64 UNALIGNED_LOAD64(const char* p) {
52 uint64 result;
53 memcpy(&result, p, sizeof(result));
54 return result;
55}
56
57static uint32 UNALIGNED_LOAD32(const char* p) {
58 uint32 result;
59 memcpy(&result, p, sizeof(result));
60 return result;
61}
62
63#ifdef WORDS_BIGENDIAN
64#define uint32_in_expected_order(x) (swap32(x))
65#define uint64_in_expected_order(x) (swap64(x))
66#else
67#define uint32_in_expected_order(x) (x)
68#define uint64_in_expected_order(x) (x)
69#endif
70
71#if !defined(LIKELY)
72#if HAVE_BUILTIN_EXPECT
73#define LIKELY(x) (__builtin_expect(!!(x), 1))
74#else
75#define LIKELY(x) (x)
76#endif
77#endif
78
79static uint64 Fetch64(const char* p) {
80 return uint64_in_expected_order(UNALIGNED_LOAD64(p));
81}
82
83static uint32 Fetch32(const char* p) {
84 return uint32_in_expected_order(UNALIGNED_LOAD32(p));
85}
86
87// Some primes between 2^63 and 2^64 for various uses.
88static const uint64 k0 = 0xc3a5c85c97cb3127ULL;
89static const uint64 k1 = 0xb492b66fbe98f273ULL;
90static const uint64 k2 = 0x9ae16a3b2f90404fULL;
91
92// Bitwise right rotate. Normally this will compile to a single
93// instruction, especially if the shift is a manifest constant.
94static uint64 Rotate(uint64 val, int shift) {
95 // Avoid shifting by 64: doing so yields an undefined result.
96 return shift == 0 ? val : ((val >> shift) | (val << (64 - shift)));
97}
98
99static uint64 ShiftMix(uint64 val) {
100 return val ^ (val >> 47);
101}
102
103static uint64 HashLen16(uint64 u, uint64 v) {
104 return Hash128to64(uint128(u, v));
105}
106
107static uint64 HashLen16(uint64 u, uint64 v, uint64 mul) {
108 // Murmur-inspired hashing.
109 uint64 a = (u ^ v) * mul;
110 a ^= (a >> 47);
111 uint64 b = (v ^ a) * mul;
112 b ^= (b >> 47);
113 b *= mul;
114 return b;
115}
116
117static uint64 HashLen0to16(const char* s, size_t len) {
118 if (len >= 8) {
119 uint64 mul = k2 + len * 2;
120 uint64 a = Fetch64(s) + k2;
121 uint64 b = Fetch64(s + len - 8);
122 uint64 c = Rotate(b, 37) * mul + a;
123 uint64 d = (Rotate(a, 25) + b) * mul;
124 return HashLen16(c, d, mul);
125 }
126 if (len >= 4) {
127 uint64 mul = k2 + len * 2;
128 uint64 a = Fetch32(s);
129 return HashLen16(len + (a << 3), Fetch32(s + len - 4), mul);
130 }
131 if (len > 0) {
132 uint8 a = s[0];
133 uint8 b = s[len >> 1];
134 uint8 c = s[len - 1];
135 uint32 y = static_cast<uint32>(a) + (static_cast<uint32>(b) << 8);
136 uint32 z = static_cast<uint32>(len) + (static_cast<uint32>(c) << 2);
137 return ShiftMix(y * k2 ^ z * k0) * k2;
138 }
139 return k2;
140}
141
142// This probably works well for 16-byte strings as well, but it may be overkill
143// in that case.
144static uint64 HashLen17to32(const char* s, size_t len) {
145 uint64 mul = k2 + len * 2;
146 uint64 a = Fetch64(s) * k1;
147 uint64 b = Fetch64(s + 8);
148 uint64 c = Fetch64(s + len - 8) * mul;
149 uint64 d = Fetch64(s + len - 16) * k2;
150 return HashLen16(Rotate(a + b, 43) + Rotate(c, 30) + d, a + Rotate(b + k2, 18) + c, mul);
151}
152
153// Return a 16-byte hash for 48 bytes. Quick and dirty.
154// Callers do best to use "random-looking" values for a and b.
155static pair<uint64, uint64> WeakHashLen32WithSeeds(uint64 w, uint64 x, uint64 y, uint64 z, uint64 a,
156 uint64 b) {
157 a += w;
158 b = Rotate(b + a + z, 21);
159 uint64 c = a;
160 a += x;
161 a += y;
162 b += Rotate(a, 44);
163 return make_pair(a + z, b + c);
164}
165
166// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty.
167static pair<uint64, uint64> WeakHashLen32WithSeeds(const char* s, uint64 a, uint64 b) {
168 return WeakHashLen32WithSeeds(Fetch64(s), Fetch64(s + 8), Fetch64(s + 16), Fetch64(s + 24), a,
169 b);
170}
171
172// Return an 8-byte hash for 33 to 64 bytes.
173static uint64 HashLen33to64(const char* s, size_t len) {
174 uint64 mul = k2 + len * 2;
175 uint64 a = Fetch64(s) * k2;
176 uint64 b = Fetch64(s + 8);
177 uint64 c = Fetch64(s + len - 24);
178 uint64 d = Fetch64(s + len - 32);
179 uint64 e = Fetch64(s + 16) * k2;
180 uint64 f = Fetch64(s + 24) * 9;
181 uint64 g = Fetch64(s + len - 8);
182 uint64 h = Fetch64(s + len - 16) * mul;
183 uint64 u = Rotate(a + g, 43) + (Rotate(b, 30) + c) * 9;
184 uint64 v = ((a + g) ^ d) + f + 1;
185 uint64 w = swap64((u + v) * mul) + h;
186 uint64 x = Rotate(e + f, 42) + c;
187 uint64 y = (swap64((v + w) * mul) + g) * mul;
188 uint64 z = e + f + c;
189 a = swap64((x + z) * mul + y) + b;
190 b = ShiftMix((z + a) * mul + d + h) * mul;
191 return b + x;
192}
193
194uint64 CityHash64(const char* s, size_t len) {
195 if (len <= 32) {
196 if (len <= 16) {
197 return HashLen0to16(s, len);
198 } else {
199 return HashLen17to32(s, len);
200 }
201 } else if (len <= 64) {
202 return HashLen33to64(s, len);
203 }
204
205 // For strings over 64 bytes we hash the end first, and then as we
206 // loop we keep 56 bytes of state: v, w, x, y, and z.
207 uint64 x = Fetch64(s + len - 40);
208 uint64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56);
209 uint64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));
210 pair<uint64, uint64> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
211 pair<uint64, uint64> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
212 x = x * k1 + Fetch64(s);
213
214 // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
215 len = (len - 1) & ~static_cast<size_t>(63);
216 do {
217 x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
218 y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
219 x ^= w.second;
220 y += v.first + Fetch64(s + 40);
221 z = Rotate(z + w.first, 33) * k1;
222 v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
223 w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
224 std::swap(z, x);
225 s += 64;
226 len -= 64;
227 } while (len != 0);
228 return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z,
229 HashLen16(v.second, w.second) + x);
230}
231
232uint64 CityHash64WithSeed(const char* s, size_t len, uint64 seed) {
233 return CityHash64WithSeeds(s, len, k2, seed);
234}
235
236uint64 CityHash64WithSeeds(const char* s, size_t len, uint64 seed0, uint64 seed1) {
237 return HashLen16(CityHash64(s, len) - seed0, seed1);
238}
239
240// A subroutine for CityHash128(). Returns a decent 128-bit hash for strings
241// of any length representable in signed long. Based on City and Murmur.
242static uint128 CityMurmur(const char* s, size_t len, uint128 seed) {
243 uint64 a = Uint128Low64(seed);
244 uint64 b = Uint128High64(seed);
245 uint64 c = 0;
246 uint64 d = 0;
247 signed long l = static_cast<long>(len) - 16;
248 if (l <= 0) { // len <= 16
249 a = ShiftMix(a * k1) * k1;
250 c = b * k1 + HashLen0to16(s, len);
251 d = ShiftMix(a + (len >= 8 ? Fetch64(s) : c));
252 } else { // len > 16
253 c = HashLen16(Fetch64(s + len - 8) + k1, a);
254 d = HashLen16(b + len, c + Fetch64(s + len - 16));
255 a += d;
256 do {
257 a ^= ShiftMix(Fetch64(s) * k1) * k1;
258 a *= k1;
259 b ^= a;
260 c ^= ShiftMix(Fetch64(s + 8) * k1) * k1;
261 c *= k1;
262 d ^= c;
263 s += 16;
264 l -= 16;
265 } while (l > 0);
266 }
267 a = HashLen16(a, c);
268 b = HashLen16(d, b);
269 return uint128(a ^ b, HashLen16(b, a));
270}
271
272uint128 CityHash128WithSeed(const char* s, size_t len, uint128 seed) {
273 if (len < 128) {
274 return CityMurmur(s, len, seed);
275 }
276
277 // We expect len >= 128 to be the common case. Keep 56 bytes of state:
278 // v, w, x, y, and z.
279 pair<uint64, uint64> v, w;
280 uint64 x = Uint128Low64(seed);
281 uint64 y = Uint128High64(seed);
282 uint64 z = len * k1;
283 v.first = Rotate(y ^ k1, 49) * k1 + Fetch64(s);
284 v.second = Rotate(v.first, 42) * k1 + Fetch64(s + 8);
285 w.first = Rotate(y + z, 35) * k1 + x;
286 w.second = Rotate(x + Fetch64(s + 88), 53) * k1;
287
288 // This is the same inner loop as CityHash64(), manually unrolled.
289 do {
290 x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
291 y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
292 x ^= w.second;
293 y += v.first + Fetch64(s + 40);
294 z = Rotate(z + w.first, 33) * k1;
295 v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
296 w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
297 std::swap(z, x);
298 s += 64;
299 x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
300 y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
301 x ^= w.second;
302 y += v.first + Fetch64(s + 40);
303 z = Rotate(z + w.first, 33) * k1;
304 v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
305 w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
306 std::swap(z, x);
307 s += 64;
308 len -= 128;
309 } while (LIKELY(len >= 128));
310 x += Rotate(v.first + z, 49) * k0;
311 y = y * k0 + Rotate(w.second, 37);
312 z = z * k0 + Rotate(w.first, 27);
313 w.first *= 9;
314 v.first *= k0;
315 // If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s.
316 for (size_t tail_done = 0; tail_done < len;) {
317 tail_done += 32;
318 y = Rotate(x + y, 42) * k0 + v.second;
319 w.first += Fetch64(s + len - tail_done + 16);
320 x = x * k0 + w.first;
321 z += w.second + Fetch64(s + len - tail_done);
322 w.second += v.first;
323 v = WeakHashLen32WithSeeds(s + len - tail_done, v.first + z, v.second);
324 v.first *= k0;
325 }
326 // At this point our 56 bytes of state should contain more than
327 // enough information for a strong 128-bit hash. We use two
328 // different 56-byte-to-8-byte hashes to get a 16-byte final result.
329 x = HashLen16(x, v.first);
330 y = HashLen16(y + z, w.first);
331 return uint128(HashLen16(x + v.second, w.second) + y, HashLen16(x + w.second, y + v.second));
332}
333
334uint128 CityHash128(const char* s, size_t len) {
335 return len >= 16
336 ? CityHash128WithSeed(s + 16, len - 16, uint128(Fetch64(s), Fetch64(s + 8) + k0))
337 : CityHash128WithSeed(s, len, uint128(k0, k1));
338}
339
340} // namespace Common
diff --git a/src/common/cityhash.h b/src/common/cityhash.h
new file mode 100644
index 000000000..bcebdb150
--- /dev/null
+++ b/src/common/cityhash.h
@@ -0,0 +1,110 @@
1// Copyright (c) 2011 Google, Inc.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19// THE SOFTWARE.
20//
21// CityHash, by Geoff Pike and Jyrki Alakuijala
22//
23// http://code.google.com/p/cityhash/
24//
25// This file provides a few functions for hashing strings. All of them are
26// high-quality functions in the sense that they pass standard tests such
27// as Austin Appleby's SMHasher. They are also fast.
28//
29// For 64-bit x86 code, on short strings, we don't know of anything faster than
30// CityHash64 that is of comparable quality. We believe our nearest competitor
31// is Murmur3. For 64-bit x86 code, CityHash64 is an excellent choice for hash
32// tables and most other hashing (excluding cryptography).
33//
34// For 64-bit x86 code, on long strings, the picture is more complicated.
35// On many recent Intel CPUs, such as Nehalem, Westmere, Sandy Bridge, etc.,
36// CityHashCrc128 appears to be faster than all competitors of comparable
37// quality. CityHash128 is also good but not quite as fast. We believe our
38// nearest competitor is Bob Jenkins' Spooky. We don't have great data for
39// other 64-bit CPUs, but for long strings we know that Spooky is slightly
40// faster than CityHash on some relatively recent AMD x86-64 CPUs, for example.
41// Note that CityHashCrc128 is declared in citycrc.h.
42//
43// For 32-bit x86 code, we don't know of anything faster than CityHash32 that
44// is of comparable quality. We believe our nearest competitor is Murmur3A.
45// (On 64-bit CPUs, it is typically faster to use the other CityHash variants.)
46//
47// Functions in the CityHash family are not suitable for cryptography.
48//
49// Please see CityHash's README file for more details on our performance
50// measurements and so on.
51//
52// WARNING: This code has been only lightly tested on big-endian platforms!
53// It is known to work well on little-endian platforms that have a small penalty
54// for unaligned reads, such as current Intel and AMD moderate-to-high-end CPUs.
55// It should work on all 32-bit and 64-bit platforms that allow unaligned reads;
56// bug reports are welcome.
57//
58// By the way, for some hash functions, given strings a and b, the hash
59// of a+b is easily derived from the hashes of a and b. This property
60// doesn't hold for any hash functions in this file.
61
62#pragma once
63
64#include <utility>
65#include <stdint.h>
66#include <stdlib.h> // for size_t.
67
68namespace Common {
69
70typedef std::pair<uint64_t, uint64_t> uint128;
71
72inline uint64_t Uint128Low64(const uint128& x) {
73 return x.first;
74}
75inline uint64_t Uint128High64(const uint128& x) {
76 return x.second;
77}
78
79// Hash function for a byte array.
80uint64_t CityHash64(const char* buf, size_t len);
81
82// Hash function for a byte array. For convenience, a 64-bit seed is also
83// hashed into the result.
84uint64_t CityHash64WithSeed(const char* buf, size_t len, uint64_t seed);
85
86// Hash function for a byte array. For convenience, two seeds are also
87// hashed into the result.
88uint64_t CityHash64WithSeeds(const char* buf, size_t len, uint64_t seed0, uint64_t seed1);
89
90// Hash function for a byte array.
91uint128 CityHash128(const char* s, size_t len);
92
93// Hash function for a byte array. For convenience, a 128-bit seed is also
94// hashed into the result.
95uint128 CityHash128WithSeed(const char* s, size_t len, uint128 seed);
96
97// Hash 128 input bits down to 64 bits of output.
98// This is intended to be a reasonably good hash function.
99inline uint64_t Hash128to64(const uint128& x) {
100 // Murmur-inspired hashing.
101 const uint64_t kMul = 0x9ddfea08eb382d69ULL;
102 uint64_t a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul;
103 a ^= (a >> 47);
104 uint64_t b = (Uint128High64(x) ^ a) * kMul;
105 b ^= (b >> 47);
106 b *= kMul;
107 return b;
108}
109
110} // namespace Common
diff --git a/src/common/hash.cpp b/src/common/hash.cpp
deleted file mode 100644
index a02e9e5b9..000000000
--- a/src/common/hash.cpp
+++ /dev/null
@@ -1,141 +0,0 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#if defined(_MSC_VER)
6#include <stdlib.h>
7#endif
8#include "common/common_funcs.h"
9#include "common/common_types.h"
10#include "common/hash.h"
11
12namespace Common {
13
14// MurmurHash3 was written by Austin Appleby, and is placed in the public
15// domain. The author hereby disclaims copyright to this source code.
16
17// Block read - if your platform needs to do endian-swapping or can only handle aligned reads, do
18// the conversion here
19static FORCE_INLINE u64 getblock64(const u64* p, size_t i) {
20 return p[i];
21}
22
23// Finalization mix - force all bits of a hash block to avalanche
24static FORCE_INLINE u64 fmix64(u64 k) {
25 k ^= k >> 33;
26 k *= 0xff51afd7ed558ccdllu;
27 k ^= k >> 33;
28 k *= 0xc4ceb9fe1a85ec53llu;
29 k ^= k >> 33;
30
31 return k;
32}
33
34// This is the 128-bit variant of the MurmurHash3 hash function that is targeted for 64-bit
35// platforms (MurmurHash3_x64_128). It was taken from:
36// https://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
37void MurmurHash3_128(const void* key, size_t len, u32 seed, void* out) {
38 const u8* data = (const u8*)key;
39 const size_t nblocks = len / 16;
40
41 u64 h1 = seed;
42 u64 h2 = seed;
43
44 const u64 c1 = 0x87c37b91114253d5llu;
45 const u64 c2 = 0x4cf5ad432745937fllu;
46
47 // Body
48
49 const u64* blocks = (const u64*)(data);
50
51 for (size_t i = 0; i < nblocks; i++) {
52 u64 k1 = getblock64(blocks, i * 2 + 0);
53 u64 k2 = getblock64(blocks, i * 2 + 1);
54
55 k1 *= c1;
56 k1 = _rotl64(k1, 31);
57 k1 *= c2;
58 h1 ^= k1;
59
60 h1 = _rotl64(h1, 27);
61 h1 += h2;
62 h1 = h1 * 5 + 0x52dce729;
63
64 k2 *= c2;
65 k2 = _rotl64(k2, 33);
66 k2 *= c1;
67 h2 ^= k2;
68
69 h2 = _rotl64(h2, 31);
70 h2 += h1;
71 h2 = h2 * 5 + 0x38495ab5;
72 }
73
74 // Tail
75
76 const u8* tail = (const u8*)(data + nblocks * 16);
77
78 u64 k1 = 0;
79 u64 k2 = 0;
80
81 switch (len & 15) {
82 case 15:
83 k2 ^= ((u64)tail[14]) << 48;
84 case 14:
85 k2 ^= ((u64)tail[13]) << 40;
86 case 13:
87 k2 ^= ((u64)tail[12]) << 32;
88 case 12:
89 k2 ^= ((u64)tail[11]) << 24;
90 case 11:
91 k2 ^= ((u64)tail[10]) << 16;
92 case 10:
93 k2 ^= ((u64)tail[9]) << 8;
94 case 9:
95 k2 ^= ((u64)tail[8]) << 0;
96 k2 *= c2;
97 k2 = _rotl64(k2, 33);
98 k2 *= c1;
99 h2 ^= k2;
100
101 case 8:
102 k1 ^= ((u64)tail[7]) << 56;
103 case 7:
104 k1 ^= ((u64)tail[6]) << 48;
105 case 6:
106 k1 ^= ((u64)tail[5]) << 40;
107 case 5:
108 k1 ^= ((u64)tail[4]) << 32;
109 case 4:
110 k1 ^= ((u64)tail[3]) << 24;
111 case 3:
112 k1 ^= ((u64)tail[2]) << 16;
113 case 2:
114 k1 ^= ((u64)tail[1]) << 8;
115 case 1:
116 k1 ^= ((u64)tail[0]) << 0;
117 k1 *= c1;
118 k1 = _rotl64(k1, 31);
119 k1 *= c2;
120 h1 ^= k1;
121 };
122
123 // Finalization
124
125 h1 ^= len;
126 h2 ^= len;
127
128 h1 += h2;
129 h2 += h1;
130
131 h1 = fmix64(h1);
132 h2 = fmix64(h2);
133
134 h1 += h2;
135 h2 += h1;
136
137 ((u64*)out)[0] = h1;
138 ((u64*)out)[1] = h2;
139}
140
141} // namespace Common
diff --git a/src/common/hash.h b/src/common/hash.h
index ee2560dad..73c326980 100644
--- a/src/common/hash.h
+++ b/src/common/hash.h
@@ -5,12 +5,12 @@
5#pragma once 5#pragma once
6 6
7#include <cstddef> 7#include <cstddef>
8#include <cstring>
9#include "common/cityhash.h"
8#include "common/common_types.h" 10#include "common/common_types.h"
9 11
10namespace Common { 12namespace Common {
11 13
12void MurmurHash3_128(const void* key, size_t len, u32 seed, void* out);
13
14/** 14/**
15 * Computes a 64-bit hash over the specified block of data 15 * Computes a 64-bit hash over the specified block of data
16 * @param data Block of data to compute hash over 16 * @param data Block of data to compute hash over
@@ -18,9 +18,54 @@ void MurmurHash3_128(const void* key, size_t len, u32 seed, void* out);
18 * @returns 64-bit hash value that was computed over the data block 18 * @returns 64-bit hash value that was computed over the data block
19 */ 19 */
20static inline u64 ComputeHash64(const void* data, size_t len) { 20static inline u64 ComputeHash64(const void* data, size_t len) {
21 u64 res[2]; 21 return CityHash64(static_cast<const char*>(data), len);
22 MurmurHash3_128(data, len, 0, res); 22}
23 return res[0]; 23
24/**
25 * Computes a 64-bit hash of a struct. In addition to being trivially copyable, it is also critical
26 * that either the struct includes no padding, or that any padding is initialized to a known value
27 * by memsetting the struct to 0 before filling it in.
28 */
29template <typename T>
30static inline u64 ComputeStructHash64(const T& data) {
31 static_assert(std::is_trivially_copyable<T>(),
32 "Type passed to ComputeStructHash64 must be trivially copyable");
33 return ComputeHash64(&data, sizeof(data));
24} 34}
25 35
36/// A helper template that ensures the padding in a struct is initialized by memsetting to 0.
37template <typename T>
38struct HashableStruct {
39 // In addition to being trivially copyable, T must also have a trivial default constructor,
40 // because any member initialization would be overridden by memset
41 static_assert(std::is_trivial<T>(), "Type passed to HashableStruct must be trivial");
42 /*
43 * We use a union because "implicitly-defined copy/move constructor for a union X copies the
44 * object representation of X." and "implicitly-defined copy assignment operator for a union X
45 * copies the object representation (3.9) of X." = Bytewise copy instead of memberwise copy.
46 * This is important because the padding bytes are included in the hash and comparison between
47 * objects.
48 */
49 union {
50 T state;
51 };
52
53 HashableStruct() {
54 // Memset structure to zero padding bits, so that they will be deterministic when hashing
55 std::memset(&state, 0, sizeof(T));
56 }
57
58 bool operator==(const HashableStruct<T>& o) const {
59 return std::memcmp(&state, &o.state, sizeof(T)) == 0;
60 };
61
62 bool operator!=(const HashableStruct<T>& o) const {
63 return !(*this == o);
64 };
65
66 size_t Hash() const {
67 return Common::ComputeStructHash64(state);
68 }
69};
70
26} // namespace Common 71} // namespace Common