diff options
Diffstat (limited to 'dep/g3dlite/G3D/Random.h')
-rw-r--r-- | dep/g3dlite/G3D/Random.h | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/dep/g3dlite/G3D/Random.h b/dep/g3dlite/G3D/Random.h new file mode 100644 index 00000000000..54491d06f1b --- /dev/null +++ b/dep/g3dlite/G3D/Random.h @@ -0,0 +1,139 @@ +/** + @file Random.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2009-01-02 + @edited 2009-03-20 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ +#ifndef G3D_Random_h +#define G3D_Random_h + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/GMutex.h" + +namespace G3D { + +/** 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(). + + @cite 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). + */ +class Random { +protected: + + /** Constants (important for the algorithm; do not modify) */ + enum { + N = 624, + M = 397, + R = 31, + U = 11, + S = 7, + T = 15, + L = 18, + A = 0x9908B0DF, + B = 0x9D2C5680, + C = 0xEFC60000}; + + /** + Prevents multiple overlapping calls to generate(). + */ + Spinlock lock; + + /** State vector (these are the next N values that will be returned) */ + uint32* state; + + /** Index into state */ + int index; + + bool m_threadsafe; + + /** Generate the next N ints, and store them for readback later. + Called from bits() */ + virtual void generate(); + + /** For subclasses. The void* parameter is just to distinguish this from the + public constructor.*/ + Random(void*); + +public: + + /** \param threadsafe Set 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. + */ + Random(uint32 seed = 0xF018A4D2, bool threadsafe = true); + + virtual ~Random(); + + /** Each bit is random. Subclasses can choose to override just + this method and the other methods will all work automatically. */ + virtual uint32 bits(); + + /** Uniform random integer on the range [min, max] */ + virtual int integer(int min, int max); + + /** Uniform random float on the range [min, max] */ + virtual inline float uniform(float low, float high) { + // We could compute the ratio in double precision here for + // about 1.5x slower performance and slightly better + // precision. + return low + (high - low) * ((float)bits() / (float)0xFFFFFFFFUL); + } + + /** Uniform random float on the range [0, 1] */ + virtual inline float uniform() { + // We could compute the ratio in double precision here for + // about 1.5x slower performance and slightly better + // precision. + const float norm = 1.0f / (float)0xFFFFFFFFUL; + return (float)bits() * norm; + } + + /** Normally distributed reals. */ + virtual float gaussian(float mean, float stdev); + + /** Returns 3D unit vectors distributed according to + a cosine distribution about the z-axis. */ + virtual void cosHemi(float& x, float& y, float& z); + + /** Returns 3D unit vectors distributed according to a cosine + power distribution (\f$ \cos^k \theta \f$) about + the z-axis. */ + virtual void cosPowHemi(const float k, float& x, float& y, float& z); + + /** Returns 3D unit vectors uniformly distributed on the + hemisphere about the z-axis. */ + virtual void hemi(float& x, float& y, float& z); + + /** Returns 3D unit vectors uniformly distributed on the sphere */ + virtual void sphere(float& x, float& y, float& z); + + /** + 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. + */ + static Random& common(); +}; + +} + +#endif |