ROOT logo
// @(#)root/mathcore:$Id: TRandom3.cxx 37531 2010-12-10 20:38:06Z pcanal $
// Author: Peter Malzacher   31/08/99

//////////////////////////////////////////////////////////////////////////
//
// TRandom3
//
// Random number generator class based on
//   M. Matsumoto and T. Nishimura,
//   Mersenne Twistor: A 623-diminsionally equidistributed
//   uniform pseudorandom number generator
//   ACM Transactions on Modeling and Computer Simulation,
//   Vol. 8, No. 1, January 1998, pp 3--30.
//
// For more information see the Mersenne Twistor homepage
//   http://www.math.keio.ac.jp/~matumoto/emt.html
//
// Advantage: large period 2**19937-1
//            relativly fast
//              (only two times slower than TRandom, but
//               two times faster than TRandom2)
// Drawback:  a relative large internal state of 624 integers
//
//
// Aug.99 ROOT implementation based on CLHEP by P.Malzacher
//
// the original code contains the following copyright notice:
/* This library is free software; you can redistribute it and/or   */
/* modify it under the terms of the GNU Library General Public     */
/* License as published by the Free Software Foundation; either    */
/* version 2 of the License, or (at your option) any later         */
/* version.                                                        */
/* This library is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of  */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.            */
/* See the GNU Library General Public License for more details.    */
/* You should have received a copy of the GNU Library General      */
/* Public License along with this library; if not, write to the    */
/* Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA   */
/* 02111-1307  USA                                                 */
/* Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura.       */
/* When you use this, send an email to: matumoto@math.keio.ac.jp   */
/* with an appropriate reference to your work.                     */
/////////////////////////////////////////////////////////////////////

#include "TRandom3.h"
#include "TClass.h"
#include "TUUID.h"

TRandom *gRandom = new TRandom3();
#ifdef R__COMPLETE_MEM_TERMINATION
namespace {
   struct TRandomCleanup { 
      ~TRandomCleanup() { delete gRandom; gRandom = 0; }
   };
   static TRandomCleanup gCleanupRandom;
}
#endif

ClassImp(TRandom3)

//______________________________________________________________________________
TRandom3::TRandom3(UInt_t seed)
{
//*-*-*-*-*-*-*-*-*-*-*default constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
// If seed is 0, the seed is automatically computed via a TUUID object.
// In this case the seed is guaranteed to be unique in space and time.

   SetName("Random3");
   SetTitle("Random number generator: Mersenne Twistor");
   SetSeed(seed);
}

//______________________________________________________________________________
TRandom3::~TRandom3()
{
//*-*-*-*-*-*-*-*-*-*-*default destructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  ==================

}

//______________________________________________________________________________
Double_t TRandom3::Rndm(Int_t)
{
//  Machine independent random number generator.
//  Produces uniformly-distributed floating points in ]0,1]
//  Method: Mersenne Twistor

   UInt_t y;

   const Int_t  kM = 397;
   const Int_t  kN = 624;
   const UInt_t kTemperingMaskB =  0x9d2c5680;
   const UInt_t kTemperingMaskC =  0xefc60000;
   const UInt_t kUpperMask =       0x80000000;
   const UInt_t kLowerMask =       0x7fffffff;
   const UInt_t kMatrixA =         0x9908b0df;

   if (fCount624 >= kN) {
      register Int_t i;

      for (i=0; i < kN-kM; i++) {
         y = (fMt[i] & kUpperMask) | (fMt[i+1] & kLowerMask);
         fMt[i] = fMt[i+kM] ^ (y >> 1) ^ ((y & 0x1) ? kMatrixA : 0x0);
      }

      for (   ; i < kN-1    ; i++) {
         y = (fMt[i] & kUpperMask) | (fMt[i+1] & kLowerMask);
         fMt[i] = fMt[i+kM-kN] ^ (y >> 1) ^ ((y & 0x1) ? kMatrixA : 0x0);
      }

      y = (fMt[kN-1] & kUpperMask) | (fMt[0] & kLowerMask);
      fMt[kN-1] = fMt[kM-1] ^ (y >> 1) ^ ((y & 0x1) ? kMatrixA : 0x0);
      fCount624 = 0;
   }

   y = fMt[fCount624++];
   y ^=  (y >> 11);
   y ^= ((y << 7 ) & kTemperingMaskB );
   y ^= ((y << 15) & kTemperingMaskC );
   y ^=  (y >> 18);

   if (y) return ( (Double_t) y * 2.3283064365386963e-10); // * Power(2,-32)
   return Rndm();
}

//______________________________________________________________________________
void TRandom3::RndmArray(Int_t n, Float_t *array)
{
  // Return an array of n random numbers uniformly distributed in ]0,1]

  for(Int_t i=0; i<n; i++) array[i]=(Float_t)Rndm();
}

//______________________________________________________________________________
void TRandom3::RndmArray(Int_t n, Double_t *array)
{
  // Return an array of n random numbers uniformly distributed in ]0,1]

   Int_t k = 0;

   UInt_t y;

   const Int_t  kM = 397;
   const Int_t  kN = 624;
   const UInt_t kTemperingMaskB =  0x9d2c5680;
   const UInt_t kTemperingMaskC =  0xefc60000;
   const UInt_t kUpperMask =       0x80000000;
   const UInt_t kLowerMask =       0x7fffffff;
   const UInt_t kMatrixA =         0x9908b0df;

   while (k < n) {
      if (fCount624 >= kN) {
         register Int_t i;

         for (i=0; i < kN-kM; i++) {
            y = (fMt[i] & kUpperMask) | (fMt[i+1] & kLowerMask);
            fMt[i] = fMt[i+kM] ^ (y >> 1) ^ ((y & 0x1) ? kMatrixA : 0x0);
         }

         for (   ; i < kN-1    ; i++) {
            y = (fMt[i] & kUpperMask) | (fMt[i+1] & kLowerMask);
            fMt[i] = fMt[i+kM-kN] ^ (y >> 1) ^ ((y & 0x1) ? kMatrixA : 0x0);
         }

         y = (fMt[kN-1] & kUpperMask) | (fMt[0] & kLowerMask);
         fMt[kN-1] = fMt[kM-1] ^ (y >> 1) ^ ((y & 0x1) ? kMatrixA : 0x0);
         fCount624 = 0;
      }

      y = fMt[fCount624++];
      y ^=  (y >> 11);
      y ^= ((y << 7 ) & kTemperingMaskB );
      y ^= ((y << 15) & kTemperingMaskC );
      y ^=  (y >> 18);

      if (y) {
         array[k] = Double_t( y * 2.3283064365386963e-10); // * Power(2,-32)
         k++;
      }
   }
}

//______________________________________________________________________________
void TRandom3::SetSeed(UInt_t seed)
{
//  Set the random generator sequence
// if seed is 0 (default value) a TUUID is generated and used to fill
// the first 8 integers of the seed array.
// In this case the seed is guaranteed to be unique in space and time.
// Use upgraded seeding procedure to fix a known problem when seeding with values
// with many zero in the bit pattern (like 2**28).
// see http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html

   TRandom::SetSeed(seed);
   fCount624 = 624;
   Int_t i,j;
   if (seed > 0) {
      fMt[0] = fSeed;
      j = 1;
   } else {
      TUUID uid;
      UChar_t uuid[16];
      uid.GetUUID(uuid);
      for (i=0;i<8;i++) {
         fMt[i] = uuid[2*i]*256 +uuid[2*i+1];
         if (i > 1) fMt[i] += fMt[0];
      }
      j = 8;
   }
   // use multipliers from  Knuth's "Art of Computer Programming" Vol. 2, 3rd Ed. p.106
   for(i=j; i<624; i++) {
      fMt[i] = (1812433253 * ( fMt[i-1]  ^ ( fMt[i-1] >> 30)) + i);
   }
}

//______________________________________________________________________________
void TRandom3::Streamer(TBuffer &R__b)
{
   // Stream an object of class TRandom3.

   if (R__b.IsReading()) {
      UInt_t R__s, R__c;
      Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
      if (R__v > 1) {
         R__b.ReadClassBuffer(TRandom3::Class(), this, R__v, R__s, R__c);
         return;
      }
      //====process old versions before automatic schema evolution
      TRandom::Streamer(R__b);
      R__b.ReadStaticArray(fMt);
      R__b >> fCount624;
      R__b.CheckByteCount(R__s, R__c, TRandom3::IsA());
      //====end of old versions

   } else {
      R__b.WriteClassBuffer(TRandom3::Class(),this);
   }
}
 TRandom3.cxx:1
 TRandom3.cxx:2
 TRandom3.cxx:3
 TRandom3.cxx:4
 TRandom3.cxx:5
 TRandom3.cxx:6
 TRandom3.cxx:7
 TRandom3.cxx:8
 TRandom3.cxx:9
 TRandom3.cxx:10
 TRandom3.cxx:11
 TRandom3.cxx:12
 TRandom3.cxx:13
 TRandom3.cxx:14
 TRandom3.cxx:15
 TRandom3.cxx:16
 TRandom3.cxx:17
 TRandom3.cxx:18
 TRandom3.cxx:19
 TRandom3.cxx:20
 TRandom3.cxx:21
 TRandom3.cxx:22
 TRandom3.cxx:23
 TRandom3.cxx:24
 TRandom3.cxx:25
 TRandom3.cxx:26
 TRandom3.cxx:27
 TRandom3.cxx:28
 TRandom3.cxx:29
 TRandom3.cxx:30
 TRandom3.cxx:31
 TRandom3.cxx:32
 TRandom3.cxx:33
 TRandom3.cxx:34
 TRandom3.cxx:35
 TRandom3.cxx:36
 TRandom3.cxx:37
 TRandom3.cxx:38
 TRandom3.cxx:39
 TRandom3.cxx:40
 TRandom3.cxx:41
 TRandom3.cxx:42
 TRandom3.cxx:43
 TRandom3.cxx:44
 TRandom3.cxx:45
 TRandom3.cxx:46
 TRandom3.cxx:47
 TRandom3.cxx:48
 TRandom3.cxx:49
 TRandom3.cxx:50
 TRandom3.cxx:51
 TRandom3.cxx:52
 TRandom3.cxx:53
 TRandom3.cxx:54
 TRandom3.cxx:55
 TRandom3.cxx:56
 TRandom3.cxx:57
 TRandom3.cxx:58
 TRandom3.cxx:59
 TRandom3.cxx:60
 TRandom3.cxx:61
 TRandom3.cxx:62
 TRandom3.cxx:63
 TRandom3.cxx:64
 TRandom3.cxx:65
 TRandom3.cxx:66
 TRandom3.cxx:67
 TRandom3.cxx:68
 TRandom3.cxx:69
 TRandom3.cxx:70
 TRandom3.cxx:71
 TRandom3.cxx:72
 TRandom3.cxx:73
 TRandom3.cxx:74
 TRandom3.cxx:75
 TRandom3.cxx:76
 TRandom3.cxx:77
 TRandom3.cxx:78
 TRandom3.cxx:79
 TRandom3.cxx:80
 TRandom3.cxx:81
 TRandom3.cxx:82
 TRandom3.cxx:83
 TRandom3.cxx:84
 TRandom3.cxx:85
 TRandom3.cxx:86
 TRandom3.cxx:87
 TRandom3.cxx:88
 TRandom3.cxx:89
 TRandom3.cxx:90
 TRandom3.cxx:91
 TRandom3.cxx:92
 TRandom3.cxx:93
 TRandom3.cxx:94
 TRandom3.cxx:95
 TRandom3.cxx:96
 TRandom3.cxx:97
 TRandom3.cxx:98
 TRandom3.cxx:99
 TRandom3.cxx:100
 TRandom3.cxx:101
 TRandom3.cxx:102
 TRandom3.cxx:103
 TRandom3.cxx:104
 TRandom3.cxx:105
 TRandom3.cxx:106
 TRandom3.cxx:107
 TRandom3.cxx:108
 TRandom3.cxx:109
 TRandom3.cxx:110
 TRandom3.cxx:111
 TRandom3.cxx:112
 TRandom3.cxx:113
 TRandom3.cxx:114
 TRandom3.cxx:115
 TRandom3.cxx:116
 TRandom3.cxx:117
 TRandom3.cxx:118
 TRandom3.cxx:119
 TRandom3.cxx:120
 TRandom3.cxx:121
 TRandom3.cxx:122
 TRandom3.cxx:123
 TRandom3.cxx:124
 TRandom3.cxx:125
 TRandom3.cxx:126
 TRandom3.cxx:127
 TRandom3.cxx:128
 TRandom3.cxx:129
 TRandom3.cxx:130
 TRandom3.cxx:131
 TRandom3.cxx:132
 TRandom3.cxx:133
 TRandom3.cxx:134
 TRandom3.cxx:135
 TRandom3.cxx:136
 TRandom3.cxx:137
 TRandom3.cxx:138
 TRandom3.cxx:139
 TRandom3.cxx:140
 TRandom3.cxx:141
 TRandom3.cxx:142
 TRandom3.cxx:143
 TRandom3.cxx:144
 TRandom3.cxx:145
 TRandom3.cxx:146
 TRandom3.cxx:147
 TRandom3.cxx:148
 TRandom3.cxx:149
 TRandom3.cxx:150
 TRandom3.cxx:151
 TRandom3.cxx:152
 TRandom3.cxx:153
 TRandom3.cxx:154
 TRandom3.cxx:155
 TRandom3.cxx:156
 TRandom3.cxx:157
 TRandom3.cxx:158
 TRandom3.cxx:159
 TRandom3.cxx:160
 TRandom3.cxx:161
 TRandom3.cxx:162
 TRandom3.cxx:163
 TRandom3.cxx:164
 TRandom3.cxx:165
 TRandom3.cxx:166
 TRandom3.cxx:167
 TRandom3.cxx:168
 TRandom3.cxx:169
 TRandom3.cxx:170
 TRandom3.cxx:171
 TRandom3.cxx:172
 TRandom3.cxx:173
 TRandom3.cxx:174
 TRandom3.cxx:175
 TRandom3.cxx:176
 TRandom3.cxx:177
 TRandom3.cxx:178
 TRandom3.cxx:179
 TRandom3.cxx:180
 TRandom3.cxx:181
 TRandom3.cxx:182
 TRandom3.cxx:183
 TRandom3.cxx:184
 TRandom3.cxx:185
 TRandom3.cxx:186
 TRandom3.cxx:187
 TRandom3.cxx:188
 TRandom3.cxx:189
 TRandom3.cxx:190
 TRandom3.cxx:191
 TRandom3.cxx:192
 TRandom3.cxx:193
 TRandom3.cxx:194
 TRandom3.cxx:195
 TRandom3.cxx:196
 TRandom3.cxx:197
 TRandom3.cxx:198
 TRandom3.cxx:199
 TRandom3.cxx:200
 TRandom3.cxx:201
 TRandom3.cxx:202
 TRandom3.cxx:203
 TRandom3.cxx:204
 TRandom3.cxx:205
 TRandom3.cxx:206
 TRandom3.cxx:207
 TRandom3.cxx:208
 TRandom3.cxx:209
 TRandom3.cxx:210
 TRandom3.cxx:211
 TRandom3.cxx:212
 TRandom3.cxx:213
 TRandom3.cxx:214
 TRandom3.cxx:215
 TRandom3.cxx:216
 TRandom3.cxx:217
 TRandom3.cxx:218
 TRandom3.cxx:219
 TRandom3.cxx:220
 TRandom3.cxx:221
 TRandom3.cxx:222
 TRandom3.cxx:223
 TRandom3.cxx:224
 TRandom3.cxx:225
 TRandom3.cxx:226
 TRandom3.cxx:227
 TRandom3.cxx:228
 TRandom3.cxx:229
 TRandom3.cxx:230
 TRandom3.cxx:231
 TRandom3.cxx:232
 TRandom3.cxx:233
 TRandom3.cxx:234
 TRandom3.cxx:235
 TRandom3.cxx:236
 TRandom3.cxx:237
 TRandom3.cxx:238
 TRandom3.cxx:239