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" 
21namespace tMath
22namespace 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. 
27class tGenerator 
28
29public
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. 
45class tGeneratorMersenneTwister : public tGenerator 
46
47public
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 
59private
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. 
78class tGeneratorFortuna : public tGenerator 
79
80public
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 
91private
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. 
99using tDefaultGeneratorType = tGeneratorMersenneTwister
100 
101// And here is the single global default random number generator. Additional generators can be created if desired. 
102extern 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. 
108float tGetSign(const tGenerator& = DefaultGenerator); 
109bool tGetBool(const tGenerator& = DefaultGenerator); 
110uint32 tGetBits(const tGenerator& = DefaultGenerator); 
111float tGetFloat(const tGenerator& = DefaultGenerator); 
112double tGetDouble(const tGenerator& = DefaultGenerator); 
113 
114// These compute a random value in [min, max]. The templated version can be used for vectors. 
115int tGetBounded(int min, int max, const tGenerator& = DefaultGenerator); 
116float tGetBounded(float min, float max, const tGenerator& = DefaultGenerator); 
117double tGetBounded(double min, double max, const tGenerator& = DefaultGenerator); 
118template <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]. 
122template <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. 
125tVector3 tGetDir(const tVector3& centerDir, float extentAngle, const tGenerator& = DefaultGenerator); 
126 
127// Random point generation functions in R3 for various geometric primitives. 
128tVector3 tGetPointOnLineSeg(const tLineSeg&, const tGenerator& = DefaultGenerator); 
129tVector3 tGetPointOnTriangle(const tTriangle&, const tGenerator& = DefaultGenerator); 
130 
131// Plane must be normalized. Square is centered at (a,b,c). 
132tVector3 tGetPointOnUnitSquare(const tPlane&, const tGenerator& = DefaultGenerator); 
133tVector3 tGetPointOnBox(const tBox&, const tGenerator& = DefaultGenerator); 
134tVector3 tGetPointOnSphere(const tSphere&, const tGenerator& = DefaultGenerator); 
135tVector3 tGetPointOnCylinder(const tCylinder&, const tGenerator& = DefaultGenerator); 
136tVector3 tGetPointInBox(const tBox&, const tGenerator& = DefaultGenerator); 
137tVector3 tGetPointInSphere(const tSphere&, const tGenerator& = DefaultGenerator); 
138tVector3 tGetPointInCylinder(const tCylinder&, const tGenerator& = DefaultGenerator); 
139 
140 
141
142
143 
144 
145// Implementation below this line. 
146 
147 
148inline float tMath::tRandom::tGetSign(const tGenerator& gen
149
150 return (gen.GetBits() & 0x00000001) ? 1.0f : -1.0f
151
152 
153 
154inline bool tMath::tRandom::tGetBool(const tGenerator& gen
155
156 return (gen.GetBits() & 0x00000001) ? true : false
157
158 
159 
160inline uint32 tMath::tRandom::tGetBits(const tGenerator& gen
161
162 return gen.GetBits(); 
163
164 
165 
166inline float tMath::tRandom::tGetFloat(const tGenerator& gen
167
168 return float(tGetDouble(gen)); 
169
170 
171 
172inline 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 
179inline 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 
186inline 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 
193template <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 
203template <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 
209inline 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