aboutsummaryrefslogtreecommitdiff
path: root/dep/src/g3dlite/Random.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dep/src/g3dlite/Random.cpp')
-rw-r--r--dep/src/g3dlite/Random.cpp212
1 files changed, 0 insertions, 212 deletions
diff --git a/dep/src/g3dlite/Random.cpp b/dep/src/g3dlite/Random.cpp
deleted file mode 100644
index 2dda744a1ac..00000000000
--- a/dep/src/g3dlite/Random.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-/**
- @file Random.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2009-01-02
- @edited 2009-03-29
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-#include "G3D/Random.h"
-
-namespace G3D {
-
-Random& Random::common() {
- static Random r;
- return r;
-}
-
-Random::Random(void* x) : state(NULL), m_threadsafe(false) {
- (void)x;
-}
-
-
-Random::Random(uint32 seed, bool threadsafe) : m_threadsafe(threadsafe) {
- const uint32 X = 1812433253UL;
-
- state = new uint32[N];
- state[0] = seed;
- for (index = 1; index < (int)N; ++index) {
- state[index] = X * (state[index - 1] ^ (state[index - 1] >> 30)) + index;
- }
-}
-
-
-Random::~Random() {
- delete[] state;
- state = NULL;
-}
-
-
-uint32 Random::bits() {
- // See http://en.wikipedia.org/wiki/Mersenne_twister
-
- // Make a local copy of the index variable to ensure that it
- // is not out of bounds
- int localIndex = index;
-
- // Automatically checks for index < 0 if corrupted
- // by unsynchronized threads.
- if ((unsigned int)localIndex >= (unsigned int)N) {
- generate();
- localIndex = 0;
- }
- // Increment the global index. It may go out of bounds on
- // multiple threads, but the above check ensures that the
- // array index actually used never goes out of bounds.
- // It doesn't matter if we grab the same array index twice
- // on two threads, since the distribution of random numbers
- // will still be uniform.
- ++index;
- // Return the next random in the sequence
- uint32 r = state[localIndex];
-
- // Temper the result
- r ^= r >> U;
- r ^= (r << S) & B;
- r ^= (r << T) & C;
- r ^= r >> L;
-
- return r;
-}
-
-
-/** Generate the next N ints, and store them for readback later */
-void Random::generate() {
- // Lower R bits
- static const uint32 LOWER_MASK = (1LU << R) - 1;
-
- // Upper (32 - R) bits
- static const uint32 UPPER_MASK = 0xFFFFFFFF << R;
- static const uint32 mag01[2] = {0UL, (uint32)A};
-
- if (m_threadsafe) {
- bool contention = ! lock.lock();
- if (contention) {
- // Another thread just generated a set of numbers; no need for
- // this thread to do it too
- lock.unlock();
- return;
- }
- }
-
- // First N - M
- for (unsigned int i = 0; i < N - M; ++i) {
- uint32 x = (state[i] & UPPER_MASK) | (state[i + 1] & LOWER_MASK);
- state[i] = state[i + M] ^ (x >> 1) ^ mag01[x & 1];
- }
-
- // Rest
- for (unsigned int i = N - M + 1; i < N - 1; ++i) {
- uint32 x = (state[i] & UPPER_MASK) | (state[i + 1] & LOWER_MASK);
- state[i] = state[i + (M - N)] ^ (x >> 1) ^ mag01[x & 1];
- }
-
- uint32 y = (state[N - 1] & UPPER_MASK) | (state[0] & LOWER_MASK);
- state[N - 1] = state[M - 1] ^ (y >> 1) ^ mag01[y & 1];
- index = 0;
-
- if (m_threadsafe) {
- lock.unlock();
- }
-}
-
-
-int Random::integer(int low, int high) {
- int r = iFloor(low + (high - low + 1) * (double)bits() / 0xFFFFFFFFUL);
-
- // There is a *very small* chance of generating
- // a number larger than high.
- if (r > high) {
- return high;
- } else {
- return r;
- }
-}
-
-
-float Random::gaussian(float mean, float stdev) {
-
- // Using Box-Mueller method from http://www.taygeta.com/random/gaussian.html
- // Modified to specify standard deviation and mean of distribution
- float w, x1, x2;
-
- // Loop until w is less than 1 so that log(w) is negative
- do {
- x1 = uniform(-1.0, 1.0);
- x2 = uniform(-1.0, 1.0);
-
- w = float(square(x1) + square(x2));
- } while (w > 1.0f);
-
- // Transform to gassian distribution
- // Multiply by sigma (stdev ^ 2) and add mean.
- return x2 * (float)square(stdev) * sqrtf((-2.0f * logf(w) ) / w) + mean;
-}
-
-
-void Random::cosHemi(float& x, float& y, float& z) {
- const float e1 = uniform();
- const float e2 = uniform();
-
- // Jensen's method
- const float sin_theta = sqrtf(1.0f - e1);
- const float cos_theta = sqrtf(e1);
- const float phi = 6.28318531f * e2;
-
- x = cos(phi) * sin_theta;
- y = sin(phi) * sin_theta;
- z = cos_theta;
-
- // We could also use Malley's method (pbrt p.657), since they are the same cost:
- //
- // r = sqrt(e1);
- // t = 2*pi*e2;
- // x = cos(t)*r;
- // y = sin(t)*r;
- // z = sqrt(1.0 - x*x + y*y);
-}
-
-
-void Random::cosPowHemi(const float k, float& x, float& y, float& z) {
- const float e1 = uniform();
- const float e2 = uniform();
-
- const float cos_theta = pow(e1, 1.0f / (k + 1.0f));
- const float sin_theta = sqrtf(1.0f - square(cos_theta));
- const float phi = 6.28318531f * e2;
-
- x = cos(phi) * sin_theta;
- y = sin(phi) * sin_theta;
- z = cos_theta;
-}
-
-
-void Random::hemi(float& x, float& y, float& z) {
- sphere(x, y, z);
- z = fabsf(z);
-}
-
-
-void Random::sphere(float& x, float& y, float& z) {
- // Squared magnitude
- float m2;
-
- // Rejection sample
- do {
- x = uniform() * 2.0f - 1.0f,
- y = uniform() * 2.0f - 1.0f,
- z = uniform() * 2.0f - 1.0f;
- m2 = x*x + y*y + z*z;
- } while (m2 >= 1.0f);
-
- // Divide by magnitude to produce a unit vector
- float s = rsqrt(m2);
- x *= s;
- y *= s;
- z *= s;
-}
-
-} // G3D