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)
34
2
{
35
3
// Helper from Murmur3 for combining two 32-bit values.
36
4
a *= c1;
@@ -41,7 +9,7 @@ static uint32 Mur(uint32 a, uint32 h)
41
9
return h * 5 + 0xe6546b64 ;
42
10
}
43
11
44
- static uint32 Hash32Len13to24 (const char * s, size_t len)
12
+ uint32 CityHash:: Hash32Len13to24 (const char * s, size_t len)
45
13
{
46
14
auto a = Fetch32 (s - 4 + (len >> 1 ));
47
15
auto b = Fetch32 (s + 4 );
@@ -54,7 +22,7 @@ static uint32 Hash32Len13to24(const char* s, size_t len)
54
22
return fmix (Mur (f, Mur (e, Mur (d, Mur (c, Mur (b, Mur (a, h)))))));
55
23
}
56
24
57
- static uint32 Hash32Len0to4 (const char * s, size_t len)
25
+ uint32 CityHash:: Hash32Len0to4 (const char * s, size_t len)
58
26
{
59
27
uint32 b = 0 ;
60
28
uint32 c = 9 ;
@@ -67,7 +35,7 @@ static uint32 Hash32Len0to4(const char* s, size_t len)
67
35
return fmix (Mur (b, Mur (static_cast <uint32>(len), c)));
68
36
}
69
37
70
- static uint32 Hash32Len5to12 (const char * s, size_t len)
38
+ uint32 CityHash:: Hash32Len5to12 (const char * s, size_t len)
71
39
{
72
40
uint32 a = static_cast <uint32>(len), b = a * 5 , c = 9 , d = b;
73
41
a += Fetch32 (s);
@@ -79,9 +47,18 @@ static uint32 Hash32Len5to12(const char* s, size_t len)
79
47
uint32 CityHash::hash32 (const char * s, size_t len)
80
48
{
81
49
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
+ }
85
62
86
63
// len > 24
87
64
auto h = static_cast <uint32>(len), g = c1 * h, f = g;
@@ -126,15 +103,17 @@ uint32 CityHash::hash32(const char* s, size_t len)
126
103
h = Rotate32 (h, 19 );
127
104
h = h * 5 + 0xe6546b64 ;
128
105
g ^= a4;
129
- g = bswap_32 (g) * 5 ;
106
+ g = ByteOrder::swapIfBigEndian (g) * 5 ;
130
107
h += a4 * 5 ;
131
- h = bswap_32 (h);
108
+ h = ByteOrder::swapIfBigEndian (h);
132
109
f += a0;
133
110
PERMUTE3 (f, h, g);
134
111
s += 20 ;
135
112
}
136
113
while (--iters != 0 );
137
114
115
+ #undef PERMUTE3
116
+
138
117
g = Rotate32 (g, 11 ) * c1;
139
118
g = Rotate32 (g, 17 ) * c1;
140
119
f = Rotate32 (f, 11 ) * c1;
@@ -145,10 +124,11 @@ uint32 CityHash::hash32(const char* s, size_t len)
145
124
h = Rotate32 (h + f, 19 );
146
125
h = h * 5 + 0xe6546b64 ;
147
126
h = Rotate32 (h, 17 ) * c1;
127
+
148
128
return h;
149
129
}
150
130
151
- static uint64 HashLen0to16 (const char * s, size_t len)
131
+ uint64 CityHash:: HashLen0to16 (const char * s, size_t len)
152
132
{
153
133
if (len >= 8 )
154
134
{
@@ -177,33 +157,30 @@ static uint64 HashLen0to16(const char* s, size_t len)
177
157
return k2;
178
158
}
179
159
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)
183
161
{
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);
190
169
}
191
170
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)
195
173
{
196
174
a += w;
197
175
b = Rotate (b + a + z, 21 );
198
- uint64 c = a;
176
+ auto c = a;
199
177
a += x;
200
178
a += y;
201
179
b += Rotate (a, 44 );
202
- return make_pair (a + z, b + c);
180
+ return CityHash::uint128 (a + z, b + c);
203
181
}
204
182
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)
207
184
{
208
185
return WeakHashLen32WithSeeds (Fetch64 (s),
209
186
Fetch64 (s + 8 ),
@@ -213,41 +190,36 @@ static pair<uint64, uint64> WeakHashLen32WithSeeds(const char* s, uint64 a, uint
213
190
b);
214
191
}
215
192
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)
218
194
{
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;
235
211
b = ShiftMix ((z + a) * mul + d + h) * mul;
236
212
return b + x;
237
213
}
238
214
239
- uint64 CityHash64 (const char * s, size_t len)
215
+ uint64 CityHash::hash64 (const char * s, size_t len)
240
216
{
241
217
if (len <= 32 )
242
218
{
243
219
if (len <= 16 )
244
- {
245
220
return HashLen0to16 (s, len);
246
- }
247
- else
248
- {
249
- return HashLen17to32 (s, len);
250
- }
221
+
222
+ return HashLen17to32 (s, len);
251
223
}
252
224
else if (len <= 64 )
253
225
{
@@ -256,11 +228,11 @@ uint64 CityHash64(const char* s, size_t len)
256
228
257
229
// For strings over 64 bytes we hash the end first, and then as we
258
230
// 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);
264
236
x = x * k1 + Fetch64 (s);
265
237
266
238
// 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)
294
266
return HashLen16 (hash64 (s, len) - seed0, seed1);
295
267
}
296
268
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)
300
270
{
301
- uint64 a = Uint128Low64 ( seed) ;
302
- uint64 b = Uint128High64 ( seed) ;
271
+ auto a = seed. first ;
272
+ auto b = seed. second ;
303
273
uint64 c = 0 ;
304
274
uint64 d = 0 ;
305
275
if (len <= 16 )
@@ -334,25 +304,23 @@ static uint128 CityMurmur(const char* s, size_t len, uint128 seed)
334
304
return uint128 (a ^ b, HashLen16 (b, a));
335
305
}
336
306
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)
338
308
{
339
309
if (len < 128 )
340
- {
341
310
return CityMurmur (s, len, seed);
342
- }
343
311
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 ;
349
317
auto z = len * k1;
350
318
v.first = Rotate (y ^ k1, 49 ) * k1 + Fetch64 (s);
351
319
v.second = Rotate (v.first , 42 ) * k1 + Fetch64 (s + 8 );
352
320
w.first = Rotate (y + z, 35 ) * k1 + x;
353
321
w.second = Rotate (x + Fetch64 (s + 88 ), 53 ) * k1;
354
322
355
- // This is the same inner loop as CityHash64 (), manually unrolled.
323
+ // This is the same inner loop as hash64 (), manually unrolled.
356
324
do
357
325
{
358
326
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)
405
373
HashLen16 (x + w.second , y + v.second ));
406
374
}
407
375
408
- uint128 CityHash::hash128 (const char * s, size_t len)
376
+ CityHash:: uint128 CityHash::hash128 (const char * s, size_t len)
409
377
{
410
378
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));
413
381
}
0 commit comments