Skip to content

Instantly share code, notes, and snippets.

@ziap
Last active February 23, 2025 07:24
Show Gist options
  • Save ziap/e764030011b8ad6a161faf3b67f5c117 to your computer and use it in GitHub Desktop.
Save ziap/e764030011b8ad6a161faf3b67f5c117 to your computer and use it in GitHub Desktop.
A custom fast, non-cryptographic hash function
#include <stdint.h>
static inline uint64_t multiply_mix(uint64_t x, uint64_t y) {
__uint128_t m = (__uint128_t)x * (__uint128_t)y;
uint64_t hi = m >> 64;
uint64_t lo = m;
return lo ^ hi;
}
static inline uint64_t zxhash(const void *key, int len, uint64_t seed) {
const uint64_t secret = 0x9e3779b97f4a7c15;
uint64_t h = multiply_mix(seed ^ 0x243f6a8885a308d3, len ^ 0x13198a2e03707344);
if (len < 8) {
const uint8_t *bytes = key;
uint64_t block = 0;
switch (len) {
case 7: block |= (uint64_t)bytes[6] << 48;
case 6: block |= (uint64_t)bytes[5] << 40;
case 5: block |= (uint64_t)bytes[4] << 32;
case 4: block |= (uint64_t)bytes[3] << 24;
case 3: block |= (uint64_t)bytes[2] << 16;
case 2: block |= (uint64_t)bytes[1] << 8;
case 1: block |= (uint64_t)bytes[0];
}
h = multiply_mix(h, block ^ secret);
} else if (len < 128) {
const uint64_t *view = key;
while (len > 16) {
h = multiply_mix(h ^ view[0], view[1] ^ secret);
view += 2;
len -= 16;
}
h ^= *(const uint64_t *)((const uint8_t *)view + len - 8);
const uint64_t block = (len > 8) ? view[0] : 0;
h = multiply_mix(h, block ^ secret);
} else {
uint64_t s0 = 0xa4093822299f31d0;
uint64_t s1 = 0x082efa98ec4e6c89;
uint64_t s2 = 0x452821e638d01377;
uint64_t s3 = 0xbe5466cf34e90c6c;
const uint64_t *view = key;
while (len > 64) {
s0 = multiply_mix(s0 ^ view[0], view[1] ^ secret);
s1 = multiply_mix(s1 ^ view[2], view[3] ^ secret);
s2 = multiply_mix(s2 ^ view[4], view[5] ^ secret);
s3 = multiply_mix(s3 ^ view[6], view[7] ^ secret);
view += 8;
len -= 64;
}
const uint64_t *final = (const uint64_t *)((const uint8_t *)view + len - 64);
s0 = multiply_mix(s0 ^ final[0], s2 ^ final[1]);
s1 = multiply_mix(s1 ^ final[2], s3 ^ final[3]);
s0 = multiply_mix(s0 ^ final[4], s1 ^ final[5]);
h = multiply_mix(h ^ final[6], s0 ^ final[7]);
}
return multiply_mix(h ^ len, 0xffebb71d94fcdaf9);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment