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 &lt; 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}