|
|
@ -8,8 +8,8 @@ |
|
|
|
uint64_t hash=wyhash(s.c_str(), s.size(), 0, _wyp); |
|
|
|
*/ |
|
|
|
|
|
|
|
#ifndef wyhash_final_version_4 |
|
|
|
#define wyhash_final_version_4 |
|
|
|
#ifndef wyhash_final_version_4_2 |
|
|
|
#define wyhash_final_version_4_2 |
|
|
|
|
|
|
|
#ifndef WYHASH_CONDOM |
|
|
|
//protections that produce different results: |
|
|
@ -21,7 +21,7 @@ |
|
|
|
#ifndef WYHASH_32BIT_MUM |
|
|
|
//0: normal version, slow on 32 bit systems |
|
|
|
//1: faster on 32 bit systems but produces different results, incompatible with wy2u0k function |
|
|
|
#define WYHASH_32BIT_MUM 0 |
|
|
|
#define WYHASH_32BIT_MUM 0 |
|
|
|
#endif |
|
|
|
|
|
|
|
//includes |
|
|
@ -52,7 +52,7 @@ static inline void _wymum(uint64_t *A, uint64_t *B){ |
|
|
|
*A=_wyrot(hl)^hh; *B=_wyrot(lh)^ll; |
|
|
|
#endif |
|
|
|
#elif defined(__SIZEOF_INT128__) |
|
|
|
__uint128_t r=*A; r*=*B; |
|
|
|
__uint128_t r=*A; r*=*B; |
|
|
|
#if(WYHASH_CONDOM>1) |
|
|
|
*A^=(uint64_t)r; *B^=(uint64_t)(r>>64); |
|
|
|
#else |
|
|
@ -123,15 +123,15 @@ static inline uint64_t wyhash(const void *key, size_t len, uint64_t seed, const |
|
|
|
else a=b=0; |
|
|
|
} |
|
|
|
else{ |
|
|
|
size_t i=len; |
|
|
|
if(_unlikely_(i>48)){ |
|
|
|
size_t i=len; |
|
|
|
if(_unlikely_(i>=48)){ |
|
|
|
uint64_t 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)); |
|
|
|
}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; } |
|
|
@ -142,13 +142,13 @@ static inline uint64_t wyhash(const void *key, size_t len, uint64_t seed, const |
|
|
|
} |
|
|
|
|
|
|
|
//the default secret parameters |
|
|
|
static const uint64_t _wyp[4] = {0xa0761d6478bd642full, 0xe7037ed1a0b428dbull, 0x8ebc6af09c88c6e3ull, 0x589965cc75374cc3ull}; |
|
|
|
static const uint64_t _wyp[4] = {0x2d358dccaa6c78a5ull, 0x8bb84b93962eacc9ull, 0x4b33a62ed433d4a3ull, 0x4d5a2da51de1aa47ull}; |
|
|
|
|
|
|
|
//a useful 64bit-64bit mix function to produce deterministic pseudo random numbers that can pass BigCrush and PractRand |
|
|
|
static inline uint64_t wyhash64(uint64_t A, uint64_t B){ A^=0xa0761d6478bd642full; B^=0xe7037ed1a0b428dbull; _wymum(&A,&B); return _wymix(A^0xa0761d6478bd642full,B^0xe7037ed1a0b428dbull);} |
|
|
|
static inline uint64_t wyhash64(uint64_t A, uint64_t B){ A^=0x2d358dccaa6c78a5ull; B^=0x8bb84b93962eacc9ull; _wymum(&A,&B); return _wymix(A^0x2d358dccaa6c78a5ull,B^0x8bb84b93962eacc9ull);} |
|
|
|
|
|
|
|
//The wyrand PRNG that pass BigCrush and PractRand |
|
|
|
static inline uint64_t wyrand(uint64_t *seed){ *seed+=0xa0761d6478bd642full; return _wymix(*seed,*seed^0xe7037ed1a0b428dbull);} |
|
|
|
static inline uint64_t wyrand(uint64_t *seed){ *seed+=0x2d358dccaa6c78a5ull; return _wymix(*seed,*seed^0x8bb84b93962eacc9ull);} |
|
|
|
|
|
|
|
//convert any 64 bit pseudo random numbers to uniform distribution [0,1). It can be combined with wyrand, wyhash64 or wyhash. |
|
|
|
static inline double wy2u01(uint64_t r){ const double _wynorm=1.0/(1ull<<52); return (r>>12)*_wynorm;} |
|
|
@ -173,6 +173,68 @@ static inline uint64_t wytrand(uint64_t *seed){ |
|
|
|
static inline uint64_t wy2u0k(uint64_t r, uint64_t k){ _wymum(&r,&k); return k; } |
|
|
|
#endif |
|
|
|
|
|
|
|
// modified from https://github.com/going-digital/Prime64 |
|
|
|
static inline unsigned long long mul_mod(unsigned long long a, unsigned long long b, unsigned long long m) { |
|
|
|
unsigned long long r=0; |
|
|
|
while (b) { |
|
|
|
if (b & 1) { |
|
|
|
unsigned long long r2 = r + a; |
|
|
|
if (r2 < r) r2 -= m; |
|
|
|
r = r2 % m; |
|
|
|
} |
|
|
|
b >>= 1; |
|
|
|
if (b) { |
|
|
|
unsigned long long a2 = a + a; |
|
|
|
if (a2 < a) a2 -= m; |
|
|
|
a = a2 % m; |
|
|
|
} |
|
|
|
} |
|
|
|
return r; |
|
|
|
} |
|
|
|
static inline unsigned long long pow_mod(unsigned long long a, unsigned long long b, unsigned long long m) { |
|
|
|
unsigned long long r=1; |
|
|
|
while (b) { |
|
|
|
if (b&1) r=mul_mod(r,a,m); |
|
|
|
b>>=1; |
|
|
|
if (b) a=mul_mod(a,a,m); |
|
|
|
} |
|
|
|
return r; |
|
|
|
} |
|
|
|
static inline unsigned sprp(unsigned long long n, unsigned long long a) { |
|
|
|
unsigned long long d=n-1; |
|
|
|
unsigned char s=0; |
|
|
|
while (!(d & 0xff)) { d>>=8; s+=8; } |
|
|
|
if (!(d & 0xf)) { d>>=4; s+=4; } |
|
|
|
if (!(d & 0x3)) { d>>=2; s+=2; } |
|
|
|
if (!(d & 0x1)) { d>>=1; s+=1; } |
|
|
|
unsigned long long b=pow_mod(a,d,n); |
|
|
|
if ((b==1) || (b==(n-1))) return 1; |
|
|
|
unsigned char r; |
|
|
|
for (r=1; r<s; r++) { |
|
|
|
b=mul_mod(b,b,n); |
|
|
|
if (b<=1) return 0; |
|
|
|
if (b==(n-1)) return 1; |
|
|
|
} |
|
|
|
return 0; |
|
|
|
} |
|
|
|
static inline unsigned is_prime(unsigned long long n) { |
|
|
|
if (n<2||!(n&1)) return 0; |
|
|
|
if (n<4) return 1; |
|
|
|
if (!sprp(n,2)) return 0; |
|
|
|
if (n<2047) return 1; |
|
|
|
if (!sprp(n,3)) return 0; |
|
|
|
if (!sprp(n,5)) return 0; |
|
|
|
if (!sprp(n,7)) return 0; |
|
|
|
if (!sprp(n,11)) return 0; |
|
|
|
if (!sprp(n,13)) return 0; |
|
|
|
if (!sprp(n,17)) return 0; |
|
|
|
if (!sprp(n,19)) return 0; |
|
|
|
if (!sprp(n,23)) return 0; |
|
|
|
if (!sprp(n,29)) return 0; |
|
|
|
if (!sprp(n,31)) return 0; |
|
|
|
if (!sprp(n,37)) return 0; |
|
|
|
return 1; |
|
|
|
} |
|
|
|
//make your own secret |
|
|
|
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 }; |
|
|
@ -197,6 +259,7 @@ static inline void make_secret(uint64_t seed, uint64_t *secret){ |
|
|
|
if(x!=32){ ok=0; break; } |
|
|
|
#endif |
|
|
|
} |
|
|
|
if(ok&&!is_prime(secret[i])) ok=0; |
|
|
|
}while(!ok); |
|
|
|
} |
|
|
|
} |
|
|
|