1 | // tRandom.h  |
2 | //  |
3 | // Functions necessary to generate pseudo-random numbers using a number of different algorithms. Random bits, integers,  |
4 | // and floats may all be generated. The generators are objects and state isn't shared. This allows multiple generators  |
5 | // that can optionally be run on different threads. Sharing a generator between threads is not supported. One of the  |
6 | // generators implements the Mersenne Twistor algorithm by M. Matsumoto & T. Nishimura.  |
7 | //  |
8 | // Copyright (c) 2005, 2017 Tristan Grimmer.  |
9 | // Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby  |
10 | // granted, provided that the above copyright notice and this permission notice appear in all copies.  |
11 | //  |
12 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL  |
13 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,  |
14 | // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN  |
15 | // AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR  |
16 | // PERFORMANCE OF THIS SOFTWARE.  |
17 |   |
18 | #pragma once  |
19 | #include <Foundation/tPlatform.h>  |
20 | #include "Math/tGeometry.h"  |
21 | namespace tMath {  |
22 | namespace tRandom {  |
23 |   |
24 |   |
25 | // Abstract base class for all random number generators. A generator is only responsible for generating random bits.  |
26 | // Each instance of a generator should have its own state and produces its own random stream.  |
27 | class tGenerator  |
28 | {  |
29 | public:  |
30 | tGenerator() { }  |
31 | virtual ~tGenerator() { }  |
32 |   |
33 | // Reset (reseed) the generator.  |
34 | virtual void SetSeed(uint32 seed) = 0;  |
35 | virtual void SetSeed(uint64 seed) = 0;  |
36 | virtual void SetSeed(const uint32* seeds, int numSeeds) = 0;  |
37 |   |
38 | // This is it. The main interface function. Returns 32 random bits every time it's called.  |
39 | virtual uint32 GetBits() const = 0;  |
40 | };  |
41 |   |
42 |   |
43 | // A random generator using the Mersenne Twistor algorithm by M. Matsumoto & T. Nishimura, Transactions of the  |
44 | // Association for Computing Machinery, Vol 8, 1998. This generator has a large memory footprint: 19937 bits of state.  |
45 | class tGeneratorMersenneTwister : public tGenerator  |
46 | {  |
47 | public:  |
48 | tGeneratorMersenneTwister() { SetSeed(uint32(0x4242CDCD)); }  |
49 | tGeneratorMersenneTwister(uint32 seed) { SetSeed(seed); }  |
50 | tGeneratorMersenneTwister(uint64 seed) { SetSeed(seed); }  |
51 | tGeneratorMersenneTwister(const uint32* seeds, int numSeeds) { SetSeed(seeds, numSeeds); }  |
52 |   |
53 | // These may be used to reset (reseed) the generator.  |
54 | void SetSeed(uint32 seed) override;  |
55 | void SetSeed(uint64 seed) override { SetSeed( ((const uint32*)(void*)&seed), 2 ); }  |
56 | void SetSeed(const uint32* seeds, int numSeeds) override;  |
57 | uint32 GetBits() const override;  |
58 |   |
59 | private:  |
60 | static const int Dimensions = 624;  |
61 | static const int PartialDims = 397;  |
62 | static const int LeftShift = 31;  |
63 | static const uint32 Toggle = 0x9908B0DF;  |
64 | static const int TemperShiftA = 11;  |
65 | static const int TemperShiftB = 7;  |
66 | static const int TemperShiftC = 15;  |
67 | static const int TemperShiftD = 18;  |
68 | static const uint32 TemperB = 0x9D2C5680;  |
69 | static const uint32 TemperC = 0xEFC60000;  |
70 |   |
71 | // The complete state information.  |
72 | mutable uint32 StateVector[Dimensions];  |
73 | mutable int StateIndex;  |
74 | };  |
75 |   |
76 |   |
77 | // If we need a cryptographically secure random number generator we should finish implementing Fortuna.  |
78 | class tGeneratorFortuna : public tGenerator  |
79 | {  |
80 | public:  |
81 | tGeneratorFortuna() { SetSeed(uint32(0x4242CDCD)); }  |
82 | tGeneratorFortuna(uint32 seed) { SetSeed(seed); }  |
83 | tGeneratorFortuna(uint64 seed) { SetSeed(seed); }  |
84 | tGeneratorFortuna(const uint32* seeds, int numSeeds) { SetSeed(seeds, numSeeds); }  |
85 |   |
86 | void SetSeed(uint32 seed) override;  |
87 | void SetSeed(uint64 seed) override { SetSeed( ((const uint32*)(void*)&seed), 2 ); }  |
88 | void SetSeed(const uint32* seeds, int numSeeds) override;  |
89 | uint32 GetBits() const override;  |
90 |   |
91 | private:  |
92 | // The complete state information.  |
93 | mutable uint32 StateVector[1];  |
94 | mutable int StateIndex;  |
95 | };  |
96 |   |
97 |   |
98 | // We're going to use Mersenne-Twister as our default generator type.  |
99 | using tDefaultGeneratorType = tGeneratorMersenneTwister;  |
100 |   |
101 | // And here is the single global default random number generator. Additional generators can be created if desired.  |
102 | extern tDefaultGeneratorType DefaultGenerator;  |
103 |   |
104 | // Useful interface functions for generating random quantities in a variety of types from bool to double. Before  |
105 | // calling these make sure the generator being used is initialized properly. For the global default generator, waiting  |
106 | // till main() is safe, but during static initialization could cause problems. The random numbers from GetFloat and  |
107 | // GetDouble are E [0.0, 1.0], and GetSign is either -1.0 or 1.0.  |
108 | float tGetSign(const tGenerator& = DefaultGenerator);  |
109 | bool tGetBool(const tGenerator& = DefaultGenerator);  |
110 | uint32 tGetBits(const tGenerator& = DefaultGenerator);  |
111 | float tGetFloat(const tGenerator& = DefaultGenerator);  |
112 | double tGetDouble(const tGenerator& = DefaultGenerator);  |
113 |   |
114 | // These compute a random value in [min, max]. The templated version can be used for vectors.  |
115 | int tGetBounded(int min, int max, const tGenerator& = DefaultGenerator);  |
116 | float tGetBounded(float min, float max, const tGenerator& = DefaultGenerator);  |
117 | double tGetBounded(double min, double max, const tGenerator& = DefaultGenerator);  |
118 | template <typename T> T tGetBounded(T min, T max, const tGenerator& = DefaultGenerator);  |
119 |   |
120 | // This returns a random number centered around 'center' plus or minus 'extent'. eg. calling GetExtentBounded(10, 2)  |
121 | // will result in a random number in the interval [8, 12].  |
122 | template <typename T> T tGetExtentBounded(T center, T extent, const tGenerator& = DefaultGenerator);  |
123 |   |
124 | // Gets a random direction centered about the input direction within extent angle. Essentially creating a cone.  |
125 | tVector3 tGetDir(const tVector3& centerDir, float extentAngle, const tGenerator& = DefaultGenerator);  |
126 |   |
127 | // Random point generation functions in R3 for various geometric primitives.  |
128 | tVector3 tGetPointOnLineSeg(const tLineSeg&, const tGenerator& = DefaultGenerator);  |
129 | tVector3 tGetPointOnTriangle(const tTriangle&, const tGenerator& = DefaultGenerator);  |
130 |   |
131 | // Plane must be normalized. Square is centered at (a,b,c).  |
132 | tVector3 tGetPointOnUnitSquare(const tPlane&, const tGenerator& = DefaultGenerator);  |
133 | tVector3 tGetPointOnBox(const tBox&, const tGenerator& = DefaultGenerator);  |
134 | tVector3 tGetPointOnSphere(const tSphere&, const tGenerator& = DefaultGenerator);  |
135 | tVector3 tGetPointOnCylinder(const tCylinder&, const tGenerator& = DefaultGenerator);  |
136 | tVector3 tGetPointInBox(const tBox&, const tGenerator& = DefaultGenerator);  |
137 | tVector3 tGetPointInSphere(const tSphere&, const tGenerator& = DefaultGenerator);  |
138 | tVector3 tGetPointInCylinder(const tCylinder&, const tGenerator& = DefaultGenerator);  |
139 |   |
140 |   |
141 | }  |
142 | }  |
143 |   |
144 |   |
145 | // Implementation below this line.  |
146 |   |
147 |   |
148 | inline float tMath::tRandom::tGetSign(const tGenerator& gen)  |
149 | {  |
150 | return (gen.GetBits() & 0x00000001) ? 1.0f : -1.0f;  |
151 | }  |
152 |   |
153 |   |
154 | inline bool tMath::tRandom::tGetBool(const tGenerator& gen)  |
155 | {  |
156 | return (gen.GetBits() & 0x00000001) ? true : false;  |
157 | }  |
158 |   |
159 |   |
160 | inline uint32 tMath::tRandom::tGetBits(const tGenerator& gen)  |
161 | {  |
162 | return gen.GetBits();  |
163 | }  |
164 |   |
165 |   |
166 | inline float tMath::tRandom::tGetFloat(const tGenerator& gen)  |
167 | {  |
168 | return float(tGetDouble(gen));  |
169 | }  |
170 |   |
171 |   |
172 | inline int tMath::tRandom::tGetBounded(int min, int max, const tGenerator& gen)  |
173 | {  |
174 | tAssert(max >= min);  |
175 | return min + (tGetBits(gen) % (1 + max - min));  |
176 | }  |
177 |   |
178 |   |
179 | inline float tMath::tRandom::tGetBounded(float min, float max, const tGenerator& gen)  |
180 | {  |
181 | tAssert(max >= min);  |
182 | return min + (tGetFloat(gen)*(max - min));  |
183 | }  |
184 |   |
185 |   |
186 | inline double tMath::tRandom::tGetBounded(double min, double max, const tGenerator& gen)  |
187 | {  |
188 | tAssert(max >= min);  |
189 | return min + (tGetDouble(gen)*(max - min));  |
190 | }  |
191 |   |
192 |   |
193 | template <typename T> T tMath::tRandom::tGetBounded(T min, T max, const tGenerator& gen)  |
194 | {  |
195 | T result;  |
196 | for (int c = 0; c < T::GetNumComponents(); c++)  |
197 | result[c] = tGetBounded(min[c], max[c], gen);  |
198 |   |
199 | return result;  |
200 | }  |
201 |   |
202 |   |
203 | template <typename T> T tMath::tRandom::tGetExtentBounded(T center, T extent, const tGenerator& gen)  |
204 | {  |
205 | return tGetBounded(center - extent, center + extent, gen);  |
206 | }  |
207 |   |
208 |   |
209 | inline tMath::tVector3 tMath::tRandom::tGetPointOnLineSeg(const tLineSeg& seg, const tGenerator& gen)  |
210 | {  |
211 | float t = tGetFloat(gen);  |
212 | return seg.A + ((seg.B - seg.A) * t );  |
213 | }  |
214 | |