Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
Random.cs
Go to the documentation of this file.
5
6namespace System;
7
8public class Random
9{
10 private sealed class ThreadSafeRandom : Random
11 {
12 [ThreadStatic]
13 private static XoshiroImpl t_random;
14
15 private static XoshiroImpl LocalRandom => t_random ?? Create();
16
18 : base(isThreadSafeRandom: true)
19 {
20 }
21
22 [MethodImpl(MethodImplOptions.NoInlining)]
23 private static XoshiroImpl Create()
24 {
25 return t_random = new XoshiroImpl();
26 }
27
28 public override int Next()
29 {
30 return LocalRandom.Next();
31 }
32
33 public override int Next(int maxValue)
34 {
35 if (maxValue < 0)
36 {
38 }
39 return LocalRandom.Next(maxValue);
40 }
41
42 public override int Next(int minValue, int maxValue)
43 {
44 if (minValue > maxValue)
45 {
47 }
48 return LocalRandom.Next(minValue, maxValue);
49 }
50
51 public override long NextInt64()
52 {
53 return LocalRandom.NextInt64();
54 }
55
56 public override long NextInt64(long maxValue)
57 {
58 if (maxValue < 0)
59 {
61 }
62 return LocalRandom.NextInt64(maxValue);
63 }
64
65 public override long NextInt64(long minValue, long maxValue)
66 {
67 if (minValue > maxValue)
68 {
70 }
71 return LocalRandom.NextInt64(minValue, maxValue);
72 }
73
74 public override float NextSingle()
75 {
76 return LocalRandom.NextSingle();
77 }
78
79 public override double NextDouble()
80 {
81 return LocalRandom.NextDouble();
82 }
83
84 public override void NextBytes(byte[] buffer)
85 {
86 if (buffer == null)
87 {
89 }
90 LocalRandom.NextBytes(buffer);
91 }
92
93 public override void NextBytes(Span<byte> buffer)
94 {
95 LocalRandom.NextBytes(buffer);
96 }
97
98 protected override double Sample()
99 {
100 throw new NotSupportedException();
101 }
102 }
103
104 internal abstract class ImplBase
105 {
106 public abstract double Sample();
107
108 public abstract int Next();
109
110 public abstract int Next(int maxValue);
111
112 public abstract int Next(int minValue, int maxValue);
113
114 public abstract long NextInt64();
115
116 public abstract long NextInt64(long maxValue);
117
118 public abstract long NextInt64(long minValue, long maxValue);
119
120 public abstract float NextSingle();
121
122 public abstract double NextDouble();
123
124 public abstract void NextBytes(byte[] buffer);
125
126 public abstract void NextBytes(Span<byte> buffer);
127 }
128
129 private sealed class Net5CompatSeedImpl : ImplBase
130 {
132
133 public Net5CompatSeedImpl(int seed)
134 {
135 _prng = new CompatPrng(seed);
136 }
137
138 public override double Sample()
139 {
140 return _prng.Sample();
141 }
142
143 public override int Next()
144 {
145 return _prng.InternalSample();
146 }
147
148 public override int Next(int maxValue)
149 {
150 return (int)(_prng.Sample() * (double)maxValue);
151 }
152
153 public override int Next(int minValue, int maxValue)
154 {
155 long num = (long)maxValue - (long)minValue;
156 if (num > int.MaxValue)
157 {
158 return (int)((long)(_prng.GetSampleForLargeRange() * (double)num) + minValue);
159 }
160 return (int)(_prng.Sample() * (double)num) + minValue;
161 }
162
163 public override long NextInt64()
164 {
165 ulong num;
166 do
167 {
168 num = NextUInt64() >> 1;
169 }
170 while (num == long.MaxValue);
171 return (long)num;
172 }
173
174 public override long NextInt64(long maxValue)
175 {
176 return NextInt64(0L, maxValue);
177 }
178
179 public override long NextInt64(long minValue, long maxValue)
180 {
181 ulong num = (ulong)(maxValue - minValue);
182 if (num > 1)
183 {
184 int num2 = BitOperations.Log2Ceiling(num);
185 ulong num3;
186 do
187 {
188 num3 = NextUInt64() >> 64 - num2;
189 }
190 while (num3 >= num);
191 return (long)num3 + minValue;
192 }
193 return minValue;
194 }
195
196 private ulong NextUInt64()
197 {
198 return (uint)Next(4194304) | ((ulong)(uint)Next(4194304) << 22) | ((ulong)(uint)Next(1048576) << 44);
199 }
200
201 public override double NextDouble()
202 {
203 return _prng.Sample();
204 }
205
206 public override float NextSingle()
207 {
208 return (float)_prng.Sample();
209 }
210
211 public override void NextBytes(byte[] buffer)
212 {
214 }
215
216 public override void NextBytes(Span<byte> buffer)
217 {
219 }
220 }
221
222 private sealed class Net5CompatDerivedImpl : ImplBase
223 {
224 private readonly Random _parent;
225
227
229 : this(parent, Shared.Next())
230 {
231 }
232
233 public Net5CompatDerivedImpl(Random parent, int seed)
234 {
235 _parent = parent;
236 _prng = new CompatPrng(seed);
237 }
238
239 public override double Sample()
240 {
241 return _prng.Sample();
242 }
243
244 public override int Next()
245 {
246 return _prng.InternalSample();
247 }
248
249 public override int Next(int maxValue)
250 {
251 return (int)(_parent.Sample() * (double)maxValue);
252 }
253
254 public override int Next(int minValue, int maxValue)
255 {
256 long num = (long)maxValue - (long)minValue;
257 if (num > int.MaxValue)
258 {
259 return (int)((long)(_prng.GetSampleForLargeRange() * (double)num) + minValue);
260 }
261 return (int)(_parent.Sample() * (double)num) + minValue;
262 }
263
264 public override long NextInt64()
265 {
266 ulong num;
267 do
268 {
269 num = NextUInt64() >> 1;
270 }
271 while (num == long.MaxValue);
272 return (long)num;
273 }
274
275 public override long NextInt64(long maxValue)
276 {
277 return NextInt64(0L, maxValue);
278 }
279
280 public override long NextInt64(long minValue, long maxValue)
281 {
282 ulong num = (ulong)(maxValue - minValue);
283 if (num > 1)
284 {
285 int num2 = BitOperations.Log2Ceiling(num);
286 ulong num3;
287 do
288 {
289 num3 = NextUInt64() >> 64 - num2;
290 }
291 while (num3 >= num);
292 return (long)num3 + minValue;
293 }
294 return minValue;
295 }
296
297 private ulong NextUInt64()
298 {
299 return (uint)_parent.Next(4194304) | ((ulong)(uint)_parent.Next(4194304) << 22) | ((ulong)(uint)_parent.Next(1048576) << 44);
300 }
301
302 public override double NextDouble()
303 {
304 return _parent.Sample();
305 }
306
307 public override float NextSingle()
308 {
309 return (float)_parent.Sample();
310 }
311
312 public override void NextBytes(byte[] buffer)
313 {
315 }
316
317 public override void NextBytes(Span<byte> buffer)
318 {
319 for (int i = 0; i < buffer.Length; i++)
320 {
321 buffer[i] = (byte)_parent.Next();
322 }
323 }
324 }
325
326 private struct CompatPrng
327 {
328 private int[] _seedArray;
329
330 private int _inext;
331
332 private int _inextp;
333
334 public CompatPrng(int seed)
335 {
336 int[] array = new int[56];
337 int num = ((seed == int.MinValue) ? int.MaxValue : Math.Abs(seed));
338 int num2 = (array[55] = 161803398 - num);
339 int num3 = 1;
340 int num4 = 0;
341 for (int i = 1; i < 55; i++)
342 {
343 if ((num4 += 21) >= 55)
344 {
345 num4 -= 55;
346 }
347 array[num4] = num3;
348 num3 = num2 - num3;
349 if (num3 < 0)
350 {
351 num3 += int.MaxValue;
352 }
353 num2 = array[num4];
354 }
355 for (int j = 1; j < 5; j++)
356 {
357 for (int k = 1; k < 56; k++)
358 {
359 int num5 = k + 30;
360 if (num5 >= 55)
361 {
362 num5 -= 55;
363 }
364 array[k] -= array[1 + num5];
365 if (array[k] < 0)
366 {
367 array[k] += int.MaxValue;
368 }
369 }
370 }
372 _inext = 0;
373 _inextp = 21;
374 }
375
376 internal double Sample()
377 {
378 return (double)InternalSample() * 4.656612875245797E-10;
379 }
380
382 {
383 for (int i = 0; i < buffer.Length; i++)
384 {
385 buffer[i] = (byte)InternalSample();
386 }
387 }
388
389 internal int InternalSample()
390 {
391 int inext = _inext;
392 if (++inext >= 56)
393 {
394 inext = 1;
395 }
396 int inextp = _inextp;
397 if (++inextp >= 56)
398 {
399 inextp = 1;
400 }
401 int[] seedArray = _seedArray;
402 int num = seedArray[inext] - seedArray[inextp];
403 if (num == int.MaxValue)
404 {
405 num--;
406 }
407 if (num < 0)
408 {
409 num += int.MaxValue;
410 }
411 seedArray[inext] = num;
412 _inext = inext;
413 _inextp = inextp;
414 return num;
415 }
416
417 internal double GetSampleForLargeRange()
418 {
419 int num = InternalSample();
420 if (InternalSample() % 2 == 0)
421 {
422 num = -num;
423 }
424 double num2 = num;
425 num2 += 2147483646.0;
426 return num2 / 4294967293.0;
427 }
428 }
429
430 internal sealed class XoshiroImpl : ImplBase
431 {
432 private ulong _s0;
433
434 private ulong _s1;
435
436 private ulong _s2;
437
438 private ulong _s3;
439
440 public unsafe XoshiroImpl()
441 {
442 ulong* ptr = stackalloc ulong[4];
443 do
444 {
445 Interop.GetRandomBytes((byte*)ptr, 32);
446 _s0 = *ptr;
447 _s1 = ptr[1];
448 _s2 = ptr[2];
449 _s3 = ptr[3];
450 }
451 while ((_s0 | _s1 | _s2 | _s3) == 0L);
452 }
453
454 [MethodImpl(MethodImplOptions.AggressiveInlining)]
455 internal uint NextUInt32()
456 {
457 return (uint)(NextUInt64() >> 32);
458 }
459
460 [MethodImpl(MethodImplOptions.AggressiveInlining)]
461 internal ulong NextUInt64()
462 {
463 ulong s = _s0;
464 ulong s2 = _s1;
465 ulong s3 = _s2;
466 ulong s4 = _s3;
467 ulong result = BitOperations.RotateLeft(s2 * 5, 7) * 9;
468 ulong num = s2 << 17;
469 s3 ^= s;
470 s4 ^= s2;
471 s2 ^= s3;
472 s ^= s4;
473 s3 ^= num;
474 s4 = BitOperations.RotateLeft(s4, 45);
475 _s0 = s;
476 _s1 = s2;
477 _s2 = s3;
478 _s3 = s4;
479 return result;
480 }
481
482 public override int Next()
483 {
484 ulong num;
485 do
486 {
487 num = NextUInt64() >> 33;
488 }
489 while (num == int.MaxValue);
490 return (int)num;
491 }
492
493 public override int Next(int maxValue)
494 {
495 if (maxValue > 1)
496 {
497 int num = BitOperations.Log2Ceiling((uint)maxValue);
498 ulong num2;
499 do
500 {
501 num2 = NextUInt64() >> 64 - num;
502 }
503 while (num2 >= (uint)maxValue);
504 return (int)num2;
505 }
506 return 0;
507 }
508
509 public override int Next(int minValue, int maxValue)
510 {
511 ulong num = (ulong)maxValue - (ulong)minValue;
512 if (num > 1)
513 {
514 int num2 = BitOperations.Log2Ceiling(num);
515 ulong num3;
516 do
517 {
518 num3 = NextUInt64() >> 64 - num2;
519 }
520 while (num3 >= num);
521 return (int)num3 + minValue;
522 }
523 return minValue;
524 }
525
526 public override long NextInt64()
527 {
528 ulong num;
529 do
530 {
531 num = NextUInt64() >> 1;
532 }
533 while (num == long.MaxValue);
534 return (long)num;
535 }
536
537 public override long NextInt64(long maxValue)
538 {
539 if (maxValue > 1)
540 {
541 int num = BitOperations.Log2Ceiling((ulong)maxValue);
542 ulong num2;
543 do
544 {
545 num2 = NextUInt64() >> 64 - num;
546 }
547 while (num2 >= (ulong)maxValue);
548 return (long)num2;
549 }
550 return 0L;
551 }
552
553 public override long NextInt64(long minValue, long maxValue)
554 {
555 ulong num = (ulong)(maxValue - minValue);
556 if (num > 1)
557 {
558 int num2 = BitOperations.Log2Ceiling(num);
559 ulong num3;
560 do
561 {
562 num3 = NextUInt64() >> 64 - num2;
563 }
564 while (num3 >= num);
565 return (long)num3 + minValue;
566 }
567 return minValue;
568 }
569
570 public override void NextBytes(byte[] buffer)
571 {
573 }
574
575 public unsafe override void NextBytes(Span<byte> buffer)
576 {
577 ulong num = _s0;
578 ulong num2 = _s1;
579 ulong num3 = _s2;
580 ulong num4 = _s3;
581 while (buffer.Length >= 8)
582 {
583 Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(buffer), BitOperations.RotateLeft(num2 * 5, 7) * 9);
584 ulong num5 = num2 << 17;
585 num3 ^= num;
586 num4 ^= num2;
587 num2 ^= num3;
588 num ^= num4;
589 num3 ^= num5;
590 num4 = BitOperations.RotateLeft(num4, 45);
591 buffer = buffer.Slice(8);
592 }
593 if (!buffer.IsEmpty)
594 {
595 ulong num6 = BitOperations.RotateLeft(num2 * 5, 7) * 9;
596 byte* ptr = (byte*)(&num6);
597 for (int i = 0; i < buffer.Length; i++)
598 {
599 buffer[i] = ptr[i];
600 }
601 ulong num7 = num2 << 17;
602 num3 ^= num;
603 num4 ^= num2;
604 num2 ^= num3;
605 num ^= num4;
606 num3 ^= num7;
607 num4 = BitOperations.RotateLeft(num4, 45);
608 }
609 _s0 = num;
610 _s1 = num2;
611 _s2 = num3;
612 _s3 = num4;
613 }
614
615 public override double NextDouble()
616 {
617 return (double)(NextUInt64() >> 11) * 1.1102230246251565E-16;
618 }
619
620 public override float NextSingle()
621 {
622 return (float)(NextUInt64() >> 40) * 5.9604645E-08f;
623 }
624
625 public override double Sample()
626 {
627 throw new NotSupportedException();
628 }
629 }
630
631 private readonly ImplBase _impl;
632
633 public static Random Shared { get; } = new ThreadSafeRandom();
634
635
636 public Random()
637 {
638 _impl = ((GetType() == typeof(Random)) ? ((ImplBase)new XoshiroImpl()) : ((ImplBase)new Net5CompatDerivedImpl(this)));
639 }
640
641 public Random(int Seed)
642 {
643 _impl = ((GetType() == typeof(Random)) ? ((ImplBase)new Net5CompatSeedImpl(Seed)) : ((ImplBase)new Net5CompatDerivedImpl(this, Seed)));
644 }
645
646 private protected Random(bool isThreadSafeRandom)
647 {
648 _impl = null;
649 }
650
651 public virtual int Next()
652 {
653 return _impl.Next();
654 }
655
656 public virtual int Next(int maxValue)
657 {
658 if (maxValue < 0)
659 {
661 }
662 return _impl.Next(maxValue);
663 }
664
665 public virtual int Next(int minValue, int maxValue)
666 {
667 if (minValue > maxValue)
668 {
670 }
671 return _impl.Next(minValue, maxValue);
672 }
673
674 public virtual long NextInt64()
675 {
676 return _impl.NextInt64();
677 }
678
679 public virtual long NextInt64(long maxValue)
680 {
681 if (maxValue < 0)
682 {
684 }
685 return _impl.NextInt64(maxValue);
686 }
687
688 public virtual long NextInt64(long minValue, long maxValue)
689 {
690 if (minValue > maxValue)
691 {
693 }
694 return _impl.NextInt64(minValue, maxValue);
695 }
696
697 public virtual float NextSingle()
698 {
699 return _impl.NextSingle();
700 }
701
702 public virtual double NextDouble()
703 {
704 return _impl.NextDouble();
705 }
706
707 public virtual void NextBytes(byte[] buffer)
708 {
709 if (buffer == null)
710 {
712 }
714 }
715
716 public virtual void NextBytes(Span<byte> buffer)
717 {
719 }
720
721 protected virtual double Sample()
722 {
723 return _impl.Sample();
724 }
725
726 private static void ThrowMaxValueMustBeNonNegative()
727 {
728 throw new ArgumentOutOfRangeException("maxValue", SR.Format(SR.ArgumentOutOfRange_NeedNonNegNum, "maxValue"));
729 }
730
731 private static void ThrowMinMaxValueSwapped()
732 {
733 throw new ArgumentOutOfRangeException("minValue", SR.Format(SR.Argument_MinMaxValue, "minValue", "maxValue"));
734 }
735}
static unsafe void GetRandomBytes(byte *buffer, int length)
Definition Interop.cs:1871
static double Abs(double value)
static uint RotateLeft(uint value, int offset)
static int Log2Ceiling(uint value)
void NextBytes(byte[] buffer)
void NextBytes(Span< byte > buffer)
int Next(int minValue, int maxValue)
long NextInt64(long minValue, long maxValue)
int Next(int maxValue)
long NextInt64(long maxValue)
override long NextInt64(long minValue, long maxValue)
Definition Random.cs:280
override int Next(int minValue, int maxValue)
Definition Random.cs:254
Net5CompatDerivedImpl(Random parent, int seed)
Definition Random.cs:233
override void NextBytes(Span< byte > buffer)
Definition Random.cs:317
override int Next(int maxValue)
Definition Random.cs:249
override void NextBytes(byte[] buffer)
Definition Random.cs:312
override long NextInt64(long maxValue)
Definition Random.cs:275
Net5CompatDerivedImpl(Random parent)
Definition Random.cs:228
override double Sample()
Definition Random.cs:138
override long NextInt64(long maxValue)
Definition Random.cs:174
override void NextBytes(byte[] buffer)
Definition Random.cs:211
override double NextDouble()
Definition Random.cs:201
override long NextInt64(long minValue, long maxValue)
Definition Random.cs:179
override void NextBytes(Span< byte > buffer)
Definition Random.cs:216
override int Next(int minValue, int maxValue)
Definition Random.cs:153
override float NextSingle()
Definition Random.cs:206
override int Next(int maxValue)
Definition Random.cs:148
static XoshiroImpl Create()
Definition Random.cs:23
static XoshiroImpl t_random
Definition Random.cs:13
override double Sample()
Definition Random.cs:98
override double NextDouble()
Definition Random.cs:79
override long NextInt64(long minValue, long maxValue)
Definition Random.cs:65
override long NextInt64()
Definition Random.cs:51
static XoshiroImpl LocalRandom
Definition Random.cs:15
override long NextInt64(long maxValue)
Definition Random.cs:56
override void NextBytes(Span< byte > buffer)
Definition Random.cs:93
override float NextSingle()
Definition Random.cs:74
override void NextBytes(byte[] buffer)
Definition Random.cs:84
override int Next(int maxValue)
Definition Random.cs:33
override int Next(int minValue, int maxValue)
Definition Random.cs:42
override long NextInt64()
Definition Random.cs:526
override int Next()
Definition Random.cs:482
override int Next(int maxValue)
Definition Random.cs:493
unsafe override void NextBytes(Span< byte > buffer)
Definition Random.cs:575
override long NextInt64(long minValue, long maxValue)
Definition Random.cs:553
override long NextInt64(long maxValue)
Definition Random.cs:537
override int Next(int minValue, int maxValue)
Definition Random.cs:509
override void NextBytes(byte[] buffer)
Definition Random.cs:570
override double Sample()
Definition Random.cs:625
override double NextDouble()
Definition Random.cs:615
override float NextSingle()
Definition Random.cs:620
virtual double Sample()
Definition Random.cs:721
static void ThrowMinMaxValueSwapped()
Definition Random.cs:731
Random(bool isThreadSafeRandom)
Definition Random.cs:646
virtual void NextBytes(Span< byte > buffer)
Definition Random.cs:716
virtual int Next()
Definition Random.cs:651
virtual float NextSingle()
Definition Random.cs:697
virtual double NextDouble()
Definition Random.cs:702
virtual void NextBytes(byte[] buffer)
Definition Random.cs:707
Random(int Seed)
Definition Random.cs:641
virtual int Next(int minValue, int maxValue)
Definition Random.cs:665
static Random Shared
Definition Random.cs:633
virtual int Next(int maxValue)
Definition Random.cs:656
virtual long NextInt64(long maxValue)
Definition Random.cs:679
virtual long NextInt64(long minValue, long maxValue)
Definition Random.cs:688
virtual long NextInt64()
Definition Random.cs:674
static void ThrowMaxValueMustBeNonNegative()
Definition Random.cs:726
readonly ImplBase _impl
Definition Random.cs:631
static string Argument_MinMaxValue
Definition SR.cs:766
static string Format(string resourceFormat, object p1)
Definition SR.cs:118
static string ArgumentOutOfRange_NeedNonNegNum
Definition SR.cs:32
Definition SR.cs:7
static void ThrowArgumentNullException(string name)
void NextBytes(Span< byte > buffer)
Definition Random.cs:381
double GetSampleForLargeRange()
Definition Random.cs:417