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 10.2.p2)


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