├── 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 |
--------------------------------------------------------------------------------