#ifndef wyhash_final_version
#define wyhash_final_version
#ifndef WYHASH_CONDOM
#define WYHASH_CONDOM 1
#endif
#define WYHASH_32BIT_MUM 0
#include <stdint.h>
#include <string.h>
#if defined(_MSC_VER) && defined(_M_X64)
#include <intrin.h>
#pragma intrinsic(_umul128)
#endif
#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
#define _likely_(x) __builtin_expect(x, 1)
#define _unlikely_(x) __builtin_expect(x, 0)
#else
#define _likely_(x) (x)
#define _unlikely_(x) (x)
#endif
static __inline uint64_t _wyrot(uint64_t x) { return (x >> 32) | (x << 32); }
static __inline void _wymum(uint64_t *A, uint64_t *B) {
#if (WYHASH_32BIT_MUM)
uint64_t hh = (*A >> 32) * (*B >> 32), hl = (*A >> 32) * (unsigned)*B,
lh = (unsigned)*A * (*B >> 32),
ll = (uint64_t)(unsigned)*A * (unsigned)*B;
#if (WYHASH_CONDOM > 1)
*A ^= _wyrot(hl) ^ hh;
*B ^= _wyrot(lh) ^ ll;
#else
*A = _wyrot(hl) ^ hh;
*B = _wyrot(lh) ^ ll;
#endif
#elif defined(__SIZEOF_INT128__)
__uint128_t r = *A;
r *= *B;
#if (WYHASH_CONDOM > 1)
*A ^= (uint64_t)r;
*B ^= (uint64_t)(r >> 64);
#else
*A = (uint64_t)r;
*B = (uint64_t)(r >> 64);
#endif
#elif defined(_MSC_VER) && defined(_M_X64)
#if (WYHASH_CONDOM > 1)
uint64_t a, b;
a = _umul128(*A, *B, &b);
*A ^= a;
*B ^= b;
#else
*A = _umul128(*A, *B, B);
#endif
#else
uint64_t ha = *A >> 32, hb = *B >> 32, la = (uint32_t)*A, lb = (uint32_t)*B,
hi, lo;
uint64_t rh = ha * hb, rm0 = ha * lb, rm1 = hb * la, rl = la * lb,
t = rl + (rm0 << 32), c = t < rl;
lo = t + (rm1 << 32);
c += lo < t;
hi = rh + (rm0 >> 32) + (rm1 >> 32) + c;
#if (WYHASH_CONDOM > 1)
*A ^= lo;
*B ^= hi;
#else
*A = lo;
*B = hi;
#endif
#endif
}
static __inline uint64_t _wymix(uint64_t A, uint64_t B) {
_wymum(&A, &B);
return A ^ B;
}
#ifndef WYHASH_LITTLE_ENDIAN
#if defined(_WIN32) || defined(__LITTLE_ENDIAN__) || \
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
#define WYHASH_LITTLE_ENDIAN 1
#elif defined(__BIG_ENDIAN__) || \
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
#define WYHASH_LITTLE_ENDIAN 0
#endif
#endif
#if (WYHASH_LITTLE_ENDIAN)
static __inline uint64_t _wyr8(const uint8_t *p) {
uint64_t v;
memcpy(&v, p, 8);
return v;
}
static __inline uint64_t _wyr4(const uint8_t *p) {
unsigned v;
memcpy(&v, p, 4);
return v;
}
#elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
static __inline uint64_t _wyr8(const uint8_t *p) {
uint64_t v;
memcpy(&v, p, 8);
return __builtin_bswap64(v);
}
static __inline uint64_t _wyr4(const uint8_t *p) {
unsigned v;
memcpy(&v, p, 4);
return __builtin_bswap32(v);
}
#elif defined(_MSC_VER)
static __inline uint64_t _wyr8(const uint8_t *p) {
uint64_t v;
memcpy(&v, p, 8);
return _byteswap_uint64(v);
}
static __inline uint64_t _wyr4(const uint8_t *p) {
unsigned v;
memcpy(&v, p, 4);
return _byteswap_ulong(v);
}
#endif
static __inline uint64_t _wyr3(const uint8_t *p, unsigned k) {
return (((uint64_t)p[0]) << 16) | (((uint64_t)p[k >> 1]) << 8) | p[k - 1];
}
static __inline uint64_t _wyfinish16(const uint8_t *p, uint64_t len,
uint64_t seed, const uint64_t *secret,
uint64_t i) {
#if (WYHASH_CONDOM > 0)
uint64_t a, b;
if (_likely_(i <= 8)) {
if (_likely_(i >= 4)) {
a = _wyr4(p);
b = _wyr4(p + i - 4);
} else if (_likely_(i)) {
a = _wyr3(p, (unsigned)i);
b = 0;
} else
a = b = 0;
} else {
a = _wyr8(p);
b = _wyr8(p + i - 8);
}
return _wymix(secret[1] ^ len, _wymix(a ^ secret[1], b ^ seed));
#else
#define oneshot_shift ((i < 8) * ((8 - i) << 3))
return _wymix(secret[1] ^ len,
_wymix((_wyr8(p) << oneshot_shift) ^ secret[1],
(_wyr8(p + i - 8) >> oneshot_shift) ^ seed));
#endif
}
static __inline uint64_t _wyfinish(const uint8_t *p, uint64_t len,
uint64_t seed, const uint64_t *secret,
uint64_t i) {
if (_likely_(i <= 16))
return _wyfinish16(p, len, seed, secret, i);
return _wyfinish(p + 16, len,
_wymix(_wyr8(p) ^ secret[1], _wyr8(p + 8) ^ seed), secret,
i - 16);
}
static __inline uint64_t wyhash(const void *key, uint64_t len, uint64_t seed,
const uint64_t *secret) {
const uint8_t *p = (const uint8_t *)key;
uint64_t i = len;
seed ^= *secret;
if (_unlikely_(i > 64)) {
uint64_t see1 = seed;
do {
seed = _wymix(_wyr8(p) ^ secret[1], _wyr8(p + 8) ^ seed) ^
_wymix(_wyr8(p + 16) ^ secret[2], _wyr8(p + 24) ^ seed);
see1 = _wymix(_wyr8(p + 32) ^ secret[3], _wyr8(p + 40) ^ see1) ^
_wymix(_wyr8(p + 48) ^ secret[4], _wyr8(p + 56) ^ see1);
p += 64;
i -= 64;
} while (i > 64);
seed ^= see1;
}
return _wyfinish(p, len, seed, secret, i);
}
const uint64_t _wyp[5] = {0xa0761d6478bd642full, 0xe7037ed1a0b428dbull,
0x8ebc6af09c88c6e3ull, 0x589965cc75374cc3ull,
0x1d8e4e27c47d124full};
static __inline uint64_t wyhash64(uint64_t A, uint64_t B) {
A ^= _wyp[0];
B ^= _wyp[1];
_wymum(&A, &B);
return _wymix(A ^ _wyp[0], B ^ _wyp[1]);
}
static __inline uint64_t wyrand(uint64_t *seed) {
*seed += _wyp[0];
return _wymix(*seed, *seed ^ _wyp[1]);
}
static __inline double wy2u01(uint64_t r) {
const double _wynorm = 1.0 / (1ull << 52);
return (r >> 12) * _wynorm;
}
static __inline double wy2gau(uint64_t r) {
const double _wynorm = 1.0 / (1ull << 20);
return ((r & 0x1fffff) + ((r >> 21) & 0x1fffff) + ((r >> 42) & 0x1fffff)) *
_wynorm -
3.0;
}
static __inline unsigned portable_popcount(uint64_t x) {
x -= (x >> 1) & 0x5555555555555555ull;
x = (x & 0x3333333333333333ull) + ((x >> 2) & 0x3333333333333333ull);
x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0full;
x += x >> 8;
x += x >> 16;
x += x >> 32;
return x & 0x7f;
}
static __inline void make_secret(uint64_t seed, uint64_t *secret) {
uint8_t c[] = {15, 23, 27, 29, 30, 39, 43, 45, 46, 51, 53, 54,
57, 58, 60, 71, 75, 77, 78, 83, 85, 86, 89, 90,
92, 99, 101, 102, 105, 106, 108, 113, 114, 116, 120, 135,
139, 141, 142, 147, 149, 150, 153, 154, 156, 163, 165, 166,
169, 170, 172, 177, 178, 180, 184, 195, 197, 198, 201, 202,
204, 209, 210, 212, 216, 225, 226, 228, 232, 240};
for (size_t i = 0; i < 5; i++) {
uint8_t ok;
do {
ok = 1;
secret[i] = 0;
for (size_t j = 0; j < 64; j += 8)
secret[i] |= ((uint64_t)c[wyrand(&seed) % sizeof(c)]) << j;
if (secret[i] % 2 == 0) {
ok = 0;
continue;
}
for (size_t j = 0; j < i; j++)
if (portable_popcount(secret[j] ^ secret[i]) != 32) {
ok = 0;
break;
}
if (!ok)
continue;
for (uint64_t j = 3; j < 0x100000000ull; j += 2)
if (secret[i] % j == 0) {
ok = 0;
break;
}
} while (!ok);
}
}
#endif