aboutsummaryrefslogtreecommitdiff
path: root/externals/g3dlite/Random.cpp
diff options
context:
space:
mode:
authorclick <none@none>2010-06-08 08:04:26 +0200
committerclick <none@none>2010-06-08 08:04:26 +0200
commitf867f6d7a8f728e163ba785f2da45ec97fa8ba53 (patch)
treef4f099c515cbf27dac85b9ad6972fdc8f1e12fef /externals/g3dlite/Random.cpp
parentc08a7d6348a06d3b84d9a2c620a903d832199dd9 (diff)
Get g3dlib, zlib and jemalloc to build again
--HG-- branch : trunk rename : opt/cleanup/tab2spaces.sh => contrib/cleanup/tab2spaces.sh rename : opt/cleanup/whitespace.sh => contrib/cleanup/whitespace.sh rename : opt/conf_merge/README => contrib/conf_merge/README rename : opt/conf_merge/index.php => contrib/conf_merge/index.php rename : opt/conf_merge/merge.php => contrib/conf_merge/merge.php rename : doc/AuctionHouseBot.txt => docs/AuctionHouseBot.txt rename : doc/DocStructure.dox => docs/DocStructure.dox rename : doc/Doxyfile.in => docs/Doxyfile.in rename : doc/EventAI.txt => docs/EventAI.txt rename : doc/HowToScript.txt => docs/HowToScript.txt rename : doc/TextTables.txt => docs/TextTables.txt rename : doc/UnixInstall.txt => docs/UnixInstall.txt rename : externals/jemalloc/include/internal/arena.h => externals/jemalloc/jemalloc/internal/arena.h rename : externals/jemalloc/include/internal/base.h => externals/jemalloc/jemalloc/internal/base.h rename : externals/jemalloc/include/internal/chunk.h => externals/jemalloc/jemalloc/internal/chunk.h rename : externals/jemalloc/include/internal/chunk_dss.h => externals/jemalloc/jemalloc/internal/chunk_dss.h rename : externals/jemalloc/include/internal/chunk_mmap.h => externals/jemalloc/jemalloc/internal/chunk_mmap.h rename : externals/jemalloc/include/internal/chunk_swap.h => externals/jemalloc/jemalloc/internal/chunk_swap.h rename : externals/jemalloc/include/internal/ckh.h => externals/jemalloc/jemalloc/internal/ckh.h rename : externals/jemalloc/include/internal/ctl.h => externals/jemalloc/jemalloc/internal/ctl.h rename : externals/jemalloc/include/internal/extent.h => externals/jemalloc/jemalloc/internal/extent.h rename : externals/jemalloc/include/internal/hash.h => externals/jemalloc/jemalloc/internal/hash.h rename : externals/jemalloc/include/internal/huge.h => externals/jemalloc/jemalloc/internal/huge.h rename : externals/jemalloc/include/internal/jemalloc_internal.h => externals/jemalloc/jemalloc/internal/jemalloc_internal.h rename : externals/jemalloc/include/internal/jemalloc_internal.h.in => externals/jemalloc/jemalloc/internal/jemalloc_internal.h.in rename : externals/jemalloc/include/internal/mb.h => externals/jemalloc/jemalloc/internal/mb.h rename : externals/jemalloc/include/internal/mutex.h => externals/jemalloc/jemalloc/internal/mutex.h rename : externals/jemalloc/include/internal/prof.h => externals/jemalloc/jemalloc/internal/prof.h rename : externals/jemalloc/include/internal/ql.h => externals/jemalloc/jemalloc/internal/ql.h rename : externals/jemalloc/include/internal/qr.h => externals/jemalloc/jemalloc/internal/qr.h rename : externals/jemalloc/include/internal/rb.h => externals/jemalloc/jemalloc/internal/rb.h rename : externals/jemalloc/include/internal/stats.h => externals/jemalloc/jemalloc/internal/stats.h rename : externals/jemalloc/include/internal/tcache.h => externals/jemalloc/jemalloc/internal/tcache.h rename : externals/jemalloc/include/internal/totally_not_p_r_n.h => externals/jemalloc/jemalloc/internal/totally_not_p_r_n.h rename : externals/jemalloc/include/jemalloc.h => externals/jemalloc/jemalloc/jemalloc.h rename : externals/jemalloc/include/jemalloc.h.in => externals/jemalloc/jemalloc/jemalloc.h.in rename : externals/jemalloc/include/jemalloc_defs.h => externals/jemalloc/jemalloc/jemalloc_defs.h rename : externals/jemalloc/include/jemalloc_defs.h.in => externals/jemalloc/jemalloc/jemalloc_defs.h.in
Diffstat (limited to 'externals/g3dlite/Random.cpp')
-rw-r--r--externals/g3dlite/Random.cpp212
1 files changed, 212 insertions, 0 deletions
diff --git a/externals/g3dlite/Random.cpp b/externals/g3dlite/Random.cpp
new file mode 100644
index 00000000000..2dda744a1ac
--- /dev/null
+++ b/externals/g3dlite/Random.cpp
@@ -0,0 +1,212 @@
+/**
+ @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