1
+ using System ;
2
+ using System . Threading ;
3
+
4
+ namespace FixedMathSharp . Utilities
5
+ {
6
+ /// <summary>
7
+ /// Provides thread-safe, deterministic random number generation for use in simulations, games,
8
+ /// and physics engines. This utility ensures randomness is consistent across multiple threads,
9
+ /// avoiding common pitfalls of shared Random instances and aiding reproducible calculations.
10
+ /// </summary>
11
+ public static class ThreadLocalRandom
12
+ {
13
+ /// <summary>
14
+ /// Random number generator used to generate seeds,
15
+ /// which are then used to create new random number
16
+ /// generators on a per-thread basis.
17
+ /// </summary>
18
+ private static readonly Random globalRandom = new Random ( Guid . NewGuid ( ) . GetHashCode ( ) ) ;
19
+ private static readonly object globalLock = new object ( ) ;
20
+
21
+ /// <summary>
22
+ /// Random number generator
23
+ /// </summary>
24
+ private static readonly ThreadLocal < Random > threadRandom = new ThreadLocal < Random > ( NewRandom ) ;
25
+
26
+ /// <summary>
27
+ /// Creates a new instance of Random. The seed is derived
28
+ /// from a global (static) instance of Random, rather
29
+ /// than time.
30
+ /// </summary>
31
+ public static Random NewRandom ( )
32
+ {
33
+ lock ( globalLock )
34
+ return new Random ( globalRandom . Next ( ) ) ;
35
+ }
36
+
37
+ /// <summary>
38
+ /// Returns an instance of Random which can be used freely
39
+ /// within the current thread.
40
+ /// </summary>
41
+ public static Random Instance => threadRandom . Value ;
42
+
43
+ /// <summary>See <see cref="Random.Next()" /></summary>
44
+ public static int Next ( )
45
+ {
46
+ return Instance . Next ( ) ;
47
+ }
48
+
49
+ /// <summary>See <see cref="Random.Next(int)" /></summary>
50
+ public static int Next ( int maxValue )
51
+ {
52
+ return Instance . Next ( maxValue ) ;
53
+ }
54
+
55
+ /// <summary>See <see cref="Random.Next(int, int)" /></summary>
56
+ public static int Next ( int minValue , int maxValue )
57
+ {
58
+ return Instance . Next ( minValue , maxValue ) ;
59
+ }
60
+
61
+ /// <summary>
62
+ /// Returns a random Fixed64 number that is less than `max`.
63
+ /// </summary>
64
+ /// <param name="max"></param>
65
+ public static Fixed64 NextFixed64 ( Fixed64 max = default )
66
+ {
67
+ if ( max == Fixed64 . Zero )
68
+ throw new ArgumentException ( "Max value must be greater than zero." ) ;
69
+
70
+ byte [ ] buf = new byte [ 8 ] ;
71
+ Instance . NextBytes ( buf ) ;
72
+
73
+ // Use bitwise operation to ensure a non-negative long.
74
+ long longRand = BitConverter . ToInt64 ( buf , 0 ) & long . MaxValue ;
75
+
76
+ return Fixed64 . FromRaw ( longRand % max . m_rawValue ) ;
77
+ }
78
+
79
+ /// <summary>
80
+ /// Returns a random Fixed64 number that is greater than or equal to `min`, and less than `max`.
81
+ /// </summary>
82
+ /// <param name="min"></param>
83
+ /// <param name="max"></param>
84
+ public static Fixed64 NextFixed64 ( Fixed64 min , Fixed64 max )
85
+ {
86
+ if ( min >= max )
87
+ throw new ArgumentException ( "Min value must be less than max." ) ;
88
+
89
+ byte [ ] buf = new byte [ 8 ] ;
90
+ Instance . NextBytes ( buf ) ;
91
+
92
+ // Ensure non-negative random long.
93
+ long longRand = BitConverter . ToInt64 ( buf , 0 ) & long . MaxValue ;
94
+
95
+ return Fixed64 . FromRaw ( longRand % ( max . m_rawValue - min . m_rawValue ) ) + min ;
96
+ }
97
+
98
+ /// <summary>See <see cref="Random.NextDouble()" /></summary>
99
+ public static double NextDouble ( )
100
+ {
101
+ return Instance . NextDouble ( ) ;
102
+ }
103
+
104
+ /// <summary>See <see cref="Random.NextDouble()" /></summary>
105
+ public static double NextDouble ( double min , double max )
106
+ {
107
+ return Instance . NextDouble ( ) * ( max - min ) + min ;
108
+ }
109
+
110
+ /// <summary>See <see cref="Random.NextBytes(byte[])" /></summary>
111
+ public static void NextBytes ( byte [ ] buffer )
112
+ {
113
+ Instance . NextBytes ( buffer ) ;
114
+ }
115
+ }
116
+ }
0 commit comments