├── LICENSE ├── Modern Non-Cryptographic Hash Function and Pseudorandom Number Generator.pdf ├── README.md ├── SupplementsInformation.zip ├── benchmark.cpp ├── makefile ├── old_versions ├── o1hash.h ├── wyhash32.h ├── wyhash_alpha.h ├── wyhash_beta.h ├── wyhash_final1.h ├── wyhash_final2.h ├── wyhash_final4.h ├── wyhash_gamma.h ├── wyhash_v1.h ├── wyhash_v2.h ├── wyhash_v3.h ├── wyhash_v4.h ├── wyhash_v5.h └── wyhash_v6.h ├── test_vector.cpp ├── wyhash.h └── wyhash32.h /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | 26 | -------------------------------------------------------------------------------- /Modern Non-Cryptographic Hash Function and Pseudorandom Number Generator.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangyi-fudan/wyhash/46cebe9dc4e51f94d0dca287733bc5a94f76a10d/Modern Non-Cryptographic Hash Function and Pseudorandom Number Generator.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | wyhash has evolved into [rapidhash](https://github.com/Nicoshev/rapidhash) ! 2 | With improved speed, quality and compatibility. 3 | ==== 4 | 5 | No hash function is perfect, but some are useful. 6 | ==== 7 | 8 | wyhash and wyrand are the ideal 64-bit hash function and PRNG respectively: 9 | 10 | **solid**: wyhash passed SMHasher, wyrand passed BigCrush, practrand. 11 | 12 | **portable**: 64-bit/32-bit system, big/little endian. 13 | 14 | **fastest**: Efficient on 64-bit machines, especially for short keys. 15 | 16 | **simplest**: In the sense of code size. 17 | 18 | **salted**: We use dynamic secret to avoid intended attack. 19 | 20 | wyhash is the default hashing algorithm of the great [Zig](https://ziglang.org), [V](https://vlang.io), [Nim](https://nim-lang.org) and [Go (since 1.17)](https://golang.org/src/runtime/hash64.go) language. One milestone is that wyhash has deployed by Microsoft on [Windows Terminal] (https://github.com/microsoft/terminal/pull/13686). 21 | 22 | **Simple Example:** 23 | ``` 24 | #include "wyhash.h" 25 | uint64_t _wyp[4]; 26 | make_secret(time(NULL),_wyp); 27 | string s="fcdskhfjs"; 28 | uint64_t h=wyhash(s.c_str(),s.size(),0,_wyp); 29 | ``` 30 | 31 | **Limitations:** 32 | 33 | It is known now that wyhash/wyrand have their limitations: 34 | 35 | Both of them are not 64 bit collision resistant, but is about 62 bits (flyingmutant/Cyan4973/vigna) 36 | 37 | When test on longer dataset (32TB, 23 days), wyrand will fail practrand (vigna) 38 | 39 | And there may be more flaws detected in the future. 40 | 41 | User should make their own decision based the advantage and the flaws of wyhash/wyrand as no one is perfect. 42 | 43 | ---------------------------------------- 44 | 45 | **C#** https://github.com/cocowalla/wyhash-dotnet 46 | 47 | **C++** https://github.com/tommyettinger/waterhash 48 | 49 | **C++** https://github.com/alainesp/wy 50 | 51 | **GO** https://github.com/dgryski/go-wyhash 52 | 53 | **GO** https://github.com/orisano/wyhash 54 | 55 | **GO** https://github.com/littleli/go-wyhash16 56 | 57 | **GO** https://github.com/zeebo/wyhash 58 | 59 | **GO** https://github.com/lonewolf3739/wyhash-go 60 | 61 | **GO** https://github.com/zhangyunhao116/wyhash (final version 1 && 3) 62 | 63 | **Java** https://github.com/OpenHFT/Zero-Allocation-Hashing 64 | 65 | **Java** https://github.com/dynatrace-oss/hash4j (final version 3 and 4) 66 | 67 | **Kotlin Multiplatform** https://github.com/appmattus/crypto/tree/main/cryptohash 68 | 69 | **Nim** https://github.com/nim-lang/Nim/blob/devel/lib/pure/hashes.nim 70 | 71 | **Nim** https://github.com/jackhftang/wyhash.nim 72 | 73 | **Nim** https://github.com/littleli/nim-wyhash16 74 | 75 | **Rust** https://github.com/eldruin/wyhash-rs 76 | 77 | **Swift** https://github.com/lemire/SwiftWyhash 78 | 79 | **Swift** https://github.com/lemire/SwiftWyhashBenchmark 80 | 81 | **Swift** https://github.com/jeudesprits/PSWyhash 82 | 83 | **V** https://github.com/vlang/v/tree/master/vlib/hash/wyhash (v4) 84 | 85 | **Zig** https://github.com/ManDeJan/zig-wyhash 86 | 87 | **absl hashmap** https://github.com/abseil/abseil-cpp/blob/master/absl/hash/internal/low_level_hash.h 88 | 89 | ---------------------------------------- 90 | 91 | I thank these names: 92 | 93 | Reini Urban 94 | 95 | Dietrich Epp 96 | 97 | Joshua Haberman 98 | 99 | Tommy Ettinger 100 | 101 | Daniel Lemire 102 | 103 | Otmar Ertl 104 | 105 | cocowalla 106 | 107 | leo-yuriev 108 | 109 | Diego Barrios Romero 110 | 111 | paulie-g 112 | 113 | dumblob 114 | 115 | Yann Collet 116 | 117 | ivte-ms 118 | 119 | hyb 120 | 121 | James Z.M. Gao 122 | 123 | easyaspi314 (Devin) 124 | 125 | TheOneric 126 | 127 | flyingmutant 128 | 129 | vigna 130 | 131 | tansy 132 | -------------------------------------------------------------------------------- /SupplementsInformation.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangyi-fudan/wyhash/46cebe9dc4e51f94d0dca287733bc5a94f76a10d/SupplementsInformation.zip -------------------------------------------------------------------------------- /benchmark.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #ifndef XXH3 10 | #include "wyhash.h" 11 | #else 12 | #include "../xxHash/xxh3.h" 13 | #endif 14 | 15 | using namespace std; 16 | 17 | struct ha 18 | { 19 | size_t operator()(const string &s, uint64_t seed)const 20 | { 21 | #ifndef XXH3 22 | return wyhash(s.c_str(),s.size(),seed,_wyp); 23 | #else 24 | return XXH3_64bits_withSeed(s.c_str(),s.size(),seed); 25 | #endif 26 | } 27 | }; 28 | 29 | vector v; 30 | template 31 | uint64_t bench_hash(const char *name) 32 | { 33 | Hasher h; 34 | string s; 35 | timeval beg, end; 36 | uint64_t dummy=0; 37 | const uint64_t N=v.size(), R=0x1000; 38 | 39 | cerr.precision(2); 40 | cerr.setf(ios::fixed); 41 | cerr<<'|'<1) 70 | { 71 | if(help_s.compare(argv[1])==0) 72 | { 73 | cout<<"usage:\n"<\n"; 74 | cout<<"if no arguments given \'"<>s; !fi.eof(); fi>>s) 87 | if(s.size()) 88 | v.push_back(s); 89 | fi.close(); 90 | //shuffle the array to benchmark random access 91 | for(size_t i=v.size()-1; i; i--) 92 | swap(v[i],v[rand()%(i+1)]); 93 | 94 | uint64_t r=0; 95 | cerr<("wyhash"); 101 | #else 102 | r+=bench_hash("xxh3"); 103 | #endif 104 | 105 | return r; 106 | } 107 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | # wyhash bench makefile 2 | 3 | CXX = g++ 4 | CXXFLAGS = -std=c++11 -O2 -s -Wall -march=native 5 | 6 | TARGETS = test_vector wyhash0 wyhash1 wyhash2 xxh3scalar xxh3sse2 xxh3avx2 7 | 8 | all: $(TARGETS) 9 | 10 | test_vector: test_vector.cpp wyhash.h 11 | $(CXX) test_vector.cpp -o test_vector $(CXXFLAGS) 12 | 13 | wyhash0: benchmark.cpp wyhash.h 14 | $(CXX) benchmark.cpp -o wyhash0 $(CXXFLAGS) -DWYHASH_CONDOM=0 15 | 16 | wyhash1: benchmark.cpp wyhash.h 17 | $(CXX) benchmark.cpp -o wyhash1 $(CXXFLAGS) -DWYHASH_CONDOM=1 18 | 19 | wyhash2: benchmark.cpp wyhash.h 20 | $(CXX) benchmark.cpp -o wyhash2 $(CXXFLAGS) -DWYHASH_CONDOM=2 21 | 22 | xxh3scalar: benchmark.cpp 23 | $(CXX) benchmark.cpp -o xxh3scalar $(CXXFLAGS) -DXXH_VECTOR=0 -DXXH3 24 | 25 | xxh3sse2: benchmark.cpp 26 | $(CXX) benchmark.cpp -o xxh3sse2 $(CXXFLAGS) -DXXH_VECTOR=1 -DXXH3 27 | 28 | xxh3avx2: benchmark.cpp 29 | $(CXX) benchmark.cpp -o xxh3avx2 $(CXXFLAGS) -DXXH_VECTOR=2 -DXXH3 30 | 31 | clean: 32 | rm $(TARGETS) 33 | 34 | -------------------------------------------------------------------------------- /old_versions/o1hash.h: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Wang Yi 3 | This is a quick and dirty hash function designed for O(1) speed. 4 | It makes your hash table application fly in most cases. 5 | It samples first, middle and last 4 bytes to produce the hash. 6 | Do not use it in very serious applications as it's not secure. 7 | */ 8 | #ifndef O1HASH_LITTLE_ENDIAN 9 | #if defined(_WIN32) || defined(__LITTLE_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) 10 | #define O1HASH_LITTLE_ENDIAN 1 11 | #elif defined(__BIG_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) 12 | #define O1HASH_LITTLE_ENDIAN 0 13 | #endif 14 | #endif 15 | #if (O1HASH_LITTLE_ENDIAN) 16 | static inline unsigned _o1r4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return v;} 17 | #else 18 | #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) 19 | static inline unsigned _o1r4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return __builtin_bswap32(v);} 20 | #elif defined(_MSC_VER) 21 | static inline unsigned _o1r4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return _byteswap_ulong(v);} 22 | #endif 23 | #endif 24 | static inline uint64_t o1hash(const void *key, size_t len) { 25 | const uint8_t *p=(const uint8_t*)key; 26 | if(len>=4) { 27 | unsigned first=_o1r4(p), middle=_o1r4(p+(len>>1)-2), last=_o1r4(p+len-4); 28 | return (uint64_t)(first+last)*middle; 29 | } 30 | if(len){ 31 | uint64_t tail=((((unsigned)p[0])<<16) | (((unsigned)p[len>>1])<<8) | p[len-1]); 32 | return tail*0xa0761d6478bd642full; 33 | } 34 | return 0; 35 | } 36 | 37 | -------------------------------------------------------------------------------- /old_versions/wyhash32.h: -------------------------------------------------------------------------------- 1 | // Author: Wang Yi 2 | #include 3 | #include 4 | #ifndef WYHASH32_BIG_ENDIAN 5 | static inline unsigned _wyr32(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return v;} 6 | #elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) 7 | static inline unsigned _wyr32(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return __builtin_bswap32(v);} 8 | #elif defined(_MSC_VER) 9 | static inline unsigned _wyr32(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return _byteswap_ulong(v);} 10 | #endif 11 | static inline unsigned _wyr24(const uint8_t *p, unsigned k) { return (((unsigned)p[0])<<16)|(((unsigned)p[k>>1])<<8)|p[k-1];} 12 | static inline void _wymix32(unsigned *A, unsigned *B){ 13 | uint64_t c=*A^0x53c5ca59u; c*=*B^0x74743c1bu; 14 | *A=(unsigned)c; 15 | *B=(unsigned)(c>>32); 16 | } 17 | static inline unsigned wyhash32(const void *key, uint64_t len, unsigned seed) { 18 | const uint8_t *p=(const uint8_t *)key; uint64_t i=len; 19 | unsigned see1=(unsigned)len; seed^=(unsigned)(len>>32); _wymix32(&seed, &see1); 20 | for(;i>8;i-=8,p+=8){ seed^=_wyr32(p); see1^=_wyr32(p+4); _wymix32(&seed, &see1); } 21 | if(i>=4){ seed^=_wyr32(p); see1^=_wyr32(p+i-4); } else if (i) seed^=_wyr24(p,(unsigned)i); 22 | _wymix32(&seed, &see1); _wymix32(&seed, &see1); return seed^see1; 23 | } 24 | static inline uint64_t wyrand(uint64_t *seed){ 25 | *seed+=0xa0761d6478bd642full; 26 | uint64_t see1=*seed^0xe7037ed1a0b428dbull; 27 | see1*=(see1>>32)|(see1<<32); 28 | return (*seed*((*seed>>32)|(*seed<<32)))^((see1>>32)|(see1<<32)); 29 | } 30 | static inline unsigned wy32x32(unsigned a, unsigned b) { _wymix32(&a,&b); _wymix32(&a,&b); return a^b; } 31 | static inline float wy2u01(unsigned r) { const float _wynorm=1.0f/(1ull<<23); return (r>>9)*_wynorm;} 32 | static inline float wy2gau(unsigned r) { const float _wynorm=1.0f/(1ull<<9); return ((r&0x3ff)+((r>>10)&0x3ff)+((r>>20)&0x3ff))*_wynorm-3.0f;} 33 | -------------------------------------------------------------------------------- /old_versions/wyhash_alpha.h: -------------------------------------------------------------------------------- 1 | // Author: Wang Yi 2 | #ifndef wyhash_version_alpha 3 | #define wyhash_version_alpha 4 | #include 5 | #include 6 | #if defined(_MSC_VER) && defined(_M_X64) 7 | #include 8 | #pragma intrinsic(_umul128) 9 | #endif 10 | #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) 11 | #define _likely_(x) __builtin_expect(x, 1) 12 | #define _unlikely_(x) __builtin_expect(x, 0) 13 | #else 14 | #define _likely_(x) (x) 15 | #define _unlikely_(x) (x) 16 | #endif 17 | const uint64_t _wyp[2] = { 0xa0761d6478bd642full, 0xe7037ed1a0b428dbull}; 18 | static inline uint64_t _wyrotr(uint64_t v, unsigned k) { return (v >> k) | (v << (64 - k));} 19 | static inline uint64_t _wymum(uint64_t A, uint64_t B) { 20 | #ifdef UNOFFICIAL_WYHASH_32BIT 21 | uint64_t hh = (A >> 32) * (B >> 32), hl = (A >> 32) * (unsigned)B, lh = (unsigned)A * (B >> 32), ll = (uint64_t)(unsigned)A * (unsigned)B; 22 | return _wyrotr(hl, 32) ^ _wyrotr(lh, 32) ^ hh ^ ll; 23 | #else 24 | #ifdef __SIZEOF_INT128__ 25 | __uint128_t r = A; r *= B; return (r >> 64) ^ r; 26 | #elif defined(_MSC_VER) && defined(_M_X64) 27 | A = _umul128(A, B, &B); return A ^ B; 28 | #else 29 | uint64_t ha = A >> 32, hb = B >> 32, la = (uint32_t)A, lb = (uint32_t)B, hi, lo; 30 | uint64_t rh = ha * hb, rm0 = ha * lb, rm1 = hb * la, rl = la * lb, t = rl + (rm0 << 32), c = t < rl; 31 | lo = t + (rm1 << 32); c += lo < t; hi = rh + (rm0 >> 32) + (rm1 >> 32) + c; 32 | return hi ^ lo; 33 | #endif 34 | #endif 35 | } 36 | static inline uint64_t _wymix(uint64_t A, uint64_t B) { 37 | #ifdef UNOFFICIAL_WYHASH_CONDOM 38 | return (A ^ B) ^ _wymum(A, B); 39 | #else 40 | return _wymum(A, B); 41 | #endif 42 | } 43 | static inline uint64_t wyhash64(uint64_t A, uint64_t B) { return _wymum(_wymum(A ^ *_wyp, B ^ _wyp[1]), *_wyp);} 44 | static inline uint64_t wyrand(uint64_t *seed) { *seed += *_wyp; return _wymum(*seed ^ _wyp[1], *seed);} 45 | static inline double wy2u01(uint64_t r) { const double _wynorm = 1.0 / (1ull << 52); return (r >> 12) * _wynorm;} 46 | 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;} 47 | #ifndef WYHASH_LITTLE_ENDIAN 48 | #if defined(_WIN32) || defined(__LITTLE_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) 49 | #define WYHASH_LITTLE_ENDIAN 1 50 | #elif defined(__BIG_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) 51 | #define WYHASH_LITTLE_ENDIAN 0 52 | #endif 53 | #endif 54 | #if (WYHASH_LITTLE_ENDIAN) 55 | static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return v;} 56 | static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return v;} 57 | #else 58 | #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) 59 | static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return __builtin_bswap64(v);} 60 | static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return __builtin_bswap32(v);} 61 | #elif defined(_MSC_VER) 62 | static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return _byteswap_uint64(v);} 63 | static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return _byteswap_ulong(v);} 64 | #endif 65 | #endif 66 | 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];} 67 | static inline uint64_t FastestHash(const void *key, size_t len, uint64_t seed) { 68 | const uint8_t *p = (const uint8_t *)key; 69 | return _likely_(len >= 4) ? (_wyr4(p) + _wyr4(p + len - 4)) * (_wyr4(p + (len >> 1) - 2) ^ seed) : (_likely_(len) ? _wyr3(p, len) * (*_wyp ^ seed) : seed); 70 | } 71 | static inline uint64_t _wyhash(const void *key, uint64_t len, uint64_t seed, const uint64_t secret[2]) { 72 | const uint8_t *p = (const uint8_t *)key; uint64_t i = len; seed ^= secret[1]; 73 | if (_likely_(i <= 64)) { 74 | finalization: 75 | if(_likely_(i<=8)) { 76 | if(_likely_(i>=4)) return _wymix(_wyr4(p) ^ *secret, _wyr4(p + i - 4) ^ seed); 77 | else if (_likely_(i)) return _wymix(_wyr3(p, i) ^ *secret, seed); 78 | else return _wymum(*secret, seed); 79 | } 80 | else if(_likely_(i <= 16)) return _wymix(_wyr8(p) ^ *secret, _wyr8(p + i - 8) ^ seed); 81 | else{ seed = _wymix(_wyr8(p) ^ *secret, _wyr8(p + 8) ^ seed); i -= 16; p += 16; goto finalization;} 82 | } 83 | uint64_t see1 = _wyrotr(seed,16), see2 = _wyrotr(seed,32), see3 = _wyrotr(seed,48); 84 | for (; i > 64; i -= 64, p += 64) { 85 | seed = _wymix(_wyr8(p) ^ *secret, _wyr8(p + 8) ^ seed); 86 | see1 = _wymix(_wyr8(p + 16) ^ *secret, _wyr8(p + 24) ^ see1); 87 | see2 = _wymix(_wyr8(p + 32) ^ *secret, _wyr8(p + 40) ^ see2); 88 | see3 = _wymix(_wyr8(p + 48) ^ *secret, _wyr8(p + 56) ^ see3); 89 | } 90 | seed ^= see1 ^ see2 ^ see3; 91 | goto finalization; 92 | } 93 | static inline uint64_t wyhash(const void *key, uint64_t len, uint64_t seed, const uint64_t secret[2]) { return _wymum(_wyhash(key, len, seed, secret) ^ len, *secret);} 94 | static inline void make_secret(uint64_t seed, uint64_t secret[2]) { 95 | 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 }; 96 | for (size_t i = 0; i < 2; i++) { 97 | uint8_t ok; 98 | do { 99 | ok = 1; secret[i] = 0; 100 | for (size_t j = 0; j < 64; j += 8) secret[i] |= ((uint64_t)c[wyrand(&seed) % sizeof(c)]) << j; 101 | if (secret[i] % 2 == 0) { ok = 0; continue; } 102 | for (size_t j = 0; j < i; j++) 103 | #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) 104 | if (__builtin_popcountll(secret[i] ^ secret[j]) != 32) { 105 | ok = 0; 106 | break; 107 | } 108 | #elif defined(_MSC_VER) 109 | if (_mm_popcnt_u64(secret[i] ^ secret[j]) != 32) { 110 | ok = 0; 111 | break; 112 | } 113 | #endif 114 | if (!ok||secret[i]%2==0) continue; 115 | for (uint64_t j = 3; j < 0x100000000ull; j += 2) if (secret[i] % j == 0) { ok = 0; break;} 116 | } while (!ok); 117 | } 118 | } 119 | /* 120 | typedef struct wyhash_context { 121 | uint64_t secret[6]; 122 | uint64_t seed, see1, see2, see3; 123 | uint8_t buffer[64]; 124 | uint8_t left; // always in [0, 64] 125 | int loop; 126 | uint64_t total; 127 | } wyhash_context_t; 128 | static inline void wyhash_init(wyhash_context_t *const __restrict ctx, 129 | const uint64_t seed, const uint64_t secret[5]) { 130 | memcpy(ctx->secret, secret, sizeof(ctx->secret)); 131 | ctx->seed = seed ^ secret[4]; 132 | ctx->see1 = ctx->seed; 133 | ctx->see2 = ctx->seed; 134 | ctx->see3 = ctx->seed; 135 | ctx->left = 0; 136 | ctx->total = 0; 137 | ctx->loop = 0; 138 | } 139 | static inline uint64_t _wyhash_loop(wyhash_context_t *const __restrict ctx, 140 | const uint8_t *p, const uint64_t len) { 141 | uint64_t i = len; 142 | ctx->loop |= (i > 64); 143 | for (; i > 64; i -= 64, p += 64) { 144 | ctx->seed = _wymix(_wyr8(p) ^ ctx->secret[0], _wyr8(p + 8) ^ ctx->seed); 145 | ctx->see1 = _wymix(_wyr8(p + 16) ^ ctx->secret[1], _wyr8(p + 24) ^ ctx->see1); 146 | ctx->see2 = _wymix(_wyr8(p + 32) ^ ctx->secret[2], _wyr8(p + 40) ^ ctx->see2); 147 | ctx->see3 = _wymix(_wyr8(p + 48) ^ ctx->secret[3], _wyr8(p + 56) ^ ctx->see3); 148 | } 149 | return len - i; 150 | } 151 | static inline void wyhash_update(wyhash_context_t *const __restrict ctx, 152 | const void *const key, uint64_t len) { 153 | ctx->total += len; // overflow for total length is ok 154 | const uint8_t *p = (const uint8_t *)key; 155 | uint8_t slots = 64 - ctx->left; // assert left <= 64 156 | slots = len <= slots ? len : slots; 157 | memcpy(ctx->buffer + ctx->left, p, slots); 158 | p += slots; 159 | len -= slots; 160 | ctx->left += slots; 161 | ctx->left -= _wyhash_loop(ctx, ctx->buffer, ctx->left + (len > 0)); 162 | const uint64_t consumed = _wyhash_loop(ctx, p, len); 163 | p += consumed; 164 | len -= consumed; // assert len <= 64 165 | ctx->left = ctx->left > len ? ctx->left : (uint8_t)len; 166 | memcpy(ctx->buffer, p, len); 167 | } 168 | static inline uint64_t wyhash_final(wyhash_context_t *const __restrict ctx) { 169 | if (_likely_(ctx->loop)) ctx->seed ^= ctx->see1 ^ ctx->see2 ^ ctx->see3; 170 | return _wymum(_wyhash(ctx->buffer, ctx->left, ctx->seed ^ ctx->secret[4], 171 | ctx->secret) ^ 172 | ctx->total, 173 | ctx->secret[4]); 174 | } 175 | */ 176 | #endif 177 | -------------------------------------------------------------------------------- /old_versions/wyhash_beta.h: -------------------------------------------------------------------------------- 1 | // Author: Wang Yi 2 | #ifndef wyhash_version_beta 3 | #define wyhash_version_beta 4 | #include 5 | #include 6 | #if defined(_MSC_VER) && defined(_M_X64) 7 | #include 8 | #pragma intrinsic(_umul128) 9 | #endif 10 | #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) 11 | #define _likely_(x) __builtin_expect(x, 1) 12 | #define _unlikely_(x) __builtin_expect(x, 0) 13 | #else 14 | #define _likely_(x) (x) 15 | #define _unlikely_(x) (x) 16 | #endif 17 | const uint64_t _wyp[4] = {0xa0761d6478bd642full, 0xe7037ed1a0b428dbull, 0x8ebc6af09c88c6e3ull, 0x589965cc75374cc3ull}; 18 | static inline uint64_t _wyrotr(uint64_t v, unsigned k) { return (v >> k) | (v << (64 - k));} 19 | static inline uint64_t _wymum(uint64_t A, uint64_t B) { 20 | #ifdef UNOFFICIAL_WYHASH_32BIT 21 | uint64_t hh = (A >> 32) * (B >> 32), hl = (A >> 32) * (unsigned)B, lh = (unsigned)A * (B >> 32), ll = (uint64_t)(unsigned)A * (unsigned)B; 22 | return _wyrotr(hl, 32) ^ _wyrotr(lh, 32) ^ hh ^ ll; 23 | #else 24 | #ifdef __SIZEOF_INT128__ 25 | __uint128_t r = A; 26 | r *= B; 27 | return (r >> 64) ^ r; 28 | #elif defined(_MSC_VER) && defined(_M_X64) 29 | A = _umul128(A, B, &B); 30 | return A ^ B; 31 | #else 32 | uint64_t ha = A >> 32, hb = B >> 32, la = (uint32_t)A, lb = (uint32_t)B, hi, lo; 33 | uint64_t rh = ha * hb, rm0 = ha * lb, rm1 = hb * la, rl = la * lb, t = rl + (rm0 << 32), c = t < rl; 34 | lo = t + (rm1 << 32); c += lo < t; hi = rh + (rm0 >> 32) + (rm1 >> 32) + c; 35 | return hi ^ lo; 36 | #endif 37 | #endif 38 | } 39 | static inline void _wymix(uint64_t A, uint64_t B, uint64_t *C, uint64_t *D) { 40 | A^=*C; B^=*D; 41 | #ifdef UNOFFICIAL_WYHASH_32BIT 42 | uint64_t hh = (A >> 32) * (B >> 32), hl = (A >> 32) * (unsigned)B, lh = (unsigned)A * (B >> 32), ll = (uint64_t)(unsigned)A * (unsigned)B; 43 | #ifdef UNOFFICIAL_WYHASH_CONDOM 44 | *C^=_wyrotr(hl, 32) ^ hh; *D^=_wyrotr(lh, 32) ^ ll; 45 | #else 46 | *C=_wyrotr(hl, 32) ^ hh; *D=_wyrotr(lh, 32) ^ ll; 47 | #endif 48 | #else 49 | #ifdef __SIZEOF_INT128__ 50 | __uint128_t r = A; r *= B; 51 | #ifdef UNOFFICIAL_WYHASH_CONDOM 52 | *C^=(uint64_t)(r>>64); *D^=(uint64_t)r; 53 | #else 54 | *C=(uint64_t)(r>>64); *D=(uint64_t)r; 55 | #endif 56 | #elif defined(_MSC_VER) && defined(_M_X64) 57 | A = _umul128(A, B, &B); 58 | #ifdef UNOFFICIAL_WYHASH_CONDOM 59 | *C^=A; *D^=B; 60 | #else 61 | *C=A; *D=B; 62 | #endif 63 | #else 64 | uint64_t ha = A >> 32, hb = B >> 32, la = (uint32_t)A, lb = (uint32_t)B, hi, lo; 65 | uint64_t rh = ha * hb, rm0 = ha * lb, rm1 = hb * la, rl = la * lb, t = rl + (rm0 << 32), c = t < rl; 66 | lo = t + (rm1 << 32); c += lo < t; hi = rh + (rm0 >> 32) + (rm1 >> 32) + c; 67 | #ifdef UNOFFICIAL_WYHASH_CONDOM 68 | *C^= hi; *D^= lo; 69 | #else 70 | *C= hi; *D= lo; 71 | #endif 72 | #endif 73 | #endif 74 | } 75 | static inline uint64_t wyhash64(uint64_t A, uint64_t B) { return _wymum(_wymum(A ^ *_wyp, B ^ _wyp[1]), *_wyp);} 76 | static inline uint64_t wyrand(uint64_t *seed) { *seed += *_wyp; return _wymum(*seed ^ _wyp[1], *seed);} 77 | static inline double wy2u01(uint64_t r) { const double _wynorm = 1.0 / (1ull << 52); return (r >> 11) * _wynorm;} 78 | 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;} 79 | #ifndef WYHASH_LITTLE_ENDIAN 80 | #if defined(_WIN32) || defined(__LITTLE_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) 81 | #define WYHASH_LITTLE_ENDIAN 1 82 | #elif defined(__BIG_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) 83 | #define WYHASH_LITTLE_ENDIAN 0 84 | #endif 85 | #endif 86 | #if (WYHASH_LITTLE_ENDIAN) 87 | static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return v^0x5555555555555555ull;} 88 | static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return v^0x5555555555555555ull;} 89 | #else 90 | #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) 91 | static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return __builtin_bswap64(v)^0x5555555555555555ull;} 92 | static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return __builtin_bswap32(v)^0x5555555555555555ull;} 93 | #elif defined(_MSC_VER) 94 | static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return _byteswap_uint64(v)^0x5555555555555555ull;} 95 | static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return _byteswap_ulong(v)^0x5555555555555555ull;} 96 | #endif 97 | #endif 98 | 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])^0x5555555555555555ull;} 99 | static inline uint64_t FastestHash(const void *key, size_t len, uint64_t seed) { 100 | const uint8_t *p = (const uint8_t *)key; 101 | return _likely_(len >= 4) ? (_wyr4(p) + _wyr4(p + len - 4)) * (_wyr4(p + (len >> 1) - 2) ^ seed) : (_likely_(len) ? _wyr3(p, len) * (*_wyp ^ seed) : seed); 102 | } 103 | static inline uint64_t wyhash(const void *key, uint64_t len, uint64_t seed, const uint64_t secret[4]) { 104 | const uint8_t *p = (const uint8_t *)key; uint64_t i = len, see1=seed^*secret, see2=seed^secret[1], see3=seed^secret[2]; seed^=secret[3]; 105 | start: 106 | if(_likely_(i<=32)) { 107 | if(_likely_(i<=8)) { 108 | if(_likely_(i>=4)) _wymix(_wyr4(p), _wyr4(p+i-4),&seed,&see1); 109 | else if (_likely_(i)) _wymix(_wyr3(p, i), secret[3],&seed,&see1); 110 | else _wymix(secret[1], secret[2],&seed,&see1); 111 | } 112 | else if(_likely_(i<=16)) _wymix(_wyr8(p), _wyr8(p+i-8),&seed,&see1); 113 | else { _wymix(_wyr8(p), _wyr8(p+8),&seed,&see1); _wymix(_wyr8(p+i-16), _wyr8(p+i-8),&see2,&see3); } 114 | return _wymum(seed^see2^len,see1^see3^len); 115 | } 116 | else { _wymix(_wyr8(p), _wyr8(p+8),&seed,&see1); _wymix(_wyr8(p+16), _wyr8(p+24),&see2,&see3); i-=32; p+=32; goto start; } 117 | } 118 | #endif 119 | -------------------------------------------------------------------------------- /old_versions/wyhash_final1.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2020 王一 Wang Yi 2 | This is free and unencumbered software released into the public domain. http://unlicense.org/ 3 | See github.com/wangyi-fudan/wyhash/ LICENSE 4 | */ 5 | #ifndef wyhash_final_version 6 | #define wyhash_final_version 7 | //defines that change behavior 8 | #ifndef WYHASH_CONDOM 9 | #define WYHASH_CONDOM 1 //0: read 8 bytes before and after boundaries, dangerous but fastest. 1: normal valid behavior 2: extra protection against entropy loss (probability=2^-63), aka. "blind multiplication" 10 | #endif 11 | #define WYHASH_32BIT_MUM 0 //faster on 32 bit system 12 | //includes 13 | #include 14 | #include 15 | #if defined(_MSC_VER) && defined(_M_X64) 16 | #include 17 | #pragma intrinsic(_umul128) 18 | #endif 19 | #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) 20 | #define _likely_(x) __builtin_expect(x,1) 21 | #define _unlikely_(x) __builtin_expect(x,0) 22 | #else 23 | #define _likely_(x) (x) 24 | #define _unlikely_(x) (x) 25 | #endif 26 | //mum function 27 | static inline uint64_t _wyrot(uint64_t x) { return (x>>32)|(x<<32); } 28 | static inline void _wymum(uint64_t *A, uint64_t *B){ 29 | #if(WYHASH_32BIT_MUM) 30 | uint64_t hh=(*A>>32)*(*B>>32), hl=(*A>>32)*(unsigned)*B, lh=(unsigned)*A*(*B>>32), ll=(uint64_t)(unsigned)*A*(unsigned)*B; 31 | #if(WYHASH_CONDOM>1) 32 | *A^=_wyrot(hl)^hh; *B^=_wyrot(lh)^ll; 33 | #else 34 | *A=_wyrot(hl)^hh; *B=_wyrot(lh)^ll; 35 | #endif 36 | #elif defined(__SIZEOF_INT128__) 37 | __uint128_t r=*A; r*=*B; 38 | #if(WYHASH_CONDOM>1) 39 | *A^=(uint64_t)r; *B^=(uint64_t)(r>>64); 40 | #else 41 | *A=(uint64_t)r; *B=(uint64_t)(r>>64); 42 | #endif 43 | #elif defined(_MSC_VER) && defined(_M_X64) 44 | #if(WYHASH_CONDOM>1) 45 | uint64_t a, b; 46 | a=_umul128(*A,*B,&b); 47 | *A^=a; *B^=b; 48 | #else 49 | *A=_umul128(*A,*B,B); 50 | #endif 51 | #else 52 | uint64_t ha=*A>>32, hb=*B>>32, la=(uint32_t)*A, lb=(uint32_t)*B, hi, lo; 53 | uint64_t rh=ha*hb, rm0=ha*lb, rm1=hb*la, rl=la*lb, t=rl+(rm0<<32), c=t>32)+(rm1>>32)+c; 55 | #if(WYHASH_CONDOM>1) 56 | *A^=lo; *B^=hi; 57 | #else 58 | *A=lo; *B=hi; 59 | #endif 60 | #endif 61 | } 62 | static inline uint64_t _wymix(uint64_t A, uint64_t B){ _wymum(&A,&B); return A^B; } 63 | //read functions 64 | #ifndef WYHASH_LITTLE_ENDIAN 65 | #if defined(_WIN32) || defined(__LITTLE_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) 66 | #define WYHASH_LITTLE_ENDIAN 1 67 | #elif defined(__BIG_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) 68 | #define WYHASH_LITTLE_ENDIAN 0 69 | #endif 70 | #endif 71 | #if (WYHASH_LITTLE_ENDIAN) 72 | static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return v;} 73 | static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return v;} 74 | #elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) 75 | static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return __builtin_bswap64(v);} 76 | static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return __builtin_bswap32(v);} 77 | #elif defined(_MSC_VER) 78 | static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return _byteswap_uint64(v);} 79 | static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return _byteswap_ulong(v);} 80 | #endif 81 | 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];} 82 | //wyhash function 83 | static inline uint64_t _wyfinish16(const uint8_t *p, uint64_t len, uint64_t seed, const uint64_t *secret, uint64_t i){ 84 | #if(WYHASH_CONDOM>0) 85 | uint64_t a, b; 86 | if(_likely_(i<=8)){ 87 | if(_likely_(i>=4)){ a=_wyr4(p); b=_wyr4(p+i-4); } 88 | else if (_likely_(i)){ a=_wyr3(p,i); b=0; } 89 | else a=b=0; 90 | } 91 | else{ a=_wyr8(p); b=_wyr8(p+i-8); } 92 | return _wymix(secret[1]^len,_wymix(a^secret[1], b^seed)); 93 | #else 94 | #define oneshot_shift ((i<8)*((8-i)<<3)) 95 | return _wymix(secret[1]^len,_wymix((_wyr8(p)<>oneshot_shift)^seed)); 96 | #endif 97 | } 98 | 99 | static inline uint64_t _wyfinish(const uint8_t *p, uint64_t len, uint64_t seed, const uint64_t *secret, uint64_t i){ 100 | if(_likely_(i<=16)) return _wyfinish16(p,len,seed,secret,i); 101 | return _wyfinish(p+16,len,_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed),secret,i-16); 102 | } 103 | 104 | static inline uint64_t wyhash(const void *key, uint64_t len, uint64_t seed, const uint64_t *secret){ 105 | const uint8_t *p=(const uint8_t *)key; 106 | uint64_t i=len; seed^=*secret; 107 | if(_unlikely_(i>64)){ 108 | uint64_t see1=seed; 109 | do{ 110 | seed=_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed)^_wymix(_wyr8(p+16)^secret[2],_wyr8(p+24)^seed); 111 | see1=_wymix(_wyr8(p+32)^secret[3],_wyr8(p+40)^see1)^_wymix(_wyr8(p+48)^secret[4],_wyr8(p+56)^see1); 112 | p+=64; i-=64; 113 | }while(i>64); 114 | seed^=see1; 115 | } 116 | return _wyfinish(p,len,seed,secret,i); 117 | } 118 | //utility functions 119 | const uint64_t _wyp[5] = {0xa0761d6478bd642full, 0xe7037ed1a0b428dbull, 0x8ebc6af09c88c6e3ull, 0x589965cc75374cc3ull, 0x1d8e4e27c47d124full}; 120 | 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]);} 121 | static inline uint64_t wyrand(uint64_t *seed){ *seed+=_wyp[0]; return _wymix(*seed,*seed^_wyp[1]);} 122 | static inline double wy2u01(uint64_t r){ const double _wynorm=1.0/(1ull<<52); return (r>>12)*_wynorm;} 123 | 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;} 124 | static inline uint64_t wy2u0k(uint64_t r, uint64_t k){ _wymum(&r,&k); return k; } 125 | 126 | static inline void make_secret(uint64_t seed, uint64_t *secret){ 127 | 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 }; 128 | for(size_t i=0;i<5;i++){ 129 | uint8_t ok; 130 | do{ 131 | ok=1; secret[i]=0; 132 | for(size_t j=0;j<64;j+=8) secret[i]|=((uint64_t)c[wyrand(&seed)%sizeof(c)])< 4 | // contributors: Reini Urban, Dietrich Epp, Joshua Haberman, Tommy Ettinger, Daniel Lemire, Otmar Ertl, cocowalla, leo-yuriev, Diego Barrios Romero, paulie-g, dumblob, Yann Collet, ivte-ms, hyb, James Z.M. Gao, easyaspi314 (Devin), TheOneric 5 | 6 | /* quick example: 7 | string s="fjsakfdsjkf"; 8 | uint64_t hash=wyhash(s.c_str(), s.size(), 0, _wyp); 9 | */ 10 | 11 | #ifndef wyhash_final_version_2 12 | #define wyhash_final_version_2 13 | 14 | #ifndef WYHASH_CONDOM 15 | //protections that produce different results: 16 | //0: read 8 bytes before and after boundaries, dangerous but fastest 17 | //1: normal valid behavior 18 | //2: extra protection against entropy loss (probability=2^-63), aka. "blind multiplication" 19 | #define WYHASH_CONDOM 1 20 | #endif 21 | 22 | #ifndef WYHASH_32BIT_MUM 23 | //0: normal version, slow on 32 bit systems 24 | //1: faster on 32 bit systems but produces different results, incompatible with wy2u0k function 25 | #define WYHASH_32BIT_MUM 0 26 | #endif 27 | 28 | //includes 29 | #include 30 | #include 31 | #if defined(_MSC_VER) && defined(_M_X64) 32 | #include 33 | #pragma intrinsic(_umul128) 34 | #endif 35 | 36 | //likely and unlikely macros 37 | #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) 38 | #define _likely_(x) __builtin_expect(x,1) 39 | #define _unlikely_(x) __builtin_expect(x,0) 40 | #else 41 | #define _likely_(x) (x) 42 | #define _unlikely_(x) (x) 43 | #endif 44 | 45 | //128bit multiply function 46 | static inline uint64_t _wyrot(uint64_t x) { return (x>>32)|(x<<32); } 47 | static inline void _wymum(uint64_t *A, uint64_t *B){ 48 | #if(WYHASH_32BIT_MUM) 49 | uint64_t hh=(*A>>32)*(*B>>32), hl=(*A>>32)*(uint32_t)*B, lh=(uint32_t)*A*(*B>>32), ll=(uint64_t)(uint32_t)*A*(uint32_t)*B; 50 | #if(WYHASH_CONDOM>1) 51 | *A^=_wyrot(hl)^hh; *B^=_wyrot(lh)^ll; 52 | #else 53 | *A=_wyrot(hl)^hh; *B=_wyrot(lh)^ll; 54 | #endif 55 | #elif defined(__SIZEOF_INT128__) 56 | __uint128_t r=*A; r*=*B; 57 | #if(WYHASH_CONDOM>1) 58 | *A^=(uint64_t)r; *B^=(uint64_t)(r>>64); 59 | #else 60 | *A=(uint64_t)r; *B=(uint64_t)(r>>64); 61 | #endif 62 | #elif defined(_MSC_VER) && defined(_M_X64) 63 | #if(WYHASH_CONDOM>1) 64 | uint64_t a, b; 65 | a=_umul128(*A,*B,&b); 66 | *A^=a; *B^=b; 67 | #else 68 | *A=_umul128(*A,*B,B); 69 | #endif 70 | #else 71 | uint64_t ha=*A>>32, hb=*B>>32, la=(uint32_t)*A, lb=(uint32_t)*B, hi, lo; 72 | uint64_t rh=ha*hb, rm0=ha*lb, rm1=hb*la, rl=la*lb, t=rl+(rm0<<32), c=t>32)+(rm1>>32)+c; 74 | #if(WYHASH_CONDOM>1) 75 | *A^=lo; *B^=hi; 76 | #else 77 | *A=lo; *B=hi; 78 | #endif 79 | #endif 80 | } 81 | 82 | //multiply and xor mix function, aka MUM 83 | static inline uint64_t _wymix(uint64_t A, uint64_t B){ _wymum(&A,&B); return A^B; } 84 | 85 | //endian macros 86 | #ifndef WYHASH_LITTLE_ENDIAN 87 | #if defined(_WIN32) || defined(__LITTLE_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) 88 | #define WYHASH_LITTLE_ENDIAN 1 89 | #elif defined(__BIG_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) 90 | #define WYHASH_LITTLE_ENDIAN 0 91 | #else 92 | #warning could not determine endianness! Falling back to little endian. 93 | #define WYHASH_LITTLE_ENDIAN 1 94 | #endif 95 | #endif 96 | 97 | //read functions 98 | #if (WYHASH_LITTLE_ENDIAN) 99 | static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return v;} 100 | static inline uint64_t _wyr4(const uint8_t *p) { uint32_t v; memcpy(&v, p, 4); return v;} 101 | #elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) 102 | static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return __builtin_bswap64(v);} 103 | static inline uint64_t _wyr4(const uint8_t *p) { uint32_t v; memcpy(&v, p, 4); return __builtin_bswap32(v);} 104 | #elif defined(_MSC_VER) 105 | static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return _byteswap_uint64(v);} 106 | static inline uint64_t _wyr4(const uint8_t *p) { uint32_t v; memcpy(&v, p, 4); return _byteswap_ulong(v);} 107 | #else 108 | static inline uint64_t _wyr8(const uint8_t *p) { 109 | uint64_t v; memcpy(&v, p, 8); 110 | 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)); 111 | } 112 | static inline uint64_t _wyr4(const uint8_t *p) { 113 | uint32_t v; memcpy(&v, p, 4); 114 | return (((v >> 24) & 0xff)| ((v >> 8) & 0xff00)| ((v << 8) & 0xff0000)| ((v << 24) & 0xff000000)); 115 | } 116 | #endif 117 | static inline uint64_t _wyr3(const uint8_t *p, size_t k) { return (((uint64_t)p[0])<<16)|(((uint64_t)p[k>>1])<<8)|p[k-1];} 118 | 119 | //wyhash main function 120 | static inline uint64_t wyhash(const void *key, size_t len, uint64_t seed, const uint64_t *secret){ 121 | const uint8_t *p=(const uint8_t *)key; uint64_t a,b; seed^=*secret; 122 | if(_likely_(len<=16)){ 123 | #if(WYHASH_CONDOM>0) 124 | if(_likely_(len<=8)){ 125 | if(_likely_(len>=4)){ a=_wyr4(p); b=_wyr4(p+len-4); } 126 | else if (_likely_(len>0)){ a=_wyr3(p,len); b=0; } 127 | else a=b=0; 128 | } 129 | else{ a=_wyr8(p); b=_wyr8(p+len-8); } 130 | #else 131 | size_t s=(len<8)*((8-len)<<3); 132 | a=_wyr8(p)<>s; 133 | #endif 134 | } 135 | else{ 136 | size_t i=len; 137 | if(_unlikely_(i>48)){ 138 | uint64_t see1=seed, see2=seed; 139 | do{ 140 | seed=_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed); 141 | see1=_wymix(_wyr8(p+16)^secret[2],_wyr8(p+24)^see1); 142 | see2=_wymix(_wyr8(p+32)^secret[3],_wyr8(p+40)^see2); 143 | p+=48; i-=48; 144 | }while(i>48); 145 | seed^=see1^see2; 146 | } 147 | while(_unlikely_(i>16)){ seed=_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed); i-=16; p+=16; } 148 | a=_wyr8(p+i-16); b=_wyr8(p+i-8); 149 | } 150 | return _wymix(secret[1]^len,_wymix(a^secret[1], b^seed)); 151 | } 152 | 153 | //the default secret parameters 154 | static const uint64_t _wyp[4] = {0xa0761d6478bd642full, 0xe7037ed1a0b428dbull, 0x8ebc6af09c88c6e3ull, 0x589965cc75374cc3ull}; 155 | 156 | //a useful 64bit-64bit mix function to produce deterministic pseudo random numbers that can pass BigCrush and PractRand 157 | 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]);} 158 | 159 | //The wyrand PRNG that pass BigCrush and PractRand 160 | static inline uint64_t wyrand(uint64_t *seed){ *seed+=_wyp[0]; return _wymix(*seed,*seed^_wyp[1]);} 161 | 162 | //convert any 64 bit pseudo random numbers to uniform distribution [0,1). It can be combined with wyrand, wyhash64 or wyhash. 163 | static inline double wy2u01(uint64_t r){ const double _wynorm=1.0/(1ull<<52); return (r>>12)*_wynorm;} 164 | 165 | //convert any 64 bit pseudo random numbers to APPROXIMATE Gaussian distribution. It can be combined with wyrand, wyhash64 or wyhash. 166 | 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;} 167 | 168 | #if(!WYHASH_32BIT_MUM) 169 | //fast range integer random number generation on [0,k) credit to Daniel Lemire. May not work when WYHASH_32BIT_MUM=1. It can be combined with wyrand, wyhash64 or wyhash. 170 | static inline uint64_t wy2u0k(uint64_t r, uint64_t k){ _wymum(&r,&k); return k; } 171 | #endif 172 | 173 | //make your own secret 174 | static inline void make_secret(uint64_t seed, uint64_t *secret){ 175 | 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 }; 176 | for(size_t i=0;i<4;i++){ 177 | uint8_t ok; 178 | do{ 179 | ok=1; secret[i]=0; 180 | for(size_t j=0;j<64;j+=8) secret[i]|=((uint64_t)c[wyrand(&seed)%sizeof(c)])<> 1) & 0x5555555555555555; 191 | x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333); 192 | x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f; 193 | x = (x * 0x0101010101010101) >> 56; 194 | if(x!=32){ ok=0; break; } 195 | #endif 196 | } 197 | if(!ok)continue; 198 | for(uint64_t j=3;j<0x100000000ull;j+=2) if(secret[i]%j==0){ ok=0; break; } 199 | }while(!ok); 200 | } 201 | } 202 | /* This is world's fastest hash map: 2X~3X faster than bytell_hash_map. 203 | It is a probabilistic hashmap with very low error rate, please DO NOT use it in any serious tasks. 204 | It does not store the keys, but only the hash of keys. 205 | If hash(key1)==hash(key2), we are almost sure that key1==key2. 206 | Prob(Collision)=2^-64 * N * (N-1)/2, where N the number of objects stored. 207 | For 1 million keys, Prob(Colision)=2^-25, which is very safe 208 | For 16 million keys, Prob(Colision)=2^-17, which is safe 209 | For 256 million keys, Prob(Colision)=2^-9, a bit worry 210 | For 1 billion keys, Prob(Colision)=2^-5, worry but not die 211 | For more keys, define wyhashmap128 and use double hash functions to construct 128 bit keys which is very safe 212 | example code: 213 | const uint64_t size=1ull<<20; // we use fixed memory unlike auto increasing ones. it thus maximize memory usage. A power-2 size will be fastest 214 | wyhashmap_t *idx=(wyhashmap_t*)calloc(size,sizeof(wyhashmap_t)); // allocate the index and set it to zero. 215 | vector value(size); // we only care about the index, user should maintain his own value vectors. 216 | vector keys(size); // also you can maintain your own real keys 217 | string key="dhskfhdsj" // the object to be inserted into idx 218 | wyhashmap_t hash_of_key=wyhash(key.c_str(),key.size(),0,_wyp); // use double hash if wyhashmap_t is 128 bit 219 | uint64_t pos=wyhashmap(idx,size,hash_of_key); // get the position to insert 220 | if(idx[pos]) value[pos]++; // if the key is found 221 | else{ idx[pos]=hash_of_key; keys[pos]=key; value[pos]=0; } // if the key is new. you may insert the key or not if it is just a lookup 222 | free(idx); // free the index 223 | */ 224 | #if defined(__SIZEOF_INT128__) && defined(wyhashmap128) 225 | typedef __uint128_t wyhashmap_t; 226 | #else 227 | typedef uint64_t wyhashmap_t; 228 | #endif 229 | 230 | static inline uint64_t wyhashmap(wyhashmap_t *keys, uint64_t size, wyhashmap_t hash){ 231 | uint64_t i0=wy2u0k(hash,size), i; 232 | for(i=i0;i 274 | */ 275 | -------------------------------------------------------------------------------- /old_versions/wyhash_final4.h: -------------------------------------------------------------------------------- 1 | // This is free and unencumbered software released into the public domain under The Unlicense (http://unlicense.org/) 2 | // main repo: https://github.com/wangyi-fudan/wyhash 3 | // author: 王一 Wang Yi 4 | // contributors: Reini Urban, Dietrich Epp, Joshua Haberman, Tommy Ettinger, Daniel Lemire, Otmar Ertl, cocowalla, leo-yuriev, Diego Barrios Romero, paulie-g, dumblob, Yann Collet, ivte-ms, hyb, James Z.M. Gao, easyaspi314 (Devin), TheOneric 5 | 6 | /* quick example: 7 | string s="fjsakfdsjkf"; 8 | uint64_t hash=wyhash(s.c_str(), s.size(), 0, _wyp); 9 | */ 10 | 11 | #ifndef wyhash_final_version_4 12 | #define wyhash_final_version_4 13 | 14 | #ifndef WYHASH_CONDOM 15 | //protections that produce different results: 16 | //1: normal valid behavior 17 | //2: extra protection against entropy loss (probability=2^-63), aka. "blind multiplication" 18 | #define WYHASH_CONDOM 1 19 | #endif 20 | 21 | #ifndef WYHASH_32BIT_MUM 22 | //0: normal version, slow on 32 bit systems 23 | //1: faster on 32 bit systems but produces different results, incompatible with wy2u0k function 24 | #define WYHASH_32BIT_MUM 0 25 | #endif 26 | 27 | //includes 28 | #include 29 | #include 30 | #if defined(_MSC_VER) && defined(_M_X64) 31 | #include 32 | #pragma intrinsic(_umul128) 33 | #endif 34 | 35 | //likely and unlikely macros 36 | #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) 37 | #define _likely_(x) __builtin_expect(x,1) 38 | #define _unlikely_(x) __builtin_expect(x,0) 39 | #else 40 | #define _likely_(x) (x) 41 | #define _unlikely_(x) (x) 42 | #endif 43 | 44 | //128bit multiply function 45 | static inline uint64_t _wyrot(uint64_t x) { return (x>>32)|(x<<32); } 46 | static inline void _wymum(uint64_t *A, uint64_t *B){ 47 | #if(WYHASH_32BIT_MUM) 48 | uint64_t hh=(*A>>32)*(*B>>32), hl=(*A>>32)*(uint32_t)*B, lh=(uint32_t)*A*(*B>>32), ll=(uint64_t)(uint32_t)*A*(uint32_t)*B; 49 | #if(WYHASH_CONDOM>1) 50 | *A^=_wyrot(hl)^hh; *B^=_wyrot(lh)^ll; 51 | #else 52 | *A=_wyrot(hl)^hh; *B=_wyrot(lh)^ll; 53 | #endif 54 | #elif defined(__SIZEOF_INT128__) 55 | __uint128_t r=*A; r*=*B; 56 | #if(WYHASH_CONDOM>1) 57 | *A^=(uint64_t)r; *B^=(uint64_t)(r>>64); 58 | #else 59 | *A=(uint64_t)r; *B=(uint64_t)(r>>64); 60 | #endif 61 | #elif defined(_MSC_VER) && defined(_M_X64) 62 | #if(WYHASH_CONDOM>1) 63 | uint64_t a, b; 64 | a=_umul128(*A,*B,&b); 65 | *A^=a; *B^=b; 66 | #else 67 | *A=_umul128(*A,*B,B); 68 | #endif 69 | #else 70 | uint64_t ha=*A>>32, hb=*B>>32, la=(uint32_t)*A, lb=(uint32_t)*B, hi, lo; 71 | uint64_t rh=ha*hb, rm0=ha*lb, rm1=hb*la, rl=la*lb, t=rl+(rm0<<32), c=t>32)+(rm1>>32)+c; 73 | #if(WYHASH_CONDOM>1) 74 | *A^=lo; *B^=hi; 75 | #else 76 | *A=lo; *B=hi; 77 | #endif 78 | #endif 79 | } 80 | 81 | //multiply and xor mix function, aka MUM 82 | static inline uint64_t _wymix(uint64_t A, uint64_t B){ _wymum(&A,&B); return A^B; } 83 | 84 | //endian macros 85 | #ifndef WYHASH_LITTLE_ENDIAN 86 | #if defined(_WIN32) || defined(__LITTLE_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) 87 | #define WYHASH_LITTLE_ENDIAN 1 88 | #elif defined(__BIG_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) 89 | #define WYHASH_LITTLE_ENDIAN 0 90 | #else 91 | #warning could not determine endianness! Falling back to little endian. 92 | #define WYHASH_LITTLE_ENDIAN 1 93 | #endif 94 | #endif 95 | 96 | //read functions 97 | #if (WYHASH_LITTLE_ENDIAN) 98 | static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return v;} 99 | static inline uint64_t _wyr4(const uint8_t *p) { uint32_t v; memcpy(&v, p, 4); return v;} 100 | #elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) 101 | static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return __builtin_bswap64(v);} 102 | static inline uint64_t _wyr4(const uint8_t *p) { uint32_t v; memcpy(&v, p, 4); return __builtin_bswap32(v);} 103 | #elif defined(_MSC_VER) 104 | static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return _byteswap_uint64(v);} 105 | static inline uint64_t _wyr4(const uint8_t *p) { uint32_t v; memcpy(&v, p, 4); return _byteswap_ulong(v);} 106 | #else 107 | static inline uint64_t _wyr8(const uint8_t *p) { 108 | uint64_t v; memcpy(&v, p, 8); 109 | 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)); 110 | } 111 | static inline uint64_t _wyr4(const uint8_t *p) { 112 | uint32_t v; memcpy(&v, p, 4); 113 | return (((v >> 24) & 0xff)| ((v >> 8) & 0xff00)| ((v << 8) & 0xff0000)| ((v << 24) & 0xff000000)); 114 | } 115 | #endif 116 | static inline uint64_t _wyr3(const uint8_t *p, size_t k) { return (((uint64_t)p[0])<<16)|(((uint64_t)p[k>>1])<<8)|p[k-1];} 117 | //wyhash main function 118 | static inline uint64_t wyhash(const void *key, size_t len, uint64_t seed, const uint64_t *secret){ 119 | const uint8_t *p=(const uint8_t *)key; seed^=_wymix(seed^secret[0],secret[1]); uint64_t a, b; 120 | if(_likely_(len<=16)){ 121 | 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)); } 122 | else if(_likely_(len>0)){ a=_wyr3(p,len); b=0;} 123 | else a=b=0; 124 | } 125 | else{ 126 | size_t i=len; 127 | if(_unlikely_(i>48)){ 128 | uint64_t see1=seed, see2=seed; 129 | do{ 130 | seed=_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed); 131 | see1=_wymix(_wyr8(p+16)^secret[2],_wyr8(p+24)^see1); 132 | see2=_wymix(_wyr8(p+32)^secret[3],_wyr8(p+40)^see2); 133 | p+=48; i-=48; 134 | }while(_likely_(i>48)); 135 | seed^=see1^see2; 136 | } 137 | while(_unlikely_(i>16)){ seed=_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed); i-=16; p+=16; } 138 | a=_wyr8(p+i-16); b=_wyr8(p+i-8); 139 | } 140 | a^=secret[1]; b^=seed; _wymum(&a,&b); 141 | return _wymix(a^secret[0]^len,b^secret[1]); 142 | } 143 | 144 | //the default secret parameters 145 | static const uint64_t _wyp[4] = {0xa0761d6478bd642full, 0xe7037ed1a0b428dbull, 0x8ebc6af09c88c6e3ull, 0x589965cc75374cc3ull}; 146 | 147 | //a useful 64bit-64bit mix function to produce deterministic pseudo random numbers that can pass BigCrush and PractRand 148 | static inline uint64_t wyhash64(uint64_t A, uint64_t B){ A^=0xa0761d6478bd642full; B^=0xe7037ed1a0b428dbull; _wymum(&A,&B); return _wymix(A^0xa0761d6478bd642full,B^0xe7037ed1a0b428dbull);} 149 | 150 | //The wyrand PRNG that pass BigCrush and PractRand 151 | static inline uint64_t wyrand(uint64_t *seed){ *seed+=0xa0761d6478bd642full; return _wymix(*seed,*seed^0xe7037ed1a0b428dbull);} 152 | 153 | //convert any 64 bit pseudo random numbers to uniform distribution [0,1). It can be combined with wyrand, wyhash64 or wyhash. 154 | static inline double wy2u01(uint64_t r){ const double _wynorm=1.0/(1ull<<52); return (r>>12)*_wynorm;} 155 | 156 | //convert any 64 bit pseudo random numbers to APPROXIMATE Gaussian distribution. It can be combined with wyrand, wyhash64 or wyhash. 157 | 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;} 158 | 159 | #ifdef WYTRNG 160 | #include 161 | //The wytrand true random number generator, passed BigCrush. 162 | static inline uint64_t wytrand(uint64_t *seed){ 163 | struct timeval t; gettimeofday(&t,0); 164 | uint64_t teed=(((uint64_t)t.tv_sec)<<32)|t.tv_usec; 165 | teed=_wymix(teed^_wyp[0],*seed^_wyp[1]); 166 | *seed=_wymix(teed^_wyp[0],_wyp[2]); 167 | return _wymix(*seed,*seed^_wyp[3]); 168 | } 169 | #endif 170 | 171 | #if(!WYHASH_32BIT_MUM) 172 | //fast range integer random number generation on [0,k) credit to Daniel Lemire. May not work when WYHASH_32BIT_MUM=1. It can be combined with wyrand, wyhash64 or wyhash. 173 | static inline uint64_t wy2u0k(uint64_t r, uint64_t k){ _wymum(&r,&k); return k; } 174 | #endif 175 | 176 | //make your own secret 177 | static inline void make_secret(uint64_t seed, uint64_t *secret){ 178 | 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 }; 179 | for(size_t i=0;i<4;i++){ 180 | uint8_t ok; 181 | do{ 182 | ok=1; secret[i]=0; 183 | for(size_t j=0;j<64;j+=8) secret[i]|=((uint64_t)c[wyrand(&seed)%sizeof(c)])<> 1) & 0x5555555555555555; 194 | x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333); 195 | x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f; 196 | x = (x * 0x0101010101010101) >> 56; 197 | if(x!=32){ ok=0; break; } 198 | #endif 199 | } 200 | }while(!ok); 201 | } 202 | } 203 | 204 | #endif 205 | 206 | /* The Unlicense 207 | This is free and unencumbered software released into the public domain. 208 | 209 | Anyone is free to copy, modify, publish, use, compile, sell, or 210 | distribute this software, either in source code form or as a compiled 211 | binary, for any purpose, commercial or non-commercial, and by any 212 | means. 213 | 214 | In jurisdictions that recognize copyright laws, the author or authors 215 | of this software dedicate any and all copyright interest in the 216 | software to the public domain. We make this dedication for the benefit 217 | of the public at large and to the detriment of our heirs and 218 | successors. We intend this dedication to be an overt act of 219 | relinquishment in perpetuity of all present and future rights to this 220 | software under copyright law. 221 | 222 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 223 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 224 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 225 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 226 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 227 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 228 | OTHER DEALINGS IN THE SOFTWARE. 229 | 230 | For more information, please refer to 231 | */ 232 | -------------------------------------------------------------------------------- /old_versions/wyhash_gamma.h: -------------------------------------------------------------------------------- 1 | //Author: Wang Yi 2 | #ifndef wyhash_version_gamma 3 | #define wyhash_version_gamma 4 | //defines that change behavior 5 | #define WYHASH_SAFE_READ 0 //may read up to 8 bytes before/after 6 | #define WYHASH_SAFE_MUM 0 //loss of entroy every 2^66 bytes 7 | #define WYHASH_32BIT_MUM 0 //faster on 32 bit system 8 | //includes 9 | #include 10 | #include 11 | #if defined(_MSC_VER) && defined(_M_X64) 12 | #include 13 | #pragma intrinsic(_umul128) 14 | #endif 15 | #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) 16 | #define _likely_(x) __builtin_expect(x,1) 17 | #else 18 | #define _likely_(x) (x) 19 | #endif 20 | //mum function 21 | static inline uint64_t _wyrot(uint64_t x) { return (x>>32)|(x<<32); } 22 | static inline void _wymum(uint64_t *A, uint64_t *B){ 23 | #if(WYHASH_32BIT_MUM) 24 | uint64_t hh=(*A>>32)*(*B>>32), hl=(*A>>32)*(unsigned)*B, lh=(unsigned)*A*(*B>>32), ll=(uint64_t)(unsigned)*A*(unsigned)*B; 25 | #if(WYHASH_SAFE_MUM) 26 | *A|=_wyrot(hl)^hh; *B|=_wyrot(lh)^ll; 27 | #else 28 | *A=_wyrot(hl)^hh; *B=_wyrot(lh)^ll; 29 | #endif 30 | #elif defined(__SIZEOF_INT128__) 31 | __uint128_t r=*A; r*=*B; 32 | #if(WYHASH_SAFE_MUM) 33 | *A|=(uint64_t)r; *B|=(uint64_t)(r>>64); 34 | #else 35 | *A=(uint64_t)r; *B=(uint64_t)(r>>64); 36 | #endif 37 | #elif defined(_MSC_VER) && defined(_M_X64) 38 | #if(WYHASH_SAFE_MUM) 39 | uint64_t a, b; 40 | a=_umul128(*A,*B,&b); 41 | *A|=a; *B|=b; 42 | #else 43 | *A=_umul128(*A,*B,B); 44 | #endif 45 | #else 46 | uint64_t ha=*A>>32, hb=*B>>32, la=(uint32_t)*A, lb=(uint32_t)*B, hi, lo; 47 | uint64_t rh=ha*hb, rm0=ha*lb, rm1=hb*la, rl=la*lb, t=rl+(rm0<<32), c=t>32)+(rm1>>32)+c; 49 | #if(WYHASH_SAFE_MUM) 50 | *A|=lo; *B|=hi; 51 | #else 52 | *A=lo; *B=hi; 53 | #endif 54 | #endif 55 | } 56 | static inline uint64_t _wymix(uint64_t A, uint64_t B){ _wymum(&A,&B); return A^B; } 57 | //read functions 58 | #ifndef WYHASH_LITTLE_ENDIAN 59 | #if defined(_WIN32) || defined(__LITTLE_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) 60 | #define WYHASH_LITTLE_ENDIAN 1 61 | #elif defined(__BIG_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) 62 | #define WYHASH_LITTLE_ENDIAN 0 63 | #endif 64 | #endif 65 | #if (WYHASH_LITTLE_ENDIAN) 66 | static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return v;} 67 | static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return v;} 68 | #elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) 69 | static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return __builtin_bswap64(v);} 70 | static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return __builtin_bswap32(v);} 71 | #elif defined(_MSC_VER) 72 | static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return _byteswap_uint64(v);} 73 | static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return _byteswap_ulong(v);} 74 | #endif 75 | 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];} 76 | //wyhash function 77 | static inline uint64_t wyhash(const void *key, uint64_t len, uint64_t seed, const uint64_t *secret){ 78 | const uint8_t *p=(const uint8_t *)key; 79 | uint64_t i=len, see1=seed; 80 | if(_likely_(i<=64)){ 81 | start: 82 | if(_likely_(i<=16)){ 83 | uint64_t a,b; 84 | #if(WYHASH_SAFE_READ) 85 | if(_likely_(i<=8)){ 86 | if(_likely_(i>=4)){ a=_wyr4(p); b=_wyr4(p+i-4);} 87 | else if (_likely_(i)){ a=_wyr3(p,i); b=0;} 88 | else a=b=0; 89 | } 90 | else{ a=_wyr8(p); b=_wyr8(p+i-8);} 91 | #else 92 | uint64_t shift=(i<8)*((8-i)<<3); 93 | a=_wyr8(p)<>shift; 94 | #endif 95 | seed^=a^secret[0]; see1^=b^secret[1]; 96 | _wymum(&seed, &see1); 97 | return _wymix(seed^len,see1); 98 | } 99 | seed^=_wyr8(p)^secret[0]; 100 | see1^=_wyr8(p+8)^secret[1]; 101 | _wymum(&seed, &see1); 102 | i-=16; p+=16; 103 | goto start; 104 | } 105 | const uint64_t secret2=secret[0]^secret[1]; 106 | const uint64_t secret3=secret[0]+secret[1]; 107 | uint64_t see2,see3; 108 | seed=see1=see2=see3=seed^(secret[0]-secret[1]); 109 | for(;_likely_(i>64);i-=64,p+=64){ 110 | seed=_wymix(_wyr8(p)^seed,_wyr8(p+8)^*secret); 111 | see1=_wymix(_wyr8(p+16)^see1,_wyr8(p+24)^secret[1]); 112 | see2=_wymix(_wyr8(p+32)^see2,_wyr8(p+40)^secret2); 113 | see3=_wymix(_wyr8(p+48)^see3,_wyr8(p+56)^secret3); 114 | } 115 | seed^=see2; see1^=see3; goto start; 116 | } 117 | //utility functions 118 | const uint64_t _wyp[2]={0xf0b21d699cd8c593ull, 0x8be22b55d84e1b55ull}; 119 | 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]);} 120 | static inline uint64_t wyrand(uint64_t *seed){ *seed+=_wyp[0]; return _wymix(*seed,*seed^_wyp[1]);} 121 | static inline double wy2u01(uint64_t r){ const double _wynorm=1.0/(1ull<<52); return (r>>12)*_wynorm;} 122 | 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;} 123 | static inline void make_secret(uint64_t seed, uint64_t secret[2]){ 124 | 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 }; 125 | for(size_t i=0;i<2;i++){ 126 | uint8_t ok; 127 | do{ 128 | ok=1; secret[i]=0; 129 | for(size_t j=0;j<64;j+=8) secret[i]|=((uint64_t)c[wyrand(&seed)%sizeof(c)])< */ 2 | #ifndef wyhash_version_1 3 | #define wyhash_version_1 4 | #include 5 | #include 6 | #include 7 | #if defined(_MSC_VER) && defined(_M_X64) 8 | # include 9 | # pragma intrinsic(_umul128) 10 | #endif 11 | const uint64_t _wyp0 = 0xa0761d6478bd642full, _wyp1 = 0xe7037ed1a0b428dbull, 12 | _wyp2 = 0x8ebc6af09c88c6e3ull; 13 | const uint64_t _wyp3 = 0x589965cc75374cc3ull, _wyp4 = 0x1d8e4e27c47d124full, 14 | _wyp5 = 0xeb44accab455d165ull; 15 | static inline uint64_t _wymum(uint64_t A, uint64_t B) { 16 | #ifdef __SIZEOF_INT128__ 17 | __uint128_t r = A; 18 | r *= B; 19 | return (r >> 64) ^ r; 20 | #elif defined(_MSC_VER) && defined(_M_X64) 21 | A = _umul128(A, B, &B); 22 | return A ^ B; 23 | #else 24 | uint64_t ha = A >> 32, hb = B >> 32, la = (uint32_t)A, lb = (uint32_t)B, hi, 25 | lo; 26 | uint64_t rh = ha * hb, rm0 = ha * lb, rm1 = hb * la, rl = la * lb, 27 | t = rl + (rm0 << 32), c = t < rl; 28 | lo = t + (rm1 << 32); 29 | c += lo < t; 30 | hi = rh + (rm0 >> 32) + (rm1 >> 32) + c; 31 | return hi ^ lo; 32 | #endif 33 | } 34 | static inline uint64_t _wyr08(const uint8_t *p) { 35 | uint8_t v; 36 | memcpy(&v, p, 1); 37 | return v; 38 | } 39 | static inline uint64_t _wyr16(const uint8_t *p) { 40 | uint16_t v; 41 | memcpy(&v, p, 2); 42 | return v; 43 | } 44 | static inline uint64_t _wyr32(const uint8_t *p) { 45 | uint32_t v; 46 | memcpy(&v, p, 4); 47 | return v; 48 | } 49 | static inline uint64_t _wyr64(const uint8_t *p) { 50 | uint64_t v; 51 | memcpy(&v, p, 8); 52 | return v; 53 | } 54 | static inline uint64_t __wyr64(const uint8_t *p) { 55 | return (_wyr32(p) << 32) | _wyr32(p + 4); 56 | } 57 | static inline uint64_t wyhash(const void *key, uint64_t len, uint64_t seed) { 58 | const uint8_t *p = (const uint8_t *)key; 59 | uint64_t i; 60 | for (i = 0; i + 32 <= len; i += 32, p += 32) 61 | seed = 62 | _wymum(seed ^ _wyp0, 63 | _wymum(_wyr64(p) ^ _wyp1, _wyr64(p + 8) ^ _wyp2) ^ 64 | _wymum(_wyr64(p + 16) ^ _wyp3, _wyr64(p + 24) ^ _wyp4)); 65 | seed ^= _wyp0; 66 | switch (len & 31) { 67 | case 1: 68 | seed = _wymum(seed, _wyr08(p) ^ _wyp1); 69 | break; 70 | case 2: 71 | seed = _wymum(seed, _wyr16(p) ^ _wyp1); 72 | break; 73 | case 3: 74 | seed = _wymum(seed, ((_wyr16(p) << 8) | _wyr08(p + 2)) ^ _wyp1); 75 | break; 76 | case 4: 77 | seed = _wymum(seed, _wyr32(p) ^ _wyp1); 78 | break; 79 | case 5: 80 | seed = _wymum(seed, ((_wyr32(p) << 8) | _wyr08(p + 4)) ^ _wyp1); 81 | break; 82 | case 6: 83 | seed = _wymum(seed, ((_wyr32(p) << 16) | _wyr16(p + 4)) ^ _wyp1); 84 | break; 85 | case 7: 86 | seed = _wymum(seed, ((_wyr32(p) << 24) | (_wyr16(p + 4) << 8) | 87 | _wyr08(p + 6)) ^ 88 | _wyp1); 89 | break; 90 | case 8: 91 | seed = _wymum(seed, __wyr64(p) ^ _wyp1); 92 | break; 93 | case 9: 94 | seed = _wymum(__wyr64(p) ^ seed, _wyr08(p + 8) ^ _wyp2); 95 | break; 96 | case 10: 97 | seed = _wymum(__wyr64(p) ^ seed, _wyr16(p + 8) ^ _wyp2); 98 | break; 99 | case 11: 100 | seed = _wymum(__wyr64(p) ^ seed, 101 | ((_wyr16(p + 8) << 8) | _wyr08(p + 8 + 2)) ^ _wyp2); 102 | break; 103 | case 12: 104 | seed = _wymum(__wyr64(p) ^ seed, _wyr32(p + 8) ^ _wyp2); 105 | break; 106 | case 13: 107 | seed = _wymum(__wyr64(p) ^ seed, 108 | ((_wyr32(p + 8) << 8) | _wyr08(p + 8 + 4)) ^ _wyp2); 109 | break; 110 | case 14: 111 | seed = _wymum(__wyr64(p) ^ seed, 112 | ((_wyr32(p + 8) << 16) | _wyr16(p + 8 + 4)) ^ _wyp2); 113 | break; 114 | case 15: 115 | seed = _wymum(__wyr64(p) ^ seed, 116 | ((_wyr32(p + 8) << 24) | (_wyr16(p + 8 + 4) << 8) | 117 | _wyr08(p + 8 + 6)) ^ 118 | _wyp2); 119 | break; 120 | case 16: 121 | seed = _wymum(__wyr64(p) ^ seed, __wyr64(p + 8) ^ _wyp2); 122 | break; 123 | case 17: 124 | seed = _wymum(__wyr64(p) ^ seed, __wyr64(p + 8) ^ _wyp2) ^ 125 | _wymum(seed, _wyr08(p + 16) ^ _wyp3); 126 | break; 127 | case 18: 128 | seed = _wymum(__wyr64(p) ^ seed, __wyr64(p + 8) ^ _wyp2) ^ 129 | _wymum(seed, _wyr16(p + 16) ^ _wyp3); 130 | break; 131 | case 19: 132 | seed = _wymum(__wyr64(p) ^ seed, __wyr64(p + 8) ^ _wyp2) ^ 133 | _wymum(seed, 134 | ((_wyr16(p + 16) << 8) | _wyr08(p + 16 + 2)) ^ _wyp3); 135 | break; 136 | case 20: 137 | seed = _wymum(__wyr64(p) ^ seed, __wyr64(p + 8) ^ _wyp2) ^ 138 | _wymum(seed, _wyr32(p + 16) ^ _wyp3); 139 | break; 140 | case 21: 141 | seed = _wymum(__wyr64(p) ^ seed, __wyr64(p + 8) ^ _wyp2) ^ 142 | _wymum(seed, 143 | ((_wyr32(p + 16) << 8) | _wyr08(p + 16 + 4)) ^ _wyp3); 144 | break; 145 | case 22: 146 | seed = _wymum(__wyr64(p) ^ seed, __wyr64(p + 8) ^ _wyp2) ^ 147 | _wymum(seed, ((_wyr32(p + 16) << 16) | _wyr16(p + 16 + 4)) ^ 148 | _wyp3); 149 | break; 150 | case 23: 151 | seed = 152 | _wymum(__wyr64(p) ^ seed, __wyr64(p + 8) ^ _wyp2) ^ 153 | _wymum(seed, ((_wyr32(p + 16) << 24) | 154 | (_wyr16(p + 16 + 4) << 8) | _wyr08(p + 16 + 6)) ^ 155 | _wyp3); 156 | break; 157 | case 24: 158 | seed = _wymum(__wyr64(p) ^ seed, __wyr64(p + 8) ^ _wyp2) ^ 159 | _wymum(seed, __wyr64(p + 16) ^ _wyp3); 160 | break; 161 | case 25: 162 | seed = _wymum(__wyr64(p) ^ seed, __wyr64(p + 8) ^ _wyp2) ^ 163 | _wymum(__wyr64(p + 16) ^ seed, _wyr08(p + 24) ^ _wyp4); 164 | break; 165 | case 26: 166 | seed = _wymum(__wyr64(p) ^ seed, __wyr64(p + 8) ^ _wyp2) ^ 167 | _wymum(__wyr64(p + 16) ^ seed, _wyr16(p + 24) ^ _wyp4); 168 | break; 169 | case 27: 170 | seed = _wymum(__wyr64(p) ^ seed, __wyr64(p + 8) ^ _wyp2) ^ 171 | _wymum(__wyr64(p + 16) ^ seed, 172 | ((_wyr16(p + 24) << 8) | _wyr08(p + 24 + 2)) ^ _wyp4); 173 | break; 174 | case 28: 175 | seed = _wymum(__wyr64(p) ^ seed, __wyr64(p + 8) ^ _wyp2) ^ 176 | _wymum(__wyr64(p + 16) ^ seed, _wyr32(p + 24) ^ _wyp4); 177 | break; 178 | case 29: 179 | seed = _wymum(__wyr64(p) ^ seed, __wyr64(p + 8) ^ _wyp2) ^ 180 | _wymum(__wyr64(p + 16) ^ seed, 181 | ((_wyr32(p + 24) << 8) | _wyr08(p + 24 + 4)) ^ _wyp4); 182 | break; 183 | case 30: 184 | seed = 185 | _wymum(__wyr64(p) ^ seed, __wyr64(p + 8) ^ _wyp2) ^ 186 | _wymum(__wyr64(p + 16) ^ seed, 187 | ((_wyr32(p + 24) << 16) | _wyr16(p + 24 + 4)) ^ _wyp4); 188 | break; 189 | case 31: 190 | seed = _wymum(__wyr64(p) ^ seed, __wyr64(p + 8) ^ _wyp2) ^ 191 | _wymum(__wyr64(p + 16) ^ seed, 192 | ((_wyr32(p + 24) << 24) | (_wyr16(p + 24 + 4) << 8) | 193 | _wyr08(p + 24 + 6)) ^ 194 | _wyp4); 195 | break; 196 | } 197 | return _wymum(seed, len ^ _wyp5); 198 | } 199 | static inline uint64_t wyhash256(const void *key) { 200 | const uint8_t *p = (const uint8_t *)key; 201 | return _wymum(_wymum(_wyr64(p) ^ _wyp1, _wyr64(p + 8) ^ _wyp2), 202 | _wymum(_wyr64(p + 16) ^ _wyp3, _wyr64(p + 24) ^ _wyp4)); 203 | } 204 | static inline uint64_t wyhash64(uint64_t A, uint64_t B) { 205 | return _wymum(_wymum(A ^ _wyp0, B ^ _wyp1), _wyp2); 206 | } 207 | static inline double wy2u01(uint64_t r) { 208 | const double _wynorm = 1.0 / (1ull << 52); 209 | return (r & 0x000fffffffffffffull) * _wynorm; 210 | } 211 | static inline float wy2gau(uint64_t r) { 212 | const float _wynorm1 = 1.0f / (1ull << 20); 213 | return ((r & 0x1fffff) + ((r >> 21) & 0x1fffff) + (r >> 43)) * _wynorm1 - 214 | 3.0f; 215 | } 216 | static inline uint64_t wyrand(uint64_t *seed) { 217 | *seed += _wyp0; 218 | return _wymum(*seed ^ _wyp1, *seed); 219 | } 220 | static uint64_t _wyrand_seed = 0; 221 | #define WYRAND_MAX 0xffffffffffffffffull 222 | static inline void wysrand(uint64_t seed) { _wyrand_seed = seed; } 223 | static inline uint64_t wyrand(void) { 224 | uint64_t s; 225 | #if defined(_OPENMP) 226 | # pragma omp atomic capture 227 | #endif 228 | { 229 | _wyrand_seed += _wyp0; 230 | s = _wyrand_seed; 231 | } 232 | return _wymum(s ^ _wyp1, s); 233 | } 234 | #endif 235 | -------------------------------------------------------------------------------- /old_versions/wyhash_v2.h: -------------------------------------------------------------------------------- 1 | /* Author: Wang Yi */ 2 | #ifndef wyhash_version_2 3 | #define wyhash_version_2 4 | #include 5 | #include 6 | #if defined(_MSC_VER) && defined(_M_X64) 7 | # include 8 | # pragma intrinsic(_umul128) 9 | #endif 10 | const uint64_t _wyp0 = 0xa0761d6478bd642full, _wyp1 = 0xe7037ed1a0b428dbull, 11 | _wyp2 = 0x8ebc6af09c88c6e3ull, _wyp3 = 0x589965cc75374cc3ull, 12 | _wyp4 = 0x1d8e4e27c47d124full; 13 | static inline uint64_t _wymum(uint64_t A, uint64_t B) { 14 | #ifdef __SIZEOF_INT128__ 15 | __uint128_t r = A; 16 | r *= B; 17 | return (r >> 64) ^ r; 18 | #elif defined(_MSC_VER) && defined(_M_X64) 19 | A = _umul128(A, B, &B); 20 | return A ^ B; 21 | #else 22 | uint64_t ha = A >> 32, hb = B >> 32, la = (uint32_t)A, lb = (uint32_t)B, hi, 23 | lo; 24 | uint64_t rh = ha * hb, rm0 = ha * lb, rm1 = hb * la, rl = la * lb, 25 | t = rl + (rm0 << 32), c = t < rl; 26 | lo = t + (rm1 << 32); 27 | c += lo < t; 28 | hi = rh + (rm0 >> 32) + (rm1 >> 32) + c; 29 | return hi ^ lo; 30 | #endif 31 | } 32 | static inline uint64_t _wymix0(uint64_t A, uint64_t B, uint64_t seed) { 33 | return _wymum(A ^ seed ^ _wyp0, B ^ seed ^ _wyp1); 34 | } 35 | static inline uint64_t _wymix1(uint64_t A, uint64_t B, uint64_t seed) { 36 | return _wymum(A ^ seed ^ _wyp2, B ^ seed ^ _wyp3); 37 | } 38 | static inline uint64_t _wyr08(const uint8_t *p) { 39 | uint8_t v; 40 | memcpy(&v, p, 1); 41 | return v; 42 | } 43 | static inline uint64_t _wyr16(const uint8_t *p) { 44 | uint16_t v; 45 | memcpy(&v, p, 2); 46 | return v; 47 | } 48 | static inline uint64_t _wyr32(const uint8_t *p) { 49 | uint32_t v; 50 | memcpy(&v, p, 4); 51 | return v; 52 | } 53 | static inline uint64_t _wyr64(const uint8_t *p) { 54 | uint64_t v; 55 | memcpy(&v, p, 8); 56 | return v; 57 | } 58 | static inline uint64_t __wyr64(const uint8_t *p) { 59 | return (_wyr32(p) << 32) | _wyr32(p + 4); 60 | } 61 | // to avoid attacks, seed should be initialized as a secret 62 | static inline uint64_t wyhash(const void *key, uint64_t len, uint64_t seed) { 63 | const uint8_t *p = (const uint8_t *)key; 64 | uint64_t i, len1 = len; 65 | for (i = 0; i + 32 <= len; i += 32, p += 32) 66 | seed = _wymix0(_wyr64(p), _wyr64(p + 8), seed) ^ 67 | _wymix1(_wyr64(p + 16), _wyr64(p + 24), seed); 68 | switch (len & 31) { 69 | case 0: 70 | len1 = _wymix0(len1, 0, seed); 71 | break; 72 | case 1: 73 | seed = _wymix0(_wyr08(p), 0, seed); 74 | break; 75 | case 2: 76 | seed = _wymix0(_wyr16(p), 0, seed); 77 | break; 78 | case 3: 79 | seed = _wymix0((_wyr16(p) << 8) | _wyr08(p + 2), 0, seed); 80 | break; 81 | case 4: 82 | seed = _wymix0(_wyr32(p), 0, seed); 83 | break; 84 | case 5: 85 | seed = _wymix0((_wyr32(p) << 8) | _wyr08(p + 4), 0, seed); 86 | break; 87 | case 6: 88 | seed = _wymix0((_wyr32(p) << 16) | _wyr16(p + 4), 0, seed); 89 | break; 90 | case 7: 91 | seed = _wymix0( 92 | (_wyr32(p) << 24) | (_wyr16(p + 4) << 8) | _wyr08(p + 6), 0, 93 | seed); 94 | break; 95 | case 8: 96 | seed = _wymix0(__wyr64(p), 0, seed); 97 | break; 98 | case 9: 99 | seed = _wymix0(__wyr64(p), _wyr08(p + 8), seed); 100 | break; 101 | case 10: 102 | seed = _wymix0(__wyr64(p), _wyr16(p + 8), seed); 103 | break; 104 | case 11: 105 | seed = _wymix0(__wyr64(p), (_wyr16(p + 8) << 8) | _wyr08(p + 8 + 2), 106 | seed); 107 | break; 108 | case 12: 109 | seed = _wymix0(__wyr64(p), _wyr32(p + 8), seed); 110 | break; 111 | case 13: 112 | seed = _wymix0(__wyr64(p), (_wyr32(p + 8) << 8) | _wyr08(p + 8 + 4), 113 | seed); 114 | break; 115 | case 14: 116 | seed = _wymix0(__wyr64(p), 117 | (_wyr32(p + 8) << 16) | _wyr16(p + 8 + 4), seed); 118 | break; 119 | case 15: 120 | seed = _wymix0(__wyr64(p), 121 | (_wyr32(p + 8) << 24) | (_wyr16(p + 8 + 4) << 8) | 122 | _wyr08(p + 8 + 6), 123 | seed); 124 | break; 125 | case 16: 126 | seed = _wymix0(__wyr64(p), __wyr64(p + 8), seed); 127 | break; 128 | case 17: 129 | seed = _wymix0(__wyr64(p), __wyr64(p + 8), seed) ^ 130 | _wymix1(_wyr08(p + 16), 0, seed); 131 | break; 132 | case 18: 133 | seed = _wymix0(__wyr64(p), __wyr64(p + 8), seed) ^ 134 | _wymix1(_wyr16(p + 16), 0, seed); 135 | break; 136 | case 19: 137 | seed = _wymix0(__wyr64(p), __wyr64(p + 8), seed) ^ 138 | _wymix1((_wyr16(p + 16) << 8) | _wyr08(p + 16 + 2), 0, seed); 139 | break; 140 | case 20: 141 | seed = _wymix0(__wyr64(p), __wyr64(p + 8), seed) ^ 142 | _wymix1(_wyr32(p + 16), 0, seed); 143 | break; 144 | case 21: 145 | seed = _wymix0(__wyr64(p), __wyr64(p + 8), seed) ^ 146 | _wymix1((_wyr32(p + 16) << 8) | _wyr08(p + 16 + 4), 0, seed); 147 | break; 148 | case 22: 149 | seed = 150 | _wymix0(__wyr64(p), __wyr64(p + 8), seed) ^ 151 | _wymix1((_wyr32(p + 16) << 16) | _wyr16(p + 16 + 4), 0, seed); 152 | break; 153 | case 23: 154 | seed = _wymix0(__wyr64(p), __wyr64(p + 8), seed) ^ 155 | _wymix1((_wyr32(p + 16) << 24) | (_wyr16(p + 16 + 4) << 8) | 156 | _wyr08(p + 16 + 6), 157 | 0, seed); 158 | break; 159 | case 24: 160 | seed = _wymix0(__wyr64(p), __wyr64(p + 8), seed) ^ 161 | _wymix1(__wyr64(p + 16), 0, seed); 162 | break; 163 | case 25: 164 | seed = _wymix0(__wyr64(p), __wyr64(p + 8), seed) ^ 165 | _wymix1(__wyr64(p + 16), _wyr08(p + 24), seed); 166 | break; 167 | case 26: 168 | seed = _wymix0(__wyr64(p), __wyr64(p + 8), seed) ^ 169 | _wymix1(__wyr64(p + 16), _wyr16(p + 24), seed); 170 | break; 171 | case 27: 172 | seed = _wymix0(__wyr64(p), __wyr64(p + 8), seed) ^ 173 | _wymix1(__wyr64(p + 16), 174 | (_wyr16(p + 24) << 8) | _wyr08(p + 24 + 2), seed); 175 | break; 176 | case 28: 177 | seed = _wymix0(__wyr64(p), __wyr64(p + 8), seed) ^ 178 | _wymix1(__wyr64(p + 16), _wyr32(p + 24), seed); 179 | break; 180 | case 29: 181 | seed = _wymix0(__wyr64(p), __wyr64(p + 8), seed) ^ 182 | _wymix1(__wyr64(p + 16), 183 | (_wyr32(p + 24) << 8) | _wyr08(p + 24 + 4), seed); 184 | break; 185 | case 30: 186 | seed = _wymix0(__wyr64(p), __wyr64(p + 8), seed) ^ 187 | _wymix1(__wyr64(p + 16), 188 | (_wyr32(p + 24) << 16) | _wyr16(p + 24 + 4), seed); 189 | break; 190 | case 31: 191 | seed = _wymix0(__wyr64(p), __wyr64(p + 8), seed) ^ 192 | _wymix1(__wyr64(p + 16), 193 | (_wyr32(p + 24) << 24) | (_wyr16(p + 24 + 4) << 8) | 194 | _wyr08(p + 24 + 6), 195 | seed); 196 | break; 197 | } 198 | return _wymum(seed ^ len1, _wyp4); 199 | } 200 | static inline uint64_t wyhash64(uint64_t A, uint64_t B) { 201 | return _wymum(_wymum(A ^ _wyp0, B ^ _wyp1), _wyp2); 202 | } 203 | static inline double wy2u01(uint64_t r) { 204 | const double _wynorm = 1.0 / (1ull << 52); 205 | return (r & 0x000fffffffffffffull) * _wynorm; 206 | } 207 | static inline float wy2gau(uint64_t r) { 208 | const float _wynorm1 = 1.0f / (1ull << 15); 209 | return (((r >> 16) & 0xffff) + ((r >> 32) & 0xffff) + (r >> 48)) * 210 | _wynorm1 - 211 | 3.0f; 212 | } 213 | static inline uint64_t wyrand(uint64_t *seed) { 214 | *seed += _wyp0; 215 | return _wymum(*seed ^ _wyp1, *seed); 216 | } 217 | static uint64_t _wyrand_seed = 0; 218 | #define WYRAND_MAX 0xffffffffffffffffull 219 | static inline void wysrand(uint64_t seed) { _wyrand_seed = seed; } 220 | static inline uint64_t wygrand(void) { 221 | uint64_t s; 222 | #if defined(_OPENMP) 223 | # pragma omp atomic capture 224 | #endif 225 | { 226 | _wyrand_seed += _wyp0; 227 | s = _wyrand_seed; 228 | } 229 | return _wymum(s ^ _wyp1, s); 230 | } 231 | #endif 232 | -------------------------------------------------------------------------------- /old_versions/wyhash_v3.h: -------------------------------------------------------------------------------- 1 | /* Author: Wang Yi */ 2 | #ifndef wyhash_version_3 3 | #define wyhash_version_3 4 | #include 5 | #include 6 | #if defined(_MSC_VER) && defined(_M_X64) 7 | # include 8 | # pragma intrinsic(_umul128) 9 | #endif 10 | const uint64_t _wyp0 = 0xa0761d6478bd642full, _wyp1 = 0xe7037ed1a0b428dbull, 11 | _wyp2 = 0x8ebc6af09c88c6e3ull, _wyp3 = 0x589965cc75374cc3ull, 12 | _wyp4 = 0x1d8e4e27c47d124full; 13 | static inline uint64_t _wyrotr(uint64_t v, unsigned k) { 14 | return (v >> k) | (v << (64 - k)); 15 | } 16 | static inline uint64_t _wymum(uint64_t A, uint64_t B) { 17 | #ifdef WYHASH32 18 | uint64_t hh = (A >> 32) * (B >> 32), hl = (A >> 32) * (unsigned)B, 19 | lh = (unsigned)A * (B >> 32), 20 | ll = (uint64_t)(unsigned)A * (unsigned)B; 21 | return _wyrotr(hl, 32) ^ _wyrotr(lh, 32) ^ hh ^ ll; 22 | #else 23 | # ifdef __SIZEOF_INT128__ 24 | __uint128_t r = A; 25 | r *= B; 26 | return (r >> 64) ^ r; 27 | # elif defined(_MSC_VER) && defined(_M_X64) 28 | A = _umul128(A, B, &B); 29 | return A ^ B; 30 | # else 31 | uint64_t ha = A >> 32, hb = B >> 32, la = (uint32_t)A, lb = (uint32_t)B, hi, 32 | lo; 33 | uint64_t rh = ha * hb, rm0 = ha * lb, rm1 = hb * la, rl = la * lb, 34 | t = rl + (rm0 << 32), c = t < rl; 35 | lo = t + (rm1 << 32); 36 | c += lo < t; 37 | hi = rh + (rm0 >> 32) + (rm1 >> 32) + c; 38 | return hi ^ lo; 39 | # endif 40 | #endif 41 | } 42 | static inline uint64_t _wyr8(const uint8_t *p) { 43 | uint64_t v; 44 | memcpy(&v, p, 8); 45 | return v; 46 | } 47 | static inline uint64_t _wyr4(const uint8_t *p) { 48 | uint32_t v; 49 | memcpy(&v, p, 4); 50 | return v; 51 | } 52 | static inline uint64_t _wyr3(const uint8_t *p, unsigned k) { 53 | return (((uint64_t)p[0]) << 16) | (((uint64_t)p[k >> 1]) << 8) | p[k - 1]; 54 | } 55 | static inline uint64_t wyhash(const void *key, uint64_t len, uint64_t seed) { 56 | #if defined(__GNUC__) || defined(__INTEL_COMPILER) 57 | if (__builtin_expect(!len, 0)) 58 | #else 59 | if (!len) 60 | #endif 61 | return _wymum(_wymum(seed ^ _wyp0, seed ^ _wyp1), _wyp4); 62 | const uint8_t *p = (const uint8_t *)key; 63 | if (len < 4) 64 | return _wymum(_wymum(_wyr3(p, len) ^ seed ^ _wyp0, seed ^ _wyp1), 65 | len ^ _wyp4); 66 | else if (len <= 8) 67 | return _wymum( 68 | _wymum(_wyr4(p) ^ seed ^ _wyp0, _wyr4(p + len - 4) ^ seed ^ _wyp1), 69 | len ^ _wyp4); 70 | else if (len <= 16) 71 | return _wymum( 72 | _wymum(_wyr8(p) ^ seed ^ _wyp0, _wyr8(p + len - 8) ^ seed ^ _wyp1), 73 | len ^ _wyp4); 74 | else if (len <= 24) 75 | return _wymum( 76 | _wymum(_wyr8(p) ^ seed ^ _wyp0, _wyr8(p + 8) ^ seed ^ _wyp1) ^ 77 | _wymum(_wyr8(p + len - 8) ^ seed ^ _wyp2, seed ^ _wyp3), 78 | len ^ _wyp4); 79 | else if (len <= 32) 80 | return _wymum( 81 | _wymum(_wyr8(p) ^ seed ^ _wyp0, _wyr8(p + 8) ^ seed ^ _wyp1) ^ 82 | _wymum(_wyr8(p + 16) ^ seed ^ _wyp2, 83 | _wyr8(p + len - 8) ^ seed ^ _wyp3), 84 | len ^ _wyp4); 85 | uint64_t see1 = seed, i = len; 86 | if (i >= 256) 87 | for (; i >= 256; i -= 256, p += 256) { 88 | seed = 89 | _wymum(_wyr8(p) ^ seed ^ _wyp0, _wyr8(p + 8) ^ seed ^ _wyp1) ^ 90 | _wymum(_wyr8(p + 16) ^ seed ^ _wyp2, 91 | _wyr8(p + 24) ^ seed ^ _wyp3); 92 | see1 = _wymum(_wyr8(p + 32) ^ see1 ^ _wyp1, 93 | _wyr8(p + 40) ^ see1 ^ _wyp2) ^ 94 | _wymum(_wyr8(p + 48) ^ see1 ^ _wyp3, 95 | _wyr8(p + 56) ^ see1 ^ _wyp0); 96 | seed = _wymum(_wyr8(p + 64) ^ seed ^ _wyp0, 97 | _wyr8(p + 72) ^ seed ^ _wyp1) ^ 98 | _wymum(_wyr8(p + 80) ^ seed ^ _wyp2, 99 | _wyr8(p + 88) ^ seed ^ _wyp3); 100 | see1 = _wymum(_wyr8(p + 96) ^ see1 ^ _wyp1, 101 | _wyr8(p + 104) ^ see1 ^ _wyp2) ^ 102 | _wymum(_wyr8(p + 112) ^ see1 ^ _wyp3, 103 | _wyr8(p + 120) ^ see1 ^ _wyp0); 104 | seed = _wymum(_wyr8(p + 128) ^ seed ^ _wyp0, 105 | _wyr8(p + 136) ^ seed ^ _wyp1) ^ 106 | _wymum(_wyr8(p + 144) ^ seed ^ _wyp2, 107 | _wyr8(p + 152) ^ seed ^ _wyp3); 108 | see1 = _wymum(_wyr8(p + 160) ^ see1 ^ _wyp1, 109 | _wyr8(p + 168) ^ see1 ^ _wyp2) ^ 110 | _wymum(_wyr8(p + 176) ^ see1 ^ _wyp3, 111 | _wyr8(p + 184) ^ see1 ^ _wyp0); 112 | seed = _wymum(_wyr8(p + 192) ^ seed ^ _wyp0, 113 | _wyr8(p + 200) ^ seed ^ _wyp1) ^ 114 | _wymum(_wyr8(p + 208) ^ seed ^ _wyp2, 115 | _wyr8(p + 216) ^ seed ^ _wyp3); 116 | see1 = _wymum(_wyr8(p + 224) ^ see1 ^ _wyp1, 117 | _wyr8(p + 232) ^ see1 ^ _wyp2) ^ 118 | _wymum(_wyr8(p + 240) ^ see1 ^ _wyp3, 119 | _wyr8(p + 248) ^ see1 ^ _wyp0); 120 | } 121 | for (; i >= 32; i -= 32, p += 32) { 122 | seed = _wymum(_wyr8(p) ^ seed ^ _wyp0, _wyr8(p + 8) ^ seed ^ _wyp1); 123 | see1 = 124 | _wymum(_wyr8(p + 16) ^ see1 ^ _wyp2, _wyr8(p + 24) ^ see1 ^ _wyp3); 125 | } 126 | if (!i) { 127 | } else if (i < 4) 128 | seed = _wymum(_wyr3(p, i) ^ seed ^ _wyp0, seed ^ _wyp1); 129 | else if (i <= 8) 130 | seed = _wymum(_wyr4(p) ^ seed ^ _wyp0, _wyr4(p + i - 4) ^ seed ^ _wyp1); 131 | else if (i <= 16) 132 | seed = _wymum(_wyr8(p) ^ seed ^ _wyp0, _wyr8(p + i - 8) ^ seed ^ _wyp1); 133 | else if (i <= 24) { 134 | seed = _wymum(_wyr8(p) ^ seed ^ _wyp0, _wyr8(p + 8) ^ seed ^ _wyp1); 135 | see1 = _wymum(_wyr8(p + i - 8) ^ see1 ^ _wyp2, see1 ^ _wyp3); 136 | } else { 137 | seed = _wymum(_wyr8(p) ^ seed ^ _wyp0, _wyr8(p + 8) ^ seed ^ _wyp1); 138 | see1 = _wymum(_wyr8(p + 16) ^ see1 ^ _wyp2, 139 | _wyr8(p + i - 8) ^ see1 ^ _wyp3); 140 | } 141 | return _wymum(seed ^ see1, len ^ _wyp4); 142 | } 143 | static inline uint64_t wyhash64(uint64_t A, uint64_t B) { 144 | return _wymum(_wymum(A ^ _wyp0, B ^ _wyp1), _wyp2); 145 | } 146 | static inline double wy2u01(uint64_t r) { 147 | const double _wynorm = 1.0 / (1ull << 52); 148 | return (r >> 11) * _wynorm; 149 | } 150 | static inline float wy2gau(uint64_t r) { 151 | const float _wynorm1 = 1.0f / (1ull << 15); 152 | return (((r >> 16) & 0xffff) + ((r >> 32) & 0xffff) + (r >> 48)) * 153 | _wynorm1 - 154 | 3.0f; 155 | } 156 | static inline uint64_t wyrand(uint64_t *seed) { 157 | *seed += _wyp0; 158 | return _wymum(*seed ^ _wyp1, *seed); 159 | } 160 | static uint64_t _wyrand_seed = 0; 161 | #define WYRAND_MAX 0xffffffffffffffffull 162 | static inline void wysrand(uint64_t seed) { _wyrand_seed = seed; } 163 | static inline uint64_t wygrand(void) { 164 | uint64_t s; 165 | #if defined(_OPENMP) 166 | # pragma omp atomic capture 167 | #endif 168 | { 169 | _wyrand_seed += _wyp0; 170 | s = _wyrand_seed; 171 | } 172 | return _wymum(s ^ _wyp1, s); 173 | } 174 | #ifdef WYSUM 175 | static inline char *wysum(const void *key, uint64_t len, char result[15]) { 176 | static const char _wyhanzi[] = 177 | "一乙二十丁厂七卜人入八九几儿了力乃刀又三于干亏士工土才寸下大丈与万上小" 178 | "口巾山千乞川亿个勺久凡及夕丸么广亡门义之尸弓己已子卫也女飞刃习叉马乡丰" 179 | "王井开夫天无元专云扎艺木五支厅不太犬区历尤友匹车巨牙屯比互切瓦止少日中" 180 | "冈贝内水见午牛手毛气升长仁什片仆化仇币仍仅斤爪反介父从今凶分乏公仓月氏" 181 | "勿欠风丹匀乌凤勾文六方火为斗忆订计户认心尺引丑巴孔队办以允予劝双书幻玉" 182 | "刊示末未击打巧正扑扒功扔去甘世古节本术可丙左厉右石布龙平灭轧东卡北占业" 183 | "旧帅归且旦目叶甲申叮电号田由史只央兄叼叫另叨叹四生失禾丘付仗代仙们仪白" 184 | "仔他斥瓜乎丛令用甩印乐句匆册犯外处冬鸟务包饥主市立闪兰半汁汇头汉宁穴它" 185 | "讨写让礼训必议讯记永司尼民出辽奶奴加召皮边发孕圣对台矛纠母幼丝式刑动扛" 186 | "寺吉扣考托老执巩圾扩扫地扬场耳共芒亚芝朽朴机权过臣再协西压厌在有百存而" 187 | "页匠夸夺灰达列死成夹轨邪划迈毕至此贞师尘尖劣光当早吐吓虫曲团同吊吃因吸" 188 | "吗屿帆岁回岂刚则肉网年朱先丢舌竹迁乔伟传乒乓休伍伏优伐延件任伤价份华仰" 189 | "仿伙伪自血向似后行舟全会杀合兆企众爷伞创肌朵杂危旬旨负各名多争色壮冲冰" 190 | "庄庆亦刘齐交次衣产决充妄闭问闯羊并关米灯州汗污江池汤忙兴宇守宅字安讲军" 191 | "许论农讽设访寻那迅尽导异孙阵阳收阶阴防奸如妇好她妈戏羽观欢买红纤级约纪" 192 | "驰巡寿弄麦形进戒吞远违运扶抚坛技坏扰拒找批扯址走抄坝贡攻赤折抓扮抢孝均" 193 | "抛投坟抗坑坊抖护壳志扭块声把报却劫芽花芹芬苍芳严芦劳克苏杆杠杜材村杏极" 194 | "李杨求更束豆两丽医辰励否还歼来连步坚旱盯呈时吴助县里呆园旷围呀吨足邮男" 195 | "困吵串员听吩吹呜吧吼别岗帐财针钉告我乱利秃秀私每兵估体何但伸作伯伶佣低" 196 | "你住位伴身皂佛近彻役返余希坐谷妥含邻岔肝肚肠龟免狂犹角删条卵岛迎饭饮系" 197 | "言冻状亩况床库疗应冷这序辛弃冶忘闲间闷判灶灿弟汪沙汽沃泛沟没沈沉怀忧快" 198 | "完宋宏牢究穷灾良证启评补初社识诉诊词译君灵即层尿尾迟局改张忌际陆阿陈阻" 199 | "附妙妖妨努忍劲鸡驱纯纱纳纲驳纵纷纸纹纺驴纽奉玩环武青责现表规抹拢拔拣担" 200 | "坦押抽拐拖拍者顶拆拥抵拘势抱垃拉拦拌幸招坡披拨择抬其取苦若茂苹苗英范直" 201 | "茄茎茅林枝杯柜析板松枪构杰述枕丧或画卧事刺枣雨卖矿码厕奔奇奋态欧垄妻轰" 202 | "顷转斩轮软到非叔肯齿些虎虏肾贤尚旺具果味昆国昌畅明易昂典固忠咐呼鸣咏呢" 203 | "岸岩帖罗帜岭凯败贩购图钓制知垂牧物乖刮秆和季委佳侍供使例版侄侦侧凭侨佩" 204 | "货依的迫质欣征往爬彼径所舍金命斧爸采受乳贪念贫肤肺肢肿胀朋股肥服胁周昏" 205 | "鱼兔狐忽狗备饰饱饲变京享店夜庙府底剂郊废净盲放刻育闸闹郑券卷单炒炊炕炎" 206 | "炉沫浅法泄河沾泪油泊沿泡注泻泳泥沸波泼泽治怖性怕怜怪学宝宗定宜审宙官空" 207 | "帘实试郎诗肩房诚衬衫视话诞询该详建肃录隶居届刷屈弦承孟孤陕降限妹姑姐姓" 208 | "始驾参艰线练组细驶织终驻驼绍经贯奏春帮珍玻毒型挂封持项垮挎城挠政赴赵挡" 209 | "挺括拴拾挑指垫挣挤拼挖按挥挪某甚革荐巷带草茧茶荒茫荡荣故胡南药标枯柄栋" 210 | "相查柏柳柱柿栏树要咸威歪研砖厘厚砌砍面耐耍牵残殃轻鸦皆背战点临览竖省削" 211 | "尝是盼眨哄显哑冒映星昨畏趴胃贵界虹虾蚁思蚂虽品咽骂哗咱响哈咬咳哪炭峡罚" 212 | "贱贴骨钞钟钢钥钩卸缸拜看矩怎牲选适秒香种秋科重复竿段便俩贷顺修保促侮俭" 213 | "俗俘信皇泉鬼侵追俊盾待律很须叙剑逃食盆胆胜胞胖脉勉狭狮独狡狱狠贸怨急饶" 214 | "蚀饺饼弯将奖哀亭亮度迹庭疮疯疫疤姿亲音帝施闻阀阁差养美姜叛送类迷前首逆" 215 | "总炼炸炮烂剃洁洪洒浇浊洞测洗活派洽染济洋洲浑浓津恒恢恰恼恨举觉宣室宫宪" 216 | "突穿窃客冠语扁袄祖神祝误诱说诵垦退既屋昼费陡眉孩除险院娃姥姨姻娇怒架贺" 217 | "盈勇怠柔垒绑绒结绕骄绘给络骆绝绞统耕耗艳泰珠班素蚕顽盏匪捞栽捕振载赶起" 218 | "盐捎捏埋捉捆捐损都哲逝捡换挽热恐壶挨耻耽恭莲莫荷获晋恶真框桂档桐株桥桃" 219 | "格校核样根索哥速逗栗配翅辱唇夏础破原套逐烈殊顾轿较顿毙致柴桌虑监紧党晒" 220 | "眠晓鸭晃晌晕蚊哨哭恩唤啊唉罢峰圆贼贿钱钳钻铁铃铅缺氧特牺造乘敌秤租积秧" 221 | "秩称秘透笔笑笋债借值倚倾倒倘俱倡候俯倍倦健臭射躬息徒徐舰舱般航途拿爹爱" 222 | "颂翁脆脂胸胳脏胶脑狸狼逢留皱饿恋桨浆衰高席准座脊症病疾疼疲效离唐资凉站" 223 | "剖竞部旁旅畜阅羞瓶拳粉料益兼烤烘烦烧烛烟递涛浙涝酒涉消浩海涂浴浮流润浪" 224 | "浸涨烫涌悟悄悔悦害宽家宵宴宾窄容宰案请朗诸读扇袜袖袍被祥课谁调冤谅谈谊" 225 | "剥恳展剧屑弱陵陶陷陪娱娘通能难预桑绢绣验继球理捧堵描域掩捷排掉堆推掀授" 226 | "教掏掠培接控探据掘职基著勒黄萌萝菌菜萄菊萍菠营械梦梢梅检梳梯桶救副票戚" 227 | "爽聋袭盛雪辅辆虚雀堂常匙晨睁眯眼悬野啦晚啄距跃略蛇累唱患唯崖崭崇圈铜铲" 228 | "银甜梨犁移笨笼笛符第敏做袋悠偿偶偷您售停偏假得衔盘船斜盒鸽悉欲彩领脚脖" 229 | "脸脱象够猜猪猎猫猛馅馆凑减毫麻痒痕廊康庸鹿盗章竟商族旋望率着盖粘粗粒断" 230 | "剪兽清添淋淹渠渐混渔淘液淡深婆梁渗情惜惭悼惧惕惊惨惯寇寄宿窑密谋谎祸谜" 231 | "逮敢屠弹随蛋隆隐婚婶颈绩绪续骑绳维绵绸绿琴斑替款堪搭塔越趁趋超提堤博揭" 232 | "喜插揪搜煮援裁搁搂搅握揉斯期欺联散惹葬葛董葡敬葱落朝辜葵棒棋植森椅椒棵" 233 | "棍棉棚棕惠惑逼厨厦硬确雁殖裂雄暂雅辈悲紫辉敞赏掌晴暑最量喷晶喇遇喊景践" 234 | "跌跑遗蛙蛛蜓喝喂喘喉幅帽赌赔黑铸铺链销锁锄锅锈锋锐短智毯鹅剩稍程稀税筐" 235 | "等筑策筛筒答筋筝傲傅牌堡集焦傍储奥街"; 236 | uint64_t h = wyhash(key, len, 0); 237 | memcpy(result + 1, _wyhanzi + (h & 2047) * 3, 3); 238 | memcpy(result + 4, _wyhanzi + ((h >> 11) & 2047) * 3, 3); 239 | memcpy(result + 7, _wyhanzi + ((h >> 22) & 2047) * 3, 3); 240 | memcpy(result + 10, _wyhanzi + ((h >> 33) & 2047) * 3, 3); 241 | result[0] = 'w'; 242 | result[13] = 'y'; 243 | result[14] = 0; 244 | return result; 245 | } 246 | #endif 247 | #endif 248 | -------------------------------------------------------------------------------- /old_versions/wyhash_v4.h: -------------------------------------------------------------------------------- 1 | // Author: Wang Yi 2 | #ifndef wyhash_version_4 3 | #define wyhash_version_4 4 | #include 5 | #include 6 | #if defined(_MSC_VER) && defined(_M_X64) 7 | # include 8 | # pragma intrinsic(_umul128) 9 | #endif 10 | const uint64_t _wyp0 = 0xa0761d6478bd642full, _wyp1 = 0xe7037ed1a0b428dbull, 11 | _wyp2 = 0x8ebc6af09c88c6e3ull, _wyp3 = 0x589965cc75374cc3ull, 12 | _wyp4 = 0x1d8e4e27c47d124full; 13 | static inline uint64_t _wyrotr(uint64_t v, unsigned k) { 14 | return (v >> k) | (v << (64 - k)); 15 | } 16 | static inline uint64_t _wymum(uint64_t A, uint64_t B) { 17 | #ifdef WYHASH32 18 | uint64_t hh = (A >> 32) * (B >> 32), hl = (A >> 32) * (unsigned)B, 19 | lh = (unsigned)A * (B >> 32), 20 | ll = (uint64_t)(unsigned)A * (unsigned)B; 21 | return _wyrotr(hl, 32) ^ _wyrotr(lh, 32) ^ hh ^ ll; 22 | #else 23 | # ifdef __SIZEOF_INT128__ 24 | __uint128_t r = A; 25 | r *= B; 26 | return (r >> 64) ^ r; 27 | # elif defined(_MSC_VER) && defined(_M_X64) 28 | A = _umul128(A, B, &B); 29 | return A ^ B; 30 | # else 31 | uint64_t ha = A >> 32, hb = B >> 32, la = (uint32_t)A, lb = (uint32_t)B, hi, 32 | lo; 33 | uint64_t rh = ha * hb, rm0 = ha * lb, rm1 = hb * la, rl = la * lb, 34 | t = rl + (rm0 << 32), c = t < rl; 35 | lo = t + (rm1 << 32); 36 | c += lo < t; 37 | hi = rh + (rm0 >> 32) + (rm1 >> 32) + c; 38 | return hi ^ lo; 39 | # endif 40 | #endif 41 | } 42 | #ifndef WYHASH_LITTLE_ENDIAN 43 | # if defined(_WIN32) || defined(__LITTLE_ENDIAN__) || \ 44 | (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) 45 | # define WYHASH_LITTLE_ENDIAN 1 46 | # elif defined(__BIG_ENDIAN__) || \ 47 | (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) 48 | # define WYHASH_LITTLE_ENDIAN 0 49 | # endif 50 | #endif 51 | #if (WYHASH_LITTLE_ENDIAN) 52 | static inline uint64_t _wyr8(const uint8_t *p) { 53 | uint64_t v; 54 | memcpy(&v, p, 8); 55 | return v; 56 | } 57 | static inline uint64_t _wyr4(const uint8_t *p) { 58 | unsigned v; 59 | memcpy(&v, p, 4); 60 | return v; 61 | } 62 | #else 63 | # if defined(__GNUC__) || defined(__INTEL_COMPILER) 64 | static inline uint64_t _wyr8(const uint8_t *p) { 65 | uint64_t v; 66 | memcpy(&v, p, 8); 67 | return __builtin_bswap64(v); 68 | } 69 | static inline uint64_t _wyr4(const uint8_t *p) { 70 | unsigned v; 71 | memcpy(&v, p, 4); 72 | return __builtin_bswap32(v); 73 | } 74 | # elif defined(_MSC_VER) 75 | static inline uint64_t _wyr8(const uint8_t *p) { 76 | uint64_t v; 77 | memcpy(&v, p, 8); 78 | return _byteswap_uint64(v); 79 | } 80 | static inline uint64_t _wyr4(const uint8_t *p) { 81 | unsigned v; 82 | memcpy(&v, p, 4); 83 | return _byteswap_ulong(v); 84 | } 85 | # endif 86 | #endif 87 | static inline uint64_t _wyr3(const uint8_t *p, unsigned k) { 88 | return (((uint64_t)p[0]) << 16) | (((uint64_t)p[k >> 1]) << 8) | p[k - 1]; 89 | } 90 | static inline uint64_t wyhash(const void *key, uint64_t len, uint64_t seed) { 91 | #if defined(__GNUC__) || defined(__INTEL_COMPILER) 92 | # define _like_(x) __builtin_expect(x, 1) 93 | # define _unlike_(x) __builtin_expect(x, 0) 94 | #else 95 | # define _like_(x) (x) 96 | # define _unlike_(x) (x) 97 | #endif 98 | const uint8_t *p = (const uint8_t *)key; 99 | uint64_t i = len; 100 | label: 101 | if (_unlike_(i < 4)) 102 | return _wymum( 103 | _wymum((_like_(i) ? _wyr3(p, i) : 0) ^ seed ^ _wyp0, seed ^ _wyp1), 104 | len ^ _wyp4); 105 | else if (_like_(i <= 8)) 106 | return _wymum( 107 | _wymum(_wyr4(p) ^ seed ^ _wyp0, _wyr4(p + i - 4) ^ seed ^ _wyp1), 108 | len ^ _wyp4); 109 | else if (_like_(i <= 16)) 110 | return _wymum( 111 | _wymum(_wyr8(p) ^ seed ^ _wyp0, _wyr8(p + i - 8) ^ seed ^ _wyp1), 112 | len ^ _wyp4); 113 | else if (_like_(i <= 32)) 114 | return _wymum( 115 | _wymum(_wyr8(p) ^ seed ^ _wyp0, _wyr8(p + 8) ^ seed ^ _wyp1) ^ 116 | _wymum(_wyr8(p + i - 16) ^ seed ^ _wyp2, 117 | _wyr8(p + i - 8) ^ seed ^ _wyp3), 118 | len ^ _wyp4); 119 | else if (_like_(i <= 64)) 120 | return _wymum( 121 | _wymum(_wyr8(p) ^ seed ^ _wyp0, _wyr8(p + 8) ^ seed ^ _wyp1) ^ 122 | _wymum(_wyr8(p + 16) ^ seed ^ _wyp2, 123 | _wyr8(p + 24) ^ seed ^ _wyp3) ^ 124 | _wymum(_wyr8(p + i - 32) ^ seed ^ _wyp1, 125 | _wyr8(p + i - 24) ^ seed ^ _wyp2) ^ 126 | _wymum(_wyr8(p + i - 16) ^ seed ^ _wyp3, 127 | _wyr8(p + i - 8) ^ seed ^ _wyp0), 128 | len ^ _wyp4); 129 | uint64_t see1 = seed, see2 = seed, see3 = seed; 130 | for (; i >= 64; i -= 64, p += 64) { 131 | seed = _wymum(_wyr8(p) ^ seed ^ _wyp0, _wyr8(p + 8) ^ seed ^ _wyp1); 132 | see1 = 133 | _wymum(_wyr8(p + 16) ^ see1 ^ _wyp2, _wyr8(p + 24) ^ see1 ^ _wyp3); 134 | see2 = 135 | _wymum(_wyr8(p + 32) ^ see2 ^ _wyp1, _wyr8(p + 40) ^ see2 ^ _wyp2); 136 | see3 = 137 | _wymum(_wyr8(p + 48) ^ see3 ^ _wyp3, _wyr8(p + 56) ^ see3 ^ _wyp0); 138 | } 139 | seed ^= see1 ^ see2 ^ see3; 140 | goto label; 141 | } 142 | static inline uint64_t wyhash64(uint64_t A, uint64_t B) { 143 | return _wymum(_wymum(A ^ _wyp0, B ^ _wyp1), _wyp2); 144 | } 145 | static inline uint64_t wyrand(uint64_t *seed) { 146 | *seed += _wyp0; 147 | return _wymum(*seed ^ _wyp1, *seed); 148 | } 149 | static inline double wy2u01(uint64_t r) { 150 | const double _wynorm = 1.0 / (1ull << 52); 151 | return (r >> 11) * _wynorm; 152 | } 153 | static inline double wy2gau(uint64_t r) { 154 | const double _wynorm = 1.0 / (1ull << 20); 155 | return ((r & 0x1fffff) + ((r >> 21) & 0x1fffff) + ((r >> 42) & 0x1fffff)) * 156 | _wynorm - 157 | 3.0; 158 | } 159 | #ifdef __cplusplus 160 | # include 161 | template // the minimum fast hash table/set 163 | static inline size_t 164 | key2pos(const KeyT &key, std::vector &keys, std::vector &used) { 165 | HashT hasher; 166 | EqT equaler; 167 | uint64_t h = hasher(key); 168 | for (uint64_t j = 1, r = h; j; j++, r = wyhash64(h, j)) { 169 | for (size_t j = 0; j < 16; j++) { 170 | size_t p = _wyrotr(r, j << 2) >> (64 - Bits); 171 | if (equaler(key, keys[p]) || !used[p]) return p; 172 | } 173 | } 174 | return ~0ull; 175 | } 176 | /* hashmap/hashset example 177 | #include 178 | #include "wyhash.h" 179 | using namespace std; 180 | struct hasher{ size_t operator()(const string &s)const{ return 181 | wyhash(s.c_str(),s.size(),0); }}; int main(void){ std::vector 182 | keys(1ull<<20); std::vector used(1ull<<20); std::vector 183 | values(1ull<<20); string s; size_t pos=0; for(cin>>s; !cin.eof(); cin>>s){ 184 | pos=key2pos<20,string, hasher>(s,keys,used); 185 | if(!used[pos]){ keys[pos]=s; used[pos]=true; values[pos]=0; } 186 | else values[pos]++; 187 | } 188 | return pos; 189 | }*/ 190 | // the minimum bloom filter. parameters calculator: https://hur.st/bloomfilter/ 191 | static inline void bfpush(uint64_t hash_of_key, std::vector &bitset, 192 | size_t size, size_t round) { 193 | for (size_t i = 0; i < round; i++) 194 | bitset[(((__uint128_t)wyhash64(hash_of_key, i)) * size) >> 64] = true; 195 | } 196 | static inline size_t bftest(uint64_t hash_of_key, std::vector &bitset, 197 | size_t size, size_t round) { 198 | for (size_t i = 0; i < round; i++) 199 | if (!bitset[(((__uint128_t)wyhash64(hash_of_key, i)) * size) >> 64]) 200 | return false; 201 | return true; 202 | } 203 | /*bloom filter example 204 | #include 205 | #include "wyhash.h" 206 | using namespace std; 207 | int main(void){ 208 | size_t size=0x2000000; std::vector bits(size); 209 | string s; 210 | for(cin>>s; !cin.eof(); cin>>s) 211 | bfpush(wyhash(s.c_str(),s.size(),0),bits,size,4); 212 | cout< 2 | #ifndef wyhash_version_5 3 | #define wyhash_version_5 4 | #include 5 | #include 6 | #if defined(_MSC_VER) && defined(_M_X64) 7 | # include 8 | # pragma intrinsic(_umul128) 9 | #endif 10 | #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) 11 | # define _likely_(x) __builtin_expect(x, 1) 12 | #else 13 | # define _likely_(x) (x) 14 | #endif 15 | // default secret 16 | const uint64_t _wyp[6] = { 17 | 0xa0761d6478bd642full, 0xe7037ed1a0b428dbull, 18 | 0x8ebc6af09c88c6e3ull, 0x589965cc75374cc3ull, 19 | 0x1d8e4e27c47d124full, 0x72b22b96e169b471ull}; 20 | static inline uint64_t _wyrotr(uint64_t v, unsigned k) { 21 | return (v >> k) | (v << (64 - k)); 22 | } 23 | static inline uint64_t _wymum(uint64_t A, uint64_t B) { 24 | #ifdef UNOFFICIAL_WYHASH_32BIT // fast on 32 bit system 25 | uint64_t hh = (A >> 32) * (B >> 32), hl = (A >> 32) * (unsigned)B, 26 | lh = (unsigned)A * (B >> 32), 27 | ll = (uint64_t)(unsigned)A * (unsigned)B; 28 | return _wyrotr(hl, 32) ^ _wyrotr(lh, 32) ^ hh ^ ll; 29 | #else 30 | # ifdef __SIZEOF_INT128__ 31 | __uint128_t r = A; 32 | r *= B; 33 | return (r >> 64) ^ r; 34 | # elif defined(_MSC_VER) && defined(_M_X64) 35 | A = _umul128(A, B, &B); 36 | return A ^ B; 37 | # else 38 | uint64_t ha = A >> 32, hb = B >> 32, la = (uint32_t)A, lb = (uint32_t)B, hi, 39 | lo; 40 | uint64_t rh = ha * hb, rm0 = ha * lb, rm1 = hb * la, rl = la * lb, 41 | t = rl + (rm0 << 32), c = t < rl; 42 | lo = t + (rm1 << 32); 43 | c += lo < t; 44 | hi = rh + (rm0 >> 32) + (rm1 >> 32) + c; 45 | return hi ^ lo; 46 | # endif 47 | #endif 48 | } 49 | static inline uint64_t _wymix(uint64_t A, uint64_t B) { 50 | #ifdef UNOFFICIAL_WYHASH_FAST // lose entropy with probability 2^-66 per byte 51 | return _wymum(A, B); 52 | #else 53 | return A ^ B ^ _wymum(A, B); 54 | #endif 55 | } 56 | static inline uint64_t wyrand(uint64_t *seed) { 57 | *seed += _wyp[0]; 58 | return _wymum(*seed ^ _wyp[1], *seed); 59 | } 60 | static inline double wy2u01(uint64_t r) { 61 | const double _wynorm = 1.0 / (1ull << 52); 62 | return (r >> 11) * _wynorm; 63 | } 64 | static inline double wy2gau(uint64_t r) { 65 | const double _wynorm = 1.0 / (1ull << 20); 66 | return ((r & 0x1fffff) + ((r >> 21) & 0x1fffff) + ((r >> 42) & 0x1fffff)) * 67 | _wynorm - 68 | 3.0; 69 | } 70 | #ifndef WYHASH_LITTLE_ENDIAN 71 | # if defined(_WIN32) || defined(__LITTLE_ENDIAN__) || \ 72 | (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) 73 | # define WYHASH_LITTLE_ENDIAN 1 74 | # elif defined(__BIG_ENDIAN__) || \ 75 | (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) 76 | # define WYHASH_LITTLE_ENDIAN 0 77 | # endif 78 | #endif 79 | #if (WYHASH_LITTLE_ENDIAN) 80 | static inline uint64_t _wyr8(const uint8_t *p) { 81 | uint64_t v; 82 | memcpy(&v, p, 8); 83 | return v; 84 | } 85 | static inline uint64_t _wyr4(const uint8_t *p) { 86 | unsigned v; 87 | memcpy(&v, p, 4); 88 | return v; 89 | } 90 | #else 91 | # if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) 92 | static inline uint64_t _wyr8(const uint8_t *p) { 93 | uint64_t v; 94 | memcpy(&v, p, 8); 95 | return __builtin_bswap64(v); 96 | } 97 | static inline uint64_t _wyr4(const uint8_t *p) { 98 | unsigned v; 99 | memcpy(&v, p, 4); 100 | return __builtin_bswap32(v); 101 | } 102 | # elif defined(_MSC_VER) 103 | static inline uint64_t _wyr8(const uint8_t *p) { 104 | uint64_t v; 105 | memcpy(&v, p, 8); 106 | return _byteswap_uint64(v); 107 | } 108 | static inline uint64_t _wyr4(const uint8_t *p) { 109 | unsigned v; 110 | memcpy(&v, p, 4); 111 | return _byteswap_ulong(v); 112 | } 113 | # endif 114 | #endif 115 | static inline uint64_t _wyr3(const uint8_t *p, unsigned k) { 116 | return (((uint64_t)p[0]) << 16) | (((uint64_t)p[k >> 1]) << 8) | p[k - 1]; 117 | } 118 | static inline uint64_t FastestHash(const void *key, size_t len, uint64_t seed) { 119 | const uint8_t *p = (const uint8_t *)key; 120 | return _likely_(len >= 4) 121 | ? (_wyr4(p) + _wyr4(p + len - 4)) * 122 | (_wyr4(p + (len >> 1) - 2) ^ seed) 123 | : (_likely_(len) ? _wyr3(p, len) * (_wyp[0] ^ seed) : seed); 124 | } 125 | static inline uint64_t _wyhash(const void *key, uint64_t len, uint64_t seed, 126 | const uint64_t secret[6]) { 127 | const uint8_t *p = (const uint8_t *)key; 128 | uint64_t i = len; 129 | seed ^= secret[4]; 130 | if (_likely_(i <= 64)) { 131 | label: 132 | if (_likely_(i >= 8)) { 133 | if (_likely_(i <= 16)) 134 | return _wymix(_wyr8(p) ^ secret[0], _wyr8(p + i - 8) ^ seed); 135 | else if (_likely_(i <= 32)) 136 | return _wymix(_wyr8(p) ^ secret[0], _wyr8(p + 8) ^ seed) ^ 137 | _wymix(_wyr8(p + i - 16) ^ secret[1], 138 | _wyr8(p + i - 8) ^ seed); 139 | else 140 | return _wymix(_wyr8(p) ^ secret[0], _wyr8(p + 8) ^ seed) ^ 141 | _wymix(_wyr8(p + 16) ^ secret[1], _wyr8(p + 24) ^ seed) ^ 142 | _wymix(_wyr8(p + i - 32) ^ secret[2], 143 | _wyr8(p + i - 24) ^ seed) ^ 144 | _wymix(_wyr8(p + i - 16) ^ secret[3], 145 | _wyr8(p + i - 8) ^ seed); 146 | } else { 147 | if (_likely_(i >= 4)) 148 | return _wymix(_wyr4(p) ^ secret[0], _wyr4(p + i - 4) ^ seed); 149 | else 150 | return _wymix((_likely_(i) ? _wyr3(p, i) : 0) ^ secret[0], 151 | seed); 152 | } 153 | } 154 | uint64_t see1 = seed, see2 = seed, see3 = seed; 155 | for (; i > 64; i -= 64, p += 64) { 156 | seed = _wymix(_wyr8(p) ^ secret[0], _wyr8(p + 8) ^ seed); 157 | see1 = _wymix(_wyr8(p + 16) ^ secret[1], _wyr8(p + 24) ^ see1); 158 | see2 = _wymix(_wyr8(p + 32) ^ secret[2], _wyr8(p + 40) ^ see2); 159 | see3 = _wymix(_wyr8(p + 48) ^ secret[3], _wyr8(p + 56) ^ see3); 160 | } 161 | seed ^= see1 ^ see2 ^ see3; 162 | goto label; 163 | } 164 | static inline uint64_t wyhash(const void *key, uint64_t len, uint64_t seed, 165 | const uint64_t secret[6]) { 166 | return _wymum(_wyhash(key, len, seed, secret) ^ len, secret[5]); 167 | } 168 | static inline void make_secret(uint64_t seed, uint64_t secret[6]) { 169 | uint8_t c[] = {15, 23, 27, 29, 30, 39, 43, 45, 46, 51, 53, 54, 170 | 57, 58, 60, 71, 75, 77, 78, 83, 85, 86, 89, 90, 171 | 92, 99, 101, 102, 105, 106, 108, 113, 114, 116, 120, 135, 172 | 139, 141, 142, 147, 149, 150, 153, 154, 156, 163, 165, 166, 173 | 169, 170, 172, 177, 178, 180, 184, 195, 197, 198, 201, 202, 174 | 204, 209, 210, 212, 216, 225, 226, 228, 232, 240}; 175 | for (size_t i = 0; i < 6; i++) { 176 | uint8_t ok; 177 | do { 178 | ok = 1; 179 | secret[i] = 0; 180 | for (size_t j = 0; j < 64; j += 8) 181 | secret[i] |= ((uint64_t)c[wyrand(&seed) % sizeof(c)]) << j; 182 | if (secret[i] % 2 == 0) { 183 | ok = 0; 184 | continue; 185 | } 186 | for (size_t j = 0; j < i; j++) 187 | #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) 188 | if (__builtin_popcountll(secret[i] ^ secret[j]) != 32) { 189 | ok = 0; 190 | break; 191 | } 192 | #elif defined(_MSC_VER) 193 | if (_mm_popcnt_u64(secret[i] ^ secret[j]) != 32) { 194 | ok = 0; 195 | break; 196 | } 197 | #endif 198 | if (!ok) continue; 199 | for (uint64_t j = 3; j < 0x100000000ull; j += 2) 200 | if (secret[i] % j == 0) { 201 | ok = 0; 202 | break; 203 | } 204 | } while (!ok); 205 | } 206 | } 207 | static inline uint64_t wyhash64(uint64_t A, uint64_t B) { 208 | return _wymum(_wymum(A ^ _wyp[0], B ^ _wyp[1]), _wyp[2]); 209 | } 210 | typedef struct wyhash_context { 211 | uint64_t secret[5]; 212 | uint64_t seed, see1, see2, see3; 213 | uint8_t buffer[64]; 214 | uint8_t left; // always in [0, 64] 215 | int loop; 216 | uint64_t total; 217 | } wyhash_context_t; 218 | static inline void wyhash_init(wyhash_context_t *const __restrict ctx, 219 | const uint64_t seed, const uint64_t secret[5]) { 220 | memcpy(ctx->secret, secret, sizeof(ctx->secret)); 221 | ctx->seed = seed ^ secret[4]; 222 | ctx->see1 = ctx->seed; 223 | ctx->see2 = ctx->seed; 224 | ctx->see3 = ctx->seed; 225 | ctx->left = 0; 226 | ctx->total = 0; 227 | ctx->loop = 0; 228 | } 229 | static inline uint64_t _wyhash_loop(wyhash_context_t *const __restrict ctx, 230 | const uint8_t *p, const uint64_t len) { 231 | uint64_t i = len; 232 | ctx->loop |= (i > 64); 233 | for (; i > 64; i -= 64, p += 64) { 234 | ctx->seed = _wymix(_wyr8(p) ^ ctx->secret[0], _wyr8(p + 8) ^ ctx->seed); 235 | ctx->see1 = 236 | _wymix(_wyr8(p + 16) ^ ctx->secret[1], _wyr8(p + 24) ^ ctx->see1); 237 | ctx->see2 = 238 | _wymix(_wyr8(p + 32) ^ ctx->secret[2], _wyr8(p + 40) ^ ctx->see2); 239 | ctx->see3 = 240 | _wymix(_wyr8(p + 48) ^ ctx->secret[3], _wyr8(p + 56) ^ ctx->see3); 241 | } 242 | return len - i; 243 | } 244 | static inline void wyhash_update(wyhash_context_t *const __restrict ctx, 245 | const void *const key, uint64_t len) { 246 | ctx->total += len; // overflow for total length is ok 247 | const uint8_t *p = (const uint8_t *)key; 248 | uint8_t slots = 64 - ctx->left; // assert left <= 64 249 | slots = len <= slots ? len : slots; 250 | memcpy(ctx->buffer + ctx->left, p, slots); 251 | p += slots; 252 | len -= slots; 253 | ctx->left += slots; 254 | ctx->left -= _wyhash_loop(ctx, ctx->buffer, ctx->left + (len > 0)); 255 | const uint64_t consumed = _wyhash_loop(ctx, p, len); 256 | p += consumed; 257 | len -= consumed; // assert len <= 64 258 | ctx->left = ctx->left > len ? ctx->left : (uint8_t)len; 259 | memcpy(ctx->buffer, p, len); 260 | } 261 | static inline uint64_t wyhash_final(wyhash_context_t *const __restrict ctx) { 262 | if (_likely_(ctx->loop)) ctx->seed ^= ctx->see1 ^ ctx->see2 ^ ctx->see3; 263 | return _wymum(_wyhash(ctx->buffer, ctx->left, ctx->seed ^ ctx->secret[4], 264 | ctx->secret) ^ 265 | ctx->total, 266 | ctx->secret[4]); 267 | } 268 | #endif 269 | -------------------------------------------------------------------------------- /old_versions/wyhash_v6.h: -------------------------------------------------------------------------------- 1 | // Author: Wang Yi 2 | #ifndef wyhash_version_6 3 | #define wyhash_version_6 4 | #include 5 | #include 6 | #if defined(_MSC_VER) && defined(_M_X64) 7 | # include 8 | # pragma intrinsic(_umul128) 9 | #elif defined(__GNUC__) && defined(__SSE2__) 10 | # include 11 | #endif 12 | #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) 13 | # define _likely_(x) __builtin_expect(x, 1) 14 | #else 15 | # define _likely_(x) (x) 16 | #endif 17 | const uint64_t _wyp[10] = {0xb10f1ea5b4358d87ull, 0x2e63952eb46a7127ull, 18 | 0xd88be12db28d1769ull, 0xb8d2a6b2d21e6c55ull, 19 | 0xe43ad88ed1c9ac1bull, 0xe4a33a5336a35a1dull, 20 | 0xe85aca652dd266a5ull, 0x2e1d72638e6c2e4bull, 21 | 0x8ba6d4726c8db48dull, 0x935a749a3ae2478bull}; 22 | static inline uint64_t _wyrotr(uint64_t v, unsigned k) { 23 | return (v >> k) | (v << (64 - k)); 24 | } 25 | static inline uint64_t _wymum(uint64_t A, uint64_t B) { 26 | #ifdef UNOFFICIAL_WYHASH_32BIT // fast on 32 bit system 27 | uint64_t hh = (A >> 32) * (B >> 32), hl = (A >> 32) * (unsigned)B, 28 | lh = (unsigned)A * (B >> 32), 29 | ll = (uint64_t)(unsigned)A * (unsigned)B; 30 | return _wyrotr(hl, 32) ^ _wyrotr(lh, 32) ^ hh ^ ll; 31 | #else 32 | # ifdef __SIZEOF_INT128__ 33 | __uint128_t r = A; 34 | r *= B; 35 | return (r >> 64) ^ r; 36 | # elif defined(_MSC_VER) && defined(_M_X64) 37 | A = _umul128(A, B, &B); 38 | return A ^ B; 39 | # else 40 | uint64_t ha = A >> 32, hb = B >> 32, la = (uint32_t)A, lb = (uint32_t)B, hi, 41 | lo; 42 | uint64_t rh = ha * hb, rm0 = ha * lb, rm1 = hb * la, rl = la * lb, 43 | t = rl + (rm0 << 32), c = t < rl; 44 | lo = t + (rm1 << 32); 45 | c += lo < t; 46 | hi = rh + (rm0 >> 32) + (rm1 >> 32) + c; 47 | return hi ^ lo; 48 | # endif 49 | #endif 50 | } 51 | static inline uint64_t _wymix(uint64_t A, uint64_t B) { 52 | return (A ^ B) ^ _wymum(A, B); 53 | } 54 | static inline uint64_t _wymix32(uint64_t A) { 55 | return A ^ ((A >> 32) * (uint32_t)A); 56 | } 57 | static inline uint64_t wyhash64(uint64_t A, uint64_t B) { 58 | return _wymum(_wymum(A ^ _wyp[0], B ^ _wyp[1]), _wyp[2]); 59 | } 60 | static inline uint64_t wyrand(uint64_t *seed) { 61 | *seed += _wyp[0]; 62 | return _wymum(*seed ^ _wyp[1], *seed); 63 | } 64 | static inline double wy2u01(uint64_t r) { 65 | const double _wynorm = 1.0 / (1ull << 52); 66 | return (r >> 11) * _wynorm; 67 | } 68 | static inline double wy2gau(uint64_t r) { 69 | const double _wynorm = 1.0 / (1ull << 20); 70 | return ((r & 0x1fffff) + ((r >> 21) & 0x1fffff) + ((r >> 42) & 0x1fffff)) * 71 | _wynorm - 72 | 3.0; 73 | } 74 | #ifndef WYHASH_LITTLE_ENDIAN 75 | # if defined(_WIN32) || defined(__LITTLE_ENDIAN__) || \ 76 | (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) 77 | # define WYHASH_LITTLE_ENDIAN 1 78 | # elif defined(__BIG_ENDIAN__) || \ 79 | (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) 80 | # define WYHASH_LITTLE_ENDIAN 0 81 | # endif 82 | #endif 83 | #if (WYHASH_LITTLE_ENDIAN) 84 | static inline uint64_t _wyr8(const uint8_t *p) { 85 | uint64_t v; 86 | memcpy(&v, p, 8); 87 | return v; 88 | } 89 | static inline uint64_t _wyr4(const uint8_t *p) { 90 | unsigned v; 91 | memcpy(&v, p, 4); 92 | return v; 93 | } 94 | #else 95 | # if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) 96 | static inline uint64_t _wyr8(const uint8_t *p) { 97 | uint64_t v; 98 | memcpy(&v, p, 8); 99 | return __builtin_bswap64(v); 100 | } 101 | static inline uint64_t _wyr4(const uint8_t *p) { 102 | unsigned v; 103 | memcpy(&v, p, 4); 104 | return __builtin_bswap32(v); 105 | } 106 | # elif defined(_MSC_VER) 107 | static inline uint64_t _wyr8(const uint8_t *p) { 108 | uint64_t v; 109 | memcpy(&v, p, 8); 110 | return _byteswap_uint64(v); 111 | } 112 | static inline uint64_t _wyr4(const uint8_t *p) { 113 | unsigned v; 114 | memcpy(&v, p, 4); 115 | return _byteswap_ulong(v); 116 | } 117 | # endif 118 | #endif 119 | static inline uint64_t _wyr3(const uint8_t *p, unsigned k) { 120 | return (((uint64_t)p[0]) << 16) | (((uint64_t)p[k >> 1]) << 8) | p[k - 1]; 121 | } 122 | static inline uint64_t FastestHash(const void *key, size_t len, uint64_t seed) { 123 | const uint8_t *p = (const uint8_t *)key; 124 | return _likely_(len >= 4) 125 | ? (_wyr4(p) + _wyr4(p + len - 4)) * 126 | (_wyr4(p + (len >> 1) - 2) ^ seed) 127 | : (_likely_(len) ? _wyr3(p, len) * (_wyp[0] ^ seed) : seed); 128 | } 129 | 130 | static inline uint64_t _wyhash(const void *key, uint64_t len, uint64_t seed, 131 | const uint64_t secret[10]) { 132 | const uint8_t *p = (const uint8_t *)key; 133 | uint64_t i = len; 134 | seed ^= secret[8]; 135 | if (_likely_(i <= 128)) { 136 | finalization: 137 | if (_likely_(i >= 8)) { 138 | if (_likely_(i <= 16)) 139 | return _wymix(_wyr8(p) ^ secret[0], _wyr8(p + i - 8) ^ seed); 140 | else { 141 | seed = _wymix(_wyr8(p) ^ secret[0], _wyr8(p + 8) ^ seed); 142 | i -= 16; 143 | p += 16; 144 | goto finalization; 145 | } 146 | } else if (_likely_(i >= 4)) 147 | return _wymix(_wyr4(p) ^ secret[0], _wyr4(p + i - 4) ^ seed); 148 | else if (_likely_(i)) 149 | return _wymix(_wyr3(p, i) ^ secret[0], seed); 150 | else 151 | return _wymum(secret[0], seed); 152 | } 153 | #if defined(__AVX2__) 154 | __m256i se[4] = 155 | {{(int64_t)seed, (int64_t)seed, (int64_t)seed, (int64_t)seed}, 156 | {(int64_t)seed, (int64_t)seed, (int64_t)seed, (int64_t)seed}, 157 | {(int64_t)seed, (int64_t)seed, (int64_t)seed, (int64_t)seed}, 158 | {(int64_t)seed, (int64_t)seed, (int64_t)seed, (int64_t)seed}}, 159 | ma[4] = {{(int64_t)secret[0] ^ (int64_t)secret[4], 160 | (int64_t)secret[0] ^ (int64_t)secret[5], 161 | (int64_t)secret[0] ^ (int64_t)secret[6], 162 | (int64_t)secret[0] ^ (int64_t)secret[7]}, 163 | {(int64_t)secret[1] ^ (int64_t)secret[4], 164 | (int64_t)secret[1] ^ (int64_t)secret[5], 165 | (int64_t)secret[1] ^ (int64_t)secret[6], 166 | (int64_t)secret[1] ^ (int64_t)secret[7]}, 167 | {(int64_t)secret[2] ^ (int64_t)secret[4], 168 | (int64_t)secret[2] ^ (int64_t)secret[5], 169 | (int64_t)secret[2] ^ (int64_t)secret[6], 170 | (int64_t)secret[2] ^ (int64_t)secret[7]}, 171 | {(int64_t)secret[3] ^ (int64_t)secret[4], 172 | (int64_t)secret[3] ^ (int64_t)secret[5], 173 | (int64_t)secret[3] ^ (int64_t)secret[6], 174 | (int64_t)secret[3] ^ (int64_t)secret[7]}}; 175 | for (; i > 128; i -= 128, p += 128) { 176 | __m256i d[4] = {_mm256_loadu_si256((__m256i *)p), 177 | _mm256_loadu_si256((__m256i *)(p + 32)), 178 | _mm256_loadu_si256((__m256i *)(p + 64)), 179 | _mm256_loadu_si256((__m256i *)(p + 96))}; 180 | for (size_t j = 0; j < 4; j++) { 181 | se[j] = _mm256_xor_si256(_mm256_xor_si256(ma[j], d[j]), se[j]); 182 | se[j] = _mm256_xor_si256( 183 | se[j], 184 | _mm256_mul_epu32(se[j], _mm256_shuffle_epi32(se[j], 0x31))); 185 | } 186 | } 187 | for (size_t j = 0; j < 4; j++) { 188 | uint64_t *s = (uint64_t *)&se[j]; 189 | seed ^= s[0] ^ s[1] ^ s[2] ^ s[3]; 190 | } 191 | #elif defined(__SSE2__) 192 | __m128i se[8] = {{(int64_t)seed, (int64_t)seed}, 193 | {(int64_t)seed, (int64_t)seed}, 194 | {(int64_t)seed, (int64_t)seed}, 195 | {(int64_t)seed, (int64_t)seed}, 196 | {(int64_t)seed, (int64_t)seed}, 197 | {(int64_t)seed, (int64_t)seed}, 198 | {(int64_t)seed, (int64_t)seed}, 199 | {(int64_t)seed, (int64_t)seed}}, 200 | ma[8] = {{(int64_t)secret[0] ^ (int64_t)secret[4], 201 | (int64_t)secret[0] ^ (int64_t)secret[5]}, 202 | {(int64_t)secret[0] ^ (int64_t)secret[6], 203 | (int64_t)secret[0] ^ (int64_t)secret[7]}, 204 | {(int64_t)secret[1] ^ (int64_t)secret[4], 205 | (int64_t)secret[1] ^ (int64_t)secret[5]}, 206 | {(int64_t)secret[1] ^ (int64_t)secret[6], 207 | (int64_t)secret[1] ^ (int64_t)secret[7]}, 208 | {(int64_t)secret[2] ^ (int64_t)secret[4], 209 | (int64_t)secret[2] ^ (int64_t)secret[5]}, 210 | {(int64_t)secret[2] ^ (int64_t)secret[6], 211 | (int64_t)secret[2] ^ (int64_t)secret[7]}, 212 | {(int64_t)secret[3] ^ (int64_t)secret[4], 213 | (int64_t)secret[3] ^ (int64_t)secret[5]}, 214 | {(int64_t)secret[3] ^ (int64_t)secret[6], 215 | (int64_t)secret[3] ^ (int64_t)secret[7]}}; 216 | for (; i > 128; i -= 128, p += 128) { 217 | __m128i d[8] = {_mm_loadu_si128((__m128i *)p), 218 | _mm_loadu_si128((__m128i *)(p + 16)), 219 | _mm_loadu_si128((__m128i *)(p + 32)), 220 | _mm_loadu_si128((__m128i *)(p + 48)), 221 | _mm_loadu_si128((__m128i *)(p + 64)), 222 | _mm_loadu_si128((__m128i *)(p + 80)), 223 | _mm_loadu_si128((__m128i *)(p + 96)), 224 | _mm_loadu_si128((__m128i *)(p + 112))}; 225 | for (size_t j = 0; j < 8; j++) { 226 | se[j] = _mm_xor_si128(_mm_xor_si128(ma[j], d[j]), se[j]); 227 | se[j] = _mm_xor_si128( 228 | se[j], _mm_mul_epu32(se[j], _mm_shuffle_epi32(se[j], 0x31))); 229 | } 230 | } 231 | for (size_t j = 0; j < 8; j++) { 232 | uint64_t *s = (uint64_t *)&se[j]; 233 | seed ^= s[0] ^ s[1]; 234 | } 235 | #else 236 | uint64_t se[4][4] = {{seed, seed, seed, seed}, 237 | {seed, seed, seed, seed}, 238 | {seed, seed, seed, seed}, 239 | {seed, seed, seed, seed}}; 240 | uint64_t ma[4][4] = {{secret[0] ^ secret[4], secret[0] ^ secret[5], 241 | secret[0] ^ secret[6], secret[0] ^ secret[7]}, 242 | {secret[1] ^ secret[4], secret[1] ^ secret[5], 243 | secret[1] ^ secret[6], secret[1] ^ secret[7]}, 244 | {secret[2] ^ secret[4], secret[2] ^ secret[5], 245 | secret[2] ^ secret[6], secret[2] ^ secret[7]}, 246 | {secret[3] ^ secret[4], secret[3] ^ secret[5], 247 | secret[3] ^ secret[6], secret[3] ^ secret[7]}}; 248 | for (; i > 128; i -= 128, p += 128) 249 | for (size_t j = 0; j < 4; j++) 250 | for (size_t k = 0; k < 4; k++) 251 | se[j][k] = 252 | _wymix32(_wyr8(p + (j * 4 + k) * 8) ^ se[j][k] ^ ma[j][k]); 253 | for (size_t j = 0; j < 4; j++) 254 | for (size_t k = 0; k < 4; k++) seed ^= se[j][k]; 255 | #endif 256 | goto finalization; 257 | } 258 | static inline uint64_t wyhash(const void *key, uint64_t len, uint64_t seed, 259 | const uint64_t secret[10]) { 260 | uint64_t h = _wyhash(key, len, seed, secret); 261 | return _wymum(h ^ len, h ^ secret[9]); 262 | } 263 | 264 | static inline void make_secret(uint64_t seed, uint64_t secret[10]) { 265 | uint8_t c[] = {15, 23, 27, 29, 30, 39, 43, 45, 46, 51, 53, 54, 266 | 57, 58, 60, 71, 75, 77, 78, 83, 85, 86, 89, 90, 267 | 92, 99, 101, 102, 105, 106, 108, 113, 114, 116, 120, 135, 268 | 139, 141, 142, 147, 149, 150, 153, 154, 156, 163, 165, 166, 269 | 169, 170, 172, 177, 178, 180, 184, 195, 197, 198, 201, 202, 270 | 204, 209, 210, 212, 216, 225, 226, 228, 232, 240}; 271 | for (size_t i = 0; i < 10; i++) { 272 | uint8_t ok; 273 | do { 274 | ok = 1; 275 | secret[i] = 0; 276 | for (size_t j = 0; j < 64; j += 8) 277 | secret[i] |= ((uint64_t)c[wyrand(&seed) % sizeof(c)]) << j; 278 | if (secret[i] % 2 == 0) { 279 | ok = 0; 280 | continue; 281 | } 282 | for (size_t j = 0; j < i; j++) 283 | #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) 284 | if (__builtin_popcountll(secret[i] ^ secret[j]) != 32) { 285 | ok = 0; 286 | break; 287 | } 288 | #elif defined(_MSC_VER) 289 | if (_mm_popcnt_u64(secret[i] ^ secret[j]) != 32) { 290 | ok = 0; 291 | break; 292 | } 293 | #endif 294 | if (!ok) continue; 295 | for (uint64_t j = 3; j < 0x100000000ull; j += 2) 296 | if (secret[i] % j == 0) { 297 | ok = 0; 298 | break; 299 | } 300 | } while (!ok); 301 | } 302 | } 303 | #endif 304 | -------------------------------------------------------------------------------- /test_vector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define WYTRNG 5 | #include "wyhash.h" 6 | using namespace std; 7 | 8 | int main(void) { 9 | vector msgs_v = { 10 | "", 11 | "a", 12 | "abc", 13 | "message digest", 14 | "abcdefghijklmnopqrstuvwxyz", 15 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 16 | "1234567890123456789012345678901234567890123456789012345678901234567890" 17 | "1234567890" 18 | }; 19 | uint64_t hash; 20 | cout << "# wyhash message, seed" << "\n"; 21 | for (size_t i = 0; i < msgs_v.size(); i++) { 22 | hash = wyhash(msgs_v[i].c_str(), msgs_v[i].size(), i, _wyp); 23 | cout << hex << hash << " \"" << msgs_v[i] << "\", " << i << "\n"; 24 | } 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /wyhash.h: -------------------------------------------------------------------------------- 1 | // This is free and unencumbered software released into the public domain under The Unlicense (http://unlicense.org/) 2 | // main repo: https://github.com/wangyi-fudan/wyhash 3 | // author: 王一 Wang Yi 4 | // contributors: Reini Urban, Dietrich Epp, Joshua Haberman, Tommy Ettinger, Daniel Lemire, Otmar Ertl, cocowalla, leo-yuriev, Diego Barrios Romero, paulie-g, dumblob, Yann Collet, ivte-ms, hyb, James Z.M. Gao, easyaspi314 (Devin), TheOneric 5 | 6 | /* quick example: 7 | string s="fjsakfdsjkf"; 8 | uint64_t hash=wyhash(s.c_str(), s.size(), 0, _wyp); 9 | */ 10 | 11 | #ifndef wyhash_final_version_4_2 12 | #define wyhash_final_version_4_2 13 | 14 | #ifndef WYHASH_CONDOM 15 | //protections that produce different results: 16 | //1: normal valid behavior 17 | //2: extra protection against entropy loss (probability=2^-63), aka. "blind multiplication" 18 | #define WYHASH_CONDOM 1 19 | #endif 20 | 21 | #ifndef WYHASH_32BIT_MUM 22 | //0: normal version, slow on 32 bit systems 23 | //1: faster on 32 bit systems but produces different results, incompatible with wy2u0k function 24 | #define WYHASH_32BIT_MUM 0 25 | #endif 26 | 27 | //includes 28 | #include 29 | #include 30 | #if defined(_MSC_VER) && defined(_M_X64) 31 | #include 32 | #pragma intrinsic(_umul128) 33 | #endif 34 | 35 | //likely and unlikely macros 36 | #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) 37 | #define _likely_(x) __builtin_expect(x,1) 38 | #define _unlikely_(x) __builtin_expect(x,0) 39 | #else 40 | #define _likely_(x) (x) 41 | #define _unlikely_(x) (x) 42 | #endif 43 | 44 | //128bit multiply function 45 | static inline uint64_t _wyrot(uint64_t x) { return (x>>32)|(x<<32); } 46 | static inline void _wymum(uint64_t *A, uint64_t *B){ 47 | #if(WYHASH_32BIT_MUM) 48 | uint64_t hh=(*A>>32)*(*B>>32), hl=(*A>>32)*(uint32_t)*B, lh=(uint32_t)*A*(*B>>32), ll=(uint64_t)(uint32_t)*A*(uint32_t)*B; 49 | #if(WYHASH_CONDOM>1) 50 | *A^=_wyrot(hl)^hh; *B^=_wyrot(lh)^ll; 51 | #else 52 | *A=_wyrot(hl)^hh; *B=_wyrot(lh)^ll; 53 | #endif 54 | #elif defined(__SIZEOF_INT128__) 55 | __uint128_t r=*A; r*=*B; 56 | #if(WYHASH_CONDOM>1) 57 | *A^=(uint64_t)r; *B^=(uint64_t)(r>>64); 58 | #else 59 | *A=(uint64_t)r; *B=(uint64_t)(r>>64); 60 | #endif 61 | #elif defined(_MSC_VER) && defined(_M_X64) 62 | #if(WYHASH_CONDOM>1) 63 | uint64_t a, b; 64 | a=_umul128(*A,*B,&b); 65 | *A^=a; *B^=b; 66 | #else 67 | *A=_umul128(*A,*B,B); 68 | #endif 69 | #else 70 | uint64_t ha=*A>>32, hb=*B>>32, la=(uint32_t)*A, lb=(uint32_t)*B, hi, lo; 71 | uint64_t rh=ha*hb, rm0=ha*lb, rm1=hb*la, rl=la*lb, t=rl+(rm0<<32), c=t>32)+(rm1>>32)+c; 73 | #if(WYHASH_CONDOM>1) 74 | *A^=lo; *B^=hi; 75 | #else 76 | *A=lo; *B=hi; 77 | #endif 78 | #endif 79 | } 80 | 81 | //multiply and xor mix function, aka MUM 82 | static inline uint64_t _wymix(uint64_t A, uint64_t B){ _wymum(&A,&B); return A^B; } 83 | 84 | //endian macros 85 | #ifndef WYHASH_LITTLE_ENDIAN 86 | #if defined(_WIN32) || defined(__LITTLE_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) 87 | #define WYHASH_LITTLE_ENDIAN 1 88 | #elif defined(__BIG_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) 89 | #define WYHASH_LITTLE_ENDIAN 0 90 | #else 91 | #warning could not determine endianness! Falling back to little endian. 92 | #define WYHASH_LITTLE_ENDIAN 1 93 | #endif 94 | #endif 95 | 96 | //read functions 97 | #if (WYHASH_LITTLE_ENDIAN) 98 | static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return v;} 99 | static inline uint64_t _wyr4(const uint8_t *p) { uint32_t v; memcpy(&v, p, 4); return v;} 100 | #elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) 101 | static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return __builtin_bswap64(v);} 102 | static inline uint64_t _wyr4(const uint8_t *p) { uint32_t v; memcpy(&v, p, 4); return __builtin_bswap32(v);} 103 | #elif defined(_MSC_VER) 104 | static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return _byteswap_uint64(v);} 105 | static inline uint64_t _wyr4(const uint8_t *p) { uint32_t v; memcpy(&v, p, 4); return _byteswap_ulong(v);} 106 | #else 107 | static inline uint64_t _wyr8(const uint8_t *p) { 108 | uint64_t v; memcpy(&v, p, 8); 109 | 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)); 110 | } 111 | static inline uint64_t _wyr4(const uint8_t *p) { 112 | uint32_t v; memcpy(&v, p, 4); 113 | return (((v >> 24) & 0xff)| ((v >> 8) & 0xff00)| ((v << 8) & 0xff0000)| ((v << 24) & 0xff000000)); 114 | } 115 | #endif 116 | static inline uint64_t _wyr3(const uint8_t *p, size_t k) { return (((uint64_t)p[0])<<16)|(((uint64_t)p[k>>1])<<8)|p[k-1];} 117 | //wyhash main function 118 | static inline uint64_t wyhash(const void *key, size_t len, uint64_t seed, const uint64_t *secret){ 119 | const uint8_t *p=(const uint8_t *)key; seed^=_wymix(seed^secret[0],secret[1]); uint64_t a, b; 120 | if(_likely_(len<=16)){ 121 | 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)); } 122 | else if(_likely_(len>0)){ a=_wyr3(p,len); b=0;} 123 | else a=b=0; 124 | } 125 | else{ 126 | size_t i=len; 127 | if(_unlikely_(i>=48)){ 128 | uint64_t see1=seed, see2=seed; 129 | do{ 130 | seed=_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed); 131 | see1=_wymix(_wyr8(p+16)^secret[2],_wyr8(p+24)^see1); 132 | see2=_wymix(_wyr8(p+32)^secret[3],_wyr8(p+40)^see2); 133 | p+=48; i-=48; 134 | }while(_likely_(i>=48)); 135 | seed^=see1^see2; 136 | } 137 | while(_unlikely_(i>16)){ seed=_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed); i-=16; p+=16; } 138 | a=_wyr8(p+i-16); b=_wyr8(p+i-8); 139 | } 140 | a^=secret[1]; b^=seed; _wymum(&a,&b); 141 | return _wymix(a^secret[0]^len,b^secret[1]); 142 | } 143 | 144 | //the default secret parameters 145 | static const uint64_t _wyp[4] = {0x2d358dccaa6c78a5ull, 0x8bb84b93962eacc9ull, 0x4b33a62ed433d4a3ull, 0x4d5a2da51de1aa47ull}; 146 | 147 | //a useful 64bit-64bit mix function to produce deterministic pseudo random numbers that can pass BigCrush and PractRand 148 | static inline uint64_t wyhash64(uint64_t A, uint64_t B){ A^=0x2d358dccaa6c78a5ull; B^=0x8bb84b93962eacc9ull; _wymum(&A,&B); return _wymix(A^0x2d358dccaa6c78a5ull,B^0x8bb84b93962eacc9ull);} 149 | 150 | //The wyrand PRNG that pass BigCrush and PractRand 151 | static inline uint64_t wyrand(uint64_t *seed){ *seed+=0x2d358dccaa6c78a5ull; return _wymix(*seed,*seed^0x8bb84b93962eacc9ull);} 152 | 153 | //convert any 64 bit pseudo random numbers to uniform distribution [0,1). It can be combined with wyrand, wyhash64 or wyhash. 154 | static inline double wy2u01(uint64_t r){ const double _wynorm=1.0/(1ull<<52); return (r>>12)*_wynorm;} 155 | 156 | //convert any 64 bit pseudo random numbers to APPROXIMATE Gaussian distribution. It can be combined with wyrand, wyhash64 or wyhash. 157 | 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;} 158 | 159 | #ifdef WYTRNG 160 | #include 161 | //The wytrand true random number generator, passed BigCrush. 162 | static inline uint64_t wytrand(uint64_t *seed){ 163 | struct timeval t; gettimeofday(&t,0); 164 | uint64_t teed=(((uint64_t)t.tv_sec)<<32)|t.tv_usec; 165 | teed=_wymix(teed^_wyp[0],*seed^_wyp[1]); 166 | *seed=_wymix(teed^_wyp[0],_wyp[2]); 167 | return _wymix(*seed,*seed^_wyp[3]); 168 | } 169 | #endif 170 | 171 | #if(!WYHASH_32BIT_MUM) 172 | //fast range integer random number generation on [0,k) credit to Daniel Lemire. May not work when WYHASH_32BIT_MUM=1. It can be combined with wyrand, wyhash64 or wyhash. 173 | static inline uint64_t wy2u0k(uint64_t r, uint64_t k){ _wymum(&r,&k); return k; } 174 | #endif 175 | 176 | // modified from https://github.com/going-digital/Prime64 177 | static inline unsigned long long mul_mod(unsigned long long a, unsigned long long b, unsigned long long m) { 178 | unsigned long long r=0; 179 | while (b) { 180 | if (b & 1) { 181 | unsigned long long r2 = r + a; 182 | if (r2 < r) r2 -= m; 183 | r = r2 % m; 184 | } 185 | b >>= 1; 186 | if (b) { 187 | unsigned long long a2 = a + a; 188 | if (a2 < a) a2 -= m; 189 | a = a2 % m; 190 | } 191 | } 192 | return r; 193 | } 194 | static inline unsigned long long pow_mod(unsigned long long a, unsigned long long b, unsigned long long m) { 195 | unsigned long long r=1; 196 | while (b) { 197 | if (b&1) r=mul_mod(r,a,m); 198 | b>>=1; 199 | if (b) a=mul_mod(a,a,m); 200 | } 201 | return r; 202 | } 203 | unsigned sprp(unsigned long long n, unsigned long long a) { 204 | unsigned long long d=n-1; 205 | unsigned char s=0; 206 | while (!(d & 0xff)) { d>>=8; s+=8; } 207 | if (!(d & 0xf)) { d>>=4; s+=4; } 208 | if (!(d & 0x3)) { d>>=2; s+=2; } 209 | if (!(d & 0x1)) { d>>=1; s+=1; } 210 | unsigned long long b=pow_mod(a,d,n); 211 | if ((b==1) || (b==(n-1))) return 1; 212 | unsigned char r; 213 | for (r=1; r> 1) & 0x5555555555555555; 256 | x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333); 257 | x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f; 258 | x = (x * 0x0101010101010101) >> 56; 259 | if(x!=32){ ok=0; break; } 260 | #endif 261 | } 262 | if(ok&&!is_prime(secret[i])) ok=0; 263 | }while(!ok); 264 | } 265 | } 266 | 267 | #endif 268 | 269 | /* The Unlicense 270 | This is free and unencumbered software released into the public domain. 271 | 272 | Anyone is free to copy, modify, publish, use, compile, sell, or 273 | distribute this software, either in source code form or as a compiled 274 | binary, for any purpose, commercial or non-commercial, and by any 275 | means. 276 | 277 | In jurisdictions that recognize copyright laws, the author or authors 278 | of this software dedicate any and all copyright interest in the 279 | software to the public domain. We make this dedication for the benefit 280 | of the public at large and to the detriment of our heirs and 281 | successors. We intend this dedication to be an overt act of 282 | relinquishment in perpetuity of all present and future rights to this 283 | software under copyright law. 284 | 285 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 286 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 287 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 288 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 289 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 290 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 291 | OTHER DEALINGS IN THE SOFTWARE. 292 | 293 | For more information, please refer to 294 | */ 295 | -------------------------------------------------------------------------------- /wyhash32.h: -------------------------------------------------------------------------------- 1 | // Author: Wang Yi 2 | #include 3 | #include 4 | #ifndef WYHASH32_BIG_ENDIAN 5 | static inline unsigned _wyr32(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return v;} 6 | #elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) 7 | static inline unsigned _wyr32(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return __builtin_bswap32(v);} 8 | #elif defined(_MSC_VER) 9 | static inline unsigned _wyr32(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return _byteswap_ulong(v);} 10 | #endif 11 | static inline unsigned _wyr24(const uint8_t *p, unsigned k) { return (((unsigned)p[0])<<16)|(((unsigned)p[k>>1])<<8)|p[k-1];} 12 | static inline void _wymix32(unsigned *A, unsigned *B){ 13 | uint64_t c=*A^0x53c5ca59u; c*=*B^0x74743c1bu; 14 | *A=(unsigned)c; 15 | *B=(unsigned)(c>>32); 16 | } 17 | // This version is vulnerable when used with a few bad seeds, which should be skipped beforehand: 18 | // 0x429dacdd, 0xd637dbf3 19 | static inline unsigned wyhash32(const void *key, uint64_t len, unsigned seed) { 20 | const uint8_t *p=(const uint8_t *)key; uint64_t i=len; 21 | unsigned see1=(unsigned)len; seed^=(unsigned)(len>>32); _wymix32(&seed, &see1); 22 | for(;i>8;i-=8,p+=8){ seed^=_wyr32(p); see1^=_wyr32(p+4); _wymix32(&seed, &see1); } 23 | if(i>=4){ seed^=_wyr32(p); see1^=_wyr32(p+i-4); } else if (i) seed^=_wyr24(p,(unsigned)i); 24 | _wymix32(&seed, &see1); _wymix32(&seed, &see1); return seed^see1; 25 | } 26 | // duplicate definition in wyhash.h also 27 | #ifndef wyhash_final_version_3 28 | static inline uint64_t wyrand(uint64_t *seed){ 29 | *seed+=0xa0761d6478bd642full; 30 | uint64_t see1=*seed^0xe7037ed1a0b428dbull; 31 | see1*=(see1>>32)|(see1<<32); 32 | return (*seed*((*seed>>32)|(*seed<<32)))^((see1>>32)|(see1<<32)); 33 | } 34 | #endif 35 | static inline unsigned wy32x32(unsigned a, unsigned b) { _wymix32(&a,&b); _wymix32(&a,&b); return a^b; } 36 | static inline float wy2u01(unsigned r) { const float _wynorm=1.0f/(1ull<<23); return (r>>9)*_wynorm;} 37 | static inline float wy2gau(unsigned r) { const float _wynorm=1.0f/(1ull<<9); return ((r&0x3ff)+((r>>10)&0x3ff)+((r>>20)&0x3ff))*_wynorm-3.0f;} 38 | --------------------------------------------------------------------------------