Geant4-11
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
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
61 assert( theGenerator.get() != 0 && theEngine.get() != 0 );
62 return true;
63 }
64
66 { }
67
68 private:
69
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.
168 static defaults theDefaults;
169 return theDefaults;
170 }
171
172#endif
173
174 } // namespace
175
176//---------------------------- HepRandom ---------------------------------
177
179{ }
180
182{
183 setTheSeed(seed);
184}
185
187{
188 theDefaults().resetEngine( algorithm );
189}
190
192{
193 theDefaults().resetEngine( algorithm );
194}
195
197{ }
198
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
210 return flat();
211}
212
213std::string HepRandom::name() const {return "HepRandom";}
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
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
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
264{
265 return theDefaults().theGenerator.get();
266}
267
269{
270 return theDefaults().theEngine.get();
271}
272
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 ) {
304}
305
307{
308 theDefaults().theEngine->showStatus();
309}
310
312{
313 return static_cast<int>( theDefaults().ensureInitialized() );
314}
315
316} // namespace CLHEP
static HepRandom * getTheGenerator()
Definition: Random.cc:263
static HepRandomEngine * getTheEngine()
Definition: Random.cc:268
static const long * getTheSeeds()
Definition: Random.cc:249
virtual double operator()()
Definition: Random.cc:209
void flatArray(const int size, double *vect)
Definition: Random.cc:204
static std::ostream & saveStaticRandomStates(std::ostream &os)
Definition: Random.cc:298
static std::ostream & saveFullState(std::ostream &os)
Definition: Random.cc:288
virtual HepRandomEngine & engine()
Definition: Random.cc:214
static std::istream & restoreFullState(std::istream &is)
Definition: Random.cc:293
static void restoreEngineStatus(const char filename[]="Config.conf")
Definition: Random.cc:283
static void showEngineStatus()
Definition: Random.cc:306
virtual std::istream & get(std::istream &is)
Definition: Random.cc:228
static int createInstance()
Definition: Random.cc:311
static long getTheSeed()
Definition: Random.cc:239
static void setTheSeeds(const long *seeds, int aux=-1)
Definition: Random.cc:244
virtual ~HepRandom()
Definition: Random.cc:196
static void setTheSeed(long seed, int lxr=3)
Definition: Random.cc:234
virtual std::ostream & put(std::ostream &os) const
Definition: Random.cc:227
double flat()
Definition: Random.cc:199
static void setTheEngine(HepRandomEngine *theNewEngine)
Definition: Random.cc:273
virtual std::string name() const
Definition: Random.cc:213
static void saveEngineStatus(const char filename[]="Config.conf")
Definition: Random.cc:278
static void getTheTableSeeds(long *seeds, int index)
Definition: Random.cc:254
static std::istream & restoreStaticRandomStates(std::istream &is)
Definition: Random.cc:302
static std::istream & restore(std::istream &is)
static std::ostream & save(std::ostream &os)
Definition: DoubConv.h:17
std::istream & operator>>(std::istream &is, HepRandom &dist)
Definition: Random.cc:223
static constexpr double lux
std::ostream & operator<<(std::ostream &os, const HepRandom &dist)
Definition: Random.cc:219
double flat()
Definition: G4AblaRandom.cc:48
G4ThreadLocal IRandomGenerator * theGenerator
Definition: G4INCLRandom.cc:60
void resetEngine(HepRandomEngine *newEngine)
Definition: Random.cc:52
std::shared_ptr< HepRandomEngine > theEngine
Definition: Random.cc:76
defaults const & operator=(defaults const &)=delete
std::shared_ptr< HepRandom > theGenerator
Definition: Random.cc:75
defaults(defaults const &other)=delete
void resetEngine(HepRandomEngine &newEngine)
Definition: Random.cc:56
#define CLHEP_THREAD_LOCAL
Definition: thread_local.h:13