COMBINATORIAL_BLAS  1.6
hash.cpp
Go to the documentation of this file.
1 #include <stdint.h>
2 #include <cstring>
3 #include "CombBLAS/hash.hpp"
4 
5 namespace combblas {
6 
7 uint64_t inline _rotl64(uint64_t value, int8_t amount) {
8  return ((value) << (amount)) | ((value) >> (64 - (amount)));
9 }
10 
11 uint32_t SuperFastHash (const char * data, int len) {
12 uint32_t hash = len, tmp;
13 int rem;
14 
15  if (len <= 0 || data == NULL) return 0;
16 
17  rem = len & 3;
18  len >>= 2;
19 
20  /* Main loop */
21  for (;len > 0; len--) {
22  hash += get16bits (data);
23  tmp = (get16bits (data+2) << 11) ^ hash;
24  hash = (hash << 16) ^ tmp;
25  data += 2*sizeof (uint16_t);
26  hash += hash >> 11;
27  }
28 
29  /* Handle end cases */
30  switch (rem) {
31  case 3: hash += get16bits (data);
32  hash ^= hash << 16;
33  hash ^= data[sizeof (uint16_t)] << 18;
34  hash += hash >> 11;
35  break;
36  case 2: hash += get16bits (data);
37  hash ^= hash << 11;
38  hash += hash >> 17;
39  break;
40  case 1: hash += *data;
41  hash ^= hash << 10;
42  hash += hash >> 1;
43  }
44 
45  /* Force "avalanching" of final 127 bits */
46  hash ^= hash << 3;
47  hash += hash >> 5;
48  hash ^= hash << 4;
49  hash += hash >> 17;
50  hash ^= hash << 25;
51  hash += hash >> 6;
52 
53  return hash;
54 }
55 
56 
57 
58 
59 //-----------------------------------------------------------------------------
60 // Block read - if your platform needs to do endian-swapping or can only
61 // handle aligned reads, do the conversion here
62 
63 inline uint64_t getblock ( const uint64_t * p, int i )
64 {
65  return p[i];
66 }
67 
68 //----------
69 // Block mix - combine the key bits with the hash bits and scramble everything
70 
71 inline void bmix64 ( uint64_t & h1, uint64_t & h2, uint64_t & k1, uint64_t & k2, uint64_t & c1, uint64_t & c2 )
72 {
73  k1 *= c1;
74  k1 = _rotl64(k1,23);
75  k1 *= c2;
76  h1 ^= k1;
77  h1 += h2;
78 
79  h2 = _rotl64(h2,41);
80 
81  k2 *= c2;
82  k2 = _rotl64(k2,23);
83  k2 *= c1;
84  h2 ^= k2;
85  h2 += h1;
86 
87  h1 = h1*3+0x52dce729;
88  h2 = h2*3+0x38495ab5;
89 
90  c1 = c1*5+0x7b7d159c;
91  c2 = c2*5+0x6bce6396;
92 }
93 
94 //----------
95 // Finalization mix - avalanches all bits to within 0.05% bias
96 
97 inline uint64_t fmix64 ( uint64_t k )
98 {
99  k ^= k >> 33;
100  k *= 0xff51afd7ed558ccd;
101  k ^= k >> 33;
102  k *= 0xc4ceb9fe1a85ec53;
103  k ^= k >> 33;
104 
105  return k;
106 }
107 
108 void MurmurHash3_x64_128 ( const void * key, const int len, const uint32_t seed, void * out )
109 {
110  const uint8_t * data = (const uint8_t*)key;
111  const int nblocks = len / 16;
112 
113  uint64_t h1 = 0x9368e53c2f6af274 ^ seed;
114  uint64_t h2 = 0x586dcd208f7cd3fd ^ seed;
115 
116  uint64_t c1 = 0x87c37b91114253d5;
117  uint64_t c2 = 0x4cf5ad432745937f;
118 
119  //----------
120  // body
121 
122  const uint64_t * blocks = (const uint64_t *)(data);
123 
124  for(int i = 0; i < nblocks; i++)
125  {
126  uint64_t k1 = getblock(blocks,i*2+0);
127  uint64_t k2 = getblock(blocks,i*2+1);
128 
129  bmix64(h1,h2,k1,k2,c1,c2);
130  }
131 
132  //----------
133  // tail
134 
135  const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
136 
137  uint64_t k1 = 0;
138  uint64_t k2 = 0;
139 
140  switch(len & 15)
141  {
142  case 15: k2 ^= uint64_t(tail[14]) << 48;
143  case 14: k2 ^= uint64_t(tail[13]) << 40;
144  case 13: k2 ^= uint64_t(tail[12]) << 32;
145  case 12: k2 ^= uint64_t(tail[11]) << 24;
146  case 11: k2 ^= uint64_t(tail[10]) << 16;
147  case 10: k2 ^= uint64_t(tail[ 9]) << 8;
148  case 9: k2 ^= uint64_t(tail[ 8]) << 0;
149 
150  case 8: k1 ^= uint64_t(tail[ 7]) << 56;
151  case 7: k1 ^= uint64_t(tail[ 6]) << 48;
152  case 6: k1 ^= uint64_t(tail[ 5]) << 40;
153  case 5: k1 ^= uint64_t(tail[ 4]) << 32;
154  case 4: k1 ^= uint64_t(tail[ 3]) << 24;
155  case 3: k1 ^= uint64_t(tail[ 2]) << 16;
156  case 2: k1 ^= uint64_t(tail[ 1]) << 8;
157  case 1: k1 ^= uint64_t(tail[ 0]) << 0;
158  bmix64(h1,h2,k1,k2,c1,c2);
159  };
160 
161  //----------
162  // finalization
163 
164  h2 ^= len;
165 
166  h1 += h2;
167  h2 += h1;
168 
169  h1 = fmix64(h1);
170  h2 = fmix64(h2);
171 
172  h1 += h2;
173  h2 += h1;
174 
175  ((uint64_t*)out)[0] = h1;
176  ((uint64_t*)out)[1] = h2;
177 }
178 
179 //-----------------------------------------------------------------------------
180 // If we need a smaller hash value, it's faster to just use a portion of the
181 // 128-bit hash
182 
183 void MurmurHash3_x64_32 ( const void * key, int len, uint32_t seed, void * out )
184 {
185  uint32_t temp[4];
186 
187  MurmurHash3_x64_128(key,len,seed,temp);
188 
189  *(uint32_t*)out = temp[0];
190 }
191 
192 //----------
193 
194 void MurmurHash3_x64_64 ( const void * key, int len, uint32_t seed, void * out )
195 {
196  uint64_t temp[2];
197 
198  MurmurHash3_x64_128(key,len,seed,temp);
199 
200  *(uint64_t*)out = temp[0];
201 }
202 
203 //-----------------------------------------------------------------------------
204 
205 }
void bmix64(uint64_t &h1, uint64_t &h2, uint64_t &k1, uint64_t &k2, uint64_t &c1, uint64_t &c2)
Definition: hash.cpp:71
uint32_t SuperFastHash(const char *data, int len)
Definition: hash.cpp:11
uint64_t getblock(const uint64_t *p, int i)
Definition: hash.cpp:63
uint64_t fmix64(uint64_t k)
Definition: hash.cpp:97
void MurmurHash3_x64_32(const void *key, int len, uint32_t seed, void *out)
Definition: hash.cpp:183
void MurmurHash3_x64_128(const void *key, const int len, const uint32_t seed, void *out)
Definition: hash.cpp:108
Definition: CCGrid.h:4
uint64_t _rotl64(uint64_t value, int8_t amount)
Definition: hash.cpp:7
void MurmurHash3_x64_64(const void *key, int len, uint32_t seed, void *out)
Definition: hash.cpp:194
unsigned int hash(unsigned int a)
Definition: utils.h:79