A game about forced loneliness, made by TACStudios
1using System;
2using System.Runtime.CompilerServices;
3using static Unity.Mathematics.math;
4using System.Diagnostics;
5using Unity.IL2CPP.CompilerServices;
6
7namespace Unity.Mathematics
8{
9 /// <summary>
10 /// Random Number Generator based on xorshift.
11 /// Designed for minimal state (32bits) to be easily embeddable into components.
12 /// Core functionality is integer multiplication free to improve vectorization
13 /// on less capable SIMD instruction sets.
14 /// </summary>
15 [Il2CppEagerStaticClassConstruction]
16 [Serializable]
17 public partial struct Random
18 {
19 /// <summary>
20 /// The random number generator state. It should not be zero.
21 /// </summary>
22 public uint state;
23
24 /// <summary>
25 /// Constructs a Random instance with a given seed value. The seed must be non-zero.
26 /// </summary>
27 /// <param name="seed">The seed to initialize with.</param>
28 [MethodImpl(MethodImplOptions.AggressiveInlining)]
29 public Random(uint seed)
30 {
31 state = seed;
32 CheckInitState();
33 NextState();
34 }
35
36 /// <summary>
37 /// Constructs a <see cref="Random"/> instance with an index that gets hashed. The index must not be uint.MaxValue.
38 /// </summary>
39 /// <remarks>
40 /// Use this function when you expect to create several Random instances in a loop.
41 /// </remarks>
42 /// <example>
43 /// <code>
44 /// for (uint i = 0; i < 4096; ++i)
45 /// {
46 /// Random rand = Random.CreateFromIndex(i);
47 ///
48 /// // Random numbers drawn from loop iteration j will be very different
49 /// // from every other loop iteration k.
50 /// rand.NextUInt();
51 /// }
52 /// </code>
53 /// </example>
54 /// <param name="index">An index that will be hashed for Random creation. Must not be uint.MaxValue.</param>
55 /// <returns><see cref="Random"/> created from an index.</returns>
56 [MethodImpl(MethodImplOptions.AggressiveInlining)]
57 public static Random CreateFromIndex(uint index)
58 {
59 CheckIndexForHash(index);
60
61 // Wang hash will hash 61 to zero but we want uint.MaxValue to hash to zero. To make this happen
62 // we must offset by 62.
63 return new Random(WangHash(index + 62u));
64 }
65
66 [MethodImpl(MethodImplOptions.AggressiveInlining)]
67 internal static uint WangHash(uint n)
68 {
69 // https://gist.github.com/badboy/6267743#hash-function-construction-principles
70 // Wang hash: this has the property that none of the outputs will
71 // collide with each other, which is important for the purposes of
72 // seeding a random number generator. This was verified empirically
73 // by checking all 2^32 uints.
74 n = (n ^ 61u) ^ (n >> 16);
75 n *= 9u;
76 n = n ^ (n >> 4);
77 n *= 0x27d4eb2du;
78 n = n ^ (n >> 15);
79
80 return n;
81 }
82
83 /// <summary>
84 /// Initialized the state of the Random instance with a given seed value. The seed must be non-zero.
85 /// </summary>
86 /// <param name="seed">The seed to initialize with.</param>
87 [MethodImpl(MethodImplOptions.AggressiveInlining)]
88 public void InitState(uint seed = 0x6E624EB7u)
89 {
90 state = seed;
91 NextState();
92 }
93
94 /// <summary>Returns a uniformly random bool value.</summary>
95 /// <returns>A uniformly random boolean value.</returns>
96 [MethodImpl(MethodImplOptions.AggressiveInlining)]
97 public bool NextBool()
98 {
99 return (NextState() & 1) == 1;
100 }
101
102 /// <summary>Returns a uniformly random bool2 value.</summary>
103 /// <returns>A uniformly random bool2 value.</returns>
104 [MethodImpl(MethodImplOptions.AggressiveInlining)]
105 public bool2 NextBool2()
106 {
107 uint v = NextState();
108 return (uint2(v) & uint2(1, 2)) == 0;
109 }
110
111 /// <summary>Returns a uniformly random bool3 value.</summary>
112 /// <returns>A uniformly random bool3 value.</returns>
113 [MethodImpl(MethodImplOptions.AggressiveInlining)]
114 public bool3 NextBool3()
115 {
116 uint v = NextState();
117 return (uint3(v) & uint3(1, 2, 4)) == 0;
118 }
119
120 /// <summary>Returns a uniformly random bool4 value.</summary>
121 /// <returns>A uniformly random bool4 value.</returns>
122 [MethodImpl(MethodImplOptions.AggressiveInlining)]
123 public bool4 NextBool4()
124 {
125 uint v = NextState();
126 return (uint4(v) & uint4(1, 2, 4, 8)) == 0;
127 }
128
129
130 /// <summary>Returns a uniformly random int value in the interval [-2147483647, 2147483647].</summary>
131 /// <returns>A uniformly random integer value.</returns>
132 [MethodImpl(MethodImplOptions.AggressiveInlining)]
133 public int NextInt()
134 {
135 return (int)NextState() ^ -2147483648;
136 }
137
138 /// <summary>Returns a uniformly random int2 value with all components in the interval [-2147483647, 2147483647].</summary>
139 /// <returns>A uniformly random int2 value.</returns>
140 [MethodImpl(MethodImplOptions.AggressiveInlining)]
141 public int2 NextInt2()
142 {
143 return int2((int)NextState(), (int)NextState()) ^ -2147483648;
144 }
145
146 /// <summary>Returns a uniformly random int3 value with all components in the interval [-2147483647, 2147483647].</summary>
147 /// <returns>A uniformly random int3 value.</returns>
148 [MethodImpl(MethodImplOptions.AggressiveInlining)]
149 public int3 NextInt3()
150 {
151 return int3((int)NextState(), (int)NextState(), (int)NextState()) ^ -2147483648;
152 }
153
154 /// <summary>Returns a uniformly random int4 value with all components in the interval [-2147483647, 2147483647].</summary>
155 /// <returns>A uniformly random int4 value.</returns>
156 [MethodImpl(MethodImplOptions.AggressiveInlining)]
157 public int4 NextInt4()
158 {
159 return int4((int)NextState(), (int)NextState(), (int)NextState(), (int)NextState()) ^ -2147483648;
160 }
161
162 /// <summary>Returns a uniformly random int value in the interval [0, max).</summary>
163 /// <param name="max">The maximum value to generate, exclusive.</param>
164 /// <returns>A uniformly random int value in the range [0, max).</returns>
165 [MethodImpl(MethodImplOptions.AggressiveInlining)]
166 public int NextInt(int max)
167 {
168 CheckNextIntMax(max);
169 return (int)((NextState() * (ulong)max) >> 32);
170 }
171
172 /// <summary>Returns a uniformly random int2 value with all components in the interval [0, max).</summary>
173 /// <param name="max">The componentwise maximum value to generate, exclusive.</param>
174 /// <returns>A uniformly random int2 value with all components in the range [0, max).</returns>
175 [MethodImpl(MethodImplOptions.AggressiveInlining)]
176 public int2 NextInt2(int2 max)
177 {
178 CheckNextIntMax(max.x);
179 CheckNextIntMax(max.y);
180 return int2((int)(NextState() * (ulong)max.x >> 32),
181 (int)(NextState() * (ulong)max.y >> 32));
182 }
183
184 /// <summary>Returns a uniformly random int3 value with all components in the interval [0, max).</summary>
185 /// <param name="max">The componentwise maximum value to generate, exclusive.</param>
186 /// <returns>A uniformly random int3 value with all components in the range [0, max).</returns>
187 [MethodImpl(MethodImplOptions.AggressiveInlining)]
188 public int3 NextInt3(int3 max)
189 {
190 CheckNextIntMax(max.x);
191 CheckNextIntMax(max.y);
192 CheckNextIntMax(max.z);
193 return int3((int)(NextState() * (ulong)max.x >> 32),
194 (int)(NextState() * (ulong)max.y >> 32),
195 (int)(NextState() * (ulong)max.z >> 32));
196 }
197
198 /// <summary>Returns a uniformly random int4 value with all components in the interval [0, max).</summary>
199 /// <param name="max">The componentwise maximum value to generate, exclusive.</param>
200 /// <returns>A uniformly random int4 value with all components in the range [0, max).</returns>
201 [MethodImpl(MethodImplOptions.AggressiveInlining)]
202 public int4 NextInt4(int4 max)
203 {
204 CheckNextIntMax(max.x);
205 CheckNextIntMax(max.y);
206 CheckNextIntMax(max.z);
207 CheckNextIntMax(max.w);
208 return int4((int)(NextState() * (ulong)max.x >> 32),
209 (int)(NextState() * (ulong)max.y >> 32),
210 (int)(NextState() * (ulong)max.z >> 32),
211 (int)(NextState() * (ulong)max.w >> 32));
212 }
213
214 /// <summary>Returns a uniformly random int value in the interval [min, max).</summary>
215 /// <param name="min">The minimum value to generate, inclusive.</param>
216 /// <param name="max">The maximum value to generate, exclusive.</param>
217 /// <returns>A uniformly random integer between [min, max).</returns>
218 [MethodImpl(MethodImplOptions.AggressiveInlining)]
219 public int NextInt(int min, int max)
220 {
221 CheckNextIntMinMax(min, max);
222 uint range = (uint)(max - min);
223 return (int)(NextState() * (ulong)range >> 32) + min;
224 }
225
226 /// <summary>Returns a uniformly random int2 value with all components in the interval [min, max).</summary>
227 /// <param name="min">The componentwise minimum value to generate, inclusive.</param>
228 /// <param name="max">The componentwise maximum value to generate, exclusive.</param>
229 /// <returns>A uniformly random int2 between [min, max).</returns>
230 [MethodImpl(MethodImplOptions.AggressiveInlining)]
231 public int2 NextInt2(int2 min, int2 max)
232 {
233 CheckNextIntMinMax(min.x, max.x);
234 CheckNextIntMinMax(min.y, max.y);
235 uint2 range = (uint2)(max - min);
236 return int2((int)(NextState() * (ulong)range.x >> 32),
237 (int)(NextState() * (ulong)range.y >> 32)) + min;
238 }
239
240 /// <summary>Returns a uniformly random int3 value with all components in the interval [min, max).</summary>
241 /// <param name="min">The componentwise minimum value to generate, inclusive.</param>
242 /// <param name="max">The componentwise maximum value to generate, exclusive.</param>
243 /// <returns>A uniformly random int3 between [min, max).</returns>
244 [MethodImpl(MethodImplOptions.AggressiveInlining)]
245 public int3 NextInt3(int3 min, int3 max)
246 {
247 CheckNextIntMinMax(min.x, max.x);
248 CheckNextIntMinMax(min.y, max.y);
249 CheckNextIntMinMax(min.z, max.z);
250 uint3 range = (uint3)(max - min);
251 return int3((int)(NextState() * (ulong)range.x >> 32),
252 (int)(NextState() * (ulong)range.y >> 32),
253 (int)(NextState() * (ulong)range.z >> 32)) + min;
254 }
255
256 /// <summary>Returns a uniformly random int4 value with all components in the interval [min, max).</summary>
257 /// <param name="min">The componentwise minimum value to generate, inclusive.</param>
258 /// <param name="max">The componentwise maximum value to generate, exclusive.</param>
259 /// <returns>A uniformly random int4 between [min, max).</returns>
260 [MethodImpl(MethodImplOptions.AggressiveInlining)]
261 public int4 NextInt4(int4 min, int4 max)
262 {
263 CheckNextIntMinMax(min.x, max.x);
264 CheckNextIntMinMax(min.y, max.y);
265 CheckNextIntMinMax(min.z, max.z);
266 CheckNextIntMinMax(min.w, max.w);
267 uint4 range = (uint4)(max - min);
268 return int4((int)(NextState() * (ulong)range.x >> 32),
269 (int)(NextState() * (ulong)range.y >> 32),
270 (int)(NextState() * (ulong)range.z >> 32),
271 (int)(NextState() * (ulong)range.w >> 32)) + min;
272 }
273
274 /// <summary>Returns a uniformly random uint value in the interval [0, 4294967294].</summary>
275 /// <returns>A uniformly random unsigned integer.</returns>
276 [MethodImpl(MethodImplOptions.AggressiveInlining)]
277 public uint NextUInt()
278 {
279 return NextState() - 1u;
280 }
281
282 /// <summary>Returns a uniformly random uint2 value with all components in the interval [0, 4294967294].</summary>
283 /// <returns>A uniformly random uint2.</returns>
284 [MethodImpl(MethodImplOptions.AggressiveInlining)]
285 public uint2 NextUInt2()
286 {
287 return uint2(NextState(), NextState()) - 1u;
288 }
289
290 /// <summary>Returns a uniformly random uint3 value with all components in the interval [0, 4294967294].</summary>
291 /// <returns>A uniformly random uint3.</returns>
292 [MethodImpl(MethodImplOptions.AggressiveInlining)]
293 public uint3 NextUInt3()
294 {
295 return uint3(NextState(), NextState(), NextState()) - 1u;
296 }
297
298 /// <summary>Returns a uniformly random uint4 value with all components in the interval [0, 4294967294].</summary>
299 /// <returns>A uniformly random uint4.</returns>
300 [MethodImpl(MethodImplOptions.AggressiveInlining)]
301 public uint4 NextUInt4()
302 {
303 return uint4(NextState(), NextState(), NextState(), NextState()) - 1u;
304 }
305
306
307 /// <summary>Returns a uniformly random uint value in the interval [0, max).</summary>
308 /// <param name="max">The maximum value to generate, exclusive.</param>
309 /// <returns>A uniformly random unsigned integer in the range [0, max).</returns>
310 [MethodImpl(MethodImplOptions.AggressiveInlining)]
311 public uint NextUInt(uint max)
312 {
313 return (uint)((NextState() * (ulong)max) >> 32);
314 }
315
316 /// <summary>Returns a uniformly random uint2 value with all components in the interval [0, max).</summary>
317 /// <param name="max">The componentwise maximum value to generate, exclusive.</param>
318 /// <returns>A uniformly random uint2 in the range [0, max).</returns>
319 [MethodImpl(MethodImplOptions.AggressiveInlining)]
320 public uint2 NextUInt2(uint2 max)
321 {
322 return uint2( (uint)(NextState() * (ulong)max.x >> 32),
323 (uint)(NextState() * (ulong)max.y >> 32));
324 }
325
326 /// <summary>Returns a uniformly random uint3 value with all components in the interval [0, max).</summary>
327 /// <param name="max">The componentwise maximum value to generate, exclusive.</param>
328 /// <returns>A uniformly random uint3 in the range [0, max).</returns>
329 [MethodImpl(MethodImplOptions.AggressiveInlining)]
330 public uint3 NextUInt3(uint3 max)
331 {
332 return uint3( (uint)(NextState() * (ulong)max.x >> 32),
333 (uint)(NextState() * (ulong)max.y >> 32),
334 (uint)(NextState() * (ulong)max.z >> 32));
335 }
336
337 /// <summary>Returns a uniformly random uint4 value with all components in the interval [0, max).</summary>
338 /// <param name="max">The componentwise maximum value to generate, exclusive.</param>
339 /// <returns>A uniformly random uint4 in the range [0, max).</returns>
340 [MethodImpl(MethodImplOptions.AggressiveInlining)]
341 public uint4 NextUInt4(uint4 max)
342 {
343 return uint4( (uint)(NextState() * (ulong)max.x >> 32),
344 (uint)(NextState() * (ulong)max.y >> 32),
345 (uint)(NextState() * (ulong)max.z >> 32),
346 (uint)(NextState() * (ulong)max.w >> 32));
347 }
348
349 /// <summary>Returns a uniformly random uint value in the interval [min, max).</summary>
350 /// <param name="min">The minimum value to generate, inclusive.</param>
351 /// <param name="max">The maximum value to generate, exclusive.</param>
352 /// <returns>A uniformly random unsigned integer in the range [min, max).</returns>
353 [MethodImpl(MethodImplOptions.AggressiveInlining)]
354 public uint NextUInt(uint min, uint max)
355 {
356 CheckNextUIntMinMax(min, max);
357 uint range = max - min;
358 return (uint)(NextState() * (ulong)range >> 32) + min;
359 }
360
361 /// <summary>Returns a uniformly random uint2 value with all components in the interval [min, max).</summary>
362 /// <param name="min">The componentwise minimum value to generate, inclusive.</param>
363 /// <param name="max">The componentwise maximum value to generate, exclusive.</param>
364 /// <returns>A uniformly random uint2 in the range [min, max).</returns>
365 [MethodImpl(MethodImplOptions.AggressiveInlining)]
366 public uint2 NextUInt2(uint2 min, uint2 max)
367 {
368 CheckNextUIntMinMax(min.x, max.x);
369 CheckNextUIntMinMax(min.y, max.y);
370 uint2 range = max - min;
371 return uint2((uint)(NextState() * (ulong)range.x >> 32),
372 (uint)(NextState() * (ulong)range.y >> 32)) + min;
373 }
374
375 /// <summary>Returns a uniformly random uint3 value with all components in the interval [min, max).</summary>
376 /// <param name="min">The componentwise minimum value to generate, inclusive.</param>
377 /// <param name="max">The componentwise maximum value to generate, exclusive.</param>
378 /// <returns>A uniformly random uint3 in the range [min, max).</returns>
379 [MethodImpl(MethodImplOptions.AggressiveInlining)]
380 public uint3 NextUInt3(uint3 min, uint3 max)
381 {
382 CheckNextUIntMinMax(min.x, max.x);
383 CheckNextUIntMinMax(min.y, max.y);
384 CheckNextUIntMinMax(min.z, max.z);
385 uint3 range = max - min;
386 return uint3((uint)(NextState() * (ulong)range.x >> 32),
387 (uint)(NextState() * (ulong)range.y >> 32),
388 (uint)(NextState() * (ulong)range.z >> 32)) + min;
389 }
390
391 /// <summary>Returns a uniformly random uint4 value with all components in the interval [min, max).</summary>
392 /// <param name="min">The componentwise minimum value to generate, inclusive.</param>
393 /// <param name="max">The componentwise maximum value to generate, exclusive.</param>
394 /// <returns>A uniformly random uint4 in the range [min, max).</returns>
395 [MethodImpl(MethodImplOptions.AggressiveInlining)]
396 public uint4 NextUInt4(uint4 min, uint4 max)
397 {
398 CheckNextUIntMinMax(min.x, max.x);
399 CheckNextUIntMinMax(min.y, max.y);
400 CheckNextUIntMinMax(min.z, max.z);
401 CheckNextUIntMinMax(min.w, max.w);
402 uint4 range = (uint4)(max - min);
403 return uint4((uint)(NextState() * (ulong)range.x >> 32),
404 (uint)(NextState() * (ulong)range.y >> 32),
405 (uint)(NextState() * (ulong)range.z >> 32),
406 (uint)(NextState() * (ulong)range.w >> 32)) + min;
407 }
408
409 /// <summary>Returns a uniformly random float value in the interval [0, 1).</summary>
410 /// <returns>A uniformly random float value in the range [0, 1).</returns>
411 [MethodImpl(MethodImplOptions.AggressiveInlining)]
412 public float NextFloat()
413 {
414 return asfloat(0x3f800000 | (NextState() >> 9)) - 1.0f;
415 }
416
417 /// <summary>Returns a uniformly random float2 value with all components in the interval [0, 1).</summary>
418 /// <returns>A uniformly random float2 value in the range [0, 1).</returns>
419 [MethodImpl(MethodImplOptions.AggressiveInlining)]
420 public float2 NextFloat2()
421 {
422 return asfloat(0x3f800000 | (uint2(NextState(), NextState()) >> 9)) - 1.0f;
423 }
424
425 /// <summary>Returns a uniformly random float3 value with all components in the interval [0, 1).</summary>
426 /// <returns>A uniformly random float3 value in the range [0, 1).</returns>
427 [MethodImpl(MethodImplOptions.AggressiveInlining)]
428 public float3 NextFloat3()
429 {
430 return asfloat(0x3f800000 | (uint3(NextState(), NextState(), NextState()) >> 9)) - 1.0f;
431 }
432
433 /// <summary>Returns a uniformly random float4 value with all components in the interval [0, 1).</summary>
434 /// <returns>A uniformly random float4 value in the range [0, 1).</returns>
435 [MethodImpl(MethodImplOptions.AggressiveInlining)]
436 public float4 NextFloat4()
437 {
438 return asfloat(0x3f800000 | (uint4(NextState(), NextState(), NextState(), NextState()) >> 9)) - 1.0f;
439 }
440
441
442 /// <summary>Returns a uniformly random float value in the interval [0, max).</summary>
443 /// <param name="max">The maximum value to generate, exclusive.</param>
444 /// <returns>A uniformly random float value in the range [0, max).</returns>
445 [MethodImpl(MethodImplOptions.AggressiveInlining)]
446 public float NextFloat(float max) { return NextFloat() * max; }
447
448 /// <summary>Returns a uniformly random float2 value with all components in the interval [0, max).</summary>
449 /// <param name="max">The componentwise maximum value to generate, exclusive.</param>
450 /// <returns>A uniformly random float2 value in the range [0, max).</returns>
451 [MethodImpl(MethodImplOptions.AggressiveInlining)]
452 public float2 NextFloat2(float2 max) { return NextFloat2() * max; }
453
454 /// <summary>Returns a uniformly random float3 value with all components in the interval [0, max).</summary>
455 /// <param name="max">The componentwise maximum value to generate, exclusive.</param>
456 /// <returns>A uniformly random float3 value in the range [0, max).</returns>
457 [MethodImpl(MethodImplOptions.AggressiveInlining)]
458 public float3 NextFloat3(float3 max) { return NextFloat3() * max; }
459
460 /// <summary>Returns a uniformly random float4 value with all components in the interval [0, max).</summary>
461 /// <param name="max">The componentwise maximum value to generate, exclusive.</param>
462 /// <returns>A uniformly random float4 value in the range [0, max).</returns>
463 [MethodImpl(MethodImplOptions.AggressiveInlining)]
464 public float4 NextFloat4(float4 max) { return NextFloat4() * max; }
465
466
467 /// <summary>Returns a uniformly random float value in the interval [min, max).</summary>
468 /// <param name="min">The minimum value to generate, inclusive.</param>
469 /// <param name="max">The maximum value to generate, exclusive.</param>
470 /// <returns>A uniformly random float value in the range [min, max).</returns>
471 [MethodImpl(MethodImplOptions.AggressiveInlining)]
472 public float NextFloat(float min, float max) { return NextFloat() * (max - min) + min; }
473
474 /// <summary>Returns a uniformly random float2 value with all components in the interval [min, max).</summary>
475 /// <param name="min">The componentwise minimum value to generate, inclusive.</param>
476 /// <param name="max">The componentwise maximum value to generate, exclusive.</param>
477 /// <returns>A uniformly random float2 value in the range [min, max).</returns>
478 [MethodImpl(MethodImplOptions.AggressiveInlining)]
479 public float2 NextFloat2(float2 min, float2 max) { return NextFloat2() * (max - min) + min; }
480
481 /// <summary>Returns a uniformly random float3 value with all components in the interval [min, max).</summary>
482 /// <param name="min">The componentwise minimum value to generate, inclusive.</param>
483 /// <param name="max">The componentwise maximum value to generate, exclusive.</param>
484 /// <returns>A uniformly random float3 value in the range [min, max).</returns>
485 [MethodImpl(MethodImplOptions.AggressiveInlining)]
486 public float3 NextFloat3(float3 min, float3 max) { return NextFloat3() * (max - min) + min; }
487
488 /// <summary>Returns a uniformly random float4 value with all components in the interval [min, max).</summary>
489 /// <param name="min">The componentwise minimum value to generate, inclusive.</param>
490 /// <param name="max">The componentwise maximum value to generate, exclusive.</param>
491 /// <returns>A uniformly random float4 value in the range [min, max).</returns>
492 [MethodImpl(MethodImplOptions.AggressiveInlining)]
493 public float4 NextFloat4(float4 min, float4 max) { return NextFloat4() * (max - min) + min; }
494
495
496
497 /// <summary>Returns a uniformly random double value in the interval [0, 1).</summary>
498 /// <returns>A uniformly random double value in the range [0, 1).</returns>
499 [MethodImpl(MethodImplOptions.AggressiveInlining)]
500 public double NextDouble()
501 {
502 ulong sx = ((ulong)NextState() << 20) ^ NextState();
503 return asdouble(0x3ff0000000000000 | sx) - 1.0;
504 }
505
506 /// <summary>Returns a uniformly random double2 value with all components in the interval [0, 1).</summary>
507 /// <returns>A uniformly random double2 value in the range [0, 1).</returns>
508 [MethodImpl(MethodImplOptions.AggressiveInlining)]
509 public double2 NextDouble2()
510 {
511 ulong sx = ((ulong)NextState() << 20) ^ NextState();
512 ulong sy = ((ulong)NextState() << 20) ^ NextState();
513 return double2(asdouble(0x3ff0000000000000 | sx),
514 asdouble(0x3ff0000000000000 | sy)) - 1.0;
515 }
516
517 /// <summary>Returns a uniformly random double3 value with all components in the interval [0, 1).</summary>
518 /// <returns>A uniformly random double3 value in the range [0, 1).</returns>
519 [MethodImpl(MethodImplOptions.AggressiveInlining)]
520 public double3 NextDouble3()
521 {
522 ulong sx = ((ulong)NextState() << 20) ^ NextState();
523 ulong sy = ((ulong)NextState() << 20) ^ NextState();
524 ulong sz = ((ulong)NextState() << 20) ^ NextState();
525 return double3(asdouble(0x3ff0000000000000 | sx),
526 asdouble(0x3ff0000000000000 | sy),
527 asdouble(0x3ff0000000000000 | sz)) - 1.0;
528 }
529
530 /// <summary>Returns a uniformly random double4 value with all components in the interval [0, 1).</summary>
531 /// <returns>A uniformly random double4 value in the range [0, 1).</returns>
532 [MethodImpl(MethodImplOptions.AggressiveInlining)]
533 public double4 NextDouble4()
534 {
535 ulong sx = ((ulong)NextState() << 20) ^ NextState();
536 ulong sy = ((ulong)NextState() << 20) ^ NextState();
537 ulong sz = ((ulong)NextState() << 20) ^ NextState();
538 ulong sw = ((ulong)NextState() << 20) ^ NextState();
539 return double4(asdouble(0x3ff0000000000000 | sx),
540 asdouble(0x3ff0000000000000 | sy),
541 asdouble(0x3ff0000000000000 | sz),
542 asdouble(0x3ff0000000000000 | sw)) - 1.0;
543 }
544
545
546 /// <summary>Returns a uniformly random double value in the interval [0, max).</summary>
547 /// <param name="max">The maximum value to generate, exclusive.</param>
548 /// <returns>A uniformly random double value in the range [0, max).</returns>
549 [MethodImpl(MethodImplOptions.AggressiveInlining)]
550 public double NextDouble(double max) { return NextDouble() * max; }
551
552 /// <summary>Returns a uniformly random double2 value with all components in the interval [0, max).</summary>
553 /// <param name="max">The componentwise maximum value to generate, exclusive.</param>
554 /// <returns>A uniformly random double2 value in the range [0, max).</returns>
555 [MethodImpl(MethodImplOptions.AggressiveInlining)]
556 public double2 NextDouble2(double2 max) { return NextDouble2() * max; }
557
558 /// <summary>Returns a uniformly random double3 value with all components in the interval [0, max).</summary>
559 /// <param name="max">The componentwise maximum value to generate, exclusive.</param>
560 /// <returns>A uniformly random double3 value in the range [0, max).</returns>
561 [MethodImpl(MethodImplOptions.AggressiveInlining)]
562 public double3 NextDouble3(double3 max) { return NextDouble3() * max; }
563
564 /// <summary>Returns a uniformly random double4 value with all components in the interval [0, max).</summary>
565 /// <param name="max">The componentwise maximum value to generate, exclusive.</param>
566 /// <returns>A uniformly random double4 value in the range [0, max).</returns>
567 [MethodImpl(MethodImplOptions.AggressiveInlining)]
568 public double4 NextDouble4(double4 max) { return NextDouble4() * max; }
569
570
571 /// <summary>Returns a uniformly random double value in the interval [min, max).</summary>
572 /// <param name="min">The minimum value to generate, inclusive.</param>
573 /// <param name="max">The maximum value to generate, exclusive.</param>
574 /// <returns>A uniformly random double value in the range [min, max).</returns>
575 [MethodImpl(MethodImplOptions.AggressiveInlining)]
576 public double NextDouble(double min, double max) { return NextDouble() * (max - min) + min; }
577
578 /// <summary>Returns a uniformly random double2 value with all components in the interval [min, max).</summary>
579 /// <param name="min">The componentwise minimum value to generate, inclusive.</param>
580 /// <param name="max">The componentwise maximum value to generate, exclusive.</param>
581 /// <returns>A uniformly random double2 value in the range [min, max).</returns>
582 [MethodImpl(MethodImplOptions.AggressiveInlining)]
583 public double2 NextDouble2(double2 min, double2 max) { return NextDouble2() * (max - min) + min; }
584
585 /// <summary>Returns a uniformly random double3 value with all components in the interval [min, max).</summary>
586 /// <param name="min">The componentwise minimum value to generate, inclusive.</param>
587 /// <param name="max">The componentwise maximum value to generate, exclusive.</param>
588 /// <returns>A uniformly random double3 value in the range [min, max).</returns>
589 [MethodImpl(MethodImplOptions.AggressiveInlining)]
590 public double3 NextDouble3(double3 min, double3 max) { return NextDouble3() * (max - min) + min; }
591
592 /// <summary>Returns a uniformly random double4 value with all components in the interval [min, max).</summary>
593 /// <param name="min">The componentwise minimum value to generate, inclusive.</param>
594 /// <param name="max">The componentwise maximum value to generate, exclusive.</param>
595 /// <returns>A uniformly random double4 value in the range [min, max).</returns>
596 [MethodImpl(MethodImplOptions.AggressiveInlining)]
597 public double4 NextDouble4(double4 min, double4 max) { return NextDouble4() * (max - min) + min; }
598
599 /// <summary>Returns a unit length float2 vector representing a uniformly random 2D direction.</summary>
600 /// <returns>A uniformly random unit length float2 vector.</returns>
601 [MethodImpl(MethodImplOptions.AggressiveInlining)]
602 public float2 NextFloat2Direction()
603 {
604 float angle = NextFloat() * PI * 2.0f;
605 float s, c;
606 sincos(angle, out s, out c);
607 return float2(c, s);
608 }
609
610 /// <summary>Returns a unit length double2 vector representing a uniformly random 2D direction.</summary>
611 /// <returns>A uniformly random unit length double2 vector.</returns>
612 [MethodImpl(MethodImplOptions.AggressiveInlining)]
613 public double2 NextDouble2Direction()
614 {
615 double angle = NextDouble() * PI_DBL * 2.0;
616 double s, c;
617 sincos(angle, out s, out c);
618 return double2(c, s);
619 }
620
621 /// <summary>Returns a unit length float3 vector representing a uniformly random 3D direction.</summary>
622 /// <returns>A uniformly random unit length float3 vector.</returns>
623 [MethodImpl(MethodImplOptions.AggressiveInlining)]
624 public float3 NextFloat3Direction()
625 {
626 float2 rnd = NextFloat2();
627 float z = rnd.x * 2.0f - 1.0f;
628 float r = sqrt(max(1.0f - z * z, 0.0f));
629 float angle = rnd.y * PI * 2.0f;
630 float s, c;
631 sincos(angle, out s, out c);
632 return float3(c*r, s*r, z);
633 }
634
635 /// <summary>Returns a unit length double3 vector representing a uniformly random 3D direction.</summary>
636 /// <returns>A uniformly random unit length double3 vector.</returns>
637 [MethodImpl(MethodImplOptions.AggressiveInlining)]
638 public double3 NextDouble3Direction()
639 {
640 double2 rnd = NextDouble2();
641 double z = rnd.x * 2.0 - 1.0;
642 double r = sqrt(max(1.0 - z * z, 0.0));
643 double angle = rnd.y * PI_DBL * 2.0;
644 double s, c;
645 sincos(angle, out s, out c);
646 return double3(c * r, s * r, z);
647 }
648
649 /// <summary>Returns a unit length quaternion representing a uniformly 3D rotation.</summary>
650 /// <returns>A uniformly random unit length quaternion.</returns>
651 [MethodImpl(MethodImplOptions.AggressiveInlining)]
652 public quaternion NextQuaternionRotation()
653 {
654 float3 rnd = NextFloat3(float3(2.0f * PI, 2.0f * PI, 1.0f));
655 float u1 = rnd.z;
656 float2 theta_rho = rnd.xy;
657
658 float i = sqrt(1.0f - u1);
659 float j = sqrt(u1);
660
661 float2 sin_theta_rho;
662 float2 cos_theta_rho;
663 sincos(theta_rho, out sin_theta_rho, out cos_theta_rho);
664
665 quaternion q = quaternion(i * sin_theta_rho.x, i * cos_theta_rho.x, j * sin_theta_rho.y, j * cos_theta_rho.y);
666 return quaternion(select(q.value, -q.value, q.value.w < 0.0f));
667 }
668
669 [MethodImpl(MethodImplOptions.AggressiveInlining)]
670 private uint NextState()
671 {
672 CheckState();
673 uint t = state;
674 state ^= state << 13;
675 state ^= state >> 17;
676 state ^= state << 5;
677 return t;
678 }
679
680 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
681 private void CheckInitState()
682 {
683#if ENABLE_UNITY_COLLECTIONS_CHECKS
684 if (state == 0)
685 throw new System.ArgumentException("Seed must be non-zero");
686#endif
687 }
688
689 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
690 static void CheckIndexForHash(uint index)
691 {
692 if (index == uint.MaxValue)
693 throw new System.ArgumentException("Index must not be uint.MaxValue");
694 }
695
696 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
697 private void CheckState()
698 {
699#if ENABLE_UNITY_COLLECTIONS_CHECKS
700 if(state == 0)
701 throw new System.ArgumentException("Invalid state 0. Random object has not been properly initialized");
702#endif
703 }
704
705 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
706 private void CheckNextIntMax(int max)
707 {
708#if ENABLE_UNITY_COLLECTIONS_CHECKS
709 if (max < 0)
710 throw new System.ArgumentException("max must be positive");
711#endif
712 }
713
714 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
715 private void CheckNextIntMinMax(int min, int max)
716 {
717#if ENABLE_UNITY_COLLECTIONS_CHECKS
718 if (min > max)
719 throw new System.ArgumentException("min must be less than or equal to max");
720#endif
721 }
722
723 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
724 private void CheckNextUIntMinMax(uint min, uint max)
725 {
726#if ENABLE_UNITY_COLLECTIONS_CHECKS
727 if (min > max)
728 throw new System.ArgumentException("min must be less than or equal to max");
729#endif
730 }
731
732 }
733}