Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/clhep/src/RanluxppEngine.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/RanluxppEngine.cc (Version 11.3.0) and /externals/clhep/src/RanluxppEngine.cc (Version 10.6.p3)


  1 //                                                  1 
  2 // -*- C++ -*-                                    
  3 //                                                
  4 // -------------------------------------------    
  5 //                             HEP Random         
  6 //                       --- RanluxppEngine --    
  7 //                     class implementation fi    
  8 // -------------------------------------------    
  9 // Implementation of the RANLUX++ generator       
 10 //                                                
 11 // RANLUX++ is an LCG equivalent of RANLUX usi    
 12 //                                                
 13 // The idea of the generator (such as the init    
 14 // for the modulo operation are described in      
 15 // A. Sibidanov, *A revision of the subtract-w    
 16 // *Computer Physics Communications*, 221(2017    
 17 // preprint https://arxiv.org/pdf/1705.03123.p    
 18 //                                                
 19 // The code is loosely based on the Assembly i    
 20 // available at https://github.com/sibidanov/r    
 21 //                                                
 22 // Compared to the original generator, this im    
 23 // that the modulo operation of the LCG always    
 24 // to the modulus (based on notes by M. Lüsch    
 25 // LCG state back to RANLUX numbers (implement    
 26 // This avoids a bias in the generated numbers    
 27 // state, that is smaller than the modulus \f$    
 28 // a power of 2!), have a higher probability o    
 29 // implementation draws 48 random bits for eac    
 30 // (instead of 52 bits as in the original gene    
 31 // properties from understanding the original     
 32 // chaotic dynamical system.                      
 33 //                                                
 34 // These modifications and the portable implem    
 35 // J. Hahnfeld, L. Moneta, *A Portable Impleme    
 36 // preprint https://arxiv.org/pdf/2106.02504.p    
 37                                                   
 38 #include "CLHEP/Random/RanluxppEngine.h"          
 39                                                   
 40 #include "CLHEP/Random/engineIDulong.h"           
 41 #include "CLHEP/Utility/atomic_int.h"             
 42                                                   
 43 #include "CLHEP/Random/ranluxpp/mulmod.h"         
 44 #include "CLHEP/Random/ranluxpp/ranlux_lcg.h"     
 45                                                   
 46 #include <cassert>                                
 47 #include <fstream>                                
 48 #include <ios>                                    
 49 #include <cstdint>                                
 50                                                   
 51 namespace CLHEP {                                 
 52                                                   
 53 namespace {                                       
 54 // Number of instances with automatic seed sel    
 55 CLHEP_ATOMIC_INT_TYPE numberOfEngines(0);         
 56                                                   
 57 const uint64_t kA_2048[] = {                      
 58     0xed7faa90747aaad9, 0x4cec2c78af55c101, 0x    
 59     0x6d8a15a13bee7cb0, 0x20b2ca60cb78c509, 0x    
 60     0xff74e54107684ed2, 0x492edfcc0cc8e753, 0x    
 61 };                                                
 62 } // namespace                                    
 63                                                   
 64 RanluxppEngine::RanluxppEngine() : HepRandomEn    
 65   int numEngines = ++numberOfEngines;             
 66   setSeed(numEngines);                            
 67 }                                                 
 68                                                   
 69 RanluxppEngine::RanluxppEngine(long seed) : He    
 70   theSeed = seed;                                 
 71   setSeed(seed);                                  
 72 }                                                 
 73                                                   
 74 RanluxppEngine::RanluxppEngine(std::istream &i    
 75   get(is);                                        
 76 }                                                 
 77                                                   
 78 RanluxppEngine::~RanluxppEngine() = default;      
 79                                                   
 80 static constexpr int kMaxPos = 9 * 64;            
 81 static constexpr int kBits = 48;                  
 82                                                   
 83 void RanluxppEngine::advance() {                  
 84   uint64_t lcg[9];                                
 85   to_lcg(fState, fCarry, lcg);                    
 86   mulmod(kA_2048, lcg);                           
 87   to_ranlux(lcg, fState, fCarry);                 
 88   fPosition = 0;                                  
 89 }                                                 
 90                                                   
 91 uint64_t RanluxppEngine::nextRandomBits() {       
 92   if (fPosition + kBits > kMaxPos) {              
 93     advance();                                    
 94   }                                               
 95                                                   
 96   int idx = fPosition / 64;                       
 97   int offset = fPosition % 64;                    
 98   int numBits = 64 - offset;                      
 99                                                   
100   uint64_t bits = fState[idx] >> offset;          
101   if (numBits < kBits) {                          
102     bits |= fState[idx + 1] << numBits;           
103   }                                               
104   bits &= ((uint64_t(1) << kBits) - 1);           
105                                                   
106   fPosition += kBits;                             
107   assert(fPosition <= kMaxPos && "position out    
108                                                   
109   return bits;                                    
110 }                                                 
111                                                   
112 double RanluxppEngine::flat() {                   
113   // RandomEngine wants a "double random value    
114   // exclude all zero bits.                       
115   uint64_t random;                                
116   do {                                            
117     random = nextRandomBits();                    
118   } while (random == 0);                          
119                                                   
120   static constexpr double div = 1.0 / (uint64_    
121   return random * div;                            
122 }                                                 
123                                                   
124 void RanluxppEngine::flatArray(const int size,    
125   for (int i = 0; i < size; i++) {                
126     vect[i] = flat();                             
127   }                                               
128 }                                                 
129                                                   
130 void RanluxppEngine::setSeed(long seed, int) {    
131   theSeed = seed;                                 
132                                                   
133   uint64_t lcg[9];                                
134   lcg[0] = 1;                                     
135   for (int i = 1; i < 9; i++) {                   
136     lcg[i] = 0;                                   
137   }                                               
138                                                   
139   uint64_t a_seed[9];                             
140   // Skip 2 ** 96 states.                         
141   powermod(kA_2048, a_seed, uint64_t(1) << 48)    
142   powermod(a_seed, a_seed, uint64_t(1) << 48);    
143   // Skip more states according to seed.          
144   powermod(a_seed, a_seed, seed);                 
145   mulmod(a_seed, lcg);                            
146                                                   
147   to_ranlux(lcg, fState, fCarry);                 
148   fPosition = 0;                                  
149 }                                                 
150                                                   
151 void RanluxppEngine::setSeeds(const long *seed    
152   theSeeds = seeds;                               
153   setSeed(*seeds, 0);                             
154 }                                                 
155                                                   
156 void RanluxppEngine::skip(uint64_t n) {           
157   int left = (kMaxPos - fPosition) / kBits;       
158   assert(left >= 0 && "position was out of ran    
159   if (n < (uint64_t)left) {                       
160     // Just skip the next few entries in the c    
161     fPosition += n * kBits;                       
162     return;                                       
163   }                                               
164                                                   
165   n -= left;                                      
166   // Need to advance and possibly skip over bl    
167   int nPerState = kMaxPos / kBits;                
168   int skip = int(n / nPerState);                  
169                                                   
170   uint64_t a_skip[9];                             
171   powermod(kA_2048, a_skip, skip + 1);            
172                                                   
173   uint64_t lcg[9];                                
174   to_lcg(fState, fCarry, lcg);                    
175   mulmod(a_skip, lcg);                            
176   to_ranlux(lcg, fState, fCarry);                 
177                                                   
178   // Potentially skip numbers in the freshly g    
179   int remaining = int(n - skip * nPerState);      
180   assert(remaining >= 0 && "should not end up     
181   fPosition = remaining * kBits;                  
182   assert(fPosition <= kMaxPos && "position out    
183 }                                                 
184                                                   
185 void RanluxppEngine::saveStatus(const char fil    
186   std::ofstream os(filename);                     
187   put(os);                                        
188   os.close();                                     
189 }                                                 
190                                                   
191 void RanluxppEngine::restoreStatus(const char     
192   std::ifstream is(filename);                     
193   get(is);                                        
194   is.close();                                     
195 }                                                 
196                                                   
197 void RanluxppEngine::showStatus() const {         
198   std::cout                                       
199       << "--------------------- RanluxppEngine    
200       << std::endl;                               
201   std::cout << " fState[] = {";                   
202   std::cout << std::hex << std::setfill('0');     
203   for (int i = 0; i < 9; i++) {                   
204     if (i % 3 == 0) {                             
205       std::cout << std::endl << "     ";          
206     } else {                                      
207       std::cout << " ";                           
208     }                                             
209     std::cout << "0x" << std::setw(16) << fSta    
210   }                                               
211   std::cout << std::endl << " }" << std::endl;    
212   std::cout << std::dec;                          
213   std::cout << " fCarry = " << fCarry << ", fP    
214             << std::endl;                         
215   std::cout                                       
216       << "------------------------------------    
217       << std::endl;                               
218 }                                                 
219                                                   
220 std::string RanluxppEngine::name() const { ret    
221                                                   
222 std::string RanluxppEngine::engineName() { ret    
223                                                   
224 std::string RanluxppEngine::beginTag() { retur    
225                                                   
226 std::ostream &RanluxppEngine::put(std::ostream    
227   os << beginTag() << "\n";                       
228   const std::vector<unsigned long> state = put    
229   for (unsigned long v : state) {                 
230     os << v << "\n";                              
231   }                                               
232   return os;                                      
233 }                                                 
234                                                   
235 std::istream &RanluxppEngine::get(std::istream    
236   std::string tag;                                
237   is >> tag;                                      
238   if (tag != beginTag()) {                        
239     is.clear(std::ios::badbit | is.rdstate());    
240     std::cerr << "No RanluxppEngine found at c    
241     return is;                                    
242   }                                               
243   return getState(is);                            
244 }                                                 
245                                                   
246 std::istream &RanluxppEngine::getState(std::is    
247   std::vector<unsigned long> state;               
248   state.reserve(VECTOR_STATE_SIZE);               
249   for (unsigned int i = 0; i < VECTOR_STATE_SI    
250     unsigned long v;                              
251     is >> v;                                      
252     state.push_back(v);                           
253   }                                               
254                                                   
255   getState(state);                                
256   return is;                                      
257 }                                                 
258                                                   
259 std::vector<unsigned long> RanluxppEngine::put    
260   std::vector<unsigned long> v;                   
261   v.reserve(VECTOR_STATE_SIZE);                   
262   v.push_back(engineIDulong<RanluxppEngine>())    
263                                                   
264   // unsigned long is only guaranteed to be 32    
265   // values in fState.                            
266   for (int i = 0; i < 9; i++) {                   
267     unsigned long lower = static_cast<uint32_t    
268     v.push_back(lower);                           
269     unsigned long upper = static_cast<uint32_t    
270     v.push_back(upper);                           
271   }                                               
272                                                   
273   v.push_back(fCarry);                            
274   v.push_back(fPosition);                         
275   return v;                                       
276 }                                                 
277                                                   
278 bool RanluxppEngine::get(const std::vector<uns    
279   if (v[0] != engineIDulong<RanluxppEngine>())    
280     std::cerr << "RanluxppEngine::get(): "        
281               << "vector has wrong ID word - s    
282     return false;                                 
283   }                                               
284   return getState(v);                             
285 }                                                 
286                                                   
287 bool RanluxppEngine::getState(const std::vecto    
288   if (v.size() != VECTOR_STATE_SIZE) {            
289     std::cerr << "RanluxppEngine::getState():     
290               << "vector has wrong length - st    
291     return false;                                 
292   }                                               
293                                                   
294   // Assemble the state vector (see RanluxppEn    
295   for (int i = 0; i < 9; i++) {                   
296     uint64_t lower = v[2 * i + 1];                
297     uint64_t upper = v[2 * i + 2];                
298     fState[i] = (upper << 32) + lower;            
299   }                                               
300   fCarry = (unsigned int)v[19];                   
301   fPosition = (int)v[20];                         
302                                                   
303   return true;                                    
304 }                                                 
305                                                   
306 } // namespace CLHEP                              
307