Replace PRNG with a standard MT.
RandomGen r; r(); now generates [0,2^31-1] on 32-bit platforms, not [0,2^31-2]. No longer uses MAX_INT, so the default behavior doesn't depend on the size of an int. RandomInt no longer generates a float and truncates it. That limited the values that could be returned to those that fit in a 32-bit float. Remove NR code. It's not free. This code is not threadsafe. Locking access would kill performance. The old code wasn't, either. I think most symptoms would be innocuous enough to not worry about.
This commit is contained in:
+56
-32
@@ -15,51 +15,75 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
|
||||||
int randseed = time(NULL);
|
RandomGen g_RandomNumberGenerator;
|
||||||
|
|
||||||
// From "Numerical Recipes in C".
|
MersenneTwister::MersenneTwister( int iSeed )
|
||||||
static float RandomFloatFromSeed( int &seed )
|
|
||||||
{
|
{
|
||||||
const int MASK = 123459876;
|
Reset( iSeed );
|
||||||
seed ^= MASK;
|
|
||||||
|
|
||||||
const int IA = 16807;
|
|
||||||
const int IM = 2147483647;
|
|
||||||
|
|
||||||
const int IQ = 127773;
|
|
||||||
const int IR = 2836;
|
|
||||||
|
|
||||||
long k = seed / IQ;
|
|
||||||
seed = IA*(seed-k*IQ)-IR*k;
|
|
||||||
if( seed < 0 )
|
|
||||||
seed += IM;
|
|
||||||
|
|
||||||
const float AM = .999999f / IM;
|
|
||||||
float ans = AM * seed;
|
|
||||||
|
|
||||||
seed ^= MASK;
|
|
||||||
return ans;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float RandomFloat()
|
void MersenneTwister::Reset( int iSeed )
|
||||||
{
|
{
|
||||||
return RandomFloatFromSeed( randseed );
|
if( iSeed == 0 )
|
||||||
|
iSeed = time(NULL);
|
||||||
|
|
||||||
|
m_Values[0] = iSeed;
|
||||||
|
m_iNext = 0;
|
||||||
|
for( int i = 1; i < 624; ++i )
|
||||||
|
m_Values[i] = ((69069 * m_Values[i-1]) + 1) & 0xFFFFFFFF;
|
||||||
|
|
||||||
|
GenerateValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
RandomGen::RandomGen( unsigned long seed_ )
|
void MersenneTwister::GenerateValues()
|
||||||
{
|
{
|
||||||
seed = seed_;
|
static const int mask[] = { 0, 0x9908B0DF };
|
||||||
if(seed == 0)
|
|
||||||
seed = time(NULL);
|
for( int i = 0; i < 227; ++i )
|
||||||
|
{
|
||||||
|
int iVal = (m_Values[i] & 0x80000000) | (m_Values[i+1] & 0x7FFFFFFF);
|
||||||
|
int iNext = (i + 397);
|
||||||
|
|
||||||
|
m_Values[i] = m_Values[iNext];
|
||||||
|
m_Values[i] ^= (iVal >> 1);
|
||||||
|
m_Values[i] ^= mask[iVal&1];
|
||||||
|
}
|
||||||
|
|
||||||
|
for( int i = 227; i < 623; ++i )
|
||||||
|
{
|
||||||
|
int iVal = (m_Values[i] & 0x80000000) | (m_Values[i+1] & 0x7FFFFFFF);
|
||||||
|
int iNext = (i + 397) - 624;
|
||||||
|
|
||||||
|
m_Values[i] = m_Values[iNext];
|
||||||
|
m_Values[i] ^= (iVal >> 1);
|
||||||
|
m_Values[i] ^= mask[iVal&1];
|
||||||
|
}
|
||||||
|
|
||||||
|
int iVal = (m_Values[623] & 0x80000000) + (m_Values[0] & 0x7FFFFFFF);
|
||||||
|
int iNext = (623 + 397) - 624;
|
||||||
|
m_Values[623] = m_Values[iNext] ^ (iVal>>1);
|
||||||
|
m_Values[623] ^= mask[iVal&1];
|
||||||
}
|
}
|
||||||
|
|
||||||
int RandomGen::operator() ( int n )
|
int MersenneTwister::Temper( int iVal )
|
||||||
{
|
{
|
||||||
float f = RandomFloatFromSeed(seed) * (n);
|
iVal ^= (iVal >> 11);
|
||||||
int ans = int(f);
|
iVal ^= (iVal << 7) & 0x9D2C5680;
|
||||||
return ans;
|
iVal ^= (iVal << 15) & 0xEFC60000;
|
||||||
|
iVal ^= (iVal >> 18);
|
||||||
|
return iVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int MersenneTwister::operator()()
|
||||||
|
{
|
||||||
|
if( m_iNext == 624 )
|
||||||
|
{
|
||||||
|
m_iNext = 0;
|
||||||
|
GenerateValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Temper( m_Values[m_iNext++] );
|
||||||
|
}
|
||||||
|
|
||||||
void fapproach( float& val, float other_val, float to_move )
|
void fapproach( float& val, float other_val, float to_move )
|
||||||
{
|
{
|
||||||
|
|||||||
+29
-13
@@ -227,8 +227,34 @@ inline uint32_t Swap24LE( uint32_t n ) { return Swap24( n ); }
|
|||||||
inline uint16_t Swap16LE( uint16_t n ) { return Swap16( n ); }
|
inline uint16_t Swap16LE( uint16_t n ) { return Swap16( n ); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct MersenneTwister
|
||||||
|
{
|
||||||
|
MersenneTwister( int iSeed = 0 ); // 0 = time()
|
||||||
|
int operator()(); // returns [0,2^31-1]
|
||||||
|
int operator()( int n ) // returns [0,n)
|
||||||
|
{
|
||||||
|
return (*this)() % n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reset( int iSeed );
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int Temper( int iValue );
|
||||||
|
void GenerateValues();
|
||||||
|
|
||||||
|
int m_Values[624];
|
||||||
|
int m_iNext;
|
||||||
|
};
|
||||||
|
typedef MersenneTwister RandomGen;
|
||||||
|
|
||||||
|
extern RandomGen g_RandomNumberGenerator;
|
||||||
|
|
||||||
// [0.0f,1.0f)
|
// [0.0f,1.0f)
|
||||||
float RandomFloat();
|
inline float RandomFloat()
|
||||||
|
{
|
||||||
|
return g_RandomNumberGenerator() / 2147483648.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Returns a float between dLow and dHigh inclusive
|
// Returns a float between dLow and dHigh inclusive
|
||||||
inline float RandomFloat( float fLow, float fHigh )
|
inline float RandomFloat( float fLow, float fHigh )
|
||||||
@@ -239,25 +265,15 @@ inline float RandomFloat( float fLow, float fHigh )
|
|||||||
// Returns an integer between nLow and nHigh inclusive
|
// Returns an integer between nLow and nHigh inclusive
|
||||||
inline int RandomInt( int nLow, int nHigh )
|
inline int RandomInt( int nLow, int nHigh )
|
||||||
{
|
{
|
||||||
return int( RandomFloat() * (nHigh - nLow + 1) + nLow );
|
return int( g_RandomNumberGenerator(nHigh - nLow + 1) + nLow );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns an integer between 0 and n-1 inclusive (replacement for rand() % n).
|
// Returns an integer between 0 and n-1 inclusive (replacement for rand() % n).
|
||||||
inline int RandomInt( int n )
|
inline int RandomInt( int n )
|
||||||
{
|
{
|
||||||
return RandomInt( 0, n-1 );
|
return int( g_RandomNumberGenerator(n) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Alternative: */
|
|
||||||
class RandomGen
|
|
||||||
{
|
|
||||||
int seed;
|
|
||||||
|
|
||||||
public:
|
|
||||||
RandomGen( unsigned long seed = 0 );
|
|
||||||
int operator() ( int n = INT_MAX-1 ); // return number [0,n)
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Simple function for generating random numbers
|
// Simple function for generating random numbers
|
||||||
inline float randomf( const float low=-1.0f, const float high=1.0f )
|
inline float randomf( const float low=-1.0f, const float high=1.0f )
|
||||||
|
|||||||
Reference in New Issue
Block a user