Created
April 10, 2023 15:52
-
-
Save Hexlord/3d94373ac617e53877267c838afea242 to your computer and use it in GitHub Desktop.
wyhash denoised
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
inline constexpr u64 _wyrot(u64 x) { | |
return (x >> 32) | (x << 32); | |
} | |
// 128bit multiply function. | |
inline constexpr void _wymum(u64 *A, u64 *B) { | |
#if defined(__SIZEOF_INT128__) | |
__uint128_t r = *A; | |
r *= *B; | |
*A = (u64)r; | |
*B = (u64)(r >> 64); | |
#else | |
u64 ha = *A >> 32, hb = *B >> 32, la = (uint32_t)*A, lb = (uint32_t)*B, hi, lo; | |
u64 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; | |
*A = lo; | |
*B = hi; | |
#endif | |
} | |
// Multiply and xor mix function. | |
inline constexpr u64 _wymix(u64 A, u64 B) { | |
_wymum(&A, &B); | |
return A ^ B; | |
} | |
//read functions | |
#if(BX_CPU_ENDIAN_LITTLE) | |
inline constexpr u64 _read8(const char *p) { | |
u64 Result = 0; | |
for(var Index = 0u; Index < 8u; ++Index) { | |
Result = Result << 8; | |
Result |= (byte)p[Index]; | |
} | |
return Result; | |
} | |
inline constexpr u64 _read8(const byte *p) { | |
u64 Result = 0; | |
for(var Index = 0u; Index < 8u; ++Index) { | |
Result = Result << 8; | |
Result |= p[Index]; | |
} | |
return Result; | |
} | |
inline constexpr u64 _read4(const char *p) { | |
u64 Result = 0; | |
for(var Index = 0u; Index < 4u; ++Index) { | |
Result = Result << 8; | |
Result |= (byte)p[Index]; | |
} | |
return Result; | |
} | |
inline constexpr u64 _read4(const byte *p) { | |
u64 Result = 0; | |
for(var Index = 0u; Index < 4u; ++Index) { | |
Result = Result << 8; | |
Result |= p[Index]; | |
} | |
return Result; | |
} | |
inline constexpr u64 _wyr8(const char *p) { | |
return _read8(p); | |
} | |
inline constexpr u64 _wyr8(const byte *p) { | |
return _read8(p); | |
} | |
inline constexpr u64 _wyr4(const char *p) { | |
return _read4(p); | |
} | |
inline constexpr u64 _wyr4(const byte *p) { | |
return _read4(p); | |
} | |
#elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) | |
inline constexpr u64 _wyr8(const byte *p) { | |
var v = _read8(p); | |
return __builtin_bswap64(v); | |
} | |
inline constexpr u64 _wyr8(const char *p) { | |
var v = _read8(p); | |
return __builtin_bswap64(v); | |
} | |
inline constexpr u64 _wyr4(const byte *p) { | |
var v = _read4(p); | |
return __builtin_bswap32(v); | |
} | |
inline constexpr u64 _wyr4(const char *p) { | |
var v = _read4(p); | |
return __builtin_bswap32(v); | |
} | |
#else | |
inline constexpr u64 _wyr8(const byte *p) { | |
var v = _read8(p); | |
return ( | |
((v >> 56) & 0xff) | ((v >> 40) & 0xff00) | ((v >> 24) & 0xff0000) | ((v >> 8) & 0xff000000) | ((v << 8) & 0xff00000000) | |
| ((v << 24) & 0xff0000000000) | ((v << 40) & 0xff000000000000) | ((v << 56) & 0xff00000000000000)); | |
} | |
inline constexpr u64 _wyr8(const char *p) { | |
var v = _read8(p); | |
return ( | |
((v >> 56) & 0xff) | ((v >> 40) & 0xff00) | ((v >> 24) & 0xff0000) | ((v >> 8) & 0xff000000) | ((v << 8) & 0xff00000000) | |
| ((v << 24) & 0xff0000000000) | ((v << 40) & 0xff000000000000) | ((v << 56) & 0xff00000000000000)); | |
} | |
inline constexpr u64 _wyr4(const byte *p) { | |
var v = _read4(p); | |
return (((v >> 24) & 0xff) | ((v >> 8) & 0xff00) | ((v << 8) & 0xff0000) | ((v << 24) & 0xff000000)); | |
} | |
inline constexpr u64 _wyr4(const char *p) { | |
var v = _read4(p); | |
return (((v >> 24) & 0xff) | ((v >> 8) & 0xff00) | ((v << 8) & 0xff0000) | ((v << 24) & 0xff000000)); | |
} | |
#endif | |
inline constexpr u64 _wyr3(const byte *p, size_t k) { | |
return (((u64)p[0]) << 16) | (((u64)p[k >> 1]) << 8) | (byte)p[k - 1]; | |
} | |
inline constexpr u64 _wyr3(const char *p, size_t k) { | |
return (((u64)p[0]) << 16) | (((u64)p[k >> 1]) << 8) | (byte)p[k - 1]; | |
} | |
// The default secret parameters. | |
inline constexpr u64 secret[4] = {0xa0761d6478bd642full, 0xe7037ed1a0b428dbull, 0x8ebc6af09c88c6e3ull, 0x589965cc75374cc3ull}; | |
inline constexpr hash ComputeHashWy64(const byte *p, u32 len, u64 seed) { | |
seed ^= _wymix(seed ^ secret[0], secret[1]); | |
u64 a, b; | |
if(Likely(len <= 16)) { | |
if(Likely(len >= 4)) { | |
a = (_wyr4(p) << 32) | _wyr4(p + ((len >> 3) << 2)); | |
b = (_wyr4(p + len - 4) << 32) | _wyr4(p + len - 4 - ((len >> 3) << 2)); | |
} else if(Likely(len > 0)) { | |
a = _wyr3(p, len); | |
b = 0; | |
} else | |
a = b = 0; | |
} else { | |
var i = len; | |
if(Unlikely(i > 48)) { | |
u64 see1 = seed, see2 = seed; | |
do { | |
seed = _wymix(_wyr8(p) ^ secret[1], _wyr8(p + 8) ^ seed); | |
see1 = _wymix(_wyr8(p + 16) ^ secret[2], _wyr8(p + 24) ^ see1); | |
see2 = _wymix(_wyr8(p + 32) ^ secret[3], _wyr8(p + 40) ^ see2); | |
p += 48; | |
i -= 48; | |
} while(Likely(i > 48)); | |
seed ^= see1 ^ see2; | |
} | |
while(Unlikely(i > 16)) { | |
seed = _wymix(_wyr8(p) ^ secret[1], _wyr8(p + 8) ^ seed); | |
i -= 16; | |
p += 16; | |
} | |
a = _wyr8(p + i - 16); | |
b = _wyr8(p + i - 8); | |
} | |
a ^= secret[1]; | |
b ^= seed; | |
_wymum(&a, &b); | |
return _wymix(a ^ secret[0] ^ len, b ^ secret[1]); | |
} | |
inline constexpr hash ComputeHashWy64(const char *p, u32 len, u64 seed) { | |
seed ^= _wymix(seed ^ secret[0], secret[1]); | |
u64 a, b; | |
if(Likely(len <= 16)) { | |
if(Likely(len >= 4)) { | |
a = (_wyr4(p) << 32) | _wyr4(p + ((len >> 3) << 2)); | |
b = (_wyr4(p + len - 4) << 32) | _wyr4(p + len - 4 - ((len >> 3) << 2)); | |
} else if(Likely(len > 0)) { | |
a = _wyr3(p, len); | |
b = 0; | |
} else | |
a = b = 0; | |
} else { | |
var i = len; | |
if(Unlikely(i > 48)) { | |
u64 see1 = seed, see2 = seed; | |
do { | |
seed = _wymix(_wyr8(p) ^ secret[1], _wyr8(p + 8) ^ seed); | |
see1 = _wymix(_wyr8(p + 16) ^ secret[2], _wyr8(p + 24) ^ see1); | |
see2 = _wymix(_wyr8(p + 32) ^ secret[3], _wyr8(p + 40) ^ see2); | |
p += 48; | |
i -= 48; | |
} while(Likely(i > 48)); | |
seed ^= see1 ^ see2; | |
} | |
while(Unlikely(i > 16)) { | |
seed = _wymix(_wyr8(p) ^ secret[1], _wyr8(p + 8) ^ seed); | |
i -= 16; | |
p += 16; | |
} | |
a = _wyr8(p + i - 16); | |
b = _wyr8(p + i - 8); | |
} | |
a ^= secret[1]; | |
b ^= seed; | |
_wymum(&a, &b); | |
return _wymix(a ^ secret[0] ^ len, b ^ secret[1]); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment