Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
hash-fct.C
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
33# include <time.h>
34# include <gsl/gsl_rng.h>
35# include <stdexcept>
36# include "hash-fct.H"
37
38# include <ah-errors.H>
39
40namespace Aleph
41{
42
43const unsigned Default_Hash_Seed = 52679987;
44
45static long tab[256];
46
47static bool init = false;
48
50{
52 gsl_rng_set(r, time(nullptr) % gsl_rng_max(r));
53
54 for (int i = 0; i < 256; ++i)
55 tab[i] = gsl_rng_get(r);
56
57 gsl_rng_free(r);
58
59 init = true;
60}
61
83size_t jsw_hash(const void * key, size_t len)
84{
86 << "jsw_hash: init_jsw() has not been called";
87
88 const unsigned char *p = (const unsigned char*) key;
89 size_t h = 16777551;
90
91 for (size_t i = 0; i < len; i++)
92 h = (h << 1 | h >> 31) ^ tab[p[i]];
93
94 return h;
95}
96
101size_t jsw_hash(const char * key)
102{
104 << "jsw_hash: init_jsw() has not been called";
105
106 const unsigned char * p = (const unsigned char*) key;
107 size_t h = 16777551;
108
109 while (*p)
110 h = (h << 1 | h >> 31) ^ tab[*p++];
111
112 return h;
113}
114
115
116/* The following is just a exact copy of functions implemented by Peter
117 Scott. They are at:
118
119 https://github.com/PeterScott/murmur3
120
121 They are a port of MurmurHash by Austin Appleby. See
122
123 http://en.wikipedia.org/wiki/MurmurHash
124
125 For more details
126*/
127
128
129#ifdef __GNUC__
130#define FORCE_INLINE __attribute__((always_inline)) inline
131#else
132#define FORCE_INLINE inline
133#endif
134
136{
137 return (x << r) | (x >> (32 - r));
138}
139
141{
142 return (x << r) | (x >> (64 - r));
143}
144
145#define ROTL32(x,y) rotl32(x,y)
146#define ROTL64(x,y) rotl64(x,y)
147
148#define BIG_CONSTANT(x) (x##LLU)
149
150//-----------------------------------------------------------------------------
151// Block read - if your platform needs to do endian-swapping or can only
152// handle aligned reads, do the conversion here
153
154#define getblock(p, i) (p[i])
155
156//-----------------------------------------------------------------------------
157// Finalization mix - force all bits of a hash block to avalanche
158
160{
161 h ^= h >> 16;
162 h *= 0x85ebca6b;
163 h ^= h >> 13;
164 h *= 0xc2b2ae35;
165 h ^= h >> 16;
166
167 return h;
168}
169
170//----------
171
173{
174 k ^= k >> 33;
175 k *= BIG_CONSTANT(0xff51afd7ed558ccd);
176 k ^= k >> 33;
177 k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);
178 k ^= k >> 33;
179
180 return k;
181}
182
183//-----------------------------------------------------------------------------
184
185void MurmurHash3_x86_32 ( const void * key, int len,
186 uint32_t seed, void * out )
187{
188 const uint8_t * data = (const uint8_t*)key;
189 const int nblocks = len / 4;
190 int i;
191
192 uint32_t h1 = seed;
193
194 uint32_t c1 = 0xcc9e2d51;
195 uint32_t c2 = 0x1b873593;
196
197 //----------
198 // body
199
200 const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
201
202 for(i = -nblocks; i; i++)
203 {
204 uint32_t k1 = getblock(blocks,i);
205
206 k1 *= c1;
207 k1 = ROTL32(k1,15);
208 k1 *= c2;
209
210 h1 ^= k1;
211 h1 = ROTL32(h1,13);
212 h1 = h1*5+0xe6546b64;
213 }
214
215 //----------
216 // tail
217
218 const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
219
220 uint32_t k1 = 0;
221
222 switch(len & 3)
223 {
224 case 3: k1 ^= tail[2] << 16; [[fallthrough]];
225 case 2: k1 ^= tail[1] << 8; [[fallthrough]];
226 case 1: k1 ^= tail[0];
227 k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
228 };
229
230 //----------
231 // finalization
232
233 h1 ^= len;
234
235 h1 = fmix32(h1);
236
237 *(uint32_t*)out = h1;
238}
239
240//-----------------------------------------------------------------------------
241
242void MurmurHash3_x86_128 ( const void * key, const int len,
243 uint32_t seed, void * out )
244{
245 const uint8_t * data = (const uint8_t*)key;
246 const int nblocks = len / 16;
247 int i;
248
249 uint32_t h1 = seed;
250 uint32_t h2 = seed;
251 uint32_t h3 = seed;
252 uint32_t h4 = seed;
253
254 uint32_t c1 = 0x239b961b;
255 uint32_t c2 = 0xab0e9789;
256 uint32_t c3 = 0x38b34ae5;
257 uint32_t c4 = 0xa1e38b93;
258
259 //----------
260 // body
261
262 const uint32_t * blocks = (const uint32_t *)(data + nblocks*16);
263
264 for(i = -nblocks; i; i++)
265 {
266 uint32_t k1 = getblock(blocks,i*4+0);
267 uint32_t k2 = getblock(blocks,i*4+1);
268 uint32_t k3 = getblock(blocks,i*4+2);
269 uint32_t k4 = getblock(blocks,i*4+3);
270
271 k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
272
273 h1 = ROTL32(h1,19); h1 += h2; h1 = h1*5+0x561ccd1b;
274
275 k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
276
277 h2 = ROTL32(h2,17); h2 += h3; h2 = h2*5+0x0bcaa747;
278
279 k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
280
281 h3 = ROTL32(h3,15); h3 += h4; h3 = h3*5+0x96cd1c35;
282
283 k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
284
285 h4 = ROTL32(h4,13); h4 += h1; h4 = h4*5+0x32ac3b17;
286 }
287
288 //----------
289 // tail
290
291 const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
292
293 uint32_t k1 = 0;
294 uint32_t k2 = 0;
295 uint32_t k3 = 0;
296 uint32_t k4 = 0;
297
298 switch(len & 15)
299 {
300 case 15: k4 ^= tail[14] << 16; [[fallthrough]];
301 case 14: k4 ^= tail[13] << 8; [[fallthrough]];
302 case 13: k4 ^= tail[12] << 0;
303 k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
304 [[fallthrough]];
305 case 12: k3 ^= tail[11] << 24; [[fallthrough]];
306 case 11: k3 ^= tail[10] << 16; [[fallthrough]];
307 case 10: k3 ^= tail[ 9] << 8; [[fallthrough]];
308 case 9: k3 ^= tail[ 8] << 0;
309 k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
310 [[fallthrough]];
311 case 8: k2 ^= tail[ 7] << 24; [[fallthrough]];
312 case 7: k2 ^= tail[ 6] << 16; [[fallthrough]];
313 case 6: k2 ^= tail[ 5] << 8; [[fallthrough]];
314 case 5: k2 ^= tail[ 4] << 0;
315 k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
316 [[fallthrough]];
317 case 4: k1 ^= tail[ 3] << 24; [[fallthrough]];
318 case 3: k1 ^= tail[ 2] << 16; [[fallthrough]];
319 case 2: k1 ^= tail[ 1] << 8; [[fallthrough]];
320 case 1: k1 ^= tail[ 0] << 0;
321 k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
322 };
323
324 //----------
325 // finalization
326
327 h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len;
328
329 h1 += h2; h1 += h3; h1 += h4;
330 h2 += h1; h3 += h1; h4 += h1;
331
332 h1 = fmix32(h1);
333 h2 = fmix32(h2);
334 h3 = fmix32(h3);
335 h4 = fmix32(h4);
336
337 h1 += h2; h1 += h3; h1 += h4;
338 h2 += h1; h3 += h1; h4 += h1;
339
340 ((uint32_t*)out)[0] = h1;
341 ((uint32_t*)out)[1] = h2;
342 ((uint32_t*)out)[2] = h3;
343 ((uint32_t*)out)[3] = h4;
344}
345
346//-----------------------------------------------------------------------------
347
348void MurmurHash3_x64_128 ( const void * key, const int len,
349 const uint32_t seed, void * out )
350{
351 const uint8_t * data = (const uint8_t*)key;
352 const int nblocks = len / 16;
353 int i;
354
355 uint64_t h1 = seed;
356 uint64_t h2 = seed;
357
358 uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5);
359 uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f);
360
361 //----------
362 // body
363
364 const uint64_t * blocks = (const uint64_t *)(data);
365
366 for(i = 0; i < nblocks; i++)
367 {
368 uint64_t k1 = getblock(blocks,i*2+0);
369 uint64_t k2 = getblock(blocks,i*2+1);
370
371 k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
372
373 h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;
374
375 k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
376
377 h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
378 }
379
380 //----------
381 // tail
382
383 const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
384
385 uint64_t k1 = 0;
386 uint64_t k2 = 0;
387
388 switch(len & 15)
389 {
390 case 15: k2 ^= (uint64_t)(tail[14]) << 48; [[fallthrough]];
391 case 14: k2 ^= (uint64_t)(tail[13]) << 40; [[fallthrough]];
392 case 13: k2 ^= (uint64_t)(tail[12]) << 32; [[fallthrough]];
393 case 12: k2 ^= (uint64_t)(tail[11]) << 24; [[fallthrough]];
394 case 11: k2 ^= (uint64_t)(tail[10]) << 16; [[fallthrough]];
395 case 10: k2 ^= (uint64_t)(tail[ 9]) << 8; [[fallthrough]];
396 case 9: k2 ^= (uint64_t)(tail[ 8]) << 0;
397 k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
398 [[fallthrough]];
399 case 8: k1 ^= (uint64_t)(tail[ 7]) << 56; [[fallthrough]];
400 case 7: k1 ^= (uint64_t)(tail[ 6]) << 48; [[fallthrough]];
401 case 6: k1 ^= (uint64_t)(tail[ 5]) << 40; [[fallthrough]];
402 case 5: k1 ^= (uint64_t)(tail[ 4]) << 32; [[fallthrough]];
403 case 4: k1 ^= (uint64_t)(tail[ 3]) << 24; [[fallthrough]];
404 case 3: k1 ^= (uint64_t)(tail[ 2]) << 16; [[fallthrough]];
405 case 2: k1 ^= (uint64_t)(tail[ 1]) << 8; [[fallthrough]];
406 case 1: k1 ^= (uint64_t)(tail[ 0]) << 0;
407 k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
408 };
409
410 //----------
411 // finalization
412
413 h1 ^= len; h2 ^= len;
414
415 h1 += h2;
416 h2 += h1;
417
418 h1 = fmix64(h1);
419 h2 = fmix64(h2);
420
421 h1 += h2;
422 h2 += h1;
423
424 ((uint64_t*)out)[0] = h1;
425 ((uint64_t*)out)[1] = h2;
426}
427
428} // end namespace Aleph
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:522
long double h
Definition btreepic.C:154
#define ROTL64(x, y)
Definition hash-fct.C:146
#define getblock(p, i)
Definition hash-fct.C:154
#define BIG_CONSTANT(x)
Definition hash-fct.C:148
#define ROTL32(x, y)
Definition hash-fct.C:145
#define FORCE_INLINE
Definition hash-fct.C:132
Collection of general-purpose hash functions.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
static uint32_t fmix32(uint32_t h)
Definition hash-fct.C:159
void MurmurHash3_x86_32(const void *key, int len, uint32_t seed, void *out)
Definition hash-fct.C:185
void MurmurHash3_x64_128(const void *key, const int len, const uint32_t seed, void *out)
Definition hash-fct.C:348
static uint32_t rotl32(uint32_t x, int8_t r)
Definition hash-fct.C:135
size_t jsw_hash(const void *key, size_t len)
JSW hash (Julienne Walker)
Definition hash-fct.C:83
static long tab[256]
Definition hash-fct.C:45
static uint64_t fmix64(uint64_t k)
Definition hash-fct.C:172
static uint64_t rotl64(uint64_t x, int8_t r)
Definition hash-fct.C:140
static bool init
Definition hash-fct.C:47
void MurmurHash3_x86_128(const void *key, const int len, uint32_t seed, void *out)
Definition hash-fct.C:242
const unsigned Default_Hash_Seed
Hash functions (implementaciones concretas).
Definition hash-fct.C:43
void init_jsw() noexcept
Definition hash-fct.C:49
DynList< T > maps(const C &c, Op op)
Classic map operation.