Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/clhep/src/Random.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/Random.cc (Version 11.3.0) and /externals/clhep/src/Random.cc (Version 11.0.p4)


  1 // -*- C++ -*-                                      1 // -*- C++ -*-
  2 //                                                  2 //
  3 // -------------------------------------------      3 // -----------------------------------------------------------------------
  4 //                             HEP Random           4 //                             HEP Random
  5 //                          --- HepRandom ---       5 //                          --- HepRandom ---
  6 //                      class implementation f      6 //                      class implementation file
  7 // -------------------------------------------      7 // -----------------------------------------------------------------------
  8 // This file is part of Geant4 (simulation too      8 // This file is part of Geant4 (simulation toolkit for HEP).
  9                                                     9 
 10 // ===========================================     10 // =======================================================================
 11 // Gabriele Cosmo - Created: 5th September 199     11 // Gabriele Cosmo - Created: 5th September 1995
 12 //                - Minor corrections: 31st Oc     12 //                - Minor corrections: 31st October 1996
 13 //                - Added methods for engine s     13 //                - Added methods for engine status: 19th November 1996
 14 //                - HepRandom defined as singl     14 //                - HepRandom defined as singleton, constructors are
 15 //                  kept public for backward c     15 //                  kept public for backward compatibility: 27th Feb 1998
 16 //                - Relocated Poisson and Gaus     16 //                - Relocated Poisson and Gauss data and simplified
 17 //                  initialisation of static g     17 //                  initialisation of static generator: 5th Jan 1999
 18 // ===========================================     18 // =======================================================================
 19                                                    19 
 20 #include "CLHEP/Random/MixMaxRng.h"                20 #include "CLHEP/Random/MixMaxRng.h"
 21 #include "CLHEP/Random/Random.h"                   21 #include "CLHEP/Random/Random.h"
 22 #include "CLHEP/Random/StaticRandomStates.h"       22 #include "CLHEP/Random/StaticRandomStates.h"
 23 #include "CLHEP/Utility/memory.h"                  23 #include "CLHEP/Utility/memory.h"
 24 #include "CLHEP/Utility/thread_local.h"            24 #include "CLHEP/Utility/thread_local.h"
 25 #include "CLHEP/Utility/use_atomic.h"              25 #include "CLHEP/Utility/use_atomic.h"
 26                                                    26 
 27 // -----------------------------                   27 // -----------------------------
 28 // Static members initialisation                   28 // Static members initialisation
 29 // -----------------------------                   29 // -----------------------------
 30                                                    30 
 31 #include "CLHEP/Random/SeedTable.h"                31 #include "CLHEP/Random/SeedTable.h"
 32                                                    32 
 33 #include <assert.h>                                33 #include <assert.h>
 34 #include <iostream>                                34 #include <iostream>
 35 #include <type_traits>                             35 #include <type_traits>
 36 #include <string>                                  36 #include <string>
 37                                                    37 
 38 namespace CLHEP {                                  38 namespace CLHEP {
 39                                                    39 
 40   namespace {                                      40   namespace {
 41                                                    41 
 42     struct defaults {                              42     struct defaults {
 43                                                    43 
 44       defaults()                                   44       defaults()
 45         : theGenerator( &theDefaultGenerator,      45         : theGenerator( &theDefaultGenerator, do_nothing_deleter() )
 46         , theEngine   ( &theDefaultEngine, do_     46         , theEngine   ( &theDefaultEngine, do_nothing_deleter() )
 47       { }                                          47       { }
 48                                                    48 
 49       defaults(defaults const& other) = delete     49       defaults(defaults const& other) = delete;
 50       defaults const& operator=(defaults const     50       defaults const& operator=(defaults const&) = delete;
 51                                                    51 
 52       void  resetEngine( HepRandomEngine * new     52       void  resetEngine( HepRandomEngine * newEngine ) {
 53         theEngine.reset( newEngine );              53         theEngine.reset( newEngine );
 54       }                                            54       }
 55                                                    55 
 56       void  resetEngine( HepRandomEngine & new     56       void  resetEngine( HepRandomEngine & newEngine ) {
 57         theEngine.reset( &newEngine, do_nothin     57         theEngine.reset( &newEngine, do_nothing_deleter() );
 58       }                                            58       }
 59                                                    59 
 60       bool  ensureInitialized()  {                 60       bool  ensureInitialized()  {
 61         assert( theGenerator.get() != 0  && th     61         assert( theGenerator.get() != 0  && theEngine.get() != 0 );
 62         return true;                               62         return true;
 63       }                                            63       }
 64                                                    64 
 65       ~defaults()                                  65       ~defaults()
 66       { }                                          66       { }
 67                                                    67 
 68     private:                                       68     private:
 69                                                    69 
 70       HepRandom theDefaultGenerator;               70       HepRandom theDefaultGenerator;
 71       MixMaxRng theDefaultEngine;                  71       MixMaxRng theDefaultEngine;
 72                                                    72 
 73     public:                                        73     public:
 74                                                    74 
 75       std::shared_ptr<HepRandom      >  theGen     75       std::shared_ptr<HepRandom      >  theGenerator;
 76       std::shared_ptr<HepRandomEngine>  theEng     76       std::shared_ptr<HepRandomEngine>  theEngine;
 77     };  // defaults                                77     };  // defaults
 78                                                    78 
 79                                                    79 
 80 #ifdef CLHEP_USE_ATOMIC                            80 #ifdef CLHEP_USE_ATOMIC
 81                                                    81 
 82     // The ThreadSafeDefaultCache is used only     82     // The ThreadSafeDefaultCache is used only by the function named theDefaults.
 83     // It is a singly linked list that is inte     83     // It is a singly linked list that is intended to hold one object of
 84     // type "defaults" per thread.                 84     // type "defaults" per thread.
 85                                                    85 
 86     class ThreadSafeDefaultsCache {                86     class ThreadSafeDefaultsCache {
 87     public:                                        87     public:
 88                                                    88 
 89       ThreadSafeDefaultsCache();                   89       ThreadSafeDefaultsCache();
 90                                                    90 
 91       // The destructor deletes the objects of     91       // The destructor deletes the objects of type "defaults"
 92       ~ThreadSafeDefaultsCache();                  92       ~ThreadSafeDefaultsCache();
 93                                                    93 
 94       // Creates new objects and adds them to      94       // Creates new objects and adds them to the linked list in a thread safe manner.
 95       defaults* createNewDefaults();               95       defaults* createNewDefaults();
 96                                                    96 
 97       // Note that there are no other function     97       // Note that there are no other functions. No erasing or moving or other accessors.
 98                                                    98 
 99     private:                                       99     private:
100                                                   100 
101       class DefaultsNode {                        101       class DefaultsNode {
102       public:                                     102       public:
103         DefaultsNode(DefaultsNode* iNext);        103         DefaultsNode(DefaultsNode* iNext);
104         DefaultsNode const* next() const { ret    104         DefaultsNode const* next() const { return next_; }
105         void setNext(DefaultsNode* v) { next_     105         void setNext(DefaultsNode* v) { next_ = v; }
106         defaults* addressOfDefaults() { return    106         defaults* addressOfDefaults() { return &defaults_; }
107       private:                                    107       private:
108         DefaultsNode* next_;                      108         DefaultsNode* next_;
109         defaults defaults_;                       109         defaults defaults_;
110       };                                          110       };
111                                                   111 
112       // points to first node in the linked li    112       // points to first node in the linked list
113       std::atomic<DefaultsNode*> front_;          113       std::atomic<DefaultsNode*> front_;
114     };                                            114     };
115                                                   115 
116     ThreadSafeDefaultsCache::ThreadSafeDefault    116     ThreadSafeDefaultsCache::ThreadSafeDefaultsCache() :
117       front_(nullptr) {                           117       front_(nullptr) {
118     }                                             118     }
119                                                   119 
120     defaults* ThreadSafeDefaultsCache::createN    120     defaults* ThreadSafeDefaultsCache::createNewDefaults() {
121       DefaultsNode* expected = front_.load();     121       DefaultsNode* expected = front_.load();
122       DefaultsNode* newNode = new DefaultsNode    122       DefaultsNode* newNode = new DefaultsNode(expected);
123       while (!front_.compare_exchange_strong(e    123       while (!front_.compare_exchange_strong(expected, newNode)) {
124         // another thread changed front_ befor    124         // another thread changed front_ before us so try again
125         newNode->setNext(expected);               125         newNode->setNext(expected);
126       }                                           126       }
127       return newNode->addressOfDefaults();        127       return newNode->addressOfDefaults();
128     }                                             128     }
129                                                   129 
130     ThreadSafeDefaultsCache::DefaultsNode::Def    130     ThreadSafeDefaultsCache::DefaultsNode::DefaultsNode(DefaultsNode* iNext) :
131       next_(iNext),                               131       next_(iNext),
132       defaults_() {                               132       defaults_() {
133     }                                             133     }
134                                                   134 
135     ThreadSafeDefaultsCache::~ThreadSafeDefaul    135     ThreadSafeDefaultsCache::~ThreadSafeDefaultsCache() {
136       DefaultsNode const* node = front_.load()    136       DefaultsNode const* node = front_.load();
137       while (node) {                              137       while (node) {
138         DefaultsNode const* next = node->next(    138         DefaultsNode const* next = node->next();
139         delete node;                              139         delete node;
140         node = next;                              140         node = next;
141       }                                           141       }
142     }                                             142     }
143                                                   143 
144     defaults &  theDefaults()  {                  144     defaults &  theDefaults()  {
145                                                   145 
146       // We need to have different engines on     146       // We need to have different engines on different threads because
147       // the engines are not thread safe. One     147       // the engines are not thread safe. One cannot generate random numbers
148       // using the same engine on different th    148       // using the same engine on different threads simultaneously.
149       // Originally we had the defaults object    149       // Originally we had the defaults object itself as a thread local,
150       // but that was failing because on Mac O    150       // but that was failing because on Mac OSX there is not full
151       // support for thread locals yet.  Objec    151       // support for thread locals yet.  Objects containing std::shared_ptr
152       // in thread local storage were causing     152       // in thread local storage were causing failures. So now we create
153       // a container of them that is a functio    153       // a container of them that is a function static (not thread local)
154       // and the thread local contains only a     154       // and the thread local contains only a pointer to an object in the
155       // container.                               155       // container.
156       static ThreadSafeDefaultsCache defaultsF    156       static ThreadSafeDefaultsCache defaultsForAllThreads;
157                                                   157 
158       // A pointer for each thread to defaults    158       // A pointer for each thread to defaults object built for each thread.
159       static CLHEP_THREAD_LOCAL defaults* theD    159       static CLHEP_THREAD_LOCAL defaults* theDefaults = defaultsForAllThreads.createNewDefaults();
160                                                   160 
161       return *theDefaults;                        161       return *theDefaults;
162     }                                             162     }
163 #else                                             163 #else
164                                                   164 
165     // This version is used with old compilers    165     // This version is used with old compilers not supporting atomics.
166     // In that case, the code should not be ex    166     // In that case, the code should not be executed in more than one thread.
167     defaults &  theDefaults()  {                  167     defaults &  theDefaults()  {
168       static defaults theDefaults;                168       static defaults theDefaults;
169       return theDefaults;                         169       return theDefaults;
170     }                                             170     }
171                                                   171 
172 #endif                                            172 #endif
173                                                   173 
174   }  // namespace                                 174   }  // namespace
175                                                   175 
176 //---------------------------- HepRandom -----    176 //---------------------------- HepRandom ---------------------------------
177                                                   177 
178 HepRandom::HepRandom()                            178 HepRandom::HepRandom()
179 { }                                               179 { }
180                                                   180 
181 HepRandom::HepRandom(long seed)                   181 HepRandom::HepRandom(long seed)
182 {                                                 182 {
183   setTheSeed(seed);                               183   setTheSeed(seed);
184 }                                                 184 }
185                                                   185 
186 HepRandom::HepRandom(HepRandomEngine & algorit    186 HepRandom::HepRandom(HepRandomEngine & algorithm)
187 {                                                 187 {
188   theDefaults().resetEngine( algorithm );         188   theDefaults().resetEngine( algorithm );
189 }                                                 189 }
190                                                   190 
191 HepRandom::HepRandom(HepRandomEngine * algorit    191 HepRandom::HepRandom(HepRandomEngine * algorithm)
192 {                                                 192 {
193   theDefaults().resetEngine( algorithm );         193   theDefaults().resetEngine( algorithm );
194 }                                                 194 }
195                                                   195 
196 HepRandom::~HepRandom()                           196 HepRandom::~HepRandom()
197 { }                                               197 { }
198                                                   198 
199 double HepRandom::flat()                          199 double HepRandom::flat()
200 {                                                 200 {
201   return theDefaults().theEngine->flat();         201   return theDefaults().theEngine->flat();
202 }                                                 202 }
203                                                   203 
204 void HepRandom::flatArray(const int size, doub    204 void HepRandom::flatArray(const int size, double* vect)
205 {                                                 205 {
206   theDefaults().theEngine->flatArray(size,vect    206   theDefaults().theEngine->flatArray(size,vect);
207 }                                                 207 }
208                                                   208 
209 double HepRandom::operator()() {                  209 double HepRandom::operator()() {
210   return flat();                                  210   return flat();
211 }                                                 211 }
212                                                   212 
213 std::string HepRandom::name() const {return "H    213 std::string HepRandom::name() const {return "HepRandom";}
214 HepRandomEngine & HepRandom::engine() {           214 HepRandomEngine & HepRandom::engine() {
215   std::cerr << "HepRandom::engine() called --     215   std::cerr << "HepRandom::engine() called -- there is no assigned engine!\n";
216   return *theDefaults().theEngine.get();          216   return *theDefaults().theEngine.get();
217 }                                                 217 }
218                                                   218 
219 std::ostream & operator<< (std::ostream & os,     219 std::ostream & operator<< (std::ostream & os, const HepRandom & dist) {
220   return dist.put(os);                            220   return dist.put(os);
221 }                                                 221 }
222                                                   222 
223 std::istream & operator>> (std::istream & is,     223 std::istream & operator>> (std::istream & is, HepRandom & dist) {
224   return dist.get(is);                            224   return dist.get(is);
225 }                                                 225 }
226                                                   226 
227 std::ostream & HepRandom::put(std::ostream & o    227 std::ostream & HepRandom::put(std::ostream & os) const {return os;}
228 std::istream & HepRandom::get(std::istream & i    228 std::istream & HepRandom::get(std::istream & is) {return is;}
229                                                   229 
230 // --------------------------                     230 // --------------------------
231 // Static methods definitions                     231 // Static methods definitions
232 // --------------------------                     232 // --------------------------
233                                                   233 
234 void HepRandom::setTheSeed(long seed, int lux)    234 void HepRandom::setTheSeed(long seed, int lux)
235 {                                                 235 {
236   theDefaults().theEngine->setSeed(seed,lux);     236   theDefaults().theEngine->setSeed(seed,lux);
237 }                                                 237 }
238                                                   238 
239 long HepRandom::getTheSeed()                      239 long HepRandom::getTheSeed()
240 {                                                 240 {
241   return theDefaults().theEngine->getSeed();      241   return theDefaults().theEngine->getSeed();
242 }                                                 242 }
243                                                   243 
244 void HepRandom::setTheSeeds(const long* seeds,    244 void HepRandom::setTheSeeds(const long* seeds, int aux)
245 {                                                 245 {
246   theDefaults().theEngine->setSeeds(seeds,aux)    246   theDefaults().theEngine->setSeeds(seeds,aux);
247 }                                                 247 }
248                                                   248 
249 const long* HepRandom::getTheSeeds ()             249 const long* HepRandom::getTheSeeds ()
250 {                                                 250 {
251   return theDefaults().theEngine->getSeeds();     251   return theDefaults().theEngine->getSeeds();
252 }                                                 252 }
253                                                   253 
254 void HepRandom::getTheTableSeeds(long* seeds,     254 void HepRandom::getTheTableSeeds(long* seeds, int index)
255 {                                                 255 {
256   if ((index >= 0) && (index < 215)) {            256   if ((index >= 0) && (index < 215)) {
257     seeds[0] = seedTable[index][0];               257     seeds[0] = seedTable[index][0];
258     seeds[1] = seedTable[index][1];               258     seeds[1] = seedTable[index][1];
259   }                                               259   }
260   else seeds = NULL;                              260   else seeds = NULL;
261 }                                                 261 }
262                                                   262 
263 HepRandom * HepRandom::getTheGenerator()          263 HepRandom * HepRandom::getTheGenerator()
264 {                                                 264 {
265   return theDefaults().theGenerator.get();        265   return theDefaults().theGenerator.get();
266 }                                                 266 }
267                                                   267 
268 HepRandomEngine * HepRandom::getTheEngine()       268 HepRandomEngine * HepRandom::getTheEngine()
269 {                                                 269 {
270   return theDefaults().theEngine.get();           270   return theDefaults().theEngine.get();
271 }                                                 271 }
272                                                   272 
273 void HepRandom::setTheEngine (HepRandomEngine*    273 void HepRandom::setTheEngine (HepRandomEngine* theNewEngine)
274 {                                                 274 {
275   theDefaults().theEngine.reset( theNewEngine,    275   theDefaults().theEngine.reset( theNewEngine, do_nothing_deleter() );
276 }                                                 276 }
277                                                   277 
278 void HepRandom::saveEngineStatus( const char f    278 void HepRandom::saveEngineStatus( const char filename[] )
279 {                                                 279 {
280   theDefaults().theEngine->saveStatus( filenam    280   theDefaults().theEngine->saveStatus( filename );
281 }                                                 281 }
282                                                   282 
283 void HepRandom::restoreEngineStatus( const cha    283 void HepRandom::restoreEngineStatus( const char filename[] )
284 {                                                 284 {
285   theDefaults().theEngine->restoreStatus( file    285   theDefaults().theEngine->restoreStatus( filename );
286 }                                                 286 }
287                                                   287 
288 std::ostream& HepRandom::saveFullState ( std::    288 std::ostream& HepRandom::saveFullState ( std::ostream & os ) {
289   os << *getTheEngine();                          289   os << *getTheEngine();
290   return os;                                      290   return os;
291 }                                                 291 }
292                                                   292 
293 std::istream& HepRandom::restoreFullState ( st    293 std::istream& HepRandom::restoreFullState ( std::istream & is ) {
294   is >> *getTheEngine();                          294   is >> *getTheEngine();
295   return is;                                      295   return is;
296 }                                                 296 }
297                                                   297 
298 std::ostream& HepRandom::saveStaticRandomState    298 std::ostream& HepRandom::saveStaticRandomStates ( std::ostream & os ) {
299   return StaticRandomStates::save(os);            299   return StaticRandomStates::save(os);
300 }                                                 300 }
301                                                   301 
302 std::istream& HepRandom::restoreStaticRandomSt    302 std::istream& HepRandom::restoreStaticRandomStates ( std::istream & is ) {
303   return StaticRandomStates::restore(is);         303   return StaticRandomStates::restore(is);
304 }                                                 304 }
305                                                   305 
306 void HepRandom::showEngineStatus()                306 void HepRandom::showEngineStatus()
307 {                                                 307 {
308   theDefaults().theEngine->showStatus();          308   theDefaults().theEngine->showStatus();
309 }                                                 309 }
310                                                   310 
311 int HepRandom::createInstance()                   311 int HepRandom::createInstance()
312 {                                                 312 {
313   return static_cast<int>( theDefaults().ensur    313   return static_cast<int>( theDefaults().ensureInitialized() );
314 }                                                 314 }
315                                                   315 
316 }  // namespace CLHEP                             316 }  // namespace CLHEP
317                                                   317