FNV-1a
FNV-1a
uint32_t fnv1a32(const char *data, size_t len) {
uint32_t hash = 2166136261;
for (char *byte = data; byte < (data + len); byte++) {
hash ^= *byte;
hash *= 16777619;
}
return hash;
}
fnv1a32("ab", 2)
uint32_t fnv1a32(const char *data, size_t len) {
> uint32_t hash = 2166136261;
for (char *byte = data; byte < (data + len); byte++) {
hash ^= *byte;
hash *= 16777619;
}
return hash;
}
hash: 1000 0001 0001 1100 1001 1101 1100 0101
*byte: (unset)
fnv1a32("ab", 2)
uint32_t fnv1a32(const char *data, size_t len) {
uint32_t hash = 2166136261;
> for (char *byte = data; byte < (data + len); byte++) {
hash ^= *byte;
hash *= 16777619;
}
return hash;
}
hash: 1000 0001 0001 1100 1001 1101 1100 0101
*byte: 0110 0001
fnv1a32("ab", 2)
uint32_t fnv1a32(const char *data, size_t len) {
uint32_t hash = 2166136261;
for (char *byte = data; byte < (data + len); byte++) {
> hash ^= *byte;
hash *= 16777619;
}
return hash;
}
hash: 1000 0001 0001 1100 1001 1101 1010 0100
*byte: 0110 0001
fnv1a32("ab", 2)
uint32_t fnv1a32(const char *data, size_t len) {
uint32_t hash = 2166136261;
for (char *byte = data; byte < (data + len); byte++) {
hash ^= *byte;
> hash *= 16777619;
}
return hash;
}
hash: 1110 0100 0000 1100 0010 1001 0010 1100
*byte: 0110 0001
fnv1a32("ab", 2)
uint32_t fnv1a32(const char *data, size_t len) {
uint32_t hash = 2166136261;
> for (char *byte = data; byte < (data + len); byte++) {
hash ^= *byte;
hash *= 16777619;
}
return hash;
}
hash: 1110 0100 0000 1100 0010 1001 0010 1100
*byte: 0110 0010
fnv1a32("ab", 2)
uint32_t fnv1a32(const char *data, size_t len) {
uint32_t hash = 2166136261;
for (char *byte = data; byte < (data + len); byte++) {
> hash ^= *byte;
hash *= 16777619;
}
return hash;
}
hash: 1110 0100 0000 1100 0010 1001 0100 1110
*byte: 0110 0001
fnv1a32("ab", 2)
uint32_t fnv1a32(const char *data, size_t len) {
uint32_t hash = 2166136261;
for (char *byte = data; byte < (data + len); byte++) {
hash ^= *byte;
> hash *= 16777619;
}
return hash;
}
hash: 0100 1101 0010 0101 0000 0101 1100 1010
*byte: 0110 0001
MurmurHash3
MurmurHash3
uint32_t murmurhash3_32(const char *data, size_t len, uint32_t seed) {
static const uint32_t c1 = 0xcc9e2d51;
static const uint32_t c2 = 0x1b873593;
static const uint32_t r1 = 15;
static const uint32_t r2 = 13;
static const uint32_t m = 5;
static const uint32_t n = 0xe6546b64;
uint32_t hash = seed;
const int nblocks = len / 4;
const uint32_t *blocks = (const uint32_t *) data;
for (int i = 0; i < nblocks; i++) {
uint32_t k = blocks[i];
k *= c1;
k = (k << r1) | (k >> (32 - r1));
k *= c2;
hash ^= k;
hash = ((hash << r2) | (hash >> (32 - r2))) * m + n;
}
const uint8_t *tail = (const uint8_t *) (data + nblocks * 4);
uint32_t k1 = 0;
switch (len & 3) {
case 3:
k1 ^= tail[2] << 16;
case 2:
k1 ^= tail[1] << 8;
case 1:
k1 ^= tail[0];
k1 *= c1;
k1 = (k1 << r1) | (k1 >> (32 - r1));
k1 *= c2;
hash ^= k1;
}
hash ^= len;
hash ^= (hash >> 16);
hash *= 0x85ebca6b;
hash ^= (hash >> 13);
hash *= 0xc2b2ae35;
hash ^= (hash >> 16);
return hash;
}
MurmurHash3
uint32_t murmurhash3_32(const char *data,
size_t len,
uint32_t seed);
MurmurHash3
static const uint32_t c1 = 0xcc9e2d51;
static const uint32_t c2 = 0x1b873593;
static const uint32_t r1 = 15;
static const uint32_t r2 = 13;
static const uint32_t m = 5;
static const uint32_t n = 0xe6546b64;
uint32_t hash = seed;
MurmurHash3
const size_t nblocks = len / 4;
const uint32_t *blocks = (const uint32_t *) data;
for (size_t i = 0; i < nblocks; i++) {
uint32_t k = blocks[i];
k *= c1;
k = (k << r1) | (k >> (32 - r1));
k *= c2;
hash ^= k;
hash = ((hash << r2) | (hash >> (32 - r2))) * m + n;
}
MurmurHash3
const uint8_t *tail;
tail = (const uint8_t *) (data + nblocks * 4);
MurmurHash3
uint32_t k1 = 0;
switch (len & 3) {
case 3:
k1 ^= tail[2] << 16;
case 2:
k1 ^= tail[1] << 8;
case 1:
k1 ^= tail[0];
k1 *= c1;
k1 = (k1 << r1) | (k1 >> (32 - r1));
k1 *= c2;
hash ^= k1;
}
MurmurHash3
hash ^= len;
hash ^= (hash >> 16);
hash *= 0x85ebca6b;
hash ^= (hash >> 13);
hash *= 0xc2b2ae35;
hash ^= (hash >> 16);
return hash;
MurmurHash3
Corpus |
CPU time (ms) |
% FNV-1a |
Collisions |
Numbers |
69.10 |
125% |
4 (0.002%) |
Words |
69.23 |
102% |
6 (0.003%) |
Holmes |
0.95 |
30% |
0 |
MurmurHash3
xxHash
xxHash
const uint32_t xxhash32_prime1 = 2654435761U;
const uint32_t xxhash32_prime2 = 2246822519U;
const uint32_t xxhash32_prime3 = 3266489917U;
const uint32_t xxhash32_prime4 = 668265263U;
const uint32_t xxhash32_prime5 = 374761393U;
inline uint32_t xxhash32_rotl(uint32_t x, int r) {
return (x << r) | (x >> (32 - r));
}
inline uint32_t xxhash32_mix(uint32_t v, uint32_t chunk) {
v += chunk * xxhash32_prime2;
v = xxhash32_rotl(v, 13);
return v * xxhash32_prime1;
}
uint32_t xxhash32(const char *data, size_t len, uint32_t seed) {
const char *p = data;
const char *end = data + len;
uint32_t hash = 0;
if (len >= 16) {
uint32_t v1 = seed + xxhash32_prime1 + xxhash32_prime2;
uint32_t v2 = seed + xxhash32_prime2;
uint32_t v3 = seed;
uint32_t v4 = seed - xxhash32_prime1;
for (; p <= (end - 16); p += 16) {
const uint32_t *chunk = (const uint32_t *) p;
v1 = xxhash32_mix(v1, chunk[0]);
v2 = xxhash32_mix(v2, chunk[1]);
v3 = xxhash32_mix(v3, chunk[2]);
v4 = xxhash32_mix(v4, chunk[3]);
}
hash = xxhash32_rotl(v1, 1) +
xxhash32_rotl(v2, 7) +
xxhash32_rotl(v3, 12) +
xxhash32_rotl(v4, 18);
} else {
hash = seed + xxhash32_prime5;
}
for (; (p + 4) <= end; p += 4) {
hash += *((const uint32_t *) p) * xxhash32_prime3;
hash = xxhash32_rotl(hash, 17) * xxhash32_prime4;
}
for (; p < end; p++) {
hash += ((uint8_t) *p) * xxhash32_prime5;
hash = xxhash32_rotl(hash, 11) * xxhash32_prime1;
}
hash ^= hash >> 15;
hash *= xxhash32_prime2;
hash ^= hash >> 13;
hash *= xxhash32_prime3;
hash ^= hash >> 16;
return hash;
}
xxHash
uint32_t v1 = seed + xxhash32_prime1 + xxhash32_prime2;
uint32_t v2 = seed + xxhash32_prime2;
uint32_t v3 = seed;
uint32_t v4 = seed - xxhash32_prime1;
xxHash
for (; p <= (end - 16); p += 16) {
const uint32_t *chunk = (const uint32_t *) p;
v1 = xxhash32_mix(v1, chunk[0]);
v2 = xxhash32_mix(v2, chunk[1]);
v3 = xxhash32_mix(v3, chunk[2]);
v4 = xxhash32_mix(v4, chunk[3]);
}
xxHash
inline uint32_t xxhash32_rotl(uint32_t x, int r) {
return (x << r) | (x >> (32 - r));
}
inline uint32_t xxhash32_mix(uint32_t v, uint32_t in) {
v += in * xxhash32_prime2;
v = xxhash32_rotl(v, 13);
return v * xxhash32_prime1;
}
xxHash
hash = xxhash32_rotl(v1, 1) +
xxhash32_rotl(v2, 7) +
xxhash32_rotl(v3, 12) +
xxhash32_rotl(v4, 18);
xxHash
if (len >= 16) {
/* what you just saw */
} else {
hash = seed + xxhash32_prime5;
}
xxHash
for (; (p + 4) <= end; p += 4) {
hash += *((const uint32_t *) p) * xxhash32_prime3;
hash = xxhash32_rotl(hash, 17) * xxhash32_prime4;
}
for (; p < end; p++) {
hash += ((uint8_t) *p) * xxhash32_prime5;
hash = xxhash32_rotl(hash, 11) * xxhash32_prime1;
}
xxHash
hash ^= hash >> 15;
hash *= xxhash32_prime2;
hash ^= hash >> 13;
hash *= xxhash32_prime3;
hash ^= hash >> 16;
return hash;
xxHash
Corpus |
CPU time (ms) |
% FNV-1a |
Collisions |
Numbers |
69.41 |
125% |
2 (0.001%) |
Words |
73.97 |
109% |
6 (0.003%) |
Holmes |
0.396 |
12.6% |
0 |
xxHash