-
Notifications
You must be signed in to change notification settings - Fork 139
Expand file tree
/
Copy pathWyHash.java
More file actions
222 lines (200 loc) · 9.66 KB
/
WyHash.java
File metadata and controls
222 lines (200 loc) · 9.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
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
/*
* Copyright 2013-2025 chronicle.software; SPDX-License-Identifier: Apache-2.0
*/
package net.openhft.hashing;
import static java.nio.ByteOrder.LITTLE_ENDIAN;
/**
* Adapted version of WyHash implementation from https://github.com/wangyi-fudan/wyhash
* Original @author <a href="mailto:godspeed_china@yeah.net">Wang Yi</a>
* Adapted @author <a href="mailto:firestrand@gmail.com">Travis Silvers</a>
* This implementation provides endian-independent hash values, but it's slower on big-endian
* platforms.
* The original C based version is also much faster.
*/
class WyHash {
// Primes
public static final long _wyp0 = 0xa0761d6478bd642fL;
public static final long _wyp1 = 0xe7037ed1a0b428dbL;
public static final long _wyp2 = 0x8ebc6af09c88c6e3L;
public static final long _wyp3 = 0x589965cc75374cc3L;
public static final long _wyp4 = 0x1d8e4e27c47d124fL;
private static long _wymum(final long lhs, final long rhs) {
return Maths.unsignedLongMulXorFold(lhs, rhs);
}
private static <T> long _wyr3(final Access<T> access, T in, final long index, long k) {
return ((long) access.u8(in, index) << 16) |
((long) access.u8(in, index + (k >>> 1)) << 8) |
((long) access.u8(in, index + k - 1));
}
private static <T> long u64Rorate32(final Access<T> access, T in, final long index) {
return (access.u32(in, index) << 32) | access.u32(in, index + 4);
}
/**
*
* @param seed seed for the hash
* @param input the type wrapped by the Access, ex. byte[], ByteBuffer, etc.
* @param access class wrapping optimized access pattern to the input
* @param off offset to the input
* @param length length to read from input
* @param <T> byte[], ByteBuffer, etc.
* @return hash result
*/
static <T> long wyHash64(long seed, T input, Access<T> access, long off, long length) {
if(length <= 0)
return 0;
else if(length<4)
return _wymum(_wymum(_wyr3(access, input,off,length)^seed^_wyp0,
seed^_wyp1)^seed,length^_wyp4);
else if(length<=8)
return _wymum(_wymum(access.u32(input, off) ^ seed ^ _wyp0,
access.u32(input, off + length - 4) ^ seed ^ _wyp1)
^ seed, length ^ _wyp4);
else if(length<=16)
return _wymum(_wymum(u64Rorate32(access, input,off)^seed^_wyp0,
u64Rorate32(access, input,off+length-8)^seed^_wyp1)
^seed,length^_wyp4);
else if(length<=24)
return _wymum(_wymum(u64Rorate32(access, input,off)^seed^_wyp0,
u64Rorate32(access, input,off+8)^seed^_wyp1)^
_wymum(u64Rorate32(access, input,off+length-8)
^seed^_wyp2,seed^_wyp3),length^_wyp4);
else if(length<=32)
return _wymum(_wymum(u64Rorate32(access, input,off)^seed^_wyp0,
u64Rorate32(access, input,off+8)^seed^_wyp1)
^_wymum(u64Rorate32(access, input,off+16)^seed^_wyp2,
u64Rorate32(access, input,off+length-8)^seed^_wyp3),length^_wyp4);
long see1=seed; long i=length, p=off;
for(;i>256;i-=256,p+=256){
seed = _wymum(access.i64(input, p) ^ seed ^ _wyp0,
access.i64(input, p + 8) ^ seed ^ _wyp1) ^
_wymum(access.i64(input, p + 16) ^ seed ^ _wyp2,
access.i64(input, p + 24) ^ seed ^ _wyp3);
see1 = _wymum(access.i64(input, p + 32) ^ see1 ^ _wyp1,
access.i64(input, p + 40) ^ see1 ^ _wyp2) ^
_wymum(access.i64(input, p + 48) ^ see1 ^ _wyp3,
access.i64(input, p + 56) ^ see1 ^ _wyp0);
seed = _wymum(access.i64(input, p + 64) ^ seed ^ _wyp0,
access.i64(input, p + 72) ^ seed ^ _wyp1) ^
_wymum(access.i64(input, p + 80) ^ seed ^ _wyp2,
access.i64(input, p + 88) ^ seed ^ _wyp3);
see1 = _wymum(access.i64(input, p + 96) ^ see1 ^ _wyp1,
access.i64(input, p + 104) ^ see1 ^ _wyp2) ^
_wymum(access.i64(input, p + 112) ^ see1 ^ _wyp3,
access.i64(input, p + 120) ^ see1 ^ _wyp0);
seed = _wymum(access.i64(input, p + 128) ^ seed ^ _wyp0,
access.i64(input, p + 136) ^ seed ^ _wyp1) ^
_wymum(access.i64(input, p + 144) ^ seed ^ _wyp2,
access.i64(input, p + 152) ^ seed ^ _wyp3);
see1 = _wymum(access.i64(input, p + 160) ^ see1 ^ _wyp1,
access.i64(input, p + 168) ^ see1 ^ _wyp2) ^
_wymum(access.i64(input, p + 176) ^ see1 ^ _wyp3,
access.i64(input, p + 184) ^ see1 ^ _wyp0);
seed = _wymum(access.i64(input, p + 192) ^ seed ^ _wyp0,
access.i64(input, p + 200) ^ seed ^ _wyp1) ^
_wymum(access.i64(input, p + 208) ^ seed ^ _wyp2,
access.i64(input, p + 216) ^ seed ^ _wyp3);
see1 = _wymum(access.i64(input, p + 224) ^ see1 ^ _wyp1,
access.i64(input, p + 232) ^ see1 ^ _wyp2) ^
_wymum(access.i64(input, p + 240) ^ see1 ^ _wyp3,
access.i64(input, p + 248) ^ see1 ^ _wyp0);
}
for (; i > 32; i -= 32, p += 32) {
seed = _wymum(access.i64(input, p) ^ seed ^ _wyp0,
access.i64(input, p + 8) ^ seed ^ _wyp1);
see1 = _wymum(access.i64(input, p + 16) ^ see1 ^ _wyp2,
access.i64(input, p + 24) ^ see1 ^ _wyp3);
}
if (i < 4) {
seed = _wymum(_wyr3(access, input, p, i) ^ seed ^ _wyp0, seed ^ _wyp1);
} else if (i <= 8) {
seed = _wymum(access.u32(input, p) ^ seed ^ _wyp0,
access.u32(input, p + i - 4) ^ seed ^ _wyp1);
} else if (i <= 16) {
seed = _wymum(u64Rorate32(access, input, p) ^ seed ^ _wyp0,
u64Rorate32(access, input, p + i - 8) ^ seed ^ _wyp1);
} else if (i <= 24) {
seed = _wymum(u64Rorate32(access, input, p) ^ seed ^ _wyp0,
u64Rorate32(access, input, p + 8) ^ seed ^ _wyp1);
see1 = _wymum(u64Rorate32(access, input, p + i - 8) ^ see1 ^ _wyp2, see1 ^ _wyp3);
} else {
seed = _wymum(u64Rorate32(access, input, p) ^ seed ^ _wyp0,
u64Rorate32(access, input, p + 8) ^ seed ^ _wyp1);
see1 = _wymum(u64Rorate32(access, input, p + 16) ^ see1 ^ _wyp2,
u64Rorate32(access, input, p + i - 8) ^ see1 ^ _wyp3);
}
return _wymum(seed ^ see1, length ^ _wyp4);
}
static LongHashFunction asLongHashFunctionWithoutSeed() {
return AsLongHashFunction.SEEDLESS_INSTANCE;
}
private static class AsLongHashFunction extends LongHashFunction {
private static final long serialVersionUID = 0L;
static final AsLongHashFunction SEEDLESS_INSTANCE = new AsLongHashFunction();
private Object readResolve() {
return SEEDLESS_INSTANCE;
}
public long seed() {
return 0L;
}
@Override
public long hashLong(long input) {
input = Primitives.nativeToLittleEndian(input);
long hi = input & 0xFFFFFFFFL;
long lo = (input >>> 32) & 0xFFFFFFFFL;
return _wymum(_wymum(hi ^ seed() ^ _wyp0,
lo ^ seed() ^ _wyp1)
^ seed(), 8 ^ _wyp4);
}
@Override
public long hashInt(int input) {
input = Primitives.nativeToLittleEndian(input);
long longInput = (input & 0xFFFFFFFFL);
return _wymum(_wymum(longInput ^ seed() ^ _wyp0,
longInput ^ seed() ^ _wyp1)
^ seed(), 4 ^ _wyp4);
}
@Override
public long hashShort(short input) {
input = Primitives.nativeToLittleEndian(input);
long hi = (input >>> 8) & 0xFFL;
long wyr3 = hi | hi << 8 | (input & 0xFFL) << 16;
return _wymum(_wymum(wyr3 ^ seed() ^ _wyp0,
seed() ^ _wyp1) ^ seed(), 2 ^ _wyp4);
}
@Override
public long hashChar(final char input) {
return hashShort((short)input);
}
@Override
public long hashByte(final byte input) {
long hi = input & 0xFFL;
long wyr3 = hi | hi << 8 | hi << 16;
return _wymum(_wymum(wyr3 ^ seed() ^ _wyp0,
seed() ^ _wyp1) ^ seed(), 1 ^ _wyp4);
}
@Override
public long hashVoid() {
return 0;
}
@Override
public <T> long hash(final T input, final Access<T> access,
final long off, final long len) {
long seed = seed();
return WyHash.wyHash64(seed, input, access.byteOrder(input, LITTLE_ENDIAN), off, len);
}
}
static LongHashFunction asLongHashFunctionWithSeed(long seed) {
return new AsLongHashFunctionSeeded(seed);
}
private static class AsLongHashFunctionSeeded extends AsLongHashFunction {
private static final long serialVersionUID = 0L;
private final long seed;
private AsLongHashFunctionSeeded(long seed) {
this.seed = seed;
}
@Override
public long seed() {
return seed;
}
}
}