14static inline void _wymum(uint64_t* A, uint64_t* B) {
18 *B = (uint64_t)(r >> 64);
22static inline uint64_t _wymix(uint64_t A, uint64_t B) {
28static inline uint64_t _wyr8(
const uint8_t* p) {
33static inline uint64_t _wyr4(
const uint8_t* p) {
38static inline uint64_t _wyr3(
const uint8_t* p,
size_t k) {
39 return (((uint64_t)p[0]) << 16) | (((uint64_t)p[k >> 1]) << 8) | p[k - 1];
43static inline uint64_t wyhash(
const void* key,
size_t len, uint64_t seed,
const uint64_t* secret) {
44 const uint8_t* p = (
const uint8_t*)key;
47 if (__builtin_expect(len <= 16,
true)) {
48 if (__builtin_expect(len >= 4,
true)) {
49 a = (_wyr4(p) << 32) | _wyr4(p + ((len >> 3) << 2));
50 b = (_wyr4(p + len - 4) << 32) | _wyr4(p + len - 4 - ((len >> 3) << 2));
51 }
else if (__builtin_expect(len > 0,
true)) {
58 if (__builtin_expect(i > 48,
false)) {
59 uint64_t see1 = seed, see2 = seed;
61 seed = _wymix(_wyr8(p) ^ secret[1], _wyr8(p + 8) ^ seed);
62 see1 = _wymix(_wyr8(p + 16) ^ secret[2], _wyr8(p + 24) ^ see1);
63 see2 = _wymix(_wyr8(p + 32) ^ secret[3], _wyr8(p + 40) ^ see2);
66 }
while (__builtin_expect(i > 48,
true));
69 while (__builtin_expect(i > 16,
false)) {
70 seed = _wymix(_wyr8(p) ^ secret[1], _wyr8(p + 8) ^ seed);
74 a = _wyr8(p + i - 16);
77 return _wymix(secret[1] ^ len, _wymix(a ^ secret[1], b ^ seed));
81static const uint64_t _wyp[4] = {0xa0761d6478bd642full, 0xe7037ed1a0b428dbull, 0x8ebc6af09c88c6e3ull,
82 0x589965cc75374cc3ull};
85static inline uint64_t wyhash64(uint64_t A, uint64_t B) {
86 A ^= 0xa0761d6478bd642full;
87 B ^= 0xe7037ed1a0b428dbull;
89 return _wymix(A ^ 0xa0761d6478bd642full, B ^ 0xe7037ed1a0b428dbull);
94uint64_t gen_random_seed() {
95 std::random_device rd;
96 std::uniform_int_distribution<uint64_t> dis(0, std::numeric_limits<uint64_t>::max());
119 static const uint64_t seed = impl::gen_random_seed();
120 return impl::wyhash(key, len, seed, impl::_wyp);
135static inline uint64_t
wyhash_combine(uint64_t a, uint64_t b) {
return impl::wyhash64(a, b); }
153 size_t operator()(
const std::string& s)
const {
return wyhash_bytes(s.c_str(), s.size()); }
161template <
typename T1,
typename T2>
165 size_t operator()(
const std::pair<T1, T2>& p)
const {
166 return wyhash_combine(first_hash(p.first), second_hash(p.second));
170#define _wyhash_for_integral_type(T) \
173 size_t operator()(T t) const { return wyhash_bytes((void*)&t, sizeof(T)); } \
176_wyhash_for_integral_type(
bool);
177_wyhash_for_integral_type(
char);
178_wyhash_for_integral_type(
unsigned char);
179_wyhash_for_integral_type(
signed char);
180_wyhash_for_integral_type(
short);
181_wyhash_for_integral_type(
unsigned short);
182_wyhash_for_integral_type(
int);
183_wyhash_for_integral_type(
unsigned int);
184_wyhash_for_integral_type(
long);
185_wyhash_for_integral_type(
unsigned long);
186_wyhash_for_integral_type(
long long);
187_wyhash_for_integral_type(
unsigned long long);
189#undef _wyhash_for_integral_type
static uint64_t wyhash_combine(uint64_t a, uint64_t b)
Combine two hash values to produce a new hash value.
Definition: wyhash.hpp:135
static uint64_t wyhash_bytes(const void *key, size_t len)
Hash function for arbitrary bytes using wyhash.
Definition: wyhash.hpp:118
Hash function class like std::hash but uses wyhash.
Definition: wyhash.hpp:148