TRandom3.cxx

Go to the documentation of this file.
00001 // @(#)root/mathcore:$Id: TRandom3.cxx 37531 2010-12-10 20:38:06Z pcanal $
00002 // Author: Peter Malzacher   31/08/99
00003 
00004 //////////////////////////////////////////////////////////////////////////
00005 //
00006 // TRandom3
00007 //
00008 // Random number generator class based on
00009 //   M. Matsumoto and T. Nishimura,
00010 //   Mersenne Twistor: A 623-diminsionally equidistributed
00011 //   uniform pseudorandom number generator
00012 //   ACM Transactions on Modeling and Computer Simulation,
00013 //   Vol. 8, No. 1, January 1998, pp 3--30.
00014 //
00015 // For more information see the Mersenne Twistor homepage
00016 //   http://www.math.keio.ac.jp/~matumoto/emt.html
00017 //
00018 // Advantage: large period 2**19937-1
00019 //            relativly fast
00020 //              (only two times slower than TRandom, but
00021 //               two times faster than TRandom2)
00022 // Drawback:  a relative large internal state of 624 integers
00023 //
00024 //
00025 // Aug.99 ROOT implementation based on CLHEP by P.Malzacher
00026 //
00027 // the original code contains the following copyright notice:
00028 /* This library is free software; you can redistribute it and/or   */
00029 /* modify it under the terms of the GNU Library General Public     */
00030 /* License as published by the Free Software Foundation; either    */
00031 /* version 2 of the License, or (at your option) any later         */
00032 /* version.                                                        */
00033 /* This library is distributed in the hope that it will be useful, */
00034 /* but WITHOUT ANY WARRANTY; without even the implied warranty of  */
00035 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.            */
00036 /* See the GNU Library General Public License for more details.    */
00037 /* You should have received a copy of the GNU Library General      */
00038 /* Public License along with this library; if not, write to the    */
00039 /* Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA   */
00040 /* 02111-1307  USA                                                 */
00041 /* Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura.       */
00042 /* When you use this, send an email to: matumoto@math.keio.ac.jp   */
00043 /* with an appropriate reference to your work.                     */
00044 /////////////////////////////////////////////////////////////////////
00045 
00046 #include "TRandom3.h"
00047 #include "TClass.h"
00048 #include "TUUID.h"
00049 
00050 TRandom *gRandom = new TRandom3();
00051 #ifdef R__COMPLETE_MEM_TERMINATION
00052 namespace {
00053    struct TRandomCleanup { 
00054       ~TRandomCleanup() { delete gRandom; gRandom = 0; }
00055    };
00056    static TRandomCleanup gCleanupRandom;
00057 }
00058 #endif
00059 
00060 ClassImp(TRandom3)
00061 
00062 //______________________________________________________________________________
00063 TRandom3::TRandom3(UInt_t seed)
00064 {
00065 //*-*-*-*-*-*-*-*-*-*-*default constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00066 // If seed is 0, the seed is automatically computed via a TUUID object.
00067 // In this case the seed is guaranteed to be unique in space and time.
00068 
00069    SetName("Random3");
00070    SetTitle("Random number generator: Mersenne Twistor");
00071    SetSeed(seed);
00072 }
00073 
00074 //______________________________________________________________________________
00075 TRandom3::~TRandom3()
00076 {
00077 //*-*-*-*-*-*-*-*-*-*-*default destructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00078 //*-*                  ==================
00079 
00080 }
00081 
00082 //______________________________________________________________________________
00083 Double_t TRandom3::Rndm(Int_t)
00084 {
00085 //  Machine independent random number generator.
00086 //  Produces uniformly-distributed floating points in ]0,1]
00087 //  Method: Mersenne Twistor
00088 
00089    UInt_t y;
00090 
00091    const Int_t  kM = 397;
00092    const Int_t  kN = 624;
00093    const UInt_t kTemperingMaskB =  0x9d2c5680;
00094    const UInt_t kTemperingMaskC =  0xefc60000;
00095    const UInt_t kUpperMask =       0x80000000;
00096    const UInt_t kLowerMask =       0x7fffffff;
00097    const UInt_t kMatrixA =         0x9908b0df;
00098 
00099    if (fCount624 >= kN) {
00100       register Int_t i;
00101 
00102       for (i=0; i < kN-kM; i++) {
00103          y = (fMt[i] & kUpperMask) | (fMt[i+1] & kLowerMask);
00104          fMt[i] = fMt[i+kM] ^ (y >> 1) ^ ((y & 0x1) ? kMatrixA : 0x0);
00105       }
00106 
00107       for (   ; i < kN-1    ; i++) {
00108          y = (fMt[i] & kUpperMask) | (fMt[i+1] & kLowerMask);
00109          fMt[i] = fMt[i+kM-kN] ^ (y >> 1) ^ ((y & 0x1) ? kMatrixA : 0x0);
00110       }
00111 
00112       y = (fMt[kN-1] & kUpperMask) | (fMt[0] & kLowerMask);
00113       fMt[kN-1] = fMt[kM-1] ^ (y >> 1) ^ ((y & 0x1) ? kMatrixA : 0x0);
00114       fCount624 = 0;
00115    }
00116 
00117    y = fMt[fCount624++];
00118    y ^=  (y >> 11);
00119    y ^= ((y << 7 ) & kTemperingMaskB );
00120    y ^= ((y << 15) & kTemperingMaskC );
00121    y ^=  (y >> 18);
00122 
00123    if (y) return ( (Double_t) y * 2.3283064365386963e-10); // * Power(2,-32)
00124    return Rndm();
00125 }
00126 
00127 //______________________________________________________________________________
00128 void TRandom3::RndmArray(Int_t n, Float_t *array)
00129 {
00130   // Return an array of n random numbers uniformly distributed in ]0,1]
00131 
00132   for(Int_t i=0; i<n; i++) array[i]=(Float_t)Rndm();
00133 }
00134 
00135 //______________________________________________________________________________
00136 void TRandom3::RndmArray(Int_t n, Double_t *array)
00137 {
00138   // Return an array of n random numbers uniformly distributed in ]0,1]
00139 
00140    Int_t k = 0;
00141 
00142    UInt_t y;
00143 
00144    const Int_t  kM = 397;
00145    const Int_t  kN = 624;
00146    const UInt_t kTemperingMaskB =  0x9d2c5680;
00147    const UInt_t kTemperingMaskC =  0xefc60000;
00148    const UInt_t kUpperMask =       0x80000000;
00149    const UInt_t kLowerMask =       0x7fffffff;
00150    const UInt_t kMatrixA =         0x9908b0df;
00151 
00152    while (k < n) {
00153       if (fCount624 >= kN) {
00154          register Int_t i;
00155 
00156          for (i=0; i < kN-kM; i++) {
00157             y = (fMt[i] & kUpperMask) | (fMt[i+1] & kLowerMask);
00158             fMt[i] = fMt[i+kM] ^ (y >> 1) ^ ((y & 0x1) ? kMatrixA : 0x0);
00159          }
00160 
00161          for (   ; i < kN-1    ; i++) {
00162             y = (fMt[i] & kUpperMask) | (fMt[i+1] & kLowerMask);
00163             fMt[i] = fMt[i+kM-kN] ^ (y >> 1) ^ ((y & 0x1) ? kMatrixA : 0x0);
00164          }
00165 
00166          y = (fMt[kN-1] & kUpperMask) | (fMt[0] & kLowerMask);
00167          fMt[kN-1] = fMt[kM-1] ^ (y >> 1) ^ ((y & 0x1) ? kMatrixA : 0x0);
00168          fCount624 = 0;
00169       }
00170 
00171       y = fMt[fCount624++];
00172       y ^=  (y >> 11);
00173       y ^= ((y << 7 ) & kTemperingMaskB );
00174       y ^= ((y << 15) & kTemperingMaskC );
00175       y ^=  (y >> 18);
00176 
00177       if (y) {
00178          array[k] = Double_t( y * 2.3283064365386963e-10); // * Power(2,-32)
00179          k++;
00180       }
00181    }
00182 }
00183 
00184 //______________________________________________________________________________
00185 void TRandom3::SetSeed(UInt_t seed)
00186 {
00187 //  Set the random generator sequence
00188 // if seed is 0 (default value) a TUUID is generated and used to fill
00189 // the first 8 integers of the seed array.
00190 // In this case the seed is guaranteed to be unique in space and time.
00191 // Use upgraded seeding procedure to fix a known problem when seeding with values
00192 // with many zero in the bit pattern (like 2**28).
00193 // see http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html
00194 
00195    TRandom::SetSeed(seed);
00196    fCount624 = 624;
00197    Int_t i,j;
00198    if (seed > 0) {
00199       fMt[0] = fSeed;
00200       j = 1;
00201    } else {
00202       TUUID uid;
00203       UChar_t uuid[16];
00204       uid.GetUUID(uuid);
00205       for (i=0;i<8;i++) {
00206          fMt[i] = uuid[2*i]*256 +uuid[2*i+1];
00207          if (i > 1) fMt[i] += fMt[0];
00208       }
00209       j = 8;
00210    }
00211    // use multipliers from  Knuth's "Art of Computer Programming" Vol. 2, 3rd Ed. p.106
00212    for(i=j; i<624; i++) {
00213       fMt[i] = (1812433253 * ( fMt[i-1]  ^ ( fMt[i-1] >> 30)) + i);
00214    }
00215 }
00216 
00217 //______________________________________________________________________________
00218 void TRandom3::Streamer(TBuffer &R__b)
00219 {
00220    // Stream an object of class TRandom3.
00221 
00222    if (R__b.IsReading()) {
00223       UInt_t R__s, R__c;
00224       Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
00225       if (R__v > 1) {
00226          R__b.ReadClassBuffer(TRandom3::Class(), this, R__v, R__s, R__c);
00227          return;
00228       }
00229       //====process old versions before automatic schema evolution
00230       TRandom::Streamer(R__b);
00231       R__b.ReadStaticArray(fMt);
00232       R__b >> fCount624;
00233       R__b.CheckByteCount(R__s, R__c, TRandom3::IsA());
00234       //====end of old versions
00235 
00236    } else {
00237       R__b.WriteClassBuffer(TRandom3::Class(),this);
00238    }
00239 }

Generated on Tue Jul 5 14:34:28 2011 for ROOT_528-00b_version by  doxygen 1.5.1