// small, fast 64 bit hash function. // // https://github.com/N-R-K/ChibiHash // https://nrk.neocities.org/articles/chibihash // // This is free and unencumbered software released into the public domain. // For more information, please refer to #include #include #include "chibihash.h" static inline uint64_t chibihash64__load64le(const uint8_t *p) { return (uint64_t)p[0] << 0 | (uint64_t)p[1] << 8 | (uint64_t)p[2] << 16 | (uint64_t)p[3] << 24 | (uint64_t)p[4] << 32 | (uint64_t)p[5] << 40 | (uint64_t)p[6] << 48 | (uint64_t)p[7] << 56; } uint64_t chibihash64(const void *keyIn, ptrdiff_t len, uint64_t seed) { const uint8_t *k = (const uint8_t *)keyIn; ptrdiff_t l = len; const uint64_t P1 = UINT64_C(0x2B7E151628AED2A5); const uint64_t P2 = UINT64_C(0x9E3793492EEDC3F7); const uint64_t P3 = UINT64_C(0x3243F6A8885A308D); uint64_t h[4] = { P1, P2, P3, seed }; for (; l >= 32; l -= 32) { for (int i = 0; i < 4; ++i, k += 8) { uint64_t lane = chibihash64__load64le(k); h[i] ^= lane; h[i] *= P1; h[(i+1)&3] ^= ((lane << 40) | (lane >> 24)); } } h[0] += ((uint64_t)len << 32) | ((uint64_t)len >> 32); if (l & 1) { h[0] ^= k[0]; --l, ++k; } h[0] *= P2; h[0] ^= h[0] >> 31; for (int i = 1; l >= 8; l -= 8, k += 8, ++i) { h[i] ^= chibihash64__load64le(k); h[i] *= P2; h[i] ^= h[i] >> 31; } for (int i = 0; l > 0; l -= 2, k += 2, ++i) { h[i] ^= (k[0] | ((uint64_t)k[1] << 8)); h[i] *= P3; h[i] ^= h[i] >> 31; } uint64_t x = seed; x ^= h[0] * ((h[2] >> 32)|1); x ^= h[1] * ((h[3] >> 32)|1); x ^= h[2] * ((h[0] >> 32)|1); x ^= h[3] * ((h[1] >> 32)|1); // moremur: https://mostlymangling.blogspot.com/2019/12/stronger-better-morer-moremur-better.html x ^= x >> 27; x *= UINT64_C(0x3C79AC492BA7B653); x ^= x >> 33; x *= UINT64_C(0x1C69B3F74AC4AE35); x ^= x >> 27; return x; }