// @(#)root/mathcore:$Id$ // Author: Rene Brun, Lorenzo Moneta 17/05/2006 ////////////////////////////////////////////////////////////////////////// // // TRandom2 // // Random number generator class based on the maximally quidistributed combined // Tausworthe generator by L'Ecuyer. // // The period of the generator is 2**88 (about 10**26) and it uses only 3 words // for the state. // // For more information see: // P. L'Ecuyer, Mathematics of Computation, 65, 213 (1996) // P. L'Ecuyer, Mathematics of Computation, 68, 225 (1999) // // The publication are available online at // http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps // http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps ////////////////////////////////////////////////////////////////////////// #include "TRandom2.h" #include "TRandom3.h" #include "TUUID.h" ClassImp(TRandom2) //______________________________________________________________________________ TRandom2::TRandom2(UInt_t seed) { //*-*-*-*-*-*-*-*-*-*-*default constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-* //*-* =================== SetName("Random2"); SetTitle("Random number generator with period of about 10**26"); SetSeed(seed); } //______________________________________________________________________________ TRandom2::~TRandom2() { //*-*-*-*-*-*-*-*-*-*-*default destructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-* //*-* ================== } //______________________________________________________________________________ Double_t TRandom2::Rndm(Int_t) { // TausWorth generator from L'Ecuyer, uses as seed 3x32bits integers // Use a mask of 0xffffffffUL to make in work on 64 bit machines // Periodicity of about 10**26 #define TAUSWORTHE(s,a,b,c,d) (((s &c) <>b) const double kScale = 2.3283064365386963e-10; // range in 32 bit ( 1/(2**32) fSeed = TAUSWORTHE (fSeed, 13, 19, 4294967294UL, 12); fSeed1 = TAUSWORTHE (fSeed1, 2, 25, 4294967288UL, 4); fSeed2 = TAUSWORTHE (fSeed2, 3, 11, 4294967280UL, 17); UInt_t iy = fSeed ^ fSeed1 ^ fSeed2; if (iy) return kScale*static_cast(iy); return Rndm(); } //______________________________________________________________________________ void TRandom2::RndmArray(Int_t n, Float_t *array) { // Return an array of n random numbers uniformly distributed in ]0,1] const double kScale = 2.3283064365386963e-10; // range in 32 bit ( 1/(2**32) UInt_t iy; for(Int_t i=0; i(iy)); else array[i] = Rndm(); } } //______________________________________________________________________________ void TRandom2::RndmArray(Int_t n, Double_t *array) { // Return an array of n random numbers uniformly distributed in ]0,1] const double kScale = 2.3283064365386963e-10; // range in 32 bit ( 1/(2**32) UInt_t iy; for(Int_t i=0; i(iy); else array[i] = Rndm(); } } //______________________________________________________________________________ void TRandom2::SetSeed(UInt_t seed) { // Set the generator seed. // If the seed given is zero, generate automatically seed values which // are different every time by using TRandom3 and TUUID // If a seed is given generate the other two needed for the generator state using // a linear congruential generator // The only condition, stated at the end of the 1999 L'Ecuyer paper is that the seeds // must be greater than 1,7 and 15. #define LCG(n) ((69069 * n) & 0xffffffffUL) // linear congurential generator if (seed > 0) { fSeed = LCG (seed); if (fSeed < 2) fSeed += 2UL; fSeed1 = LCG (fSeed); if (fSeed1 < 8) fSeed1 += 8UL; fSeed2 = LCG (fSeed1); if (fSeed2 < 16) fSeed2 += 16UL; } else { // initialize using a TUUID TUUID u; UChar_t uuid[16]; u.GetUUID(uuid); fSeed = int(uuid[3])*16777216 + int(uuid[2])*65536 + int(uuid[1])*256 + int(uuid[0]); fSeed1 = int(uuid[7])*16777216 + int(uuid[6])*65536 + int(uuid[5])*256 + int(uuid[4]); fSeed2 = int(uuid[11])*16777216 + int(uuid[10])*65536 + int(uuid[9])*256 + int(uuid[8]); // use also the other bytes UInt_t seed3 = int(uuid[15])*16777216 + int(uuid[14])*65536 + int(uuid[13])*256 + int(uuid[12]); fSeed2 += seed3; // TRandom r3(0); // fSeed = static_cast (4294967296.*r3.Rndm()); // fSeed1 = static_cast (4294967296.*r3.Rndm()); // fSeed2 = static_cast (4294967296.*r3.Rndm()); if (fSeed < 2) fSeed += 2UL; if (fSeed1 < 8) fSeed1 += 8UL; if (fSeed2 < 16) fSeed2 += 16UL; } // "warm it up" by calling it 6 times for (int i = 0; i < 6; ++i) Rndm(); return; }