blob: 53df375c7f30c725c5f75709517f221f71a4ebc0 [file] [log] [blame]
//--------------------------------------------------------------
// ____ _ _
// / ___|____ _ _ ____ ____| |__ | |
// | | / ___| | | | _ \/ ___| _ \| |
// | |___| | | |_| | | | | |___| | | ||_|
// \____|_| \_____|_| |_|\____|_| |_|(_) Media benchmarks
//
// © 2006, Intel Corporation, licensed under Apache 2.0
//
// file : RandomGenerator.cpp
// author : Scott Ettinger - scott.m.ettinger@intel.com
// description : Random number generator object.
// The uniform distribution generator is based
// on the ran2() function
// modified :
//---------------------------------------------------------------
#if defined(HAVE_CONFIG_H)
# include "config.h"
#endif
#include "RandomGenerator.h"
//Random generator numerical constants
#define IM1 2147483563
#define IM2 2147483399
#define AM (1.0/IM1)
#define IMM1 (IM1-1)
#define IA1 40014
#define IA2 40692
#define IQ1 53668
#define IQ2 52774
#define IR1 12211
#define IR2 3791
#define NDIV (1+IMM1/NTAB)
#define EPS 1.2e-7
#define RNMX (1.0 - EPS)
RandomGenerator::RandomGenerator()
{ mIy = 0; mIdum2 = 123456789; mIset = 0;
Seed(1);
}
//Generate pseudo-random values from 0 to 1. This algorithm
//is known to be portable and to have very little serial correlation.
double RandomGenerator::Rand()
{ if (mIdum <= 0) // initialize if negative
{ mIdum = mIdum2 = (-mIdum < 1) ? 1 : -mIdum; // guarantee positive and non-zero
for(int i = NTAB + 7; i >= 0; i--) // load shuffle table after 8 warm-ups
{ long k = mIdum / IQ1;
mIdum = IA1 * (mIdum - k * IQ1) - k * IR1;
if (mIdum < 0) mIdum += IM1;
if (i < NTAB) mIv[i] = mIdum;
}
mIy = mIv[0];
}
long k = mIdum / IQ1; //otherwise update to new state
mIdum = IA1 * (mIdum - k * IQ1) - k * IR1;
if (mIdum < 0) mIdum += IM1;
k = mIdum2 / IQ2;
mIdum2 = IA2 * (mIdum2 - k * IQ2) - k * IR2;
if (mIdum2 < 0) mIdum2 += IM2;
int j = mIy / NDIV;
mIy = mIv[j] - mIdum2;
mIv[j] = mIdum;
if(mIy < 1) mIy += IMM1;
double temp;
if ((temp = AM * mIy) > RNMX)
return RNMX;
else
return temp;
}
//Generate random numbers from a Normal distribution N(0,1)
double RandomGenerator::RandN()
{ double fac, rsq, v1, v2;
if (mIset == 0)
{ do
{ v1 = 2.0 * Rand() - 1.0; //use fundamental transformation law of probabilities
v2 = 2.0 * Rand() - 1.0;
rsq = v1 * v1 + v2 * v2;
} while (rsq >= 1.0 || rsq == 0.0);
fac = sqrt(-2.0 * log(rsq)/rsq);
mGset = v1 * fac;
mIset = 1;
return ((v2 * fac));
}
else
{ mIset=0;
return mGset;
}
}
//Generate Exponentially distributed random numbers
double RandomGenerator::RandExp()
{
double d = Rand();
while(d == 0)
d = Rand();
return -log(d);
}