BadScript 2
Loading...
Searching...
No Matches
BadHashCode.cs
Go to the documentation of this file.
1using System.Runtime.CompilerServices;
2
3namespace BadScript2.Utility;
4
10public static class BadHashCode
11{
12 private const uint PRIME1 = 2654435761U;
13 private const uint PRIME2 = 2246822519U;
14 private const uint PRIME3 = 3266489917U;
15 private const uint PRIME4 = 668265263U;
16 private const uint PRIME5 = 374761393U;
17 private static readonly uint s_Seed = GenerateGlobalSeed();
18
29 [MethodImpl(MethodImplOptions.AggressiveInlining)]
30 public static uint RotateLeft(uint value, int offset)
31 {
32 return value << offset | value >> 32 - offset;
33 }
34
45 [MethodImpl(MethodImplOptions.AggressiveInlining)]
46 public static ulong RotateLeft(ulong value, int offset)
47 {
48 return value << offset | value >> 64 - offset;
49 }
50
61 [MethodImpl(MethodImplOptions.AggressiveInlining)]
62 public static uint RotateRight(uint value, int offset)
63 {
64 return value >> offset | value << 32 - offset;
65 }
66
77 [MethodImpl(MethodImplOptions.AggressiveInlining)]
78 public static ulong RotateRight(ulong value, int offset)
79 {
80 return value >> offset | value << 64 - offset;
81 }
82
83 private static uint GenerateGlobalSeed()
84 {
85 return (uint)new Random().Next();
86 }
87
88 public static int Combine<T1>(T1 value1)
89 {
90 // Provide a way of diffusing bits from something with a limited
91 // input hash space. For example, many enums only have a few
92 // possible hashes, only using the bottom few bits of the code. Some
93 // collections are built on the assumption that hashes are spread
94 // over a larger space, so diffusing the bits may help the
95 // collection work more efficiently.
96
97 uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
98
99 uint hash = MixEmptyState();
100 hash += 4;
101
102 hash = QueueRound(hash, hc1);
103
104 hash = MixFinal(hash);
105
106 return (int)hash;
107 }
108
109 public static int Combine<T1, T2>(T1 value1, T2 value2)
110 {
111 uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
112 uint hc2 = (uint)(value2?.GetHashCode() ?? 0);
113
114 uint hash = MixEmptyState();
115 hash += 8;
116
117 hash = QueueRound(hash, hc1);
118 hash = QueueRound(hash, hc2);
119
120 hash = MixFinal(hash);
121
122 return (int)hash;
123 }
124
125 public static int Combine<T1, T2, T3>(T1 value1, T2 value2, T3 value3)
126 {
127 uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
128 uint hc2 = (uint)(value2?.GetHashCode() ?? 0);
129 uint hc3 = (uint)(value3?.GetHashCode() ?? 0);
130
131 uint hash = MixEmptyState();
132 hash += 12;
133
134 hash = QueueRound(hash, hc1);
135 hash = QueueRound(hash, hc2);
136 hash = QueueRound(hash, hc3);
137
138 hash = MixFinal(hash);
139
140 return (int)hash;
141 }
142
143 public static int Combine<T1, T2, T3, T4>(T1 value1, T2 value2, T3 value3, T4 value4)
144 {
145 uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
146 uint hc2 = (uint)(value2?.GetHashCode() ?? 0);
147 uint hc3 = (uint)(value3?.GetHashCode() ?? 0);
148 uint hc4 = (uint)(value4?.GetHashCode() ?? 0);
149
150 Initialize(out uint v1, out uint v2, out uint v3, out uint v4);
151
152 v1 = Round(v1, hc1);
153 v2 = Round(v2, hc2);
154 v3 = Round(v3, hc3);
155 v4 = Round(v4, hc4);
156
157 uint hash = MixState(v1, v2, v3, v4);
158 hash += 16;
159
160 hash = MixFinal(hash);
161
162 return (int)hash;
163 }
164
165 public static int Combine<T1, T2, T3, T4, T5>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5)
166 {
167 uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
168 uint hc2 = (uint)(value2?.GetHashCode() ?? 0);
169 uint hc3 = (uint)(value3?.GetHashCode() ?? 0);
170 uint hc4 = (uint)(value4?.GetHashCode() ?? 0);
171 uint hc5 = (uint)(value5?.GetHashCode() ?? 0);
172
173 Initialize(out uint v1, out uint v2, out uint v3, out uint v4);
174
175 v1 = Round(v1, hc1);
176 v2 = Round(v2, hc2);
177 v3 = Round(v3, hc3);
178 v4 = Round(v4, hc4);
179
180 uint hash = MixState(v1, v2, v3, v4);
181 hash += 20;
182
183 hash = QueueRound(hash, hc5);
184
185 hash = MixFinal(hash);
186
187 return (int)hash;
188 }
189
191 T1 value1,
192 T2 value2,
193 T3 value3,
194 T4 value4,
195 T5 value5,
196 T6 value6)
197 {
198 uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
199 uint hc2 = (uint)(value2?.GetHashCode() ?? 0);
200 uint hc3 = (uint)(value3?.GetHashCode() ?? 0);
201 uint hc4 = (uint)(value4?.GetHashCode() ?? 0);
202 uint hc5 = (uint)(value5?.GetHashCode() ?? 0);
203 uint hc6 = (uint)(value6?.GetHashCode() ?? 0);
204
205 Initialize(out uint v1, out uint v2, out uint v3, out uint v4);
206
207 v1 = Round(v1, hc1);
208 v2 = Round(v2, hc2);
209 v3 = Round(v3, hc3);
210 v4 = Round(v4, hc4);
211
212 uint hash = MixState(v1, v2, v3, v4);
213 hash += 24;
214
215 hash = QueueRound(hash, hc5);
216 hash = QueueRound(hash, hc6);
217
218 hash = MixFinal(hash);
219
220 return (int)hash;
221 }
222
224 T1 value1,
225 T2 value2,
226 T3 value3,
227 T4 value4,
228 T5 value5,
229 T6 value6,
230 T7 value7)
231 {
232 uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
233 uint hc2 = (uint)(value2?.GetHashCode() ?? 0);
234 uint hc3 = (uint)(value3?.GetHashCode() ?? 0);
235 uint hc4 = (uint)(value4?.GetHashCode() ?? 0);
236 uint hc5 = (uint)(value5?.GetHashCode() ?? 0);
237 uint hc6 = (uint)(value6?.GetHashCode() ?? 0);
238 uint hc7 = (uint)(value7?.GetHashCode() ?? 0);
239
240 Initialize(out uint v1, out uint v2, out uint v3, out uint v4);
241
242 v1 = Round(v1, hc1);
243 v2 = Round(v2, hc2);
244 v3 = Round(v3, hc3);
245 v4 = Round(v4, hc4);
246
247 uint hash = MixState(v1, v2, v3, v4);
248 hash += 28;
249
250 hash = QueueRound(hash, hc5);
251 hash = QueueRound(hash, hc6);
252 hash = QueueRound(hash, hc7);
253
254 hash = MixFinal(hash);
255
256 return (int)hash;
257 }
258
260 T1 value1,
261 T2 value2,
262 T3 value3,
263 T4 value4,
264 T5 value5,
265 T6 value6,
266 T7 value7,
267 T8 value8)
268 {
269 uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
270 uint hc2 = (uint)(value2?.GetHashCode() ?? 0);
271 uint hc3 = (uint)(value3?.GetHashCode() ?? 0);
272 uint hc4 = (uint)(value4?.GetHashCode() ?? 0);
273 uint hc5 = (uint)(value5?.GetHashCode() ?? 0);
274 uint hc6 = (uint)(value6?.GetHashCode() ?? 0);
275 uint hc7 = (uint)(value7?.GetHashCode() ?? 0);
276 uint hc8 = (uint)(value8?.GetHashCode() ?? 0);
277
278 Initialize(out uint v1, out uint v2, out uint v3, out uint v4);
279
280 v1 = Round(v1, hc1);
281 v2 = Round(v2, hc2);
282 v3 = Round(v3, hc3);
283 v4 = Round(v4, hc4);
284
285 v1 = Round(v1, hc5);
286 v2 = Round(v2, hc6);
287 v3 = Round(v3, hc7);
288 v4 = Round(v4, hc8);
289
290 uint hash = MixState(v1, v2, v3, v4);
291 hash += 32;
292
293 hash = MixFinal(hash);
294
295 return (int)hash;
296 }
297
298 [MethodImpl(MethodImplOptions.AggressiveInlining)]
299 private static void Initialize(out uint v1, out uint v2, out uint v3, out uint v4)
300 {
301 v1 = s_Seed + PRIME1 + PRIME2;
302 v2 = s_Seed + PRIME2;
303 v3 = s_Seed;
304 v4 = s_Seed - PRIME1;
305 }
306
307 [MethodImpl(MethodImplOptions.AggressiveInlining)]
308 private static uint Round(uint hash, uint input)
309 {
310 return RotateLeft(hash + input * PRIME2, 13) * PRIME1;
311 }
312
313 [MethodImpl(MethodImplOptions.AggressiveInlining)]
314 private static uint QueueRound(uint hash, uint queuedValue)
315 {
316 return RotateLeft(hash + queuedValue * PRIME3, 17) * PRIME4;
317 }
318
319 [MethodImpl(MethodImplOptions.AggressiveInlining)]
320 private static uint MixState(uint v1, uint v2, uint v3, uint v4)
321 {
322 return RotateLeft(v1, 1) + RotateLeft(v2, 7) + RotateLeft(v3, 12) + RotateLeft(v4, 18);
323 }
324
325 private static uint MixEmptyState()
326 {
327 return s_Seed + PRIME5;
328 }
329
330 [MethodImpl(MethodImplOptions.AggressiveInlining)]
331 private static uint MixFinal(uint hash)
332 {
333 hash ^= hash >> 15;
334 hash *= PRIME2;
335 hash ^= hash >> 13;
336 hash *= PRIME3;
337 hash ^= hash >> 16;
338
339 return hash;
340 }
341}
Implements Combination of HashCode Functions Taken from decompiled source of System....
static int Combine< T1 >(T1 value1)
static int Combine< T1, T2, T3, T4 >(T1 value1, T2 value2, T3 value3, T4 value4)
static int Combine< T1, T2, T3, T4, T5, T6 >(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6)
static uint MixState(uint v1, uint v2, uint v3, uint v4)
static uint QueueRound(uint hash, uint queuedValue)
static ulong RotateRight(ulong value, int offset)
Rotates the specified value right by the specified number of bits. Similar in behavior to the x86 ins...
static int Combine< T1, T2, T3, T4, T5, T6, T7, T8 >(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8)
static uint Round(uint hash, uint input)
static uint MixFinal(uint hash)
static void Initialize(out uint v1, out uint v2, out uint v3, out uint v4)
static uint RotateLeft(uint value, int offset)
Rotates the specified value left by the specified number of bits. Similar in behavior to the x86 inst...
static int Combine< T1, T2, T3 >(T1 value1, T2 value2, T3 value3)
static ulong RotateLeft(ulong value, int offset)
Rotates the specified value left by the specified number of bits. Similar in behavior to the x86 inst...
static int Combine< T1, T2 >(T1 value1, T2 value2)
static int Combine< T1, T2, T3, T4, T5, T6, T7 >(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7)
static uint RotateRight(uint value, int offset)
Rotates the specified value right by the specified number of bits. Similar in behavior to the x86 ins...
static readonly uint s_Seed
static int Combine< T1, T2, T3, T4, T5 >(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5)
Contains Utility Functions and Classes.
Definition BadEnum.cs:5