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