ZXC 0.15.0
High-performance asymmetric lossless compression library
Loading...
Searching...
No Matches
rapidhash.h
1/* SPDX-License-Identifier: MIT */
2/*
3 * rapidhash V3 - Very fast, high quality, platform-independent hashing algorithm.
4 *
5 * Based on 'wyhash', by Wang Yi <godspeed_china@yeah.net>
6 *
7 * Copyright (C) 2025 Nicolas De Carli
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in all
17 * copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 *
27 * You can contact the author at:
28 * - rapidhash source repository: https://github.com/Nicoshev/rapidhash
29 */
30
31 #pragma once
32
33/*
34 * Includes.
35 */
36 #include <stdint.h>
37 #include <string.h>
38 #if defined(_MSC_VER)
39 # include <intrin.h>
40 # if defined(_M_X64) && !defined(_M_ARM64EC)
41 # pragma intrinsic(_umul128)
42 # endif
43 #endif
44
45 /*
46 * C/C++ macros.
47 */
48
49 #ifdef _MSC_VER
50 # define RAPIDHASH_ALWAYS_INLINE __forceinline
51 #elif defined(__GNUC__)
52 # define RAPIDHASH_ALWAYS_INLINE inline __attribute__((__always_inline__))
53 #else
54 # define RAPIDHASH_ALWAYS_INLINE inline
55 #endif
56
57 #ifdef __cplusplus
58 # define RAPIDHASH_NOEXCEPT noexcept
59 # define RAPIDHASH_CONSTEXPR constexpr
60 # ifndef RAPIDHASH_INLINE
61 # define RAPIDHASH_INLINE RAPIDHASH_ALWAYS_INLINE
62 # endif
63 # if __cplusplus >= 201402L && !defined(_MSC_VER)
64 # define RAPIDHASH_INLINE_CONSTEXPR RAPIDHASH_ALWAYS_INLINE constexpr
65 # else
66 # define RAPIDHASH_INLINE_CONSTEXPR RAPIDHASH_ALWAYS_INLINE
67 # endif
68 #else
69 # define RAPIDHASH_NOEXCEPT
70 # define RAPIDHASH_CONSTEXPR static const
71 # ifndef RAPIDHASH_INLINE
72 # define RAPIDHASH_INLINE static RAPIDHASH_ALWAYS_INLINE
73 # endif
74 # define RAPIDHASH_INLINE_CONSTEXPR RAPIDHASH_INLINE
75 #endif
76
77 /*
78 * Unrolled macro.
79 * Improves large input speed, but increases code size and worsens small input speed.
80 *
81 * RAPIDHASH_COMPACT: Normal behavior.
82 * RAPIDHASH_UNROLLED:
83 *
84 */
85 #ifndef RAPIDHASH_UNROLLED
86 # define RAPIDHASH_COMPACT
87 #elif defined(RAPIDHASH_COMPACT)
88 # error "cannot define RAPIDHASH_COMPACT and RAPIDHASH_UNROLLED simultaneously."
89 #endif
90
91 /*
92 * Protection macro, alters behaviour of rapid_mum multiplication function.
93 *
94 * RAPIDHASH_FAST: Normal behavior, max speed.
95 * RAPIDHASH_PROTECTED: Extra protection against entropy loss.
96 */
97 #ifndef RAPIDHASH_PROTECTED
98 # define RAPIDHASH_FAST
99 #elif defined(RAPIDHASH_FAST)
100 # error "cannot define RAPIDHASH_PROTECTED and RAPIDHASH_FAST simultaneously."
101 #endif
102
103 /*
104 * Likely and unlikely macros.
105 */
106 #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
107 # define _likely_(x) __builtin_expect(x,1)
108 # define _unlikely_(x) __builtin_expect(x,0)
109 #else
110 # define _likely_(x) (x)
111 # define _unlikely_(x) (x)
112 #endif
113
114 /*
115 * Endianness macros.
116 */
117 #ifndef RAPIDHASH_LITTLE_ENDIAN
118 # if defined(_WIN32) || defined(__LITTLE_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
119 # define RAPIDHASH_LITTLE_ENDIAN
120 # elif defined(__BIG_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
121 # define RAPIDHASH_BIG_ENDIAN
122 # else
123 # warning "could not determine endianness! Falling back to little endian."
124 # define RAPIDHASH_LITTLE_ENDIAN
125 # endif
126 #endif
127
128 /*
129 * Default secret parameters.
130 */
131 RAPIDHASH_CONSTEXPR uint64_t rapid_secret[8] = {
132 0x2d358dccaa6c78a5ull,
133 0x8bb84b93962eacc9ull,
134 0x4b33a62ed433d4a3ull,
135 0x4d5a2da51de1aa47ull,
136 0xa0761d6478bd642full,
137 0xe7037ed1a0b428dbull,
138 0x90ed1765281c388cull,
139 0xaaaaaaaaaaaaaaaaull};
140
141 /*
142 * 64*64 -> 128bit multiply function.
143 *
144 * @param A Address of 64-bit number.
145 * @param B Address of 64-bit number.
146 *
147 * Calculates 128-bit C = *A * *B.
148 *
149 * When RAPIDHASH_FAST is defined:
150 * Overwrites A contents with C's low 64 bits.
151 * Overwrites B contents with C's high 64 bits.
152 *
153 * When RAPIDHASH_PROTECTED is defined:
154 * Xors and overwrites A contents with C's low 64 bits.
155 * Xors and overwrites B contents with C's high 64 bits.
156 */
157 RAPIDHASH_INLINE_CONSTEXPR void rapid_mum(uint64_t *A, uint64_t *B) RAPIDHASH_NOEXCEPT {
158 #if defined(__SIZEOF_INT128__)
159 __uint128_t r=*A; r*=*B;
160 #ifdef RAPIDHASH_PROTECTED
161 *A^=(uint64_t)r; *B^=(uint64_t)(r>>64);
162 #else
163 *A=(uint64_t)r; *B=(uint64_t)(r>>64);
164 #endif
165 #elif defined(_MSC_VER) && (defined(_WIN64) || defined(_M_HYBRID_CHPE_ARM64))
166 #if defined(_M_X64)
167 #ifdef RAPIDHASH_PROTECTED
168 uint64_t a, b;
169 a=_umul128(*A,*B,&b);
170 *A^=a; *B^=b;
171 #else
172 *A=_umul128(*A,*B,B);
173 #endif
174 #else
175 #ifdef RAPIDHASH_PROTECTED
176 uint64_t a, b;
177 b = __umulh(*A, *B);
178 a = *A * *B;
179 *A^=a; *B^=b;
180 #else
181 uint64_t c = __umulh(*A, *B);
182 *A = *A * *B;
183 *B = c;
184 #endif
185 #endif
186 #else
187 uint64_t ha=*A>>32, hb=*B>>32, la=(uint32_t)*A, lb=(uint32_t)*B;
188 uint64_t rh=ha*hb, rm0=ha*lb, rm1=hb*la, rl=la*lb, t=rl+(rm0<<32), c=t<rl;
189 uint64_t lo=t+(rm1<<32);
190 c+=lo<t;
191 uint64_t hi=rh+(rm0>>32)+(rm1>>32)+c;
192 #ifdef RAPIDHASH_PROTECTED
193 *A^=lo; *B^=hi;
194 #else
195 *A=lo; *B=hi;
196 #endif
197 #endif
198 }
199
200 /*
201 * Multiply and xor mix function.
202 *
203 * @param A 64-bit number.
204 * @param B 64-bit number.
205 *
206 * Calculates 128-bit C = A * B.
207 * Returns 64-bit xor between high and low 64 bits of C.
208 */
209 RAPIDHASH_INLINE_CONSTEXPR uint64_t rapid_mix(uint64_t A, uint64_t B) RAPIDHASH_NOEXCEPT { rapid_mum(&A,&B); return A^B; }
210
211 /*
212 * Read functions.
213 */
214 #ifdef RAPIDHASH_LITTLE_ENDIAN
215 RAPIDHASH_INLINE uint64_t rapid_read64(const uint8_t *p) RAPIDHASH_NOEXCEPT { uint64_t v; memcpy(&v, p, sizeof(uint64_t)); return v;}
216 RAPIDHASH_INLINE uint64_t rapid_read32(const uint8_t *p) RAPIDHASH_NOEXCEPT { uint32_t v; memcpy(&v, p, sizeof(uint32_t)); return v;}
217 #elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
218 RAPIDHASH_INLINE uint64_t rapid_read64(const uint8_t *p) RAPIDHASH_NOEXCEPT { uint64_t v; memcpy(&v, p, sizeof(uint64_t)); return __builtin_bswap64(v);}
219 RAPIDHASH_INLINE uint64_t rapid_read32(const uint8_t *p) RAPIDHASH_NOEXCEPT { uint32_t v; memcpy(&v, p, sizeof(uint32_t)); return __builtin_bswap32(v);}
220 #elif defined(_MSC_VER)
221 RAPIDHASH_INLINE uint64_t rapid_read64(const uint8_t *p) RAPIDHASH_NOEXCEPT { uint64_t v; memcpy(&v, p, sizeof(uint64_t)); return _byteswap_uint64(v);}
222 RAPIDHASH_INLINE uint64_t rapid_read32(const uint8_t *p) RAPIDHASH_NOEXCEPT { uint32_t v; memcpy(&v, p, sizeof(uint32_t)); return _byteswap_ulong(v);}
223 #else
224 RAPIDHASH_INLINE uint64_t rapid_read64(const uint8_t *p) RAPIDHASH_NOEXCEPT {
225 uint64_t v; memcpy(&v, p, 8);
226 return (((v >> 56) & 0xff)| ((v >> 40) & 0xff00)| ((v >> 24) & 0xff0000)| ((v >> 8) & 0xff000000)| ((v << 8) & 0xff00000000)| ((v << 24) & 0xff0000000000)| ((v << 40) & 0xff000000000000)| ((v << 56) & 0xff00000000000000));
227 }
228 RAPIDHASH_INLINE uint64_t rapid_read32(const uint8_t *p) RAPIDHASH_NOEXCEPT {
229 uint32_t v; memcpy(&v, p, 4);
230 return (((v >> 24) & 0xff)| ((v >> 8) & 0xff00)| ((v << 8) & 0xff0000)| ((v << 24) & 0xff000000));
231 }
232 #endif
233
234 /*
235 * rapidhash main function.
236 *
237 * @param key Buffer to be hashed.
238 * @param len @key length, in bytes.
239 * @param seed 64-bit seed used to alter the hash result predictably.
240 * @param secret Triplet of 64-bit secrets used to alter hash result predictably.
241 *
242 * Returns a 64-bit hash.
243 */
244RAPIDHASH_INLINE_CONSTEXPR uint64_t rapidhash_internal(const void *key, size_t len, uint64_t seed, const uint64_t* secret) RAPIDHASH_NOEXCEPT {
245 const uint8_t *p=(const uint8_t *)key;
246 seed ^= rapid_mix(seed ^ secret[2], secret[1]);
247 uint64_t a=0, b=0;
248 size_t i = len;
249 if (_likely_(len <= 16)) {
250 if (len >= 4) {
251 seed ^= len;
252 if (len >= 8) {
253 const uint8_t* plast = p + len - 8;
254 a = rapid_read64(p);
255 b = rapid_read64(plast);
256 } else {
257 const uint8_t* plast = p + len - 4;
258 a = rapid_read32(p);
259 b = rapid_read32(plast);
260 }
261 } else if (len > 0) {
262 a = (((uint64_t)p[0])<<45)|p[len-1];
263 b = p[len>>1];
264 } else
265 a = b = 0;
266 } else {
267 if (len > 112) {
268 uint64_t see1 = seed, see2 = seed;
269 uint64_t see3 = seed, see4 = seed;
270 uint64_t see5 = seed, see6 = seed;
271#ifdef RAPIDHASH_COMPACT
272 do {
273 seed = rapid_mix(rapid_read64(p) ^ secret[0], rapid_read64(p + 8) ^ seed);
274 see1 = rapid_mix(rapid_read64(p + 16) ^ secret[1], rapid_read64(p + 24) ^ see1);
275 see2 = rapid_mix(rapid_read64(p + 32) ^ secret[2], rapid_read64(p + 40) ^ see2);
276 see3 = rapid_mix(rapid_read64(p + 48) ^ secret[3], rapid_read64(p + 56) ^ see3);
277 see4 = rapid_mix(rapid_read64(p + 64) ^ secret[4], rapid_read64(p + 72) ^ see4);
278 see5 = rapid_mix(rapid_read64(p + 80) ^ secret[5], rapid_read64(p + 88) ^ see5);
279 see6 = rapid_mix(rapid_read64(p + 96) ^ secret[6], rapid_read64(p + 104) ^ see6);
280 p += 112;
281 i -= 112;
282 } while(i > 112);
283#else
284 while (i > 224) {
285 seed = rapid_mix(rapid_read64(p) ^ secret[0], rapid_read64(p + 8) ^ seed);
286 see1 = rapid_mix(rapid_read64(p + 16) ^ secret[1], rapid_read64(p + 24) ^ see1);
287 see2 = rapid_mix(rapid_read64(p + 32) ^ secret[2], rapid_read64(p + 40) ^ see2);
288 see3 = rapid_mix(rapid_read64(p + 48) ^ secret[3], rapid_read64(p + 56) ^ see3);
289 see4 = rapid_mix(rapid_read64(p + 64) ^ secret[4], rapid_read64(p + 72) ^ see4);
290 see5 = rapid_mix(rapid_read64(p + 80) ^ secret[5], rapid_read64(p + 88) ^ see5);
291 see6 = rapid_mix(rapid_read64(p + 96) ^ secret[6], rapid_read64(p + 104) ^ see6);
292 seed = rapid_mix(rapid_read64(p + 112) ^ secret[0], rapid_read64(p + 120) ^ seed);
293 see1 = rapid_mix(rapid_read64(p + 128) ^ secret[1], rapid_read64(p + 136) ^ see1);
294 see2 = rapid_mix(rapid_read64(p + 144) ^ secret[2], rapid_read64(p + 152) ^ see2);
295 see3 = rapid_mix(rapid_read64(p + 160) ^ secret[3], rapid_read64(p + 168) ^ see3);
296 see4 = rapid_mix(rapid_read64(p + 176) ^ secret[4], rapid_read64(p + 184) ^ see4);
297 see5 = rapid_mix(rapid_read64(p + 192) ^ secret[5], rapid_read64(p + 200) ^ see5);
298 see6 = rapid_mix(rapid_read64(p + 208) ^ secret[6], rapid_read64(p + 216) ^ see6);
299 p += 224;
300 i -= 224;
301 }
302 if (i > 112) {
303 seed = rapid_mix(rapid_read64(p) ^ secret[0], rapid_read64(p + 8) ^ seed);
304 see1 = rapid_mix(rapid_read64(p + 16) ^ secret[1], rapid_read64(p + 24) ^ see1);
305 see2 = rapid_mix(rapid_read64(p + 32) ^ secret[2], rapid_read64(p + 40) ^ see2);
306 see3 = rapid_mix(rapid_read64(p + 48) ^ secret[3], rapid_read64(p + 56) ^ see3);
307 see4 = rapid_mix(rapid_read64(p + 64) ^ secret[4], rapid_read64(p + 72) ^ see4);
308 see5 = rapid_mix(rapid_read64(p + 80) ^ secret[5], rapid_read64(p + 88) ^ see5);
309 see6 = rapid_mix(rapid_read64(p + 96) ^ secret[6], rapid_read64(p + 104) ^ see6);
310 p += 112;
311 i -= 112;
312 }
313#endif
314 seed ^= see1;
315 see2 ^= see3;
316 see4 ^= see5;
317 seed ^= see6;
318 see2 ^= see4;
319 seed ^= see2;
320 }
321 if (i > 16) {
322 seed = rapid_mix(rapid_read64(p) ^ secret[2], rapid_read64(p + 8) ^ seed);
323 if (i > 32) {
324 seed = rapid_mix(rapid_read64(p + 16) ^ secret[2], rapid_read64(p + 24) ^ seed);
325 if (i > 48) {
326 seed = rapid_mix(rapid_read64(p + 32) ^ secret[1], rapid_read64(p + 40) ^ seed);
327 if (i > 64) {
328 seed = rapid_mix(rapid_read64(p + 48) ^ secret[1], rapid_read64(p + 56) ^ seed);
329 if (i > 80) {
330 seed = rapid_mix(rapid_read64(p + 64) ^ secret[2], rapid_read64(p + 72) ^ seed);
331 if (i > 96) {
332 seed = rapid_mix(rapid_read64(p + 80) ^ secret[1], rapid_read64(p + 88) ^ seed);
333 }
334 }
335 }
336 }
337 }
338 }
339 a=rapid_read64(p+i-16) ^ i; b=rapid_read64(p+i-8);
340 }
341 a ^= secret[1];
342 b ^= seed;
343 rapid_mum(&a, &b);
344 return rapid_mix(a ^ secret[7], b ^ secret[1] ^ i);
345}
346
347 /*
348 * rapidhashMicro main function.
349 *
350 * @param key Buffer to be hashed.
351 * @param len @key length, in bytes.
352 * @param seed 64-bit seed used to alter the hash result predictably.
353 * @param secret Triplet of 64-bit secrets used to alter hash result predictably.
354 *
355 * Returns a 64-bit hash.
356 */
357 RAPIDHASH_INLINE_CONSTEXPR uint64_t rapidhashMicro_internal(const void *key, size_t len, uint64_t seed, const uint64_t* secret) RAPIDHASH_NOEXCEPT {
358 const uint8_t *p=(const uint8_t *)key;
359 seed ^= rapid_mix(seed ^ secret[2], secret[1]);
360 uint64_t a=0, b=0;
361 size_t i = len;
362 if (_likely_(len <= 16)) {
363 if (len >= 4) {
364 seed ^= len;
365 if (len >= 8) {
366 const uint8_t* plast = p + len - 8;
367 a = rapid_read64(p);
368 b = rapid_read64(plast);
369 } else {
370 const uint8_t* plast = p + len - 4;
371 a = rapid_read32(p);
372 b = rapid_read32(plast);
373 }
374 } else if (len > 0) {
375 a = (((uint64_t)p[0])<<45)|p[len-1];
376 b = p[len>>1];
377 } else
378 a = b = 0;
379 } else {
380 if (i > 80) {
381 uint64_t see1 = seed, see2 = seed;
382 uint64_t see3 = seed, see4 = seed;
383 do {
384 seed = rapid_mix(rapid_read64(p) ^ secret[0], rapid_read64(p + 8) ^ seed);
385 see1 = rapid_mix(rapid_read64(p + 16) ^ secret[1], rapid_read64(p + 24) ^ see1);
386 see2 = rapid_mix(rapid_read64(p + 32) ^ secret[2], rapid_read64(p + 40) ^ see2);
387 see3 = rapid_mix(rapid_read64(p + 48) ^ secret[3], rapid_read64(p + 56) ^ see3);
388 see4 = rapid_mix(rapid_read64(p + 64) ^ secret[4], rapid_read64(p + 72) ^ see4);
389 p += 80;
390 i -= 80;
391 } while(i > 80);
392 seed ^= see1;
393 see2 ^= see3;
394 seed ^= see4;
395 seed ^= see2;
396 }
397 if (i > 16) {
398 seed = rapid_mix(rapid_read64(p) ^ secret[2], rapid_read64(p + 8) ^ seed);
399 if (i > 32) {
400 seed = rapid_mix(rapid_read64(p + 16) ^ secret[2], rapid_read64(p + 24) ^ seed);
401 if (i > 48) {
402 seed = rapid_mix(rapid_read64(p + 32) ^ secret[1], rapid_read64(p + 40) ^ seed);
403 if (i > 64) {
404 seed = rapid_mix(rapid_read64(p + 48) ^ secret[1], rapid_read64(p + 56) ^ seed);
405 }
406 }
407 }
408 }
409 a=rapid_read64(p+i-16) ^ i; b=rapid_read64(p+i-8);
410 }
411 a ^= secret[1];
412 b ^= seed;
413 rapid_mum(&a, &b);
414 return rapid_mix(a ^ secret[7], b ^ secret[1] ^ i);
415 }
416
417 /*
418 * rapidhashNano main function.
419 *
420 * @param key Buffer to be hashed.
421 * @param len @key length, in bytes.
422 * @param seed 64-bit seed used to alter the hash result predictably.
423 * @param secret Triplet of 64-bit secrets used to alter hash result predictably.
424 *
425 * Returns a 64-bit hash.
426 */
427 RAPIDHASH_INLINE_CONSTEXPR uint64_t rapidhashNano_internal(const void *key, size_t len, uint64_t seed, const uint64_t* secret) RAPIDHASH_NOEXCEPT {
428 const uint8_t *p=(const uint8_t *)key;
429 seed ^= rapid_mix(seed ^ secret[2], secret[1]);
430 uint64_t a=0, b=0;
431 size_t i = len;
432 if (_likely_(len <= 16)) {
433 if (len >= 4) {
434 seed ^= len;
435 if (len >= 8) {
436 const uint8_t* plast = p + len - 8;
437 a = rapid_read64(p);
438 b = rapid_read64(plast);
439 } else {
440 const uint8_t* plast = p + len - 4;
441 a = rapid_read32(p);
442 b = rapid_read32(plast);
443 }
444 } else if (len > 0) {
445 a = (((uint64_t)p[0])<<45)|p[len-1];
446 b = p[len>>1];
447 } else
448 a = b = 0;
449 } else {
450 if (i > 48) {
451 uint64_t see1 = seed, see2 = seed;
452 do {
453 seed = rapid_mix(rapid_read64(p) ^ secret[0], rapid_read64(p + 8) ^ seed);
454 see1 = rapid_mix(rapid_read64(p + 16) ^ secret[1], rapid_read64(p + 24) ^ see1);
455 see2 = rapid_mix(rapid_read64(p + 32) ^ secret[2], rapid_read64(p + 40) ^ see2);
456 p += 48;
457 i -= 48;
458 } while(i > 48);
459 seed ^= see1;
460 seed ^= see2;
461 }
462 if (i > 16) {
463 seed = rapid_mix(rapid_read64(p) ^ secret[2], rapid_read64(p + 8) ^ seed);
464 if (i > 32) {
465 seed = rapid_mix(rapid_read64(p + 16) ^ secret[2], rapid_read64(p + 24) ^ seed);
466 }
467 }
468 a=rapid_read64(p+i-16) ^ i; b=rapid_read64(p+i-8);
469 }
470 a ^= secret[1];
471 b ^= seed;
472 rapid_mum(&a, &b);
473 return rapid_mix(a ^ secret[7], b ^ secret[1] ^ i);
474 }
475
476/*
477 * rapidhash seeded hash function.
478 *
479 * @param key Buffer to be hashed.
480 * @param len @key length, in bytes.
481 * @param seed 64-bit seed used to alter the hash result predictably.
482 *
483 * Calls rapidhash_internal using provided parameters and default secrets.
484 *
485 * Returns a 64-bit hash.
486 */
487RAPIDHASH_INLINE_CONSTEXPR uint64_t rapidhash_withSeed(const void *key, size_t len, uint64_t seed) RAPIDHASH_NOEXCEPT {
488 return rapidhash_internal(key, len, seed, rapid_secret);
489}
490
491/*
492 * rapidhash general purpose hash function.
493 *
494 * @param key Buffer to be hashed.
495 * @param len @key length, in bytes.
496 *
497 * Calls rapidhash_withSeed using provided parameters and the default seed.
498 *
499 * Returns a 64-bit hash.
500 */
501RAPIDHASH_INLINE_CONSTEXPR uint64_t rapidhash(const void *key, size_t len) RAPIDHASH_NOEXCEPT {
502 return rapidhash_withSeed(key, len, 0);
503}
504
505/*
506 * rapidhashMicro seeded hash function.
507 *
508 * Designed for HPC and server applications, where cache misses make a noticeable performance detriment.
509 * Clang-18+ compiles it to ~140 instructions without stack usage, both on x86-64 and aarch64.
510 * Faster for sizes up to 512 bytes, just 15%-20% slower for inputs above 1kb.
511 *
512 * @param key Buffer to be hashed.
513 * @param len @key length, in bytes.
514 * @param seed 64-bit seed used to alter the hash result predictably.
515 *
516 * Calls rapidhash_internal using provided parameters and default secrets.
517 *
518 * Returns a 64-bit hash.
519 */
520 RAPIDHASH_INLINE_CONSTEXPR uint64_t rapidhashMicro_withSeed(const void *key, size_t len, uint64_t seed) RAPIDHASH_NOEXCEPT {
521 return rapidhashMicro_internal(key, len, seed, rapid_secret);
522}
523
524/*
525 * rapidhashMicro hash function.
526 *
527 * @param key Buffer to be hashed.
528 * @param len @key length, in bytes.
529 *
530 * Calls rapidhash_withSeed using provided parameters and the default seed.
531 *
532 * Returns a 64-bit hash.
533 */
534RAPIDHASH_INLINE_CONSTEXPR uint64_t rapidhashMicro(const void *key, size_t len) RAPIDHASH_NOEXCEPT {
535 return rapidhashMicro_withSeed(key, len, 0);
536}
537
538/*
539 * rapidhashNano seeded hash function.
540 *
541 * @param key Buffer to be hashed.
542 * @param len @key length, in bytes.
543 * @param seed 64-bit seed used to alter the hash result predictably.
544 *
545 * Calls rapidhash_internal using provided parameters and default secrets.
546 *
547 * Returns a 64-bit hash.
548 */
549 RAPIDHASH_INLINE_CONSTEXPR uint64_t rapidhashNano_withSeed(const void *key, size_t len, uint64_t seed) RAPIDHASH_NOEXCEPT {
550 return rapidhashNano_internal(key, len, seed, rapid_secret);
551}
552
553/*
554 * rapidhashNano hash function.
555 *
556 * Designed for Mobile and embedded applications, where keeping a small code size is a top priority.
557 * Clang-18+ compiles it to less than 100 instructions without stack usage, both on x86-64 and aarch64.
558 * The fastest for sizes up to 48 bytes, but may be considerably slower for larger inputs.
559 *
560 * @param key Buffer to be hashed.
561 * @param len @key length, in bytes.
562 *
563 * Calls rapidhash_withSeed using provided parameters and the default seed.
564 *
565 * Returns a 64-bit hash.
566 */
567RAPIDHASH_INLINE_CONSTEXPR uint64_t rapidhashNano(const void *key, size_t len) RAPIDHASH_NOEXCEPT {
568 return rapidhashNano_withSeed(key, len, 0);
569}