Skip to content

Commit 1db313b

Browse files
committed
More work.
1 parent 14cb21e commit 1db313b

File tree

2 files changed

+131
-138
lines changed

2 files changed

+131
-138
lines changed

modules/squarepine_cryptography/hash/CityHash.cpp

Lines changed: 73 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,4 @@
1-
static uint64 UNALIGNED_LOAD64(const char* p)
2-
{
3-
uint64 result;
4-
memcpy(&result, p, sizeof(result));
5-
return result;
6-
}
7-
8-
static uint32 UNALIGNED_LOAD32(const char* p)
9-
{
10-
uint32 result;
11-
memcpy(&result, p, sizeof(result));
12-
return result;
13-
}
14-
15-
static uint64 Fetch64(const char* p)
16-
{
17-
return uint64_in_expected_order(UNALIGNED_LOAD64(p));
18-
}
19-
20-
static uint32 Fetch32(const char* p)
21-
{
22-
return uint32_in_expected_order(UNALIGNED_LOAD32(p));
23-
}
24-
25-
#undef PERMUTE3
26-
#define PERMUTE3(a, b, c) \
27-
do \
28-
{ \
29-
std::swap(a, b); \
30-
std::swap(a, c); \
31-
} while (0)
32-
33-
static uint32 Mur(uint32 a, uint32 h)
1+
uint32 CityHash::Mur(uint32 a, uint32 h)
342
{
353
// Helper from Murmur3 for combining two 32-bit values.
364
a *= c1;
@@ -41,7 +9,7 @@ static uint32 Mur(uint32 a, uint32 h)
419
return h * 5 + 0xe6546b64;
4210
}
4311

44-
static uint32 Hash32Len13to24(const char* s, size_t len)
12+
uint32 CityHash::Hash32Len13to24(const char* s, size_t len)
4513
{
4614
auto a = Fetch32(s - 4 + (len >> 1));
4715
auto b = Fetch32(s + 4);
@@ -54,7 +22,7 @@ static uint32 Hash32Len13to24(const char* s, size_t len)
5422
return fmix(Mur(f, Mur(e, Mur(d, Mur(c, Mur(b, Mur(a, h)))))));
5523
}
5624

57-
static uint32 Hash32Len0to4(const char* s, size_t len)
25+
uint32 CityHash::Hash32Len0to4(const char* s, size_t len)
5826
{
5927
uint32 b = 0;
6028
uint32 c = 9;
@@ -67,7 +35,7 @@ static uint32 Hash32Len0to4(const char* s, size_t len)
6735
return fmix(Mur(b, Mur(static_cast<uint32>(len), c)));
6836
}
6937

70-
static uint32 Hash32Len5to12(const char* s, size_t len)
38+
uint32 CityHash::Hash32Len5to12(const char* s, size_t len)
7139
{
7240
uint32 a = static_cast<uint32>(len), b = a * 5, c = 9, d = b;
7341
a += Fetch32(s);
@@ -79,9 +47,18 @@ static uint32 Hash32Len5to12(const char* s, size_t len)
7947
uint32 CityHash::hash32(const char* s, size_t len)
8048
{
8149
if (len <= 24)
82-
{
83-
return len <= 12 ? (len <= 4 ? Hash32Len0to4(s, len) : Hash32Len5to12(s, len)) : Hash32Len13to24(s, len);
84-
}
50+
return len <= 12
51+
? (len <= 4 ? Hash32Len0to4(s, len) : Hash32Len5to12(s, len))
52+
: Hash32Len13to24(s, len);
53+
54+
55+
#undef PERMUTE3
56+
#define PERMUTE3(a, b, c) \
57+
for (;;) \
58+
{ \
59+
std::swap(a, b); \
60+
std::swap(a, c); \
61+
}
8562

8663
// len > 24
8764
auto h = static_cast<uint32>(len), g = c1 * h, f = g;
@@ -126,15 +103,17 @@ uint32 CityHash::hash32(const char* s, size_t len)
126103
h = Rotate32(h, 19);
127104
h = h * 5 + 0xe6546b64;
128105
g ^= a4;
129-
g = bswap_32(g) * 5;
106+
g = ByteOrder::swapIfBigEndian(g) * 5;
130107
h += a4 * 5;
131-
h = bswap_32(h);
108+
h = ByteOrder::swapIfBigEndian(h);
132109
f += a0;
133110
PERMUTE3(f, h, g);
134111
s += 20;
135112
}
136113
while (--iters != 0);
137114

115+
#undef PERMUTE3
116+
138117
g = Rotate32(g, 11) * c1;
139118
g = Rotate32(g, 17) * c1;
140119
f = Rotate32(f, 11) * c1;
@@ -145,10 +124,11 @@ uint32 CityHash::hash32(const char* s, size_t len)
145124
h = Rotate32(h + f, 19);
146125
h = h * 5 + 0xe6546b64;
147126
h = Rotate32(h, 17) * c1;
127+
148128
return h;
149129
}
150130

151-
static uint64 HashLen0to16(const char* s, size_t len)
131+
uint64 CityHash::HashLen0to16(const char* s, size_t len)
152132
{
153133
if (len >= 8)
154134
{
@@ -177,33 +157,30 @@ static uint64 HashLen0to16(const char* s, size_t len)
177157
return k2;
178158
}
179159

180-
// This probably works well for 16-byte strings as well, but it may be overkill
181-
// in that case.
182-
static uint64 HashLen17to32(const char* s, size_t len)
160+
uint64 CityHash::HashLen17to32(const char* s, size_t len)
183161
{
184-
uint64 mul = k2 + len * 2;
185-
uint64 a = Fetch64(s) * k1;
186-
uint64 b = Fetch64(s + 8);
187-
uint64 c = Fetch64(s + len - 8) * mul;
188-
uint64 d = Fetch64(s + len - 16) * k2;
189-
return HashLen16(Rotate(a + b, 43) + Rotate(c, 30) + d, a + Rotate(b + k2, 18) + c, mul);
162+
auto mul = k2 + len * 2;
163+
auto a = Fetch64(s) * k1;
164+
auto b = Fetch64(s + 8);
165+
auto c = Fetch64(s + len - 8) * mul;
166+
auto d = Fetch64(s + len - 16) * k2;
167+
return HashLen16(Rotate(a + b, 43) + Rotate(c, 30) + d,
168+
a + Rotate(b + k2, 18) + c, mul);
190169
}
191170

192-
// Return a 16-byte hash for 48 bytes. Quick and dirty.
193-
// Callers do best to use "random-looking" values for a and b.
194-
static pair<uint64, uint64> WeakHashLen32WithSeeds(uint64 w, uint64 x, uint64 y, uint64 z, uint64 a, uint64 b)
171+
CityHash::uint128 CityHash::WeakHashLen32WithSeeds(uint64 w, uint64 x, uint64 y,
172+
uint64 z, uint64 a, uint64 b)
195173
{
196174
a += w;
197175
b = Rotate(b + a + z, 21);
198-
uint64 c = a;
176+
auto c = a;
199177
a += x;
200178
a += y;
201179
b += Rotate(a, 44);
202-
return make_pair(a + z, b + c);
180+
return CityHash::uint128(a + z, b + c);
203181
}
204182

205-
// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty.
206-
static pair<uint64, uint64> WeakHashLen32WithSeeds(const char* s, uint64 a, uint64 b)
183+
CityHash::uint128 CityHash::WeakHashLen32WithSeeds(const char* s, uint64 a, uint64 b)
207184
{
208185
return WeakHashLen32WithSeeds(Fetch64(s),
209186
Fetch64(s + 8),
@@ -213,41 +190,36 @@ static pair<uint64, uint64> WeakHashLen32WithSeeds(const char* s, uint64 a, uint
213190
b);
214191
}
215192

216-
// Return an 8-byte hash for 33 to 64 bytes.
217-
static uint64 HashLen33to64(const char* s, size_t len)
193+
uint64 CityHash::HashLen33to64(const char* s, size_t len)
218194
{
219-
uint64 mul = k2 + len * 2;
220-
uint64 a = Fetch64(s) * k2;
221-
uint64 b = Fetch64(s + 8);
222-
uint64 c = Fetch64(s + len - 24);
223-
uint64 d = Fetch64(s + len - 32);
224-
uint64 e = Fetch64(s + 16) * k2;
225-
uint64 f = Fetch64(s + 24) * 9;
226-
uint64 g = Fetch64(s + len - 8);
227-
uint64 h = Fetch64(s + len - 16) * mul;
228-
uint64 u = Rotate(a + g, 43) + (Rotate(b, 30) + c) * 9;
229-
uint64 v = ((a + g) ^ d) + f + 1;
230-
uint64 w = bswap_64((u + v) * mul) + h;
231-
uint64 x = Rotate(e + f, 42) + c;
232-
uint64 y = (bswap_64((v + w) * mul) + g) * mul;
233-
uint64 z = e + f + c;
234-
a = bswap_64((x + z) * mul + y) + b;
195+
auto mul = k2 + len * 2;
196+
auto a = Fetch64(s) * k2;
197+
auto b = Fetch64(s + 8);
198+
auto c = Fetch64(s + len - 24);
199+
auto d = Fetch64(s + len - 32);
200+
auto e = Fetch64(s + 16) * k2;
201+
auto f = Fetch64(s + 24) * 9;
202+
auto g = Fetch64(s + len - 8);
203+
auto h = Fetch64(s + len - 16) * mul;
204+
auto u = Rotate(a + g, 43) + (Rotate(b, 30) + c) * 9;
205+
auto v = ((a + g) ^ d) + f + 1;
206+
auto w = ByteOrder::swapIfBigEndian((u + v) * mul) + h;
207+
auto x = Rotate(e + f, 42) + c;
208+
auto y = (ByteOrder::swapIfBigEndian((v + w) * mul) + g) * mul;
209+
auto z = e + f + c;
210+
a = ByteOrder::swapIfBigEndian((x + z) * mul + y) + b;
235211
b = ShiftMix((z + a) * mul + d + h) * mul;
236212
return b + x;
237213
}
238214

239-
uint64 CityHash64(const char* s, size_t len)
215+
uint64 CityHash::hash64(const char* s, size_t len)
240216
{
241217
if (len <= 32)
242218
{
243219
if (len <= 16)
244-
{
245220
return HashLen0to16(s, len);
246-
}
247-
else
248-
{
249-
return HashLen17to32(s, len);
250-
}
221+
222+
return HashLen17to32(s, len);
251223
}
252224
else if (len <= 64)
253225
{
@@ -256,11 +228,11 @@ uint64 CityHash64(const char* s, size_t len)
256228

257229
// For strings over 64 bytes we hash the end first, and then as we
258230
// loop we keep 56 bytes of state: v, w, x, y, and z.
259-
uint64 x = Fetch64(s + len - 40);
260-
uint64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56);
261-
uint64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));
262-
pair<uint64, uint64> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
263-
pair<uint64, uint64> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
231+
auto x = Fetch64(s + len - 40);
232+
auto y = Fetch64(s + len - 16) + Fetch64(s + len - 56);
233+
auto z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));
234+
auto v = WeakHashLen32WithSeeds(s + len - 64, len, z);
235+
auto w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
264236
x = x * k1 + Fetch64(s);
265237

266238
// Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
@@ -294,12 +266,10 @@ uint64 CityHash::hash64(const char* s, size_t len, uint64 seed0, uint64 seed1)
294266
return HashLen16(hash64(s, len) - seed0, seed1);
295267
}
296268

297-
// A subroutine for CityHash128(). Returns a decent 128-bit hash for strings
298-
// of any length representable in signed long. Based on City and Murmur.
299-
static uint128 CityMurmur(const char* s, size_t len, uint128 seed)
269+
CityHash::uint128 CityHash::CityMurmur(const char* s, size_t len, uint128 seed)
300270
{
301-
uint64 a = Uint128Low64(seed);
302-
uint64 b = Uint128High64(seed);
271+
auto a = seed.first;
272+
auto b = seed.second;
303273
uint64 c = 0;
304274
uint64 d = 0;
305275
if (len <= 16)
@@ -334,25 +304,23 @@ static uint128 CityMurmur(const char* s, size_t len, uint128 seed)
334304
return uint128(a ^ b, HashLen16(b, a));
335305
}
336306

337-
uint128 CityHash::hash128(const char* s, size_t len, uint128 seed)
307+
CityHash::uint128 CityHash::hash128(const char* s, size_t len, uint128 seed)
338308
{
339309
if (len < 128)
340-
{
341310
return CityMurmur(s, len, seed);
342-
}
343311

344-
// We expect len >= 128 to be the common case. Keep 56 bytes of state:
345-
// v, w, x, y, and z.
346-
pair<uint64, uint64> v, w;
347-
auto x = Uint128Low64(seed);
348-
auto y = Uint128High64(seed);
312+
// We expect len >= 128 to be the common case.
313+
// Keep 56 bytes of state: v, w, x, y, and z.
314+
uint128 v, w;
315+
auto x = seed.first;
316+
auto y = seed.second;
349317
auto z = len * k1;
350318
v.first = Rotate(y ^ k1, 49) * k1 + Fetch64(s);
351319
v.second = Rotate(v.first, 42) * k1 + Fetch64(s + 8);
352320
w.first = Rotate(y + z, 35) * k1 + x;
353321
w.second = Rotate(x + Fetch64(s + 88), 53) * k1;
354322

355-
// This is the same inner loop as CityHash64(), manually unrolled.
323+
// This is the same inner loop as hash64(), manually unrolled.
356324
do
357325
{
358326
x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
@@ -405,9 +373,9 @@ uint128 CityHash::hash128(const char* s, size_t len, uint128 seed)
405373
HashLen16(x + w.second, y + v.second));
406374
}
407375

408-
uint128 CityHash::hash128(const char* s, size_t len)
376+
CityHash::uint128 CityHash::hash128(const char* s, size_t len)
409377
{
410378
return len >= 16
411-
? CityHash::hash128(s + 16, len - 16, uint128(Fetch64(s), Fetch64(s + 8) + k0))
412-
: CityHash::hash128(s, len, uint128(k0, k1));
379+
? hash128(s + 16, len - 16, uint128(Fetch64(s), Fetch64(s + 8) + k0))
380+
: hash128(s, len, uint128(k0, k1));
413381
}

0 commit comments

Comments
 (0)