Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/clhep/src/DualRand.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 ]

Diff markup

Differences between /externals/clhep/src/DualRand.cc (Version 11.3.0) and /externals/clhep/src/DualRand.cc (Version 5.2)


  1 // -*- C++ -*-                                      1 
  2 //                                                
  3 // -------------------------------------------    
  4 //                           Hep Random           
  5 //                        --- DualRand ---        
  6 //                   class implementation file    
  7 // -------------------------------------------    
  8 //  Exclusive or of a feedback shift register     
  9 //  random number generator.  The feedback shi    
 10 //  127 and 97.  The integer congruence genera    
 11 //  multiplier for each stream.  The multiplie    
 12 //  full period and maximum "potency" for modu    
 13 //  the combined random number generator is 2^    
 14 //  sequences are different for each stream (n    
 15 //  different place).                             
 16 //                                                
 17 //  In the original generator used on ACPMAPS:    
 18 //  The feedback shift register generates 24 b    
 19 //  the high order 24 bits of the integer cong    
 20 //  used.                                         
 21 //                                                
 22 //  Instead, to conform with more modern engin    
 23 //  32 bits at a time and use the full 32 bits    
 24 //  generator.                                    
 25 //                                                
 26 //  References:                                   
 27 //  Knuth                                         
 28 //  Tausworthe                                    
 29 //  Golomb                                        
 30 //============================================    
 31 // Ken Smith      - Removed pow() from flat()     
 32 //                - Added conversion operators    
 33 // J. Marraffino  - Added some explicit casts     
 34 //                  machines where sizeof(int)    
 35 // M. Fischler    - Modified constructors taki    
 36 //        depend on numEngines (same seeds sho    
 37 //        produce same sequences).  Default st    
 38 //        depends on numEngines.      14 Sep 1    
 39 //                - Modified use of the variou    
 40 //                  to avoid per-instance spac    
 41 //                  correct the rounding proce    
 42 // J. Marraffino  - Remove dependence on hepSt    
 43 // M. Fischler    - Put endl at end of a save     
 44 // M. Fischler    - In restore, checkFile for     
 45 // M. Fischler    - methods for distrib. insta    
 46 // M. Fischler    - split get() into tag valid    
 47 //                  getState() for anonymous r    
 48 // Mark Fischler  - methods for vector save/re    
 49 // M. Fischler    - State-saving using only in    
 50 //                                                
 51 //============================================    
 52                                                   
 53 #include "CLHEP/Random/DualRand.h"                
 54 #include "CLHEP/Random/engineIDulong.h"           
 55 #include "CLHEP/Utility/atomic_int.h"             
 56                                                   
 57 #include <atomic>                                 
 58 #include <ostream>                                
 59 #include <string.h> // for strcmp                 
 60 #include <vector>                                 
 61 #include <iostream>                               
 62                                                   
 63 namespace CLHEP {                                 
 64                                                   
 65 namespace {                                       
 66   // Number of instances with automatic seed s    
 67   CLHEP_ATOMIC_INT_TYPE numberOfEngines(0);       
 68 }                                                 
 69                                                   
 70 static const int MarkerLen = 64; // Enough roo    
 71                                                   
 72 std::string DualRand::name() const {return "Du    
 73                                                   
 74 // The following constructors (excluding the i    
 75 // the bits of the tausworthe and the starting    
 76 // congruence based on the seed.  In addition,    
 77 // for the integer congruence based on the str    
 78 // absolutely independent streams.                
 79                                                   
 80 DualRand::DualRand()                              
 81 : HepRandomEngine(),                              
 82   numEngines(numberOfEngines++),                  
 83   tausworthe (1234567 + numEngines + 175321),     
 84   integerCong(69607 * tausworthe + 54329, numE    
 85 {                                                 
 86   theSeed = 1234567;                              
 87 }                                                 
 88                                                   
 89 DualRand::DualRand(long seed)                     
 90 : HepRandomEngine(),                              
 91   numEngines(0),                                  
 92   tausworthe ((unsigned int)seed + 175321),       
 93   integerCong(69607 * tausworthe + 54329, 8043    
 94 {                                                 
 95   theSeed = seed;                                 
 96 }                                                 
 97                                                   
 98 DualRand::DualRand(std::istream & is)             
 99 : HepRandomEngine(),                              
100   numEngines(0)                                   
101 {                                                 
102   is >> *this;                                    
103 }                                                 
104                                                   
105 DualRand::DualRand(int rowIndex, int colIndex)    
106 : HepRandomEngine(),                              
107   numEngines(0),                                  
108   tausworthe (rowIndex + 1000 * colIndex + 853    
109   integerCong(69607 * tausworthe + 54329, 1123    
110 {                                                 
111   theSeed = rowIndex;                             
112 }                                                 
113                                                   
114 DualRand::~DualRand() { }                         
115                                                   
116 double DualRand::flat() {                         
117   unsigned int ic ( integerCong );                
118   unsigned int t  ( tausworthe  );                
119   return ( (t  ^ ic) * twoToMinus_32() +          
120            (t >> 11) * twoToMinus_53() +          
121            nearlyTwoToMinus_54()          // m    
122          );                                       
123 }                                                 
124                                                   
125 void DualRand::flatArray(const int size, doubl    
126   for (int i = 0; i < size; ++i) {                
127     vect[i] = flat();                             
128   }                                               
129 }                                                 
130                                                   
131 void DualRand::setSeed(long seed, int) {          
132   theSeed = seed;                                 
133   tausworthe  = Tausworthe((unsigned int)seed     
134   integerCong = IntegerCong(69607 * tausworthe    
135 }                                                 
136                                                   
137 void DualRand::setSeeds(const long * seeds, in    
138   setSeed(seeds ? *seeds : 1234567, 0);           
139   theSeeds = seeds;                               
140 }                                                 
141                                                   
142 void DualRand::saveStatus(const char filename[    
143   std::ofstream outFile(filename, std::ios::ou    
144   if (!outFile.bad()) {                           
145     outFile << "Uvec\n";                          
146     std::vector<unsigned long> v = put();         
147     for (unsigned int i=0; i<v.size(); ++i) {     
148       outFile << v[i] << "\n";                    
149     }                                             
150   }                                               
151 }                                                 
152                                                   
153 void DualRand::restoreStatus(const char filena    
154   std::ifstream inFile(filename, std::ios::in)    
155   if (!checkFile ( inFile, filename, engineNam    
156     std::cerr << "  -- Engine state remains un    
157     return;                                       
158   }                                               
159   if ( possibleKeywordInput ( inFile, "Uvec",     
160     std::vector<unsigned long> v;                 
161     unsigned long xin;                            
162     for (unsigned int ivec=0; ivec < VECTOR_ST    
163       inFile >> xin;                              
164       if (!inFile) {                              
165         inFile.clear(std::ios::badbit | inFile    
166         std::cerr << "\nDualRand state (vector    
167          << "\nrestoreStatus has failed."         
168          << "\nInput stream is probably mispos    
169         return;                                   
170       }                                           
171       v.push_back(xin);                           
172     }                                             
173     getState(v);                                  
174     return;                                       
175   }                                               
176                                                   
177   if (!inFile.bad()) {                            
178 //     inFile >> theSeed;  removed -- encompas    
179     tausworthe.get(inFile);                       
180     integerCong.get(inFile);                      
181   }                                               
182 }                                                 
183                                                   
184 void DualRand::showStatus() const {               
185   long pr=std::cout.precision(20);                
186   std::cout << std::endl;                         
187   std::cout <<         "-------- DualRand engi    
188       << std::endl;                               
189   std::cout << "Initial seed          = " << t    
190   std::cout << "Tausworthe generator  = " << s    
191   tausworthe.put(std::cout);                      
192   std::cout << "\nIntegerCong generator = " <<    
193   integerCong.put(std::cout);                     
194   std::cout << std::endl << "-----------------    
195       << std::endl;                               
196   std::cout.precision(pr);                        
197 }                                                 
198                                                   
199 DualRand::operator double() {                     
200    return flat();                                 
201 }                                                 
202                                                   
203 DualRand::operator float() {                      
204   return (float) ( (integerCong ^ tausworthe)     
205                 + nearlyTwoToMinus_54()    );     
206           // add this so that zero never happe    
207 }                                                 
208                                                   
209 DualRand::operator unsigned int() {               
210   return (integerCong ^ tausworthe) & 0xffffff    
211 }                                                 
212                                                   
213 std::ostream & DualRand::put(std::ostream & os    
214   char beginMarker[] = "DualRand-begin";          
215   os << beginMarker << "\nUvec\n";                
216   std::vector<unsigned long> v = put();           
217   for (unsigned int i=0; i<v.size(); ++i) {       
218      os <<  v[i] <<  "\n";                        
219   }                                               
220   return os;                                      
221 }                                                 
222                                                   
223 std::vector<unsigned long> DualRand::put () co    
224   std::vector<unsigned long> v;                   
225   v.push_back (engineIDulong<DualRand>());        
226   tausworthe.put(v);                              
227   integerCong.put(v);                             
228   return v;                                       
229 }                                                 
230                                                   
231 std::istream & DualRand::get(std::istream & is    
232   char beginMarker [MarkerLen];                   
233   is >> std::ws;                                  
234   is.width(MarkerLen);  // causes the next rea    
235       // that many bytes, INCLUDING A TERMINAT    
236       // (Stroustrup, section 21.3.2)             
237   is >> beginMarker;                              
238   if (strcmp(beginMarker,"DualRand-begin")) {     
239     is.clear(std::ios::badbit | is.rdstate());    
240     std::cerr << "\nInput mispositioned or"       
241         << "\nDualRand state description missi    
242         << "\nwrong engine type found." << std    
243     return is;                                    
244   }                                               
245   return getState(is);                            
246 }                                                 
247                                                   
248 std::string DualRand::beginTag ( )  {             
249   return "DualRand-begin";                        
250 }                                                 
251                                                   
252 std::istream & DualRand::getState ( std::istre    
253   if ( possibleKeywordInput ( is, "Uvec", theS    
254     std::vector<unsigned long> v;                 
255     unsigned long uu;                             
256     for (unsigned int ivec=0; ivec < VECTOR_ST    
257       is >> uu;                                   
258       if (!is) {                                  
259         is.clear(std::ios::badbit | is.rdstate    
260         std::cerr << "\nDualRand state (vector    
261     << "\ngetState() has failed."                 
262          << "\nInput stream is probably mispos    
263         return is;                                
264       }                                           
265       v.push_back(uu);                            
266     }                                             
267     getState(v);                                  
268     return (is);                                  
269   }                                               
270                                                   
271 //  is >> theSeed;  Removed, encompassed by po    
272                                                   
273   char endMarker   [MarkerLen];                   
274   tausworthe.get(is);                             
275   integerCong.get(is);                            
276   is >> std::ws;                                  
277   is.width(MarkerLen);                            
278    is >> endMarker;                               
279   if (strcmp(endMarker,"DualRand-end")) {         
280     is.clear(std::ios::badbit | is.rdstate());    
281     std::cerr << "DualRand state description i    
282         << "\nInput stream is probably misposi    
283     return is;                                    
284   }                                               
285   return is;                                      
286 }                                                 
287                                                   
288 bool DualRand::get(const std::vector<unsigned     
289   if ((v[0] & 0xffffffffUL) != engineIDulong<D    
290     std::cerr <<                                  
291       "\nDualRand get:state vector has wrong I    
292     return false;                                 
293   }                                               
294   if (v.size() != VECTOR_STATE_SIZE) {            
295     std::cerr << "\nDualRand get:state vector     
296     << v.size() << " - state unchanged\n";        
297     return false;                                 
298   }                                               
299   return getState(v);                             
300 }                                                 
301                                                   
302 bool DualRand::getState (const std::vector<uns    
303   std::vector<unsigned long>::const_iterator i    
304   if (!tausworthe.get(iv)) return false;          
305   if (!integerCong.get(iv)) return false;         
306   if (iv != v.end()) {                            
307     std::cerr <<                                  
308       "\nDualRand get:state vector has wrong s    
309   << "\n         Apparently " << iv-v.begin()     
310     return false;                                 
311   }                                               
312   return true;                                    
313 }                                                 
314                                                   
315 DualRand::Tausworthe::Tausworthe() {              
316   words[0] = 1234567;                             
317   for (wordIndex = 1; wordIndex < 4; ++wordInd    
318     words[wordIndex] = 69607 * words[wordIndex    
319   }                                               
320 }                                                 
321                                                   
322 DualRand::Tausworthe::Tausworthe(unsigned int     
323   words[0] = seed;                                
324   for (wordIndex = 1; wordIndex < 4; ++wordInd    
325     words[wordIndex] = 69607 * words[wordIndex    
326   }                                               
327 }                                                 
328                                                   
329 DualRand::Tausworthe::operator unsigned int()     
330                                                   
331 // Mathematically:  Consider a sequence of bit    
332 // b[0]' = b[127] ^ b[97]; b[n]' = b[n-1].  Th    
333 // long period (2**127-1 according to Tauswort    
334                                                   
335 // The actual method used relies on the fact t    
336 // form bit 0 for up to 96 iterations never de    
337 // previous ones.  So you can actually compute    
338 // you can compute 32 at once -- despite 127 -    
339 // the method used in Canopy, where they wante    
340 // randoms.  I will do 32 here.                   
341                                                   
342 // When you do it this way, this looks disturb    
343 // Fibonacci.  And indeed, it is a lagged Fibo    
344 // being the XOR of a combination of shifts of    
345 // Tausworthe asserted excellent properties, I    
346 // However, the shifting and bit swapping real    
347 // serious way.                                   
348                                                   
349 // Statements have been made to the effect tha    
350 // the parking lot test because they achieve r    
351 // and this produces a characteristic pattern.    
352 // specific algorithm, which has a fairly long    
353 // effectively random.  This is evidenced by t    
354 // does pass the Diehard tests, including the     
355                                                   
356 // To avoid shuffling of variables in memory,     
357 // pointers (and those give you ifs, which are    
358 // a few iterations at once.  We do the latter    
359 // trade of room for more speed, by computing     
360 // bits at once, I will stop at this level of     
361                                                   
362 // To remind:  Each (32-bit) step takes the XO    
363 // [95-64] and places it in bits [0-31].  But     
364 // word0 as bits [0-31], in the second step, w    
365 // will no longer be needed), then word 2, the    
366 // stream contains 128 random bits which we wi    
367 // random numbers.                                
368                                                   
369 // Thus at the start of the first step, word[0    
370 // 32-bit random, and word[3] the oldest.   Af    
371 // contains the newest (now unused) random, an    
372 // Bit 0 of word[0] is logically the newest bi    
373 // the oldest.                                    
374                                                   
375   if (wordIndex <= 0) {                           
376     for (wordIndex = 0; wordIndex < 4; ++wordI    
377       words[wordIndex] = ( (words[(wordIndex+1    
378                                    (words[word    
379                        ^ ( (words[(wordIndex+1    
380                                    (words[word    
381     }                                             
382   }                                               
383   return words[--wordIndex] & 0xffffffff;         
384 }                                                 
385                                                   
386 void DualRand::Tausworthe::put(std::ostream &     
387   char beginMarker[] = "Tausworthe-begin";        
388   char endMarker[]   = "Tausworthe-end";          
389                                                   
390   long pr=os.precision(20);                       
391   os << " " << beginMarker << " ";                
392   for (int i = 0; i < 4; ++i) {                   
393     os << words[i] << " ";                        
394   }                                               
395   os << wordIndex;                                
396   os << " " <<  endMarker  << " ";                
397   os << std::endl;                                
398   os.precision(pr);                               
399 }                                                 
400                                                   
401 void DualRand::Tausworthe::put(std::vector<uns    
402   for (int i = 0; i < 4; ++i) {                   
403     v.push_back(static_cast<unsigned long>(wor    
404   }                                               
405   v.push_back(static_cast<unsigned long>(wordI    
406 }                                                 
407                                                   
408 void DualRand::Tausworthe::get(std::istream &     
409   char beginMarker [MarkerLen];                   
410   char endMarker   [MarkerLen];                   
411                                                   
412   is >> std::ws;                                  
413   is.width(MarkerLen);  // causes the next rea    
414       // that many bytes, INCLUDING A TERMINAT    
415       // (Stroustrup, section 21.3.2)             
416   is >> beginMarker;                              
417   if (strcmp(beginMarker,"Tausworthe-begin"))     
418     is.clear(std::ios::badbit | is.rdstate());    
419     std::cerr << "\nInput mispositioned or"       
420         << "\nTausworthe state description mis    
421         << "\nwrong engine type found." << std    
422   }                                               
423   for (int i = 0; i < 4; ++i) {                   
424     is >> words[i];                               
425   }                                               
426   is >> wordIndex;                                
427   is >> std::ws;                                  
428   is.width(MarkerLen);                            
429   is >> endMarker;                                
430   if (strcmp(endMarker,"Tausworthe-end")) {       
431     is.clear(std::ios::badbit | is.rdstate());    
432     std::cerr << "\nTausworthe state descripti    
433         << "\nInput stream is probably misposi    
434   }                                               
435 }                                                 
436                                                   
437 bool                                              
438 DualRand::Tausworthe::get(std::vector<unsigned    
439   for (int i = 0; i < 4; ++i) {                   
440     words[i] = (unsigned int)*iv++;               
441   }                                               
442   wordIndex = (int)*iv++;                         
443   return true;                                    
444 }                                                 
445                                                   
446 DualRand::IntegerCong::IntegerCong()              
447 : state((unsigned int)3758656018U),               
448   multiplier(66565),                              
449   addend(12341)                                   
450 {                                                 
451 }                                                 
452                                                   
453 DualRand::IntegerCong::IntegerCong(unsigned in    
454 : state(seed),                                    
455   multiplier(65536 + 1024 + 5 + (8 * 1017 * st    
456   addend(12341)                                   
457 {                                                 
458   // As to the multiplier, the following comme    
459   // We want our multipliers larger than 2^16,    
460   // 1 mod 4 (for max. period), but not equal     
461   // (for max. potency -- the smaller and high    
462   // stripes, the better)                         
463                                                   
464   // All of these will have fairly long period    
465   // of stream number, some of these will be q    
466   // as independent random engines, while othe    
467   // should not be used as stand-alone engines    
468   // generator known to be good, they allow cr    
469   // independent streams, without fear of two     
470   // nearby places in the good random sequence    
471 }                                                 
472                                                   
473 DualRand::IntegerCong::operator unsigned int()    
474   return state = (state * multiplier + addend)    
475 }                                                 
476                                                   
477 void DualRand::IntegerCong::put(std::ostream &    
478   char beginMarker[] = "IntegerCong-begin";       
479   char endMarker[]   = "IntegerCong-end";         
480                                                   
481   long pr=os.precision(20);                       
482   os << " " << beginMarker << " ";                
483   os << state << " " << multiplier << " " << a    
484   os << " " <<  endMarker  << " ";                
485   os << std::endl;                                
486   os.precision(pr);                               
487 }                                                 
488                                                   
489 void DualRand::IntegerCong::put(std::vector<un    
490   v.push_back(static_cast<unsigned long>(state    
491   v.push_back(static_cast<unsigned long>(multi    
492   v.push_back(static_cast<unsigned long>(adden    
493 }                                                 
494                                                   
495 void DualRand::IntegerCong::get(std::istream &    
496   char beginMarker [MarkerLen];                   
497   char endMarker   [MarkerLen];                   
498                                                   
499   is >> std::ws;                                  
500   is.width(MarkerLen);  // causes the next rea    
501       // that many bytes, INCLUDING A TERMINAT    
502       // (Stroustrup, section 21.3.2)             
503   is >> beginMarker;                              
504   if (strcmp(beginMarker,"IntegerCong-begin"))    
505     is.clear(std::ios::badbit | is.rdstate());    
506     std::cerr << "\nInput mispositioned or"       
507         << "\nIntegerCong state description mi    
508         << "\nwrong engine type found." << std    
509   }                                               
510   is >> state >> multiplier >> addend;            
511   is >> std::ws;                                  
512   is.width(MarkerLen);                            
513   is >> endMarker;                                
514   if (strcmp(endMarker,"IntegerCong-end")) {      
515     is.clear(std::ios::badbit | is.rdstate());    
516     std::cerr << "\nIntegerCong state descript    
517         << "\nInput stream is probably misposi    
518   }                                               
519 }                                                 
520                                                   
521 bool                                              
522 DualRand::IntegerCong::get(std::vector<unsigne    
523   state      = (unsigned int)*iv++;               
524   multiplier = (unsigned int)*iv++;               
525   addend     = (unsigned int)*iv++;               
526   return true;                                    
527 }                                                 
528                                                   
529 }  // namespace CLHEP                             
530