ATLAS Offline Software
Toggle main menu visibility
Loading...
Searching...
No Matches
Control
CxxUtils
Root
MurmurHash2.cxx
Go to the documentation of this file.
1
/*
2
* Public domain; see below.
3
*/
12
13
14
//-----------------------------------------------------------------------------
15
// MurmurHash2 was written by Austin Appleby, and is placed in the public
16
// domain. The author hereby disclaims copyright to this source code.
17
18
// Note - This code makes a few assumptions about how your machine behaves -
19
20
// 1. We can read a 4-byte value from any address without crashing
21
// 2. sizeof(int) == 4
22
23
// And it has a few limitations -
24
25
// 1. It will not work incrementally.
26
// 2. It will not produce the same results on little-endian and big-endian
27
// machines.
28
29
#include "
CxxUtils/MurmurHash2.h
"
30
31
//-----------------------------------------------------------------------------
32
// Platform-specific functions and macros
33
34
#define BIG_CONSTANT(x) (x##LLU)
35
36
//-----------------------------------------------------------------------------
37
38
39
namespace
CxxUtils
{
40
41
42
uint32_t
MurmurHash2
(
const
void
* key,
int
len, uint32_t seed )
43
{
44
// 'm' and 'r' are mixing constants generated offline.
45
// They're not really 'magic', they just happen to work well.
46
47
const
uint32_t m = 0x5bd1e995;
48
const
int
r
= 24;
49
50
// Initialize the hash to a 'random' value
51
52
uint32_t
h
= seed ^ len;
53
54
// Mix 4 bytes at a time into the hash
55
56
const
unsigned
char
* data = (
const
unsigned
char
*)key;
57
58
while
(len >= 4)
59
{
60
uint32_t k = *
reinterpret_cast<
const
uint32_t*
>
(data);
61
62
k *= m;
63
k ^= k >>
r
;
64
k *= m;
65
66
h
*= m;
67
h
^= k;
68
69
data += 4;
70
len -= 4;
71
}
72
73
// Handle the last few bytes of the input array
74
75
switch
(len)
76
{
77
case
3:
h
^= data[2] << 16;
78
// FALLTHROUGH
79
case
2:
h
^= data[1] << 8;
80
// FALLTHROUGH
81
case
1:
h
^= data[0];
82
h
*= m;
83
};
84
85
// Do a few final mixes of the hash to ensure the last few
86
// bytes are well-incorporated.
87
88
h
^=
h
>> 13;
89
h
*= m;
90
h
^=
h
>> 15;
91
92
return
h
;
93
}
94
95
//-----------------------------------------------------------------------------
96
// MurmurHash2, 64-bit versions, by Austin Appleby
97
98
// The same caveats as 32-bit MurmurHash2 apply here - beware of alignment
99
// and endian-ness issues if used across multiple platforms.
100
101
// 64-bit hash for 64-bit platforms
102
103
uint64_t
MurmurHash64A
(
const
void
* key,
int
len, uint64_t seed )
104
{
105
const
uint64_t m =
BIG_CONSTANT
(0xc6a4a7935bd1e995);
106
const
int
r
= 47;
107
108
uint64_t
h
= seed ^ (len * m);
109
110
const
uint64_t * data = (
const
uint64_t *)key;
111
const
uint64_t *
end
= data + (len/8);
112
113
while
(data !=
end
)
114
{
115
uint64_t k = *data++;
116
117
k *= m;
118
k ^= k >>
r
;
119
k *= m;
120
121
h
^= k;
122
h
*= m;
123
}
124
125
const
unsigned
char
* data2 =
reinterpret_cast<
const
unsigned
char
*
>
(data);
126
127
switch
(len & 7)
128
{
129
case
7:
h
^= uint64_t(data2[6]) << 48;
130
// FALLTHROUGH
131
case
6:
h
^= uint64_t(data2[5]) << 40;
132
// FALLTHROUGH
133
case
5:
h
^= uint64_t(data2[4]) << 32;
134
// FALLTHROUGH
135
case
4:
h
^= uint64_t(data2[3]) << 24;
136
// FALLTHROUGH
137
case
3:
h
^= uint64_t(data2[2]) << 16;
138
// FALLTHROUGH
139
case
2:
h
^= uint64_t(data2[1]) << 8;
140
// FALLTHROUGH
141
case
1:
h
^= uint64_t(data2[0]);
142
h
*= m;
143
};
144
145
h
^=
h
>>
r
;
146
h
*= m;
147
h
^=
h
>>
r
;
148
149
return
h
;
150
}
151
152
153
// 64-bit hash for 32-bit platforms
154
155
uint64_t
MurmurHash64B
(
const
void
* key,
int
len, uint64_t seed )
156
{
157
const
uint32_t m = 0x5bd1e995;
158
const
int
r
= 24;
159
160
uint32_t h1 = uint32_t(seed) ^ len;
161
uint32_t h2 = uint32_t(seed >> 32);
162
163
const
uint32_t * data = (
const
uint32_t *)key;
164
165
while
(len >= 8)
166
{
167
uint32_t k1 = *data++;
168
k1 *= m; k1 ^= k1 >>
r
; k1 *= m;
169
h1 *= m; h1 ^= k1;
170
len -= 4;
171
172
uint32_t k2 = *data++;
173
k2 *= m; k2 ^= k2 >>
r
; k2 *= m;
174
h2 *= m; h2 ^= k2;
175
len -= 4;
176
}
177
178
if
(len >= 4)
179
{
180
uint32_t k1 = *data++;
181
k1 *= m; k1 ^= k1 >>
r
; k1 *= m;
182
h1 *= m; h1 ^= k1;
183
len -= 4;
184
}
185
186
switch
(len)
187
{
188
case
3: h2 ^= (
reinterpret_cast<
unsigned
const
char
*
>
(data))[2] << 16;
189
// FALLTHROUGH
190
case
2: h2 ^= (
reinterpret_cast<
unsigned
const
char
*
>
(data))[1] << 8;
191
// FALLTHROUGH
192
case
1: h2 ^= (
reinterpret_cast<
unsigned
const
char
*
>
(data))[0];
193
h2 *= m;
194
};
195
196
h1 ^= h2 >> 18; h1 *= m;
197
h2 ^= h1 >> 22; h2 *= m;
198
h1 ^= h2 >> 17; h1 *= m;
199
h2 ^= h1 >> 19; h2 *= m;
200
201
uint64_t
h
= h1;
202
203
h
= (
h
<< 32) | h2;
204
205
return
h
;
206
}
207
208
//-----------------------------------------------------------------------------
209
// MurmurHash2A, by Austin Appleby
210
211
// This is a variant of MurmurHash2 modified to use the Merkle-Damgard
212
// construction. Bulk speed should be identical to Murmur2, small-key speed
213
// will be 10%-20% slower due to the added overhead at the end of the hash.
214
215
// This variant fixes a minor issue where null keys were more likely to
216
// collide with each other than expected, and also makes the function
217
// more amenable to incremental implementations.
218
219
220
uint32_t
MurmurHash2A
(
const
void
* key,
int
len, uint32_t seed )
221
{
222
const
uint32_t M = 0x5bd1e995;
223
const
int
R = 24;
224
uint32_t l = len;
225
226
const
unsigned
char
* data = (
const
unsigned
char
*)key;
227
228
uint32_t
h
= seed;
229
230
while
(len >= 4)
231
{
232
uint32_t k = *
reinterpret_cast<
const
uint32_t*
>
(data);
233
234
MurmurHash_mmix
(
h
,k);
235
236
data += 4;
237
len -= 4;
238
}
239
240
uint32_t t = 0;
241
242
switch
(len)
243
{
244
case
3: t ^= data[2] << 16;
245
// FALLTHROUGH
246
case
2: t ^= data[1] << 8;
247
// FALLTHROUGH
248
case
1: t ^= data[0];
249
};
250
251
MurmurHash_mmix
(
h
,t);
252
MurmurHash_mmix
(
h
,l);
253
254
h
^=
h
>> 13;
255
h
*= M;
256
h
^=
h
>> 15;
257
258
return
h
;
259
}
260
261
//-----------------------------------------------------------------------------
262
// MurmurHashNeutral2, by Austin Appleby
263
264
// Same as MurmurHash2, but endian- and alignment-neutral.
265
// Half the speed though, alas.
266
267
uint32_t
MurmurHashNeutral2
(
const
void
* key,
int
len, uint32_t seed )
268
{
269
const
uint32_t m = 0x5bd1e995;
270
const
int
r
= 24;
271
272
uint32_t
h
= seed ^ len;
273
274
const
unsigned
char
* data = (
const
unsigned
char
*)key;
275
276
while
(len >= 4)
277
{
278
uint32_t k;
279
280
k = data[0];
281
k |= data[1] << 8;
282
k |= data[2] << 16;
283
k |= data[3] << 24;
284
285
k *= m;
286
k ^= k >>
r
;
287
k *= m;
288
289
h
*= m;
290
h
^= k;
291
292
data += 4;
293
len -= 4;
294
}
295
296
switch
(len)
297
{
298
case
3:
h
^= data[2] << 16;
299
// FALLTHROUGH
300
case
2:
h
^= data[1] << 8;
301
// FALLTHROUGH
302
case
1:
h
^= data[0];
303
h
*= m;
304
};
305
306
h
^=
h
>> 13;
307
h
*= m;
308
h
^=
h
>> 15;
309
310
return
h
;
311
}
312
313
//-----------------------------------------------------------------------------
314
// MurmurHashAligned2, by Austin Appleby
315
316
// Same algorithm as MurmurHash2, but only does aligned reads - should be safer
317
// on certain platforms.
318
319
// Performance will be lower than MurmurHash2
320
321
#define MIX(h,k,m) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; }
322
323
324
uint32_t
MurmurHashAligned2
(
const
void
* key,
int
len, uint32_t seed )
325
{
326
const
uint32_t m = 0x5bd1e995;
327
const
int
r
= 24;
328
329
const
unsigned
char
* data = (
const
unsigned
char
*)key;
330
331
uint32_t
h
= seed ^ len;
332
333
int
align = (uint64_t)data & 3;
334
335
if
(align && (len >= 4))
336
{
337
// Pre-load the temp registers
338
339
uint32_t t = 0, d = 0;
340
341
switch
(align)
342
{
343
case
1: t |= data[2] << 16;
344
// FALLTHROUGH
345
case
2: t |= data[1] << 8;
346
// FALLTHROUGH
347
case
3: t |= data[0];
348
}
349
350
t <<= (8 * align);
351
352
data += 4-align;
353
len -= 4-align;
354
355
int
sl = 8 * (4-align);
356
int
sr = 8 * align;
357
358
// Mix
359
360
while
(len >= 4)
361
{
362
d = *
reinterpret_cast<
const
uint32_t *
>
(data);
363
t = (t >> sr) | (d << sl);
364
365
uint32_t k = t;
366
367
MIX
(
h
,k,m);
368
369
t = d;
370
371
data += 4;
372
len -= 4;
373
}
374
375
// Handle leftover data in temp registers
376
377
d = 0;
378
379
if
(len >= align)
380
{
381
switch
(align)
382
{
383
case
3: d |= data[2] << 16;
384
// FALLTHROUGH
385
case
2: d |= data[1] << 8;
386
// FALLTHROUGH
387
case
1: d |= data[0];
388
}
389
390
uint32_t k = (t >> sr) | (d << sl);
391
MIX
(
h
,k,m);
392
393
// At this point, we know that len < 4 and align > 0.
394
data += align;
395
len -= align;
396
// So here, we must have 0 >= len < 3.
397
398
//----------
399
// Handle tail bytes
400
401
switch
(len)
402
{
403
// can't happen --- see above.
404
//case 3: h ^= data[2] << 16;
405
// FALLTHROUGH
406
case
2:
h
^= data[1] << 8;
407
// FALLTHROUGH
408
case
1:
h
^= data[0];
409
h
*= m;
410
};
411
}
412
else
413
{
414
switch
(len)
415
{
416
// len cannot be 3, because align is at most 3.
417
//case 3: d |= data[2] << 16;
418
// FALLTHROUGH
419
case
2: d |= data[1] << 8;
420
// FALLTHROUGH
421
case
1: d |= data[0];
422
// FALLTHROUGH
423
case
0:
h
^= (t >> sr) | (d << sl);
424
h
*= m;
425
}
426
}
427
428
h
^=
h
>> 13;
429
h
*= m;
430
h
^=
h
>> 15;
431
432
return
h
;
433
}
434
else
435
{
436
while
(len >= 4)
437
{
438
uint32_t k = *
reinterpret_cast<
const
uint32_t *
>
(data);
439
440
MIX
(
h
,k,m);
441
442
data += 4;
443
len -= 4;
444
}
445
446
//----------
447
// Handle tail bytes
448
449
switch
(len)
450
{
451
case
3:
h
^= data[2] << 16;
452
// FALLTHROUGH
453
case
2:
h
^= data[1] << 8;
454
// FALLTHROUGH
455
case
1:
h
^= data[0];
456
h
*= m;
457
};
458
459
h
^=
h
>> 13;
460
h
*= m;
461
h
^=
h
>> 15;
462
463
return
h
;
464
}
465
}
466
467
//-----------------------------------------------------------------------------
468
469
470
}
// namespace CxxUtils
MIX
#define MIX(h, k, m)
Definition
MurmurHash2.cxx:321
BIG_CONSTANT
#define BIG_CONSTANT(x)
Definition
MurmurHash2.cxx:34
MurmurHash2.h
Implementation of MurmurHash2.
MurmurHash_mmix
#define MurmurHash_mmix(h, k)
Definition
MurmurHash2.h:29
h
Header file for AthHistogramAlgorithm.
r
int r
Definition
globals.cxx:22
CxxUtils
Definition
aligned_vector.h:29
CxxUtils::MurmurHash2A
uint32_t MurmurHash2A(const void *key, int len, uint32_t seed)
Definition
MurmurHash2.cxx:220
CxxUtils::MurmurHash2
uint32_t MurmurHash2(const void *key, int len, uint32_t seed)
Definition
MurmurHash2.cxx:42
CxxUtils::MurmurHash64B
uint64_t MurmurHash64B(const void *key, int len, uint64_t seed)
Definition
MurmurHash2.cxx:155
CxxUtils::MurmurHashAligned2
uint32_t MurmurHashAligned2(const void *key, int len, uint32_t seed)
Definition
MurmurHash2.cxx:324
CxxUtils::MurmurHashNeutral2
uint32_t MurmurHashNeutral2(const void *key, int len, uint32_t seed)
Definition
MurmurHash2.cxx:267
CxxUtils::end
const_iterator end() const
Return an end iterator.
CxxUtils::MurmurHash64A
uint64_t MurmurHash64A(const void *key, int len, uint64_t seed)
Definition
MurmurHash2.cxx:103
Generated on
for ATLAS Offline Software by
1.17.0