Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
RandGauss.cc
Go to the documentation of this file.
1// $Id:$
2// -*- C++ -*-
3//
4// -----------------------------------------------------------------------
5// HEP Random
6// --- RandGauss ---
7// class implementation file
8// -----------------------------------------------------------------------
9// This file is part of Geant4 (simulation toolkit for HEP).
10
11// =======================================================================
12// Gabriele Cosmo - Created: 5th September 1995
13// - Added methods to shoot arrays: 28th July 1997
14// J.Marraffino - Added default arguments as attributes and
15// operator() with arguments. Introduced method normal()
16// for computation in fire(): 16th Feb 1998
17// Gabriele Cosmo - Relocated static data from HepRandom: 5th Jan 1999
18// M Fischler - Copy constructor should supply right engine to HepRandom:
19// 1/26/00.
20// M Fischler - Workaround for problem of non-reproducing saveEngineStatus
21// by saving cached gaussian. March 2000.
22// M Fischler - Avoiding hang when file not found in restoreEngineStatus
23// 12/3/04
24// M Fischler - put and get to/from streams 12/8/04
25// M Fischler - save and restore dist to streams 12/20/04
26// M Fischler - put/get to/from streams uses pairs of ulongs when
27// storing doubles avoid problems with precision.
28// Similarly for saveEngineStatus and RestoreEngineStatus
29// and for save/restore distState
30// Care was taken that old-form output can still be read back.
31// 4/14/05
32//
33// =======================================================================
34
37#include <string.h> // for strcmp
38#include <cmath> // for std::log()
39
40namespace CLHEP {
41
42std::string RandGauss::name() const {return "RandGauss";}
44
45// Initialisation of static data
46bool RandGauss::set_st = false;
47double RandGauss::nextGauss_st = 0.0;
48
50}
51
54}
55
56double RandGauss::operator()( double mean, double stdDev ) {
57 return fire( mean, stdDev );
58}
59
61{
62 // Gaussian random numbers are generated two at the time, so every other
63 // time this is called we just return a number generated the time before.
64
65 if ( getFlag() ) {
66 setFlag(false);
67 double x = getVal();
68 return x;
69 // return getVal();
70 }
71
72 double r;
73 double v1,v2,fac,val;
75
76 do {
77 v1 = 2.0 * anEngine->flat() - 1.0;
78 v2 = 2.0 * anEngine->flat() - 1.0;
79 r = v1*v1 + v2*v2;
80 } while ( r > 1.0 );
81
82 fac = std::sqrt(-2.0*std::log(r)/r);
83 val = v1*fac;
84 setVal(val);
85 setFlag(true);
86 return v2*fac;
87}
88
89void RandGauss::shootArray( const int size, double* vect,
90 double mean, double stdDev )
91{
92 for( double* v = vect; v != vect + size; ++v )
93 *v = shoot(mean,stdDev);
94}
95
97{
98 // Gaussian random numbers are generated two at the time, so every other
99 // time this is called we just return a number generated the time before.
100
101 if ( getFlag() ) {
102 setFlag(false);
103 return getVal();
104 }
105
106 double r;
107 double v1,v2,fac,val;
108
109 do {
110 v1 = 2.0 * anEngine->flat() - 1.0;
111 v2 = 2.0 * anEngine->flat() - 1.0;
112 r = v1*v1 + v2*v2;
113 } while ( r > 1.0 );
114
115 fac = std::sqrt( -2.0*std::log(r)/r);
116 val = v1*fac;
117 setVal(val);
118 setFlag(true);
119 return v2*fac;
120}
121
123 const int size, double* vect,
124 double mean, double stdDev )
125{
126 for( double* v = vect; v != vect + size; ++v )
127 *v = shoot(anEngine,mean,stdDev);
128}
129
131{
132 // Gaussian random numbers are generated two at the time, so every other
133 // time this is called we just return a number generated the time before.
134
135 if ( set ) {
136 set = false;
137 return nextGauss;
138 }
139
140 double r;
141 double v1,v2,fac,val;
142
143 do {
144 v1 = 2.0 * localEngine->flat() - 1.0;
145 v2 = 2.0 * localEngine->flat() - 1.0;
146 r = v1*v1 + v2*v2;
147 } while ( r > 1.0 );
148
149 fac = std::sqrt(-2.0*std::log(r)/r);
150 val = v1*fac;
151 nextGauss = val;
152 set = true;
153 return v2*fac;
154}
155
156void RandGauss::fireArray( const int size, double* vect)
157{
158 for( double* v = vect; v != vect + size; ++v )
160}
161
162void RandGauss::fireArray( const int size, double* vect,
163 double mean, double stdDev )
164{
165 for( double* v = vect; v != vect + size; ++v )
166 *v = fire( mean, stdDev );
167}
168
169void RandGauss::saveEngineStatus ( const char filename[] ) {
170
171 // First save the engine status just like the base class would do:
172 getTheEngine()->saveStatus( filename );
173
174 // Now append the cached variate, if any:
175
176 std::ofstream outfile ( filename, std::ios::app );
177
178 if ( getFlag() ) {
179 std::vector<unsigned long> t(2);
181 outfile << "RANDGAUSS CACHED_GAUSSIAN: Uvec "
182 << getVal() << " " << t[0] << " " << t[1] << "\n";
183 } else {
184 outfile << "RANDGAUSS NO_CACHED_GAUSSIAN: 0 \n" ;
185 }
186
187} // saveEngineStatus
188
189void RandGauss::restoreEngineStatus( const char filename[] ) {
190
191 // First restore the engine status just like the base class would do:
192 getTheEngine()->restoreStatus( filename );
193
194 // Now find the line describing the cached variate:
195
196 std::ifstream infile ( filename, std::ios::in );
197 if (!infile) return;
198
199 char inputword[] = "NO_KEYWORD "; // leaves room for 14 characters plus \0
200 while (true) {
201 infile.width(13);
202 infile >> inputword;
203 if (strcmp(inputword,"RANDGAUSS")==0) break;
204 if (infile.eof()) break;
205 // If the file ends without the RANDGAUSS line, that means this
206 // was a file produced by an earlier version of RandGauss. We will
207 // replicated the old behavior in that case: set_st is cleared.
208 }
209
210 // Then read and use the caching info:
211
212 if (strcmp(inputword,"RANDGAUSS")==0) {
213 char setword[40]; // the longest, staticFirstUnusedBit: has length 21
214 infile.width(39);
215 infile >> setword; // setword should be CACHED_GAUSSIAN:
216 if (strcmp(setword,"CACHED_GAUSSIAN:") ==0) {
217 if (possibleKeywordInput(infile, "Uvec", nextGauss_st)) {
218 std::vector<unsigned long> t(2);
219 infile >> nextGauss_st >> t[0] >> t[1];
220 nextGauss_st = DoubConv::longs2double(t);
221 }
222 // is >> nextGauss_st encompassed by possibleKeywordInput
223 setFlag(true);
224 } else {
225 setFlag(false);
226 infile >> nextGauss_st; // because a 0 will have been output
227 }
228 } else {
229 setFlag(false);
230 }
231
232} // restoreEngineStatus
233
234 // Save and restore to/from streams
235
236std::ostream & RandGauss::put ( std::ostream & os ) const {
237 os << name() << "\n";
238 int prec = os.precision(20);
239 std::vector<unsigned long> t(2);
240 os << "Uvec\n";
242 os << defaultMean << " " << t[0] << " " << t[1] << "\n";
244 os << defaultStdDev << " " << t[0] << " " << t[1] << "\n";
245 if ( set ) {
246 t = DoubConv::dto2longs(nextGauss);
247 os << "nextGauss " << nextGauss << " " << t[0] << " " << t[1] << "\n";
248 } else {
249 os << "no_cached_nextGauss \n";
250 }
251 os.precision(prec);
252 return os;
253} // put
254
255std::istream & RandGauss::get ( std::istream & is ) {
256 std::string inName;
257 is >> inName;
258 if (inName != name()) {
259 is.clear(std::ios::badbit | is.rdstate());
260 std::cerr << "Mismatch when expecting to read state of a "
261 << name() << " distribution\n"
262 << "Name found was " << inName
263 << "\nistream is left in the badbit state\n";
264 return is;
265 }
266 std::string c1;
267 std::string c2;
268 if (possibleKeywordInput(is, "Uvec", c1)) {
269 std::vector<unsigned long> t(2);
270 is >> defaultMean >> t[0] >> t[1]; defaultMean = DoubConv::longs2double(t);
271 is >> defaultStdDev>>t[0]>>t[1]; defaultStdDev = DoubConv::longs2double(t);
272 std::string ng;
273 is >> ng;
274 set = false;
275 if (ng == "nextGauss") {
276 is >> nextGauss >> t[0] >> t[1]; nextGauss = DoubConv::longs2double(t);
277 set = true;
278 }
279 return is;
280 }
281 // is >> c1 encompassed by possibleKeywordInput
282 is >> defaultMean >> c2 >> defaultStdDev;
283 if ( (!is) || (c1 != "Mean:") || (c2 != "Sigma:") ) {
284 std::cerr << "i/o problem while expecting to read state of a "
285 << name() << " distribution\n"
286 << "default mean and/or sigma could not be read\n";
287 return is;
288 }
289 is >> c1 >> c2 >> nextGauss;
290 if ( (!is) || (c1 != "RANDGAUSS") ) {
291 is.clear(std::ios::badbit | is.rdstate());
292 std::cerr << "Failure when reading caching state of RandGauss\n";
293 return is;
294 }
295 if (c2 == "CACHED_GAUSSIAN:") {
296 set = true;
297 } else if (c2 == "NO_CACHED_GAUSSIAN:") {
298 set = false;
299 } else {
300 is.clear(std::ios::badbit | is.rdstate());
301 std::cerr << "Unexpected caching state keyword of RandGauss:" << c2
302 << "\nistream is left in the badbit state\n";
303 }
304 return is;
305} // get
306
307 // Static save and restore to/from streams
308
309std::ostream & RandGauss::saveDistState ( std::ostream & os ) {
310 int prec = os.precision(20);
311 std::vector<unsigned long> t(2);
312 os << distributionName() << "\n";
313 os << "Uvec\n";
314 if ( getFlag() ) {
316 os << "nextGauss_st " << getVal() << " " << t[0] << " " << t[1] << "\n";
317 } else {
318 os << "no_cached_nextGauss_st \n";
319 }
320 os.precision(prec);
321 return os;
322}
323
324std::istream & RandGauss::restoreDistState ( std::istream & is ) {
325 std::string inName;
326 is >> inName;
327 if (inName != distributionName()) {
328 is.clear(std::ios::badbit | is.rdstate());
329 std::cerr << "Mismatch when expecting to read static state of a "
330 << distributionName() << " distribution\n"
331 << "Name found was " << inName
332 << "\nistream is left in the badbit state\n";
333 return is;
334 }
335 std::string c1;
336 std::string c2;
337 if (possibleKeywordInput(is, "Uvec", c1)) {
338 std::vector<unsigned long> t(2);
339 std::string ng;
340 is >> ng;
341 setFlag (false);
342 if (ng == "nextGauss_st") {
343 is >> nextGauss_st >> t[0] >> t[1];
344 nextGauss_st = DoubConv::longs2double(t);
345 setFlag (true);
346 }
347 return is;
348 }
349 // is >> c1 encompassed by possibleKeywordInput
350 is >> c2 >> nextGauss_st;
351 if ( (!is) || (c1 != "RANDGAUSS") ) {
352 is.clear(std::ios::badbit | is.rdstate());
353 std::cerr << "Failure when reading caching state of static RandGauss\n";
354 return is;
355 }
356 if (c2 == "CACHED_GAUSSIAN:") {
357 setFlag(true);
358 } else if (c2 == "NO_CACHED_GAUSSIAN:") {
359 setFlag(false);
360 } else {
361 is.clear(std::ios::badbit | is.rdstate());
362 std::cerr << "Unexpected caching state keyword of static RandGauss:" << c2
363 << "\nistream is left in the badbit state\n";
364 }
365 return is;
366}
367
368std::ostream & RandGauss::saveFullState ( std::ostream & os ) {
370 saveDistState(os);
371 return os;
372}
373
374std::istream & RandGauss::restoreFullState ( std::istream & is ) {
377 return is;
378}
379
380} // namespace CLHEP
381
static double longs2double(const std::vector< unsigned long > &v)
Definition: DoubConv.cc:114
static std::vector< unsigned long > dto2longs(double d)
Definition: DoubConv.cc:98
virtual void restoreStatus(const char filename[]="Config.conf")=0
virtual double flat()=0
virtual void saveStatus(const char filename[]="Config.conf") const =0
static HepRandomEngine * getTheEngine()
Definition: Random.cc:165
static std::ostream & saveFullState(std::ostream &os)
Definition: Random.cc:185
static std::istream & restoreFullState(std::istream &is)
Definition: Random.cc:190
static std::ostream & saveDistState(std::ostream &os)
Definition: RandGauss.cc:309
std::string name() const
Definition: RandGauss.cc:42
static std::istream & restoreFullState(std::istream &is)
Definition: RandGauss.cc:374
static void restoreEngineStatus(const char filename[]="Config.conf")
Definition: RandGauss.cc:189
static double shoot()
Definition: RandGauss.cc:60
std::istream & get(std::istream &is)
Definition: RandGauss.cc:255
double defaultStdDev
Definition: RandGauss.h:152
std::ostream & put(std::ostream &os) const
Definition: RandGauss.cc:236
void fireArray(const int size, double *vect)
Definition: RandGauss.cc:156
static void shootArray(const int size, double *vect, double mean=0.0, double stdDev=1.0)
Definition: RandGauss.cc:89
HepRandomEngine & engine()
Definition: RandGauss.cc:43
static std::ostream & saveFullState(std::ostream &os)
Definition: RandGauss.cc:368
double normal()
Definition: RandGauss.cc:130
shared_ptr< HepRandomEngine > localEngine
Definition: RandGauss.h:154
double defaultMean
Definition: RandGauss.h:151
static std::string distributionName()
Definition: RandGauss.h:99
static double getVal()
Definition: RandGauss.h:145
static bool getFlag()
Definition: RandGauss.h:111
static void setVal(double nextVal)
Definition: RandGauss.h:147
static void setFlag(bool val)
Definition: RandGauss.h:113
virtual ~RandGauss()
Definition: RandGauss.cc:49
static std::istream & restoreDistState(std::istream &is)
Definition: RandGauss.cc:324
virtual double operator()()
Definition: RandGauss.cc:52
static void saveEngineStatus(const char filename[]="Config.conf")
Definition: RandGauss.cc:169
Definition: DoubConv.h:17
bool possibleKeywordInput(IS &is, const std::string &key, T &t)
Definition: RandomEngine.h:167