Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/clhep/src/RanshiEngine.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 //                      --- RanshiEngine ---
  6 //                    class implementation file
  7 // -----------------------------------------------------------------------
  8 //
  9 // This algorithm implements the random number generator as proposed by 
 10 // "F. Gutbrod, Comp. Phys. Comm. 87 (1995) 291-306". 
 11 //
 12 // =======================================================================
 13 // Ken Smith      - Created:                                 9th June 1998
 14 //                - Removed std::pow() from flat method:     21st Jul 1998
 15 //                - Added conversion operators:               6th Aug 1998
 16 // J. Marraffino  - Added some explicit casts to deal with
 17 //                  machines where sizeof(int) != sizeof(long) 22 Aug 1998
 18 // M. Fischler    - Modified constructors taking seeds to not
 19 //                  depend on numEngines (same seeds should
 20 //                  produce same sequences).  Default still
 21 //                  depends on numEngines.                      16 Sep 1998
 22 //                - Modified use of the various exponents of 2
 23 //                  to avoid per-instance space overhead and
 24 //                  correct the rounding procedure              16 Sep 1998
 25 // J. Marraffino  - Remove dependence on hepString class        13 May 1999
 26 // M. Fischler    - In restore, checkFile for file not found    03 Dec 2004
 27 // M. Fischler    - Methods for instance save/restore            12/8/04    
 28 // M. Fischler    - split get() into tag validation and 
 29 //                  getState() for anonymous restores           12/27/04    
 30 // M. Fischler    - State-saving using only ints, for portability 4/12/05
 31 // L. Garren      - use explicit 32bit mask to avoid compiler warnings  6/6/2014  
 32 // L. Garren      - adding pragma for 32bit gcc 4.9 11/20/2014  
 33 //
 34 // =======================================================================
 35 
 36 #include "CLHEP/Random/RanshiEngine.h"
 37 #include "CLHEP/Random/engineIDulong.h"
 38 #include "CLHEP/Utility/atomic_int.h"
 39 
 40 #include <atomic>
 41 #include <string.h> // for strcmp
 42 #include <iostream>
 43 #include <string>
 44 #include <vector>
 45 
 46 // don't generate warnings about agressive loop optimization
 47 #if defined __GNUC__ 
 48   #if __GNUC__ > 3 && __GNUC_MINOR__ > 8
 49     #pragma GCC diagnostic push
 50     #pragma GCC diagnostic ignored "-Waggressive-loop-optimizations"
 51   #endif
 52 #endif
 53 
 54 namespace CLHEP {
 55 
 56 namespace {
 57   // Number of instances with automatic seed selection
 58   CLHEP_ATOMIC_INT_TYPE numberOfEngines(0);
 59 }
 60 
 61 static const int MarkerLen = 64; // Enough room to hold a begin or end marker. 
 62 
 63 std::string RanshiEngine::name() const {return "RanshiEngine";}
 64 
 65 RanshiEngine::RanshiEngine()
 66 : HepRandomEngine(),
 67   halfBuff(0), numFlats(0) 
 68 {
 69   int numEngines = numberOfEngines++;
 70   int i = 0;
 71   while (i < numBuff) {    
 72     buffer[i] = (unsigned int)((numEngines+19780503L*(i+1))& 0xffffffff);
 73     ++i;
 74   }
 75   theSeed = numEngines+19780503L*++i;
 76   redSpin = (unsigned int)(theSeed & 0xffffffff);
 77 
 78   for( i = 0; i < 10000; ++i) flat();  // Warm-up by running thorugh 10000 nums
 79 }
 80 
 81 RanshiEngine::RanshiEngine(std::istream& is)
 82 : HepRandomEngine(),
 83   halfBuff(0), numFlats(0) 
 84 {
 85   is >> *this;
 86 }
 87 
 88 RanshiEngine::RanshiEngine(long seed)
 89 : HepRandomEngine(),
 90   halfBuff(0), numFlats(0) 
 91 {
 92   for (int i = 0; i < numBuff; ++i) {
 93     buffer[i] = (unsigned int)seed&0xffffffff;
 94   }
 95   theSeed = seed;
 96   redSpin = (unsigned int)(theSeed & 0xffffffff);
 97   int j;
 98   for (j = 0; j < numBuff*20; ++j) {      // "warm-up" for engine to hit
 99     flat();                               //  every ball on average 20X.
100   }
101 }
102 
103 RanshiEngine::RanshiEngine(int rowIndex, int colIndex)
104 : HepRandomEngine(),
105   halfBuff(0), numFlats(0) 
106 {
107   int i = 0;
108   while( i < numBuff ) {
109     buffer[i] = (unsigned int)((rowIndex + (i+1)*(colIndex+8))&0xffffffff);
110     ++i;
111   }
112   theSeed = rowIndex;
113   redSpin = colIndex & 0xffffffff;
114   for( i = 0; i < 100; ++i) flat();    // Warm-up by running thorugh 100 nums
115 }
116 
117 RanshiEngine::~RanshiEngine() { }
118 
119 double RanshiEngine::flat() {
120   unsigned int redAngle = (((numBuff/2) - 1) & redSpin) + halfBuff;
121   unsigned int blkSpin     = buffer[redAngle] & 0xffffffff;
122   unsigned int boostResult = blkSpin ^ redSpin;
123 
124   buffer[redAngle] = ((blkSpin << 17) | (blkSpin >> (32-17))) ^ redSpin;
125   
126   redSpin  = (blkSpin + numFlats++) & 0xffffffff;
127   halfBuff = numBuff/2 - halfBuff;
128   
129   return ( blkSpin * twoToMinus_32() +            // most significant part
130      (boostResult>>11) * twoToMinus_53() +  // fill in remaining bits
131      nearlyTwoToMinus_54());      // non-zero
132 }
133 
134 void RanshiEngine::flatArray(const int size, double* vect) {
135   for (int i = 0; i < size; ++i) {
136     vect[i] = flat();
137   }
138 }
139 
140 void RanshiEngine::setSeed(long seed, int) {
141   *this = RanshiEngine(seed); 
142 }
143 
144 void RanshiEngine::setSeeds(const long* seeds, int) {
145   if (*seeds) {
146     int i = 0;
147     while (seeds[i] && i < numBuff) {
148       buffer[i] = (unsigned int)seeds[i];
149       ++i;
150     }
151     while (i < numBuff) {
152       buffer[i] = buffer[i-1];
153       ++i;
154     }
155     theSeed = seeds[0];
156     redSpin = (unsigned int)theSeed;
157   }
158   theSeeds = seeds;
159 }
160      
161 void RanshiEngine::saveStatus(const char filename[]) const {
162   std::ofstream outFile(filename, std::ios::out);
163   if (!outFile.bad()) {
164     outFile << "Uvec\n";
165     std::vector<unsigned long> v = put();
166     for (unsigned int i=0; i<v.size(); ++i) {
167       outFile << v[i] << "\n";
168     }
169   }
170 }
171 
172 void RanshiEngine::restoreStatus(const char filename[]) {
173   std::ifstream inFile(filename, std::ios::in);
174   if (!checkFile ( inFile, filename, engineName(), "restoreStatus" )) {
175     std::cerr << "  -- Engine state remains unchanged\n";
176     return;
177   }
178   if ( possibleKeywordInput ( inFile, "Uvec", theSeed ) ) {
179     std::vector<unsigned long> v;
180     unsigned long xin;
181     for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) {
182       inFile >> xin;
183       if (!inFile) {
184         inFile.clear(std::ios::badbit | inFile.rdstate());
185         std::cerr << "\nRanshiEngine state (vector) description improper."
186          << "\nrestoreStatus has failed."
187          << "\nInput stream is probably mispositioned now." << std::endl;
188         return;
189       }
190       v.push_back(xin);
191     }
192     getState(v);
193     return;
194   }
195 
196   if (!inFile.bad()) {
197 //     inFile >> theSeed;  removed -- encompased by possibleKeywordInput
198     for (int i = 0; i < numBuff; ++i) {
199       inFile >> buffer[i];
200     }
201     inFile >> redSpin >> numFlats >> halfBuff;
202   }
203 }
204 
205 void RanshiEngine::showStatus() const {
206   std::cout << std::setprecision(20) << std::endl;
207   std::cout << "----------- Ranshi engine status ----------" << std::endl;
208   std::cout << "Initial seed      = " << theSeed << std::endl;
209   std::cout << "Current red spin  = " << redSpin << std::endl;
210   std::cout << "Values produced   = " << numFlats << std::endl;
211   std::cout << "Side of buffer    = " << (halfBuff ? "upper" : "lower")
212       << std::endl;
213   std::cout << "Current buffer    = " << std::endl;
214   for (int i = 0; i < numBuff; i+=4) {
215     std::cout << std::setw(10) << std::setiosflags(std::ios::right)
216         << buffer[i]     << std::setw(11) << buffer[i+1] << std::setw(11)
217         << buffer[i+2]   << std::setw(11) << buffer[i+3] << std::endl;
218   }
219   std::cout << "-------------------------------------------" << std::endl;
220 }
221 
222 RanshiEngine::operator double() {
223   return flat();
224 }
225 
226 RanshiEngine::operator float() {
227   unsigned int redAngle = (((numBuff/2) - 1) & redSpin) + halfBuff;
228   unsigned int blkSpin  = buffer[redAngle] & 0xffffffff;
229   
230   buffer[redAngle] = ((blkSpin << 17) | (blkSpin >> (32-17))) ^ redSpin;
231   
232   redSpin  = (blkSpin + numFlats++) & 0xffffffff;
233   halfBuff = numBuff/2 - halfBuff;
234   
235   return float(blkSpin * twoToMinus_32());
236 }
237 
238 RanshiEngine::operator unsigned int() {
239   unsigned int redAngle = (((numBuff/2) - 1) & redSpin) + halfBuff;
240   unsigned int blkSpin  = buffer[redAngle] & 0xffffffff;
241   
242   buffer[redAngle] = ((blkSpin << 17) | (blkSpin >> (32-17))) ^ redSpin;
243   
244   redSpin  = (blkSpin + numFlats++) & 0xffffffff;
245   halfBuff = numBuff/2 - halfBuff;
246   
247   return blkSpin;
248 }
249 
250 std::ostream& RanshiEngine::put (std::ostream& os ) const {
251   char beginMarker[] = "RanshiEngine-begin";
252   os << beginMarker << "\nUvec\n";
253   std::vector<unsigned long> v = put();
254   for (unsigned int i=0; i<v.size(); ++i) {
255      os <<  v[i] <<  "\n";
256   }
257   return os;  
258 }
259 
260 std::vector<unsigned long> RanshiEngine::put () const {
261   std::vector<unsigned long> v;
262   v.push_back (engineIDulong<RanshiEngine>());
263   for (int i = 0; i < numBuff; ++i) {
264     v.push_back(static_cast<unsigned long>(buffer[i]));
265   }
266   v.push_back(static_cast<unsigned long>(redSpin));
267   v.push_back(static_cast<unsigned long>(numFlats));
268   v.push_back(static_cast<unsigned long>(halfBuff));  
269   return v;
270 }
271 
272 std::istream& RanshiEngine::get (std::istream& is) {
273   char beginMarker [MarkerLen];
274   is >> std::ws;
275   is.width(MarkerLen);  // causes the next read to the char* to be <=
276       // that many bytes, INCLUDING A TERMINATION \0 
277       // (Stroustrup, section 21.3.2)
278   is >> beginMarker;
279   if (strcmp(beginMarker,"RanshiEngine-begin")) {
280     is.clear(std::ios::badbit | is.rdstate());
281     std::cerr << "\nInput mispositioned or"
282         << "\nRanshiEngine state description missing or"
283         << "\nwrong engine type found." << std::endl;
284     return is;
285   }
286   return getState(is);
287 }
288 
289 std::string RanshiEngine::beginTag ( )  { 
290   return "RanshiEngine-begin"; 
291 }
292   
293 std::istream& RanshiEngine::getState (std::istream& is) {
294   if ( possibleKeywordInput ( is, "Uvec", theSeed ) ) {
295     std::vector<unsigned long> v;
296     unsigned long uu;
297     for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) {
298       is >> uu;
299       if (!is) {
300         is.clear(std::ios::badbit | is.rdstate());
301         std::cerr << "\nRanshiEngine state (vector) description improper."
302     << "\ngetState() has failed."
303          << "\nInput stream is probably mispositioned now." << std::endl;
304         return is;
305       }
306       v.push_back(uu);
307     }
308     getState(v);
309     return (is);
310   }
311 
312 //  is >> theSeed;  Removed, encompassed by possibleKeywordInput()
313 
314   char endMarker   [MarkerLen];
315   for (int i = 0; i < numBuff; ++i) {
316     is >> buffer[i];
317   }
318   is >> redSpin >> numFlats >> halfBuff;
319   is >> std::ws;
320   is.width(MarkerLen);  
321   is >> endMarker;
322   if (strcmp(endMarker,"RanshiEngine-end")) {
323     is.clear(std::ios::badbit | is.rdstate());
324     std::cerr << "\nRanshiEngine state description incomplete."
325         << "\nInput stream is probably mispositioned now." << std::endl;
326     return is;
327   }
328   return is;
329 }
330 
331 bool RanshiEngine::get (const std::vector<unsigned long> & v) {
332   if ((v[0] & 0xffffffffUL) != engineIDulong<RanshiEngine>()) {
333     std::cerr << 
334       "\nRanshiEngine get:state vector has wrong ID word - state unchanged\n";
335     return false;
336   }
337   return getState(v);
338 }
339 
340 bool RanshiEngine::getState (const std::vector<unsigned long> & v) {
341   if (v.size() != VECTOR_STATE_SIZE ) {
342     std::cerr << 
343       "\nRanshiEngine get:state vector has wrong length - state unchanged\n";
344     return false;
345   }
346   for (int i = 0; i < numBuff; ++i) {
347     buffer[i] = (unsigned int)v[i+1];
348   }
349   redSpin  = (unsigned int)v[numBuff+1];
350   numFlats = (unsigned int)v[numBuff+2]; 
351   halfBuff = (unsigned int)v[numBuff+3];
352   return true;
353 }
354 
355 }  // namespace CLHEP
356 
357 #if defined __GNUC__ 
358   #if __GNUC__ > 3 && __GNUC_MINOR__ > 8
359     #pragma GCC diagnostic pop
360   #endif
361 #endif
362