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