Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/clhep/src/MTwistEngine.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  1 // -*- C++ -*-
  2 //
  3 // -----------------------------------------------------------------------
  4 //                             HEP Random
  5 //                        --- MTwistEngine ---
  6 //                      class implementation file
  7 // -----------------------------------------------------------------------
  8 // A "fast, compact, huge-period generator" based on M. Matsumoto and 
  9 // T. Nishimura, "Mersenne Twister: A 623-dimensionally equidistributed 
 10 // uniform pseudorandom number generator", to appear in ACM Trans. on
 11 // Modeling and Computer Simulation.  It is a twisted GFSR generator
 12 // with a Mersenne-prime period of 2^19937-1, uniform on open interval (0,1)
 13 // =======================================================================
 14 // Ken Smith      - Started initial draft:                    14th Jul 1998
 15 //                - Optimized to get std::pow() out of flat() method
 16 //                - Added conversion operators:                6th Aug 1998
 17 // J. Marraffino  - Added some explicit casts to deal with
 18 //                  machines where sizeof(int) != sizeof(long)  22 Aug 1998
 19 // M. Fischler    - Modified constructors such that no two
 20 //        seeds will match sequences, no single/double
 21 //        seeds will match, explicit seeds give 
 22 //        determined results, and default will not 
 23 //        match any of the above or other defaults.
 24 //                - Modified use of the various exponents of 2
 25 //                  to avoid per-instance space overhead and
 26 //                  correct the rounding procedure              16 Sep 1998
 27 // J. Marraffino  - Remove dependence on hepString class        13 May 1999
 28 // M. Fischler    - In restore, checkFile for file not found    03 Dec 2004
 29 // M. Fischler    - Methods for distrib. instacne save/restore  12/8/04    
 30 // M. Fischler    - split get() into tag validation and 
 31 //                  getState() for anonymous restores           12/27/04    
 32 // M. Fischler    - put/get for vectors of ulongs   3/14/05
 33 // M. Fischler    - State-saving using only ints, for portability 4/12/05
 34 // M. Fischler    - Improved seeding in setSeed  (Savanah bug #17479) 11/15/06
 35 //      - (Possible optimization - now that the seeding is improved,
 36 //        is it still necessary for ctor to "warm up" by discarding
 37 //        2000 iterations?)
 38 //        
 39 // =======================================================================
 40 
 41 #include "CLHEP/Random/Random.h"
 42 #include "CLHEP/Random/MTwistEngine.h"
 43 #include "CLHEP/Random/engineIDulong.h"
 44 #include "CLHEP/Utility/atomic_int.h"
 45 
 46 #include <atomic>
 47 #include <cmath>
 48 #include <iostream>
 49 #include <string.h>        // for strcmp
 50 #include <vector>
 51 
 52 namespace CLHEP {
 53 
 54 namespace {
 55   // Number of instances with automatic seed selection
 56   CLHEP_ATOMIC_INT_TYPE numberOfEngines(0);
 57 
 58   // Maximum index into the seed table
 59   const int maxIndex = 215;
 60 }
 61 
 62 static const int MarkerLen = 64; // Enough room to hold a begin or end marker. 
 63 
 64 std::string MTwistEngine::name() const {return "MTwistEngine";}
 65 
 66 MTwistEngine::MTwistEngine() 
 67 : HepRandomEngine()
 68 {
 69   int numEngines = numberOfEngines++;
 70   int cycle = std::abs(int(numEngines/maxIndex));
 71   int curIndex = std::abs(int(numEngines%maxIndex));
 72   long mask = ((cycle & 0x007fffff) << 8);
 73   long seedlist[2];
 74   HepRandom::getTheTableSeeds( seedlist, curIndex );
 75   seedlist[0] = (seedlist[0])^mask;
 76   seedlist[1] = 0;
 77   setSeeds( seedlist, numEngines );
 78   count624=0;
 79 
 80   for( int i=0; i < 2000; ++i ) flat();      // Warm up just a bit
 81 }
 82 
 83 MTwistEngine::MTwistEngine(long seed)  
 84 : HepRandomEngine()
 85 {
 86   long seedlist[2]={seed,17587};
 87   setSeeds( seedlist, 0 );
 88   count624=0;
 89   for( int i=0; i < 2000; ++i ) flat();      // Warm up just a bit
 90 }
 91 
 92 MTwistEngine::MTwistEngine(int rowIndex, int colIndex) 
 93 : HepRandomEngine()
 94 {
 95   int cycle = std::abs(int(rowIndex/maxIndex));
 96   int row = std::abs(int(rowIndex%maxIndex));
 97   int col = std::abs(int(colIndex%2));
 98   long mask = (( cycle & 0x000007ff ) << 20 );
 99   long seedlist[2];
100   HepRandom::getTheTableSeeds( seedlist, row );
101   seedlist[0] = (seedlist[col])^mask;
102   seedlist[1] = 690691;
103   setSeeds(seedlist, 4444772);
104   count624=0;
105   for( int i=0; i < 2000; ++i ) flat();      // Warm up just a bit
106 }
107 
108 MTwistEngine::MTwistEngine( std::istream& is )  
109 : HepRandomEngine()
110 {
111   is >> *this;
112 }
113 
114 MTwistEngine::~MTwistEngine() {}
115 
116 double MTwistEngine::flat() {
117   unsigned int y;
118 
119    if( count624 >= N ) {
120     int i;
121 
122     for( i=0; i < NminusM; ++i ) {
123       y = (mt[i] & 0x80000000) | (mt[i+1] & 0x7fffffff);
124       mt[i] = mt[i+M]       ^ (y >> 1) ^ ((y & 0x1) ? 0x9908b0df : 0x0 );
125     }
126 
127     for(    ; i < N-1    ; ++i ) {
128       y = (mt[i] & 0x80000000) | (mt[i+1] & 0x7fffffff);
129       mt[i] = mt[i-NminusM] ^ (y >> 1) ^ ((y & 0x1) ? 0x9908b0df : 0x0 );
130     }
131 
132     y = (mt[i] & 0x80000000) | (mt[0] & 0x7fffffff);
133     mt[i] = mt[M-1] ^ (y >> 1) ^ ((y & 0x1) ? 0x9908b0df : 0x0 );
134 
135     count624 = 0;
136   }
137 
138   y = mt[count624];
139   y ^= ( y >> 11);
140   y ^= ((y << 7 ) & 0x9d2c5680);
141   y ^= ((y << 15) & 0xefc60000);
142   y ^= ( y >> 18);
143 
144   return                      y * twoToMinus_32()  +    // Scale to range 
145          (mt[count624++] >> 11) * twoToMinus_53()  +    // fill remaining bits
146                       nearlyTwoToMinus_54();      // make sure non-zero
147 }
148 
149 void MTwistEngine::flatArray( const int size, double *vect ) {
150   for( int i=0; i < size; ++i) vect[i] = flat();
151 }
152 
153 void MTwistEngine::setSeed(long seed, int k) {
154 
155   // MF 11/15/06 - Change seeding algorithm to a newer one recommended 
156   //               by Matsumoto: The original algorithm was 
157   //       mt[i] = (69069 * mt[i-1]) & 0xffffffff and this gives
158   //       problems when the seed bit pattern has lots of zeros
159   //       (for example, 0x08000000).  Savanah bug #17479.
160 
161   theSeed = seed ? seed : 4357;
162   int mti;
163   const int N1=624;
164   mt[0] = (unsigned int) (theSeed&0xffffffffUL);
165   for (mti=1; mti<N1; mti++) {
166     mt[mti] = (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti); 
167         /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
168         /* In the previous versions, MSBs of the seed affect   */
169         /* only MSBs of the array mt[].                        */
170         /* 2002/01/09 modified by Makoto Matsumoto             */
171     mt[mti] &= 0xffffffffUL;
172         /* for >32 bit machines */
173   }
174   for( int i=1; i < 624; ++i ) {
175     mt[i] ^= k;     // MF 9/16/98: distinguish starting points
176   }
177   // MF 11/15/06 This distinction of starting points based on values of k
178   //             is kept even though the seeding algorithm itself is improved.
179 }
180 
181 void MTwistEngine::setSeeds(const long *seeds, int k) {
182   setSeed( (*seeds ? *seeds : 43571346), k );
183   int i;
184   for( i=1; i < 624; ++i ) {
185     mt[i] = ( seeds[1] + mt[i] ) & 0xffffffff; // MF 9/16/98 
186   }
187   theSeeds = seeds;
188 }
189 
190 void MTwistEngine::saveStatus( const char filename[] ) const
191 {
192    std::ofstream outFile( filename, std::ios::out ) ;
193    if (!outFile.bad()) {
194      outFile << theSeed << std::endl;
195      for (int i=0; i<624; ++i) outFile <<std::setprecision(20) << mt[i] << " ";
196      outFile << std::endl;
197      outFile << count624 << std::endl;
198    }
199 }
200 
201 void MTwistEngine::restoreStatus( const char filename[] )
202 {
203    std::ifstream inFile( filename, std::ios::in);
204    if (!checkFile ( inFile, filename, engineName(), "restoreStatus" )) {
205      std::cerr << "  -- Engine state remains unchanged\n";
206      return;
207    }
208 
209    if (!inFile.bad() && !inFile.eof()) {
210      inFile >> theSeed;
211      for (int i=0; i<624; ++i) inFile >> mt[i];
212      inFile >> count624;
213    }
214 }
215 
216 void MTwistEngine::showStatus() const
217 {
218    std::cout << std::endl;
219    std::cout << "--------- MTwist engine status ---------" << std::endl;
220    std::cout << std::setprecision(20);
221    std::cout << " Initial seed      = " << theSeed << std::endl;
222    std::cout << " Current index     = " << count624 << std::endl;
223    std::cout << " Array status mt[] = " << std::endl;
224    // 2014/06/06  L Garren
225    // the final line has 4 elements, not 5
226    for (int i=0; i<620; i+=5) {
227      std::cout << mt[i]   << " " << mt[i+1] << " " << mt[i+2] << " " 
228          << mt[i+3] << " " << mt[i+4] << "\n";
229    }
230    std::cout << mt[620]   << " " << mt[621] << " " << mt[622] << " " 
231        << mt[623]  << std::endl;
232    std::cout << "----------------------------------------" << std::endl;
233 }
234 
235 MTwistEngine::operator double() {
236   return flat();
237 }
238 
239 MTwistEngine::operator float() {
240   unsigned int y;
241 
242   if( count624 >= N ) {
243     int i;
244 
245     for( i=0; i < NminusM; ++i ) {
246       y = (mt[i] & 0x80000000) | (mt[i+1] & 0x7fffffff);
247       mt[i] = mt[i+M]       ^ (y >> 1) ^ ((y & 0x1) ? 0x9908b0df : 0x0 );
248     }
249 
250     for(    ; i < N-1    ; ++i ) {
251       y = (mt[i] & 0x80000000) | (mt[i+1] & 0x7fffffff);
252       mt[i] = mt[i-NminusM] ^ (y >> 1) ^ ((y & 0x1) ? 0x9908b0df : 0x0 );
253     }
254 
255     y = (mt[i] & 0x80000000) | (mt[0] & 0x7fffffff);
256     mt[i] = mt[M-1] ^ (y >> 1) ^ ((y & 0x1) ? 0x9908b0df : 0x0 );
257 
258     count624 = 0;
259   }
260 
261   y = mt[count624++];
262   y ^= ( y >> 11);
263   y ^= ((y << 7 ) & 0x9d2c5680);
264   y ^= ((y << 15) & 0xefc60000);
265   y ^= ( y >> 18);
266 
267   return (float)(y * twoToMinus_32());
268 }
269 
270 MTwistEngine::operator unsigned int() {
271   unsigned int y;
272 
273   if( count624 >= N ) {
274     int i;
275 
276     for( i=0; i < NminusM; ++i ) {
277       y = (mt[i] & 0x80000000) | (mt[i+1] & 0x7fffffff);
278       mt[i] = mt[i+M]       ^ (y >> 1) ^ ((y & 0x1) ? 0x9908b0df : 0x0 );
279     }
280 
281     for(    ; i < N-1    ; ++i ) {
282       y = (mt[i] & 0x80000000) | (mt[i+1] & 0x7fffffff);
283       mt[i] = mt[i-NminusM] ^ (y >> 1) ^ ((y & 0x1) ? 0x9908b0df : 0x0 );
284     }
285 
286     y = (mt[i] & 0x80000000) | (mt[0] & 0x7fffffff);
287     mt[i] = mt[M-1] ^ (y >> 1) ^ ((y & 0x1) ? 0x9908b0df : 0x0 );
288 
289     count624 = 0;
290   }
291 
292   y = mt[count624++];
293   y ^= ( y >> 11);
294   y ^= ((y << 7 ) & 0x9d2c5680);
295   y ^= ((y << 15) & 0xefc60000);
296   y ^= ( y >> 18);
297 
298   return y;
299 }
300 
301 std::ostream & MTwistEngine::put ( std::ostream& os ) const
302 {
303    char beginMarker[] = "MTwistEngine-begin";
304    char endMarker[]   = "MTwistEngine-end";
305 
306    long pr = os.precision(20);
307    os << " " << beginMarker << " ";
308    os << theSeed << " ";
309    for (int i=0; i<624; ++i) {
310      os << mt[i] << "\n";
311    }
312    os << count624 << " ";
313    os << endMarker << "\n";
314    os.precision(pr);
315    return os;
316 }
317 
318 std::vector<unsigned long> MTwistEngine::put () const {
319   std::vector<unsigned long> v;
320   v.push_back (engineIDulong<MTwistEngine>());
321   for (int i=0; i<624; ++i) {
322      v.push_back(static_cast<unsigned long>(mt[i]));
323   }
324   v.push_back(count624); 
325   return v;
326 }
327 
328 std::istream &  MTwistEngine::get ( std::istream& is )
329 {
330   char beginMarker [MarkerLen];
331   is >> std::ws;
332   is.width(MarkerLen);  // causes the next read to the char* to be <=
333       // that many bytes, INCLUDING A TERMINATION \0 
334       // (Stroustrup, section 21.3.2)
335   is >> beginMarker;
336   if (strcmp(beginMarker,"MTwistEngine-begin")) {
337      is.clear(std::ios::badbit | is.rdstate());
338      std::cerr << "\nInput stream mispositioned or"
339          << "\nMTwistEngine state description missing or"
340          << "\nwrong engine type found." << std::endl;
341      return is;
342    }
343   return getState(is);
344 }
345 
346 std::string MTwistEngine::beginTag ( )  { 
347   return "MTwistEngine-begin"; 
348 }
349 
350 std::istream &  MTwistEngine::getState ( std::istream& is )
351 {
352   char endMarker   [MarkerLen];
353   is >> theSeed;
354   for (int i=0; i<624; ++i)  is >> mt[i];
355   is >> count624;
356   is >> std::ws;
357   is.width(MarkerLen);  
358   is >> endMarker;
359   if (strcmp(endMarker,"MTwistEngine-end")) {
360      is.clear(std::ios::badbit | is.rdstate());
361      std::cerr << "\nMTwistEngine state description incomplete."
362          << "\nInput stream is probably mispositioned now." << std::endl;
363      return is;
364    }
365    return is;
366 }
367 
368 bool MTwistEngine::get (const std::vector<unsigned long> & v) {
369   if ((v[0] & 0xffffffffUL) != engineIDulong<MTwistEngine>()) {
370     std::cerr << 
371       "\nMTwistEngine get:state vector has wrong ID word - state unchanged\n";
372     return false;
373   }
374   return getState(v);
375 }
376 
377 bool MTwistEngine::getState (const std::vector<unsigned long> & v) {
378   if (v.size() != VECTOR_STATE_SIZE ) {
379     std::cerr << 
380       "\nMTwistEngine get:state vector has wrong length - state unchanged\n";
381     return false;
382   }
383   for (int i=0; i<624; ++i) {
384      mt[i]=(unsigned int)v[i+1];
385   }
386   count624 = (int)v[625];
387   return true;
388 }
389 
390 }  // namespace CLHEP
391