mxwcore-wotlk/deps/g3dlite/include/G3D/Random.h

165 lines
4.7 KiB
C++

/**
\file G3D/Random.h
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
\created 2009-01-02
\edited 2012-07-20
Copyright 2000-2012, 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).
\sa Noise
*/
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*);
private:
Random& operator=(const Random&) {
alwaysAssertM(false,
"There is no copy constructor or assignment operator for Random because you "
"probably didn't actually want to copy the state--it would "
"be slow and duplicate the state of a pseudo-random sequence. Maybe you could "
"provide arguments to a member variable in the constructor, "
"or pass the Random by reference?");
return *this;
}
Random(const Random& r) {
*this = r;
}
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();
virtual void reset(uint32 seed = 0xF018A4D2, bool threadsafe = true);
/** 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 positive z-axis. */
virtual void cosHemi(float& x, float& y, float& z);
/** Returns 3D unit vectors distributed according to
a cosine distribution about the z-axis. */
virtual void cosSphere(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