//------------------------------------------------------------------------
// Copyright (C) Sewell Development Corporation, 1994 - 1998.
// Web: www.sewelld.com E-mail: [email protected]
//
// LICENSE: Paid-up licensees are authorized to use this code on a site-wide
// basis and incorporate it into their software products, provided that the
// code is not resold as stand-alone source code or as part of a code library,
// and that this copyright notice and license agreement are not removed.
//------------------------------------------------------------------------
// Interface definition for random number classes.
#pragma once
//------------------------- RandomNumber ---------------------------------
// Returns pseudo-random numbers of various types from an underlying
// sequence of pseudo-random 64-bit numbers produced with a linear
// congruential generator. No more than 32-bits of data are taken from
// the sequence at each step. Therefore calls that return more than 32-bits
// of random data (i.e. the 64-bit integer return types and the double type),
// use two iterations of the underlying sequence to produce the data.
// All linear congruential generators suffer from certain statistical
// weaknesses when used for applications demanding highly random data.
// To mitigate that problem, a derived ShuffledRandomNumber class is
// provided. This overrides the GetUint32() function, which is used by all
// the other functions to get the next 32 bits of random data. The
// RandomNumber::GetUnit32() function simply returns the high order 32-bits of
// the next 64-bit value from the generator. The ShuffledRandomNumber::GetUint32()
// function takes a 32-bit CRC (cyclic redundancy check) of all 64-bits from
// the next generator value. This greatly improves the quality of the returned
// random data for statistical work - at the cost of some extra computational time.
// If your application is not demanding of this higher statistical quality,
// and you want to improve execution speed, use the RandomNumber class instead of
// the ShuffledRandomNumber class.
// A 64-bit "seed" value is passed to the constructor to supply the starting
// point in the pseudo-random 64-bit sequence. The second optional argument is
// a "prime addend" for the generator sequence, which should be a large 64-bit
// prime number. If you omit this argument, or pass a zero, a standard prime
// addend is supplied. You would typically only need to supply this argument
// if you want to generate multiple reproducible streams of random numbers
// (possibly in different threads) and you want to make sure that the streams
// are relatively independent. The NextLargePrimeAddend() routine is provided
// to help you generate unique large prime addends, or you can roll your own.
// The prime numbers generated by this call are not sequential. They are
// essentially randomly distributed (in a reproducible way) throughout the
// number space above 0x4000000000000000 (larger prime numbers generate streams
// that show less correlation with each other). See the header file
// "PrimeTest.h" for more information on how this routine tests for primality.
// You can always reproduce a given pseudo-random sequence by passing the same starting
// seed value and prime addend to the constructor as was originally passsed. You can also
// save the state of a sequence with SaveState(), or restore it later with
// RestoreState().
// If you want to start at a random point in the sequence, call the
// RandomNumberSeed() function and pass its return value to the constructor
// of RandomNumber(). RandomNumberSeed() can also be used as a general
// purpose way of coming up with a fairly random 64-bit number. It
// generates this value by taking a 64-bit CRC (cyclic redundancy check)
// of all of the following data:
// 1) The 64-bit value returned by Win32 GetSystemTimeAsFileTime().
// 2) The 32-bit value returned by Win32 GetTickCount().
// 3) The 64-bit value returned by Win32 QueryPerformanceCounter
// (if a high performance counter is available in the system).
// 4) The 64-bit cpu cycle count returned by QueryCpuCycleCounter()
// (if running on a Pentium compatible system).
unsigned __int64 RandomNumberSeed();
// Generate another large 64-bit prime number for use as a prime addend.
// This routine chews up several milliseconds of CPU time, so use it only
// when you need to (typically when multiple streams of random data are
// desired). When different prime addends are passed to different
// RandomNumber objects, the random sequences produced are different and
// essentially uncorrelated, even if the same seed is passed. We
// haven't calculated how many prime numbers this routine produces before
// it repeats - but it is many billion.
unsigned __int64 NextLargePrimeAddend(int numRabinMillerIterations = 1);
class RandomNumber {
public:
RandomNumber(unsigned __int64 seed, unsigned __int64 primeAddend = 0);
void SaveState(unsigned __int64* seed, unsigned __int64* primeAddend);
void RestoreState(unsigned __int64 seed, unsigned __int64 primeAddend);
// Return a random 32-bit unsigned integer
virtual unsigned __int32 GetUint32();
// Return a random 32-bit unsigned integer between specified minimum and maximum (inclusive).
unsigned __int32 GetUint32InRange(unsigned __int32 minimum, unsigned __int32 maximum);
// Return a random 32-bit signed integer
__int32 GetInt32() {
return (__int32) GetUint32();
}
// Return a random 32-bit integer between specified minimum and maximum (inclusive).
__int32 GetInt32InRange(__int32 minimum, __int32 maximum) {
return (__int32) GetUint32InRange( (unsigned __int32) minimum, (unsigned __int32) maximum);
}
// Return a random 64-bit unsigned integer
unsigned __int64 GetUint64();
// Return a random 64-bit signed integer
__int64 GetInt64() {
return (__int64) GetUint64();
}
// Return a random float anywhere in the valid range.
float GetFloat();
// Return a random float between the specified minimum and maximum (NOT inclusive).
float GetFloatInRange(float minimum, float maximum);
// Return a random double anywhere in the valid range.
double GetDouble();
// Return a random double between the specified minimum and maximum (NOT inclusive).
double GetDoubleInRange(double minimum, double maximum);
protected:
unsigned __int64 m_seed;
unsigned __int64 m_primeAddend;
};
// This class is identical in purpose to RandomNumber. The only difference is that
// bits from the linear congruential generator are shuffled using a CRC before they
// are returned. Which one to use is simply a tradeoff between slower execution
// times with this class versus better statistical quality of the returned bits.
class ShuffledRandomNumber : public RandomNumber {
public:
ShuffledRandomNumber(unsigned __int64 seed, unsigned __int64 primeAddend = 0)
: RandomNumber(seed, primeAddend) { }
// Return a random 32-bit unsigned integer
virtual unsigned __int32 GetUint32();
};