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