ATLAS Offline Software
MurmurHash2.cxx
Go to the documentation of this file.
1 /*
2  * Public domain; see below.
3  */
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 = *(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 = (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 ^= ((unsigned const char*)data)[2] << 16;
189  // FALLTHROUGH
190  case 2: h2 ^= ((unsigned const char*)data)[1] << 8;
191  // FALLTHROUGH
192  case 1: h2 ^= ((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 = *(uint32_t*)data;
233 
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 
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 = *(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 = *(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
beamspotman.r
def r
Definition: beamspotman.py:676
CxxUtils::MurmurHash64A
uint64_t MurmurHash64A(const void *key, int len, uint64_t seed)
Definition: MurmurHash2.cxx:103
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
python.SystemOfUnits.m
int m
Definition: SystemOfUnits.py:91
xAOD::uint32_t
setEventNumber uint32_t
Definition: EventInfo_v1.cxx:127
hist_file_dump.d
d
Definition: hist_file_dump.py:137
MurmurHash_mmix
#define MurmurHash_mmix(h, k)
Definition: MurmurHash2.h:29
CxxUtils::MurmurHashAligned2
uint32_t MurmurHashAligned2(const void *key, int len, uint32_t seed)
Definition: MurmurHash2.cxx:324
UploadAMITag.l
list l
Definition: UploadAMITag.larcaf.py:158
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
read_hist_ntuple.h1
h1
Definition: read_hist_ntuple.py:21
CxxUtils::MurmurHash2
uint32_t MurmurHash2(const void *key, int len, uint32_t seed)
Definition: MurmurHash2.cxx:42
RTTAlgmain.data2
data2
Definition: RTTAlgmain.py:54
CxxUtils::MurmurHash64B
uint64_t MurmurHash64B(const void *key, int len, uint64_t seed)
Definition: MurmurHash2.cxx:155
python.SystemOfUnits.sr
int sr
Definition: SystemOfUnits.py:113
CxxUtils::MurmurHashNeutral2
uint32_t MurmurHashNeutral2(const void *key, int len, uint32_t seed)
Definition: MurmurHash2.cxx:267
extractSporadic.h
list h
Definition: extractSporadic.py:97
CxxUtils
Definition: aligned_vector.h:29
xAOD::uint64_t
uint64_t
Definition: EventInfo_v1.cxx:123
BIG_CONSTANT
#define BIG_CONSTANT(x)
Definition: MurmurHash2.cxx:34
CxxUtils::end
auto end(range_with_at< T > &s)
Definition: range_with_at.h:68
CxxUtils::MurmurHash2A
uint32_t MurmurHash2A(const void *key, int len, uint32_t seed)
Definition: MurmurHash2.cxx:220
MIX
#define MIX(h, k, m)
Definition: MurmurHash2.cxx:321
h
MurmurHash2.h
Implementation of MurmurHash2.
fitman.k
k
Definition: fitman.py:528
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37