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
190 public static int Combine<T1, T2, T3, T4, T5, T6>(T1 value1,
191 T2 value2,
192 T3 value3,
193 T4 value4,
194 T5 value5,
195 T6 value6)
196 {
197 uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
198 uint hc2 = (uint)(value2?.GetHashCode() ?? 0);
199 uint hc3 = (uint)(value3?.GetHashCode() ?? 0);
200 uint hc4 = (uint)(value4?.GetHashCode() ?? 0);
201 uint hc5 = (uint)(value5?.GetHashCode() ?? 0);
202 uint hc6 = (uint)(value6?.GetHashCode() ?? 0);
203
204 Initialize(out uint v1, out uint v2, out uint v3, out uint v4);
205
206 v1 = Round(v1, hc1);
207 v2 = Round(v2, hc2);
208 v3 = Round(v3, hc3);
209 v4 = Round(v4, hc4);
210
211 uint hash = MixState(v1, v2, v3, v4);
212 hash += 24;
213
214 hash = QueueRound(hash, hc5);
215 hash = QueueRound(hash, hc6);
216
217 hash = MixFinal(hash);
218
219 return (int)hash;
220 }
221
222 public static int Combine<T1, T2, T3, T4, T5, T6, T7>(T1 value1,
223 T2 value2,
224 T3 value3,
225 T4 value4,
226 T5 value5,
227 T6 value6,
228 T7 value7)
229 {
230 uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
231 uint hc2 = (uint)(value2?.GetHashCode() ?? 0);
232 uint hc3 = (uint)(value3?.GetHashCode() ?? 0);
233 uint hc4 = (uint)(value4?.GetHashCode() ?? 0);
234 uint hc5 = (uint)(value5?.GetHashCode() ?? 0);
235 uint hc6 = (uint)(value6?.GetHashCode() ?? 0);
236 uint hc7 = (uint)(value7?.GetHashCode() ?? 0);
237
238 Initialize(out uint v1, out uint v2, out uint v3, out uint v4);
239
240 v1 = Round(v1, hc1);
241 v2 = Round(v2, hc2);
242 v3 = Round(v3, hc3);
243 v4 = Round(v4, hc4);
244
245 uint hash = MixState(v1, v2, v3, v4);
246 hash += 28;
247
248 hash = QueueRound(hash, hc5);
249 hash = QueueRound(hash, hc6);
250 hash = QueueRound(hash, hc7);
251
252 hash = MixFinal(hash);
253
254 return (int)hash;
255 }
256
257 public static int Combine<T1, T2, T3, T4, T5, T6, T7, T8>(T1 value1,
258 T2 value2,
259 T3 value3,
260 T4 value4,
261 T5 value5,
262 T6 value6,
263 T7 value7,
264 T8 value8)
265 {
266 uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
267 uint hc2 = (uint)(value2?.GetHashCode() ?? 0);
268 uint hc3 = (uint)(value3?.GetHashCode() ?? 0);
269 uint hc4 = (uint)(value4?.GetHashCode() ?? 0);
270 uint hc5 = (uint)(value5?.GetHashCode() ?? 0);
271 uint hc6 = (uint)(value6?.GetHashCode() ?? 0);
272 uint hc7 = (uint)(value7?.GetHashCode() ?? 0);
273 uint hc8 = (uint)(value8?.GetHashCode() ?? 0);
274
275 Initialize(out uint v1, out uint v2, out uint v3, out uint v4);
276
277 v1 = Round(v1, hc1);
278 v2 = Round(v2, hc2);
279 v3 = Round(v3, hc3);
280 v4 = Round(v4, hc4);
281
282 v1 = Round(v1, hc5);
283 v2 = Round(v2, hc6);
284 v3 = Round(v3, hc7);
285 v4 = Round(v4, hc8);
286
287 uint hash = MixState(v1, v2, v3, v4);
288 hash += 32;
289
290 hash = MixFinal(hash);
291
292 return (int)hash;
293 }
294
295 [MethodImpl(MethodImplOptions.AggressiveInlining)]
296 private static void Initialize(out uint v1, out uint v2, out uint v3, out uint v4)
297 {
298 v1 = s_Seed + PRIME1 + PRIME2;
299 v2 = s_Seed + PRIME2;
300 v3 = s_Seed;
301 v4 = s_Seed - PRIME1;
302 }
303
304 [MethodImpl(MethodImplOptions.AggressiveInlining)]
305 private static uint Round(uint hash, uint input)
306 {
307 return RotateLeft(hash + input * PRIME2, 13) * PRIME1;
308 }
309
310 [MethodImpl(MethodImplOptions.AggressiveInlining)]
311 private static uint QueueRound(uint hash, uint queuedValue)
312 {
313 return RotateLeft(hash + queuedValue * PRIME3, 17) * PRIME4;
314 }
315
316 [MethodImpl(MethodImplOptions.AggressiveInlining)]
317 private static uint MixState(uint v1, uint v2, uint v3, uint v4)
318 {
319 return RotateLeft(v1, 1) + RotateLeft(v2, 7) + RotateLeft(v3, 12) + RotateLeft(v4, 18);
320 }
321
322 private static uint MixEmptyState()
323 {
324 return s_Seed + PRIME5;
325 }
326
327 [MethodImpl(MethodImplOptions.AggressiveInlining)]
328 private static uint MixFinal(uint hash)
329 {
330 hash ^= hash >> 15;
331 hash *= PRIME2;
332 hash ^= hash >> 13;
333 hash *= PRIME3;
334 hash ^= hash >> 16;
335
336 return hash;
337 }
338}
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