COMBINATORIAL_BLAS 1.6
 
Loading...
Searching...
No Matches
hash.cpp
Go to the documentation of this file.
1#include <stdint.h>
2#include <cstring>
3#include "CombBLAS/hash.hpp"
4
5namespace combblas {
6
8 return ((value) << (amount)) | ((value) >> (64 - (amount)));
9}
10
11uint32_t SuperFastHash (const char * data, int len) {
12uint32_t hash = len, tmp;
13int 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
63inline 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
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
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
108void 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
183void 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
194void 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}
uint64_t getblock(const uint64_t *p, int i)
Definition hash.cpp:63
void MurmurHash3_x64_32(const void *key, int len, uint32_t seed, void *out)
Definition hash.cpp:183
void MurmurHash3_x64_64(const void *key, int len, uint32_t seed, void *out)
Definition hash.cpp:194
uint64_t fmix64(uint64_t k)
Definition hash.cpp:97
void MurmurHash3_x64_128(const void *key, const int len, const uint32_t seed, void *out)
Definition hash.cpp:108
uint32_t SuperFastHash(const char *data, int len)
Definition hash.cpp:11
void bmix64(uint64_t &h1, uint64_t &h2, uint64_t &k1, uint64_t &k2, uint64_t &c1, uint64_t &c2)
Definition hash.cpp:71
uint64_t _rotl64(uint64_t value, int8_t amount)
Definition hash.cpp:7
unsigned short uint16_t
Definition stdint.h:79
unsigned int uint32_t
Definition stdint.h:80
unsigned __int64 uint64_t
Definition stdint.h:90
signed char int8_t
Definition stdint.h:75