TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
G3D::Random Class Reference

#include <Random.h>

Public Member Functions

 Random (uint32 seed=0xF018A4D2, bool threadsafe=true)
 
virtual ~Random ()
 
virtual void reset (uint32 seed=0xF018A4D2, bool threadsafe=true)
 
virtual uint32 bits ()
 
virtual int integer (int min, int max)
 
virtual float uniform (float low, float high)
 
virtual float uniform ()
 
virtual float gaussian (float mean, float stdev)
 
virtual void cosHemi (float &x, float &y, float &z)
 
virtual void cosSphere (float &x, float &y, float &z)
 
virtual void cosPowHemi (const float k, float &x, float &y, float &z)
 
virtual void hemi (float &x, float &y, float &z)
 
virtual void sphere (float &x, float &y, float &z)
 

Static Public Member Functions

static Randomcommon ()
 

Protected Types

enum  {
  N = 624, M = 397, R = 31, U = 11,
  S = 7, T = 15, L = 18, A = 0x9908B0DF,
  B = 0x9D2C5680, C = 0xEFC60000
}
 

Protected Member Functions

virtual void generate ()
 
 Random (void *)
 

Protected Attributes

Spinlock lock
 
uint32state
 
int index
 
bool m_threadsafe
 

Private Member Functions

Randomoperator= (const Random &)
 
 Random (const Random &r)
 

Detailed Description

Random number generator.

Threadsafe.

Useful for generating consistent random numbers across platforms and when multiple threads are involved.

Uses the Fast Mersenne Twister (FMT-19937) algorithm.

On average, uniform() runs about 2x-3x faster than rand().

[http://www.math.sci.hiroshima-u.ac.jp/]~m-mat/MT/SFMT/index.html

On OS X, Random is about 10x faster than drand48() (which is threadsafe) and 4x faster than rand() (which is not threadsafe).

See also
Noise

Member Enumeration Documentation

anonymous enum
protected

Constants (important for the algorithm; do not modify)

Enumerator
43  {
44  N = 624,
45  M = 397,
46  R = 31,
47  U = 11,
48  S = 7,
49  T = 15,
50  L = 18,
51  A = 0x9908B0DF,
52  B = 0x9D2C5680,
53  C = 0xEFC60000};
Definition: Random.h:52
Definition: Random.h:53
Definition: Random.h:46
Definition: Random.h:50
Definition: Random.h:49
Definition: Random.h:45
Definition: Random.h:51
Definition: Random.h:47
Definition: Random.h:44
Definition: Random.h:48

Constructor & Destructor Documentation

G3D::Random::Random ( void *  x)
protected

For subclasses. The void* parameter is just to distinguish this from the public constructor.

22  : state(NULL), m_threadsafe(false) {
23  (void)x;
24 }
arena_t NULL
Definition: jemalloc_internal.h:624
G3D::int16 x
Definition: Vector2int16.h:37
uint32 * state
Definition: Random.h:61
bool m_threadsafe
Definition: Random.h:66
G3D::Random::Random ( const Random r)
inlineprivate
89  {
90  *this = r;
91  }
G3D::Random::Random ( uint32  seed = 0xF018A4D2,
bool  threadsafe = true 
)
Parameters
threadsafeSet to false if you know that this random will only be used on a single thread. This eliminates the lock and improves performance on some platforms.
27  : m_threadsafe(threadsafe) {
28  state = new uint32[N];
29  reset(seed, threadsafe);
30 }
uint32_t uint32
Definition: Define.h:150
Definition: Random.h:44
virtual void reset(uint32 seed=0xF018A4D2, bool threadsafe=true)
Definition: Random.cpp:33
uint32 * state
Definition: Random.h:61
bool m_threadsafe
Definition: Random.h:66

+ Here is the call graph for this function:

G3D::Random::~Random ( )
virtual
45  {
46  delete[] state;
47  state = NULL;
48 }
arena_t NULL
Definition: jemalloc_internal.h:624
uint32 * state
Definition: Random.h:61

Member Function Documentation

uint32 G3D::Random::bits ( )
virtual

Each bit is random. Subclasses can choose to override just this method and the other methods will all work automatically.

Reimplemented in G3D::PrecomputedRandom.

51  {
52  // See http://en.wikipedia.org/wiki/Mersenne_twister
53 
54  // Make a local copy of the index variable to ensure that it
55  // is not out of bounds
56  int localIndex = index;
57 
58  // Automatically checks for index < 0 if corrupted
59  // by unsynchronized threads.
60  if ((unsigned int)localIndex >= (unsigned int)N) {
61  generate();
62  localIndex = 0;
63  }
64  // Increment the global index. It may go out of bounds on
65  // multiple threads, but the above check ensures that the
66  // array index actually used never goes out of bounds.
67  // It doesn't matter if we grab the same array index twice
68  // on two threads, since the distribution of random numbers
69  // will still be uniform.
70  ++index;
71  // Return the next random in the sequence
72  uint32 r = state[localIndex];
73 
74  // Temper the result
75  r ^= r >> U;
76  r ^= (r << S) & B;
77  r ^= (r << T) & C;
78  r ^= r >> L;
79 
80  return r;
81 }
virtual void generate()
Definition: Random.cpp:85
Definition: Random.h:52
Definition: Random.h:53
Definition: Random.h:50
int index
Definition: Random.h:64
Definition: Random.h:49
uint32_t uint32
Definition: Define.h:150
Definition: Random.h:47
Definition: Random.h:44
Definition: Random.h:48
uint32 * state
Definition: Random.h:61

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Random & G3D::Random::common ( )
static

A shared instance for when the performance and features but not consistency of the class are desired. It is slightly (10%) faster to use a distinct instance than to use the common one.

Threadsafe.

16  {
17  static Random r;
18  return r;
19 }
Random(void *)
Definition: Random.cpp:22
void G3D::Random::cosHemi ( float &  x,
float &  y,
float &  z 
)
virtual

Returns 3D unit vectors distributed according to a cosine distribution about the positive z-axis.

Reimplemented in G3D::PrecomputedRandom.

168  {
169  const float e1 = uniform();
170  const float e2 = uniform();
171 
172  // Jensen's method
173  const float sin_theta = sqrtf(1.0f - e1);
174  const float cos_theta = sqrtf(e1);
175  const float phi = 6.28318531f * e2;
176 
177  x = cos(phi) * sin_theta;
178  y = sin(phi) * sin_theta;
179  z = cos_theta;
180 
181  // We could also use Malley's method (pbrt p.657), since they are the same cost:
182  //
183  // r = sqrt(e1);
184  // t = 2*pi*e2;
185  // x = cos(t)*r;
186  // y = sin(t)*r;
187  // z = sqrt(1.0 - x*x + y*y);
188 }
virtual float uniform()
Definition: Random.h:121
G3D::int16 z
Definition: Vector3int16.h:46
G3D::int16 y
Definition: Vector2int16.h:38
G3D::int16 x
Definition: Vector2int16.h:37

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void G3D::Random::cosPowHemi ( const float  k,
float &  x,
float &  y,
float &  z 
)
virtual

Returns 3D unit vectors distributed according to a cosine power distribution ( $ \cos^k \theta $) about the z-axis.

Reimplemented in G3D::PrecomputedRandom.

191  {
192  const float e1 = uniform();
193  const float e2 = uniform();
194 
195  const float cos_theta = pow(e1, 1.0f / (k + 1.0f));
196  const float sin_theta = sqrtf(1.0f - square(cos_theta));
197  const float phi = 6.28318531f * e2;
198 
199  x = cos(phi) * sin_theta;
200  y = sin(phi) * sin_theta;
201  z = cos_theta;
202 }
virtual float uniform()
Definition: Random.h:121
G3D::int16 z
Definition: Vector3int16.h:46
G3D::int16 y
Definition: Vector2int16.h:38
double square(double fValue)
Definition: g3dmath.h:698
G3D::Quat pow(const G3D::Quat &q, double x)
Definition: Quat.h:761
G3D::int16 x
Definition: Vector2int16.h:37

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void G3D::Random::cosSphere ( float &  x,
float &  y,
float &  z 
)
virtual

Returns 3D unit vectors distributed according to a cosine distribution about the z-axis.

159  {
160  cosHemi(x, y, z);
161  if (bits() & 1) {
162  // Choose the axis direction uniformly at random
163  z = -z;
164  }
165 }
virtual uint32 bits()
Definition: Random.cpp:51
virtual void cosHemi(float &x, float &y, float &z)
Definition: Random.cpp:168
G3D::int16 z
Definition: Vector3int16.h:46
G3D::int16 y
Definition: Vector2int16.h:38
G3D::int16 x
Definition: Vector2int16.h:37

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

float G3D::Random::gaussian ( float  mean,
float  stdev 
)
virtual

Normally distributed reals.

139  {
140 
141  // Using Box-Mueller method from http://www.taygeta.com/random/gaussian.html
142  // Modified to specify standard deviation and mean of distribution
143  float w, x1, x2;
144 
145  // Loop until w is less than 1 so that log(w) is negative
146  do {
147  x1 = uniform(-1.0, 1.0);
148  x2 = uniform(-1.0, 1.0);
149 
150  w = float(square(x1) + square(x2));
151  } while (w > 1.0f);
152 
153  // Transform to gassian distribution
154  // Multiply by sigma (stdev ^ 2) and add mean.
155  return x2 * (float)square(stdev) * sqrtf((-2.0f * logf(w) ) / w) + mean;
156 }
virtual float uniform()
Definition: Random.h:121
double square(double fValue)
Definition: g3dmath.h:698

+ Here is the call graph for this function:

void G3D::Random::generate ( )
protectedvirtual

Generate the next N ints, and store them for readback later. Called from bits()

Generate the next N ints, and store them for readback later

85  {
86  // Lower R bits
87  static const uint32 LOWER_MASK = (1LU << R) - 1;
88 
89  // Upper (32 - R) bits
90  static const uint32 UPPER_MASK = 0xFFFFFFFF << R;
91  static const uint32 mag01[2] = {0UL, (uint32)A};
92 
93  if (m_threadsafe) {
94  bool contention = ! lock.lock();
95  if (contention) {
96  // Another thread just generated a set of numbers; no need for
97  // this thread to do it too
98  lock.unlock();
99  return;
100  }
101  }
102 
103  // First N - M
104  for (unsigned int i = 0; i < N - M; ++i) {
105  uint32 x = (state[i] & UPPER_MASK) | (state[i + 1] & LOWER_MASK);
106  state[i] = state[i + M] ^ (x >> 1) ^ mag01[x & 1];
107  }
108 
109  // Rest
110  for (unsigned int i = N - M + 1; i < N - 1; ++i) {
111  uint32 x = (state[i] & UPPER_MASK) | (state[i + 1] & LOWER_MASK);
112  state[i] = state[i + (M - N)] ^ (x >> 1) ^ mag01[x & 1];
113  }
114 
115  uint32 y = (state[N - 1] & UPPER_MASK) | (state[0] & LOWER_MASK);
116  state[N - 1] = state[M - 1] ^ (y >> 1) ^ mag01[y & 1];
117  index = 0;
118 
119  if (m_threadsafe) {
120  lock.unlock();
121  }
122 }
bool lock()
Definition: GMutex.h:52
Spinlock lock
Definition: Random.h:58
Definition: Random.h:46
int index
Definition: Random.h:64
uint32_t uint32
Definition: Define.h:150
void unlock()
Definition: GMutex.h:65
G3D::int16 y
Definition: Vector2int16.h:38
Definition: Random.h:45
Definition: Random.h:51
Definition: Random.h:44
uint32_t uint32
Definition: g3dmath.h:168
G3D::int16 x
Definition: Vector2int16.h:37
uint32 * state
Definition: Random.h:61
bool m_threadsafe
Definition: Random.h:66

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void G3D::Random::hemi ( float &  x,
float &  y,
float &  z 
)
virtual

Returns 3D unit vectors uniformly distributed on the hemisphere about the z-axis.

205  {
206  sphere(x, y, z);
207  z = fabsf(z);
208 }
G3D::int16 z
Definition: Vector3int16.h:46
G3D::int16 y
Definition: Vector2int16.h:38
virtual void sphere(float &x, float &y, float &z)
Definition: Random.cpp:211
G3D::int16 x
Definition: Vector2int16.h:37

+ Here is the call graph for this function:

int G3D::Random::integer ( int  min,
int  max 
)
virtual

Uniform random integer on the range [min, max]

125  {
126  debugAssert(high >= low);
127  int r = iFloor(low + (high - low + 1) * (double)bits() / 0xFFFFFFFFUL);
128 
129  // There is a *very small* chance of generating
130  // a number larger than high.
131  if (r > high) {
132  return high;
133  } else {
134  return r;
135  }
136 }
virtual uint32 bits()
Definition: Random.cpp:51
int iFloor(double fValue)
Definition: g3dmath.h:603
#define debugAssert(exp)
Definition: debugAssert.h:160

+ Here is the call graph for this function:

Random& G3D::Random::operator= ( const Random )
inlineprivate
79  {
80  alwaysAssertM(false,
81  "There is no copy constructor or assignment operator for Random because you "
82  "probably didn't actually want to copy the state--it would "
83  "be slow and duplicate the state of a pseudo-random sequence. Maybe you could "
84  "provide arguments to a member variable in the constructor, "
85  "or pass the Random by reference?");
86  return *this;
87  }
#define alwaysAssertM(exp, message)
Definition: debugAssert.h:165
void G3D::Random::reset ( uint32  seed = 0xF018A4D2,
bool  threadsafe = true 
)
virtual
33  {
34  m_threadsafe = threadsafe;
35 
36  const uint32 X = 1812433253UL;
37 
38  state[0] = seed;
39  for (index = 1; index < (int)N; ++index) {
40  state[index] = X * (state[index - 1] ^ (state[index - 1] >> 30)) + index;
41  }
42 }
#define X
Definition: CollisionDetection.cpp:2281
int index
Definition: Random.h:64
uint32_t uint32
Definition: Define.h:150
Definition: Random.h:44
uint32 * state
Definition: Random.h:61
bool m_threadsafe
Definition: Random.h:66

+ Here is the caller graph for this function:

void G3D::Random::sphere ( float &  x,
float &  y,
float &  z 
)
virtual

Returns 3D unit vectors uniformly distributed on the sphere

Reimplemented in G3D::PrecomputedRandom.

211  {
212  // Squared magnitude
213  float m2;
214 
215  // Rejection sample
216  do {
217  x = uniform() * 2.0f - 1.0f,
218  y = uniform() * 2.0f - 1.0f,
219  z = uniform() * 2.0f - 1.0f;
220  m2 = x*x + y*y + z*z;
221  } while (m2 >= 1.0f);
222 
223  // Divide by magnitude to produce a unit vector
224  float s = rsqrt(m2);
225  x *= s;
226  y *= s;
227  z *= s;
228 }
virtual float uniform()
Definition: Random.h:121
G3D::int16 z
Definition: Vector3int16.h:46
G3D::int16 y
Definition: Vector2int16.h:38
G3D::int16 x
Definition: Vector2int16.h:37
double rsqrt(double x)
Definition: g3dmath.h:469

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

virtual float G3D::Random::uniform ( float  low,
float  high 
)
inlinevirtual

Uniform random float on the range [min, max]

Reimplemented in G3D::PrecomputedRandom.

113  {
114  // We could compute the ratio in double precision here for
115  // about 1.5x slower performance and slightly better
116  // precision.
117  return low + (high - low) * ((float)bits() / (float)0xFFFFFFFFUL);
118  }
virtual uint32 bits()
Definition: Random.cpp:51

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

virtual float G3D::Random::uniform ( )
inlinevirtual

Uniform random float on the range [0, 1]

Reimplemented in G3D::PrecomputedRandom.

121  {
122  // We could compute the ratio in double precision here for
123  // about 1.5x slower performance and slightly better
124  // precision.
125  const float norm = 1.0f / (float)0xFFFFFFFFUL;
126  return (float)bits() * norm;
127  }
virtual uint32 bits()
Definition: Random.cpp:51

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Member Data Documentation

int G3D::Random::index
protected

Index into state

Spinlock G3D::Random::lock
protected

Prevents multiple overlapping calls to generate().

bool G3D::Random::m_threadsafe
protected
uint32* G3D::Random::state
protected

State vector (these are the next N values that will be returned)


The documentation for this class was generated from the following files: