#if !defined(RANDGEN_H) #define RANDGEN_H #include /*-------------------------------------------------------------*/ // integer random number generator class Ran32 { protected: static const long a, m, q, r; long seed; public: Ran32(){}; Ran32(long s){Reset(s);} void Reset(long s); long Curr() const{return seed;} long Next(); // Returns the current value cv scaled such that 0 <= cv < n. long Curr(long n) const {return Curr() % n;} long Next(long n){return Next() % n;} long Curr(long lo, long hi) const; long Next(long lo, long hi); }; /*---------------------------------------------------------*/ // float point random number generator class fRan32 : private Ran32 { protected: static const float d; // d = 1/m public: fRan32(long s): Ran32(s) {} Ran32::Reset; // This can be public long Seed(){return seed;} float Curr() const { return float(Ran32::Curr()) * d;} float Next(){return float(Ran32::Next()) * d;} float Curr(float n) const { return (n * float(Ran32::Curr())) * d;} float Next(float n) {return (n * float(Ran32::Next())) * d;} float Curr(float lo, float hi) const; float Next(float lo, float hi); }; /*--------------------------------------------------------------------*/ // bit-wise random number generator class RanBit32 { unsigned long seed; // Assume 32 bits public: RanBit32(unsigned long s); void Reset(unsigned long s); unsigned long Seed() const; int Curr() const; int Next(); }; const long Ran32::a = 16807L; // The multiplier const long Ran32::m = 2147483647L; // The modulus const long Ran32::q = m / a; const long Ran32::r = m % a; inline RanBit32::RanBit32(unsigned long s) // Constructs a random bit sequencer using the // seed s, assumed to be > 0. { Reset(s); } inline unsigned long RanBit32::Seed() const { return seed; } inline int RanBit32::Curr() const // Returns the current random bit { return (seed & 0x80000000L) != 0; } void Ran32::Reset(long s) // Resets the random number sequence by starting // with a new seed. Note that seed must be between // [1 .. m-1] in order for things to work properly. // In particular, DON'T SET THE SEED TO ZERO. { seed = s; if (seed < 1) seed = 1; else if (seed >= m) seed = m-1; } long Ran32::Next() // Advances to the next random number, having a uniform // distribution, with a range of [1..m-1]. The period of // the sequence is m-2, or roughly 2.15x10^9 for a m = 2^31-1. { long k = seed/q; seed = a * (seed - k*q) - k*r; if (seed < 0) seed += m; return seed; } long Ran32::Curr(long lo, long hi) const // Returns the current value of the sequence, cv, and // restricts it's range to be lo <= cv <= hi. { return lo + (Curr() % (hi-lo+1)); } long Ran32::Next(long lo, long hi) // Returns the next value of the sequence, nv, and // restricts it's range to be lo <= nv <= hi. { return lo + (Next() % (hi-lo+1)); } const float fRan32::d = 1.0 / float(Ran32::m); float fRan32::Curr(float lo, float hi) const // Takes current value, and limits its range from 0 <= cv <= hi. { return lo + ((hi-lo) * float(Ran32::Curr())) * d; } float fRan32::Next(float lo, float hi) // Advances to next value, and limits its range from 0 <= nv <= hi. { return lo + ((hi-lo) * float(Ran32::Next())) * d; } void RanBit32::Reset(unsigned long s) // Initializes seed with s. Note that the seed must be // non-zero to make any sense. { seed = s; if (seed == 0) seed = 421755L; // Arbitrary value } int RanBit32::Next() // Advances to the next random bit, with a cycle // length of 2^32-1. It assumes longs are 32 bits. { const unsigned long mask = 0xAF; // Bits 7,5,3,2,1,0 if (seed & 0x80000000L) { seed <<= 1; seed ^= mask; return 1; } else { seed <<= 1; return 0; } } static Ran32 irandom(123); static fRan32 frandom(123); static RanBit32 brandom(123); void garandomize() { long seed = (unsigned long)time(NULL); irandom.Reset(seed); frandom.Reset(irandom.Next()); brandom.Reset(irandom.Next()); } // // test integer random number generator program // /* main() { ofstream out("c:/temp/ran_int.dat"); long seed, hi=0, lo=50, n=10; seed = (unsigned long)time(NULL); out << "seed: "<