ROOT logo
// @(#)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
   //  Generate number in interval (0,1)  : 0 and 1 are not included in the interval

#define TAUSWORTHE(s,a,b,c,d) (((s &c) <<d) & 0xffffffffUL ) ^ ((((s <<a) & 0xffffffffUL )^s) >>b)

   // scale by 1./(Max<UINT> + 1) = 1./4294967296 
   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<Double_t>(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<n; i++) {
      fSeed  = TAUSWORTHE (fSeed, 13, 19, 4294967294UL, 12);
      fSeed1 = TAUSWORTHE (fSeed1, 2, 25, 4294967288UL, 4);
      fSeed2 = TAUSWORTHE (fSeed2, 3, 11, 4294967280UL, 17);

      iy = fSeed ^ fSeed1 ^ fSeed2;
      if (iy) array[i] = (Float_t)(kScale*static_cast<Double_t>(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<n; i++) {
      fSeed  = TAUSWORTHE (fSeed, 13, 19, 4294967294UL, 12);
      fSeed1 = TAUSWORTHE (fSeed1, 2, 25, 4294967288UL, 4);
      fSeed2 = TAUSWORTHE (fSeed2, 3, 11, 4294967280UL, 17);

      iy = fSeed ^ fSeed1 ^ fSeed2;
      if (iy) array[i] = kScale*static_cast<Double_t>(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  =  UInt_t(uuid[3])*16777216 + UInt_t(uuid[2])*65536 + UInt_t(uuid[1])*256 + UInt_t(uuid[0]);
      fSeed1  =  UInt_t(uuid[7])*16777216 + UInt_t(uuid[6])*65536 + UInt_t(uuid[5])*256 + UInt_t(uuid[4]);
      fSeed2  =  UInt_t(uuid[11])*16777216 + UInt_t(uuid[10])*65536 + UInt_t(uuid[9])*256 + UInt_t(uuid[8]);
      // use also the other bytes
      UInt_t seed3 = UInt_t(uuid[15])*16777216 + UInt_t(uuid[14])*65536 + UInt_t(uuid[13])*256 + int(uuid[12]);
      fSeed2 += seed3; 



      //    TRandom r3(0);
      // fSeed   = static_cast<UInt_t> (4294967296.*r3.Rndm());
      // fSeed1  = static_cast<UInt_t> (4294967296.*r3.Rndm());
      // fSeed2  = static_cast<UInt_t> (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;
}

 TRandom2.cxx:1
 TRandom2.cxx:2
 TRandom2.cxx:3
 TRandom2.cxx:4
 TRandom2.cxx:5
 TRandom2.cxx:6
 TRandom2.cxx:7
 TRandom2.cxx:8
 TRandom2.cxx:9
 TRandom2.cxx:10
 TRandom2.cxx:11
 TRandom2.cxx:12
 TRandom2.cxx:13
 TRandom2.cxx:14
 TRandom2.cxx:15
 TRandom2.cxx:16
 TRandom2.cxx:17
 TRandom2.cxx:18
 TRandom2.cxx:19
 TRandom2.cxx:20
 TRandom2.cxx:21
 TRandom2.cxx:22
 TRandom2.cxx:23
 TRandom2.cxx:24
 TRandom2.cxx:25
 TRandom2.cxx:26
 TRandom2.cxx:27
 TRandom2.cxx:28
 TRandom2.cxx:29
 TRandom2.cxx:30
 TRandom2.cxx:31
 TRandom2.cxx:32
 TRandom2.cxx:33
 TRandom2.cxx:34
 TRandom2.cxx:35
 TRandom2.cxx:36
 TRandom2.cxx:37
 TRandom2.cxx:38
 TRandom2.cxx:39
 TRandom2.cxx:40
 TRandom2.cxx:41
 TRandom2.cxx:42
 TRandom2.cxx:43
 TRandom2.cxx:44
 TRandom2.cxx:45
 TRandom2.cxx:46
 TRandom2.cxx:47
 TRandom2.cxx:48
 TRandom2.cxx:49
 TRandom2.cxx:50
 TRandom2.cxx:51
 TRandom2.cxx:52
 TRandom2.cxx:53
 TRandom2.cxx:54
 TRandom2.cxx:55
 TRandom2.cxx:56
 TRandom2.cxx:57
 TRandom2.cxx:58
 TRandom2.cxx:59
 TRandom2.cxx:60
 TRandom2.cxx:61
 TRandom2.cxx:62
 TRandom2.cxx:63
 TRandom2.cxx:64
 TRandom2.cxx:65
 TRandom2.cxx:66
 TRandom2.cxx:67
 TRandom2.cxx:68
 TRandom2.cxx:69
 TRandom2.cxx:70
 TRandom2.cxx:71
 TRandom2.cxx:72
 TRandom2.cxx:73
 TRandom2.cxx:74
 TRandom2.cxx:75
 TRandom2.cxx:76
 TRandom2.cxx:77
 TRandom2.cxx:78
 TRandom2.cxx:79
 TRandom2.cxx:80
 TRandom2.cxx:81
 TRandom2.cxx:82
 TRandom2.cxx:83
 TRandom2.cxx:84
 TRandom2.cxx:85
 TRandom2.cxx:86
 TRandom2.cxx:87
 TRandom2.cxx:88
 TRandom2.cxx:89
 TRandom2.cxx:90
 TRandom2.cxx:91
 TRandom2.cxx:92
 TRandom2.cxx:93
 TRandom2.cxx:94
 TRandom2.cxx:95
 TRandom2.cxx:96
 TRandom2.cxx:97
 TRandom2.cxx:98
 TRandom2.cxx:99
 TRandom2.cxx:100
 TRandom2.cxx:101
 TRandom2.cxx:102
 TRandom2.cxx:103
 TRandom2.cxx:104
 TRandom2.cxx:105
 TRandom2.cxx:106
 TRandom2.cxx:107
 TRandom2.cxx:108
 TRandom2.cxx:109
 TRandom2.cxx:110
 TRandom2.cxx:111
 TRandom2.cxx:112
 TRandom2.cxx:113
 TRandom2.cxx:114
 TRandom2.cxx:115
 TRandom2.cxx:116
 TRandom2.cxx:117
 TRandom2.cxx:118
 TRandom2.cxx:119
 TRandom2.cxx:120
 TRandom2.cxx:121
 TRandom2.cxx:122
 TRandom2.cxx:123
 TRandom2.cxx:124
 TRandom2.cxx:125
 TRandom2.cxx:126
 TRandom2.cxx:127
 TRandom2.cxx:128
 TRandom2.cxx:129
 TRandom2.cxx:130
 TRandom2.cxx:131
 TRandom2.cxx:132
 TRandom2.cxx:133
 TRandom2.cxx:134
 TRandom2.cxx:135
 TRandom2.cxx:136
 TRandom2.cxx:137
 TRandom2.cxx:138
 TRandom2.cxx:139
 TRandom2.cxx:140
 TRandom2.cxx:141
 TRandom2.cxx:142
 TRandom2.cxx:143
 TRandom2.cxx:144
 TRandom2.cxx:145
 TRandom2.cxx:146
 TRandom2.cxx:147
 TRandom2.cxx:148
 TRandom2.cxx:149
 TRandom2.cxx:150
 TRandom2.cxx:151
 TRandom2.cxx:152
 TRandom2.cxx:153
 TRandom2.cxx:154
 TRandom2.cxx:155
 TRandom2.cxx:156
 TRandom2.cxx:157
 TRandom2.cxx:158
 TRandom2.cxx:159
 TRandom2.cxx:160