Logo ROOT   6.13/01
Reference Guide
TRandom3.cxx
Go to the documentation of this file.
1 // @(#)root/mathcore:$Id$
2 // Author: Peter Malzacher 31/08/99
3 
4 /**
5 
6 \class TRandom3
7 
8 Random number generator class based on
9  M. Matsumoto and T. Nishimura,
10  Mersenne Twister: A 623-diminsionally equidistributed
11  uniform pseudorandom number generator
12  ACM Transactions on Modeling and Computer Simulation,
13  Vol. 8, No. 1, January 1998, pp 3--30.
14 
15 For more information see the Mersenne Twister homepage
16  [http://www.math.keio.ac.jp/~matumoto/emt.html]
17 
18 Advantage:
19 
20 - large period 2**19937 -1
21 - relativly fast (slightly slower than TRandom2 but much faster than TRandom1)
22 
23 Drawback:
24 - a relative large internal state of 624 integers
25 - generate only 32 random bits
26 - not passing all the random generator tests. It fails some tests in TestU01
27  (see [http://simul.iro.umontreal.ca/testu01/tu01.html])
28 
29 An altenativly excellent generator passing all tests of TestU01, having 61 random bits and
30 fast as Mersenne and Twister is MIXMAX (TRandomMixMax).
31 
32 @ingroup Random
33 
34 */
35 
36 //////////////////////////////////////////////////////////////////////
37 // Aug.99 ROOT implementation based on CLHEP by P.Malzacher
38 //
39 // the original code contains the following copyright notice:
40 /* This library is free software; you can redistribute it and/or */
41 /* modify it under the terms of the GNU Library General Public */
42 /* License as published by the Free Software Foundation; either */
43 /* version 2 of the License, or (at your option) any later */
44 /* version. */
45 /* This library is distributed in the hope that it will be useful, */
46 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
47 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */
48 /* See the GNU Library General Public License for more details. */
49 /* You should have received a copy of the GNU Library General */
50 /* Public License along with this library; if not, write to the */
51 /* Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA */
52 /* 02111-1307 USA */
53 /* Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura. */
54 /* When you use this, send an email to: matumoto@math.keio.ac.jp */
55 /* with an appropriate reference to your work. */
56 /////////////////////////////////////////////////////////////////////
57 
58 #include "TRandom3.h"
59 #include "TBuffer.h"
60 #include "TRandom2.h"
61 #include "TClass.h"
62 #include "TUUID.h"
63 
65 #ifdef R__COMPLETE_MEM_TERMINATION
66 namespace {
67  struct TRandomCleanup {
68  ~TRandomCleanup() { delete gRandom; gRandom = 0; }
69  };
70  static TRandomCleanup gCleanupRandom;
71 }
72 #endif
73 
74 ClassImp(TRandom3);
75 
76 ////////////////////////////////////////////////////////////////////////////////
77 /// Default constructor
78 /// If seed is 0, the seed is automatically computed via a TUUID object.
79 /// In this case the seed is guaranteed to be unique in space and time.
80 
81 TRandom3::TRandom3(UInt_t seed)
82 {
83  SetName("Random3");
84  SetTitle("Random number generator: Mersenne Twister");
85  SetSeed(seed);
86 }
87 
88 ////////////////////////////////////////////////////////////////////////////////
89 /// Default destructor
90 
92 {
93 }
94 
95 ////////////////////////////////////////////////////////////////////////////////
96 /// Machine independent random number generator.
97 /// Produces uniformly-distributed floating points in (0,1)
98 /// Method: Mersenne Twister
99 
100 Double_t TRandom3::Rndm()
101 {
102  UInt_t y;
103 
104  const Int_t kM = 397;
105  const Int_t kN = 624;
106  const UInt_t kTemperingMaskB = 0x9d2c5680;
107  const UInt_t kTemperingMaskC = 0xefc60000;
108  const UInt_t kUpperMask = 0x80000000;
109  const UInt_t kLowerMask = 0x7fffffff;
110  const UInt_t kMatrixA = 0x9908b0df;
111 
112  if (fCount624 >= kN) {
113  Int_t i;
114 
115  for (i=0; i < kN-kM; i++) {
116  y = (fMt[i] & kUpperMask) | (fMt[i+1] & kLowerMask);
117  fMt[i] = fMt[i+kM] ^ (y >> 1) ^ ((y & 0x1) ? kMatrixA : 0x0);
118  }
119 
120  for ( ; i < kN-1 ; i++) {
121  y = (fMt[i] & kUpperMask) | (fMt[i+1] & kLowerMask);
122  fMt[i] = fMt[i+kM-kN] ^ (y >> 1) ^ ((y & 0x1) ? kMatrixA : 0x0);
123  }
124 
125  y = (fMt[kN-1] & kUpperMask) | (fMt[0] & kLowerMask);
126  fMt[kN-1] = fMt[kM-1] ^ (y >> 1) ^ ((y & 0x1) ? kMatrixA : 0x0);
127  fCount624 = 0;
128  }
129 
130  y = fMt[fCount624++];
131  y ^= (y >> 11);
132  y ^= ((y << 7 ) & kTemperingMaskB );
133  y ^= ((y << 15) & kTemperingMaskC );
134  y ^= (y >> 18);
135 
136  // 2.3283064365386963e-10 == 1./(max<UINt_t>+1) -> then returned value cannot be = 1.0
137  if (y) return ( (Double_t) y * 2.3283064365386963e-10); // * Power(2,-32)
138  return Rndm();
139 }
140 
141 ////////////////////////////////////////////////////////////////////////////////
142 /// Return an array of n random numbers uniformly distributed in ]0,1]
143 
144 void TRandom3::RndmArray(Int_t n, Float_t *array)
145 {
146  for(Int_t i=0; i<n; i++) array[i]=(Float_t)Rndm();
147 }
148 
149 ////////////////////////////////////////////////////////////////////////////////
150 /// Return an array of n random numbers uniformly distributed in ]0,1]
151 
152 void TRandom3::RndmArray(Int_t n, Double_t *array)
153 {
154  Int_t k = 0;
155 
156  UInt_t y;
157 
158  const Int_t kM = 397;
159  const Int_t kN = 624;
160  const UInt_t kTemperingMaskB = 0x9d2c5680;
161  const UInt_t kTemperingMaskC = 0xefc60000;
162  const UInt_t kUpperMask = 0x80000000;
163  const UInt_t kLowerMask = 0x7fffffff;
164  const UInt_t kMatrixA = 0x9908b0df;
165 
166  while (k < n) {
167  if (fCount624 >= kN) {
168  Int_t i;
169 
170  for (i=0; i < kN-kM; i++) {
171  y = (fMt[i] & kUpperMask) | (fMt[i+1] & kLowerMask);
172  fMt[i] = fMt[i+kM] ^ (y >> 1) ^ ((y & 0x1) ? kMatrixA : 0x0);
173  }
174 
175  for ( ; i < kN-1 ; i++) {
176  y = (fMt[i] & kUpperMask) | (fMt[i+1] & kLowerMask);
177  fMt[i] = fMt[i+kM-kN] ^ (y >> 1) ^ ((y & 0x1) ? kMatrixA : 0x0);
178  }
179 
180  y = (fMt[kN-1] & kUpperMask) | (fMt[0] & kLowerMask);
181  fMt[kN-1] = fMt[kM-1] ^ (y >> 1) ^ ((y & 0x1) ? kMatrixA : 0x0);
182  fCount624 = 0;
183  }
184 
185  y = fMt[fCount624++];
186  y ^= (y >> 11);
187  y ^= ((y << 7 ) & kTemperingMaskB );
188  y ^= ((y << 15) & kTemperingMaskC );
189  y ^= (y >> 18);
190 
191  if (y) {
192  array[k] = Double_t( y * 2.3283064365386963e-10); // * Power(2,-32)
193  k++;
194  }
195  }
196 }
197 
198 ////////////////////////////////////////////////////////////////////////////////
199 /// Set the random generator sequence
200 /// if seed is 0 (default value) a TUUID is generated and used to fill
201 /// the first 8 integers of the seed array.
202 /// In this case the seed is guaranteed to be unique in space and time.
203 /// Use upgraded seeding procedure to fix a known problem when seeding with values
204 /// with many zero in the bit pattern (like 2**28).
205 /// see http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html
206 
207 void TRandom3::SetSeed(ULong_t seed)
208 {
209  TRandom::SetSeed(seed);
210  fCount624 = 624;
211  if (seed > 0) {
212  fMt[0] = fSeed;
213 
214  // use multipliers from Knuth's "Art of Computer Programming" Vol. 2, 3rd Ed. p.106
215  for(Int_t i=1; i<624; i++) {
216  fMt[i] = (1812433253 * ( fMt[i-1] ^ ( fMt[i-1] >> 30)) + i );
217  }
218 
219  } else {
220 
221  // use TRandom2 (which is based on TUUId to generate the seed
222  // TRandom2 works fairly well and has been tested against example
223  // layout in https://savannah.cern.ch/bugs/?99516
224  TRandom2 r(0);
225  for (Int_t i = 0; i< 624; i++) {
226  fMt[i] = static_cast<UInt_t> (4294967296.*r.Rndm());
227  }
228  // warm up the generator calling it 10 times
229  for (Int_t i = 0; i < 10; ++i) Rndm();
230  }
231 
232 
233 }
234 
235 ////////////////////////////////////////////////////////////////////////////////
236 /// Stream an object of class TRandom3.
237 
238 void TRandom3::Streamer(TBuffer &R__b)
239 {
240  if (R__b.IsReading()) {
241  UInt_t R__s, R__c;
242  Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
243  if (R__v > 1) {
244  R__b.ReadClassBuffer(TRandom3::Class(), this, R__v, R__s, R__c);
245  return;
246  }
247  //====process old versions before automatic schema evolution
248  TRandom::Streamer(R__b);
249  R__b.ReadStaticArray(fMt);
250  R__b >> fCount624;
251  R__b.CheckByteCount(R__s, R__c, TRandom3::IsA());
252  //====end of old versions
253 
254  } else {
255  R__b.WriteClassBuffer(TRandom3::Class(),this);
256  }
257 }
Random number generator class based on M.
Definition: TRandom3.h:27
virtual Double_t Rndm()
Machine independent random number generator.
Definition: TRandom3.cxx:100
virtual ~TRandom3()
Default destructor.
Definition: TRandom3.cxx:91
Random number generator class based on the maximally quidistributed combined Tausworthe generator by ...
Definition: TRandom2.h:27
virtual void SetSeed(ULong_t seed=0)
Set the random generator sequence if seed is 0 (default value) a TUUID is generated and used to fill ...
Definition: TRandom3.cxx:207
you should not use this method at all Int_t y
Definition: TRolke.cxx:630
This is the base class for the ROOT Random number generators.
Definition: TRandom.h:27
virtual void SetSeed(ULong_t seed=0)
Set the random generator seed.
Definition: TRandom.cxx:589
TRandom * gRandom
Definition: TRandom3.cxx:64
virtual void RndmArray(Int_t n, Float_t *array)
Return an array of n random numbers uniformly distributed in ]0,1].
Definition: TRandom3.cxx:144
virtual Double_t Rndm()
TausWorth generator from L&#39;Ecuyer, uses as seed 3x32bits integers Use a mask of 0xffffffffUL to make ...
Definition: TRandom2.cxx:56
TRandom3(UInt_t seed=4357)
Default constructor If seed is 0, the seed is automatically computed via a TUUID object.
Definition: TRandom3.cxx:81
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
Definition: TRolke.cxx:630