CLHEP 2.4.6.4
C++ Class Library for High Energy Physics
Loading...
Searching...
No Matches
RandGauss.cc
Go to the documentation of this file.
1//
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
35#include "CLHEP/Random/defs.h"
36#include "CLHEP/Random/RandGauss.h"
37#include "CLHEP/Random/DoubConv.h"
38#include <cmath> // for std::log()
39#include <iostream>
40#include <string.h> // for strcmp
41#include <string>
42#include <vector>
43
44namespace CLHEP {
45
46std::string RandGauss::name() const {return "RandGauss";}
48
49// Initialisation of static data
50CLHEP_THREAD_LOCAL bool RandGauss::set_st = false;
51CLHEP_THREAD_LOCAL double RandGauss::nextGauss_st = 0.0;
52
54}
55
58}
59
60double RandGauss::operator()( double mean, double stdDev ) {
61 return fire( mean, stdDev );
62}
63
65{
66 // Gaussian random numbers are generated two at the time, so every other
67 // time this is called we just return a number generated the time before.
68
69 if ( getFlag() ) {
70 setFlag(false);
71 double x = getVal();
72 return x;
73 // return getVal();
74 }
75
76 double r;
77 double v1,v2,fac,val;
79
80 do {
81 v1 = 2.0 * anEngine->flat() - 1.0;
82 v2 = 2.0 * anEngine->flat() - 1.0;
83 r = v1*v1 + v2*v2;
84 } while ( r > 1.0 );
85
86 fac = std::sqrt(-2.0*std::log(r)/r);
87 val = v1*fac;
88 setVal(val);
89 setFlag(true);
90 return v2*fac;
91}
92
93void RandGauss::shootArray( const int size, double* vect,
94 double mean, double stdDev )
95{
96 for( double* v = vect; v != vect + size; ++v )
97 *v = shoot(mean,stdDev);
98}
99
101{
102 // Gaussian random numbers are generated two at the time, so every other
103 // time this is called we just return a number generated the time before.
104
105 if ( getFlag() ) {
106 setFlag(false);
107 return getVal();
108 }
109
110 double r;
111 double v1,v2,fac,val;
112
113 do {
114 v1 = 2.0 * anEngine->flat() - 1.0;
115 v2 = 2.0 * anEngine->flat() - 1.0;
116 r = v1*v1 + v2*v2;
117 } while ( r > 1.0 );
118
119 fac = std::sqrt( -2.0*std::log(r)/r);
120 val = v1*fac;
121 setVal(val);
122 setFlag(true);
123 return v2*fac;
124}
125
127 const int size, double* vect,
128 double mean, double stdDev )
129{
130 for( double* v = vect; v != vect + size; ++v )
131 *v = shoot(anEngine,mean,stdDev);
132}
133
135{
136 // Gaussian random numbers are generated two at the time, so every other
137 // time this is called we just return a number generated the time before.
138
139 if ( set ) {
140 set = false;
141 return nextGauss;
142 }
143
144 double r;
145 double v1,v2,fac,val;
146
147 do {
148 v1 = 2.0 * localEngine->flat() - 1.0;
149 v2 = 2.0 * localEngine->flat() - 1.0;
150 r = v1*v1 + v2*v2;
151 } while ( r > 1.0 );
152
153 fac = std::sqrt(-2.0*std::log(r)/r);
154 val = v1*fac;
155 nextGauss = val;
156 set = true;
157 return v2*fac;
158}
159
160void RandGauss::fireArray( const int size, double* vect)
161{
162 for( double* v = vect; v != vect + size; ++v )
164}
165
166void RandGauss::fireArray( const int size, double* vect,
167 double mean, double stdDev )
168{
169 for( double* v = vect; v != vect + size; ++v )
170 *v = fire( mean, stdDev );
171}
172
174{
175 return set_st;
176}
177
178void RandGauss::setFlag( bool val )
179{
180 set_st = val;
181}
182
184{
185 return nextGauss_st;
186}
187
188void RandGauss::setVal( double nextVal )
189{
190 nextGauss_st = nextVal;
191}
192
193void RandGauss::saveEngineStatus ( const char filename[] ) {
194
195 // First save the engine status just like the base class would do:
196 getTheEngine()->saveStatus( filename );
197
198 // Now append the cached variate, if any:
199
200 std::ofstream outfile ( filename, std::ios::app );
201
202 if ( getFlag() ) {
203 std::vector<unsigned long> t(2);
205 outfile << "RANDGAUSS CACHED_GAUSSIAN: Uvec "
206 << getVal() << " " << t[0] << " " << t[1] << "\n";
207 } else {
208 outfile << "RANDGAUSS NO_CACHED_GAUSSIAN: 0 \n" ;
209 }
210
211} // saveEngineStatus
212
213void RandGauss::restoreEngineStatus( const char filename[] ) {
214
215 // First restore the engine status just like the base class would do:
216 getTheEngine()->restoreStatus( filename );
217
218 // Now find the line describing the cached variate:
219
220 std::ifstream infile ( filename, std::ios::in );
221 if (!infile) return;
222
223 char inputword[] = "NO_KEYWORD "; // leaves room for 14 characters plus \0
224 while (true) {
225 infile.width(13);
226 infile >> inputword;
227 if (strcmp(inputword,"RANDGAUSS")==0) break;
228 if (infile.eof()) break;
229 // If the file ends without the RANDGAUSS line, that means this
230 // was a file produced by an earlier version of RandGauss. We will
231 // replicated the old behavior in that case: set_st is cleared.
232 }
233
234 // Then read and use the caching info:
235
236 if (strcmp(inputword,"RANDGAUSS")==0) {
237 char setword[40]; // the longest, staticFirstUnusedBit: has length 21
238 infile.width(39);
239 infile >> setword; // setword should be CACHED_GAUSSIAN:
240 if (strcmp(setword,"CACHED_GAUSSIAN:") ==0) {
241 if (possibleKeywordInput(infile, "Uvec", nextGauss_st)) {
242 std::vector<unsigned long> t(2);
243 infile >> nextGauss_st >> t[0] >> t[1];
244 nextGauss_st = DoubConv::longs2double(t);
245 }
246 // is >> nextGauss_st encompassed by possibleKeywordInput
247 setFlag(true);
248 } else {
249 setFlag(false);
250 infile >> nextGauss_st; // because a 0 will have been output
251 }
252 } else {
253 setFlag(false);
254 }
255
256} // restoreEngineStatus
257
258 // Save and restore to/from streams
259
260std::ostream & RandGauss::put ( std::ostream & os ) const {
261 os << name() << "\n";
262 long prec = os.precision(20);
263 std::vector<unsigned long> t(2);
264 os << "Uvec\n";
266 os << defaultMean << " " << t[0] << " " << t[1] << "\n";
268 os << defaultStdDev << " " << t[0] << " " << t[1] << "\n";
269 if ( set ) {
270 t = DoubConv::dto2longs(nextGauss);
271 os << "nextGauss " << nextGauss << " " << t[0] << " " << t[1] << "\n";
272 #ifdef TRACE_IO
273 std::cout << "put(): nextGauss = " << nextGauss << "\n";
274 #endif
275 } else {
276 #ifdef TRACE_IO
277 std::cout << "put(): No nextGauss \n";
278 #endif
279 os << "no_cached_nextGauss \n";
280 }
281 os.precision(prec);
282 return os;
283} // put
284
285std::istream & RandGauss::get ( std::istream & is ) {
286 std::string inName;
287 is >> inName;
288 if (inName != name()) {
289 is.clear(std::ios::badbit | is.rdstate());
290 std::cerr << "Mismatch when expecting to read state of a "
291 << name() << " distribution\n"
292 << "Name found was " << inName
293 << "\nistream is left in the badbit state\n";
294 return is;
295 }
296 std::string c1;
297 std::string c2;
298 if (possibleKeywordInput(is, "Uvec", c1)) {
299 std::vector<unsigned long> t(2);
300 is >> defaultMean >> t[0] >> t[1]; defaultMean = DoubConv::longs2double(t);
301 is >> defaultStdDev>>t[0]>>t[1]; defaultStdDev = DoubConv::longs2double(t);
302 std::string ng;
303 is >> ng;
304 set = false;
305 #ifdef TRACE_IO
306 if (ng != "nextGauss")
307 std::cout << "get(): ng = " << ng << "\n";
308 #endif
309 if (ng == "nextGauss") {
310 is >> nextGauss >> t[0] >> t[1]; nextGauss = DoubConv::longs2double(t);
311 #ifdef TRACE_IO
312 std::cout << "get(): nextGauss read back as " << nextGauss << "\n";
313 #endif
314 set = true;
315 }
316 return is;
317 }
318 // is >> c1 encompassed by possibleKeywordInput
319 is >> defaultMean >> c2 >> defaultStdDev;
320 if ( (!is) || (c1 != "Mean:") || (c2 != "Sigma:") ) {
321 std::cerr << "i/o problem while expecting to read state of a "
322 << name() << " distribution\n"
323 << "default mean and/or sigma could not be read\n";
324 return is;
325 }
326 is >> c1 >> c2 >> nextGauss;
327 if ( (!is) || (c1 != "RANDGAUSS") ) {
328 is.clear(std::ios::badbit | is.rdstate());
329 std::cerr << "Failure when reading caching state of RandGauss\n";
330 return is;
331 }
332 if (c2 == "CACHED_GAUSSIAN:") {
333 set = true;
334 } else if (c2 == "NO_CACHED_GAUSSIAN:") {
335 set = false;
336 } else {
337 is.clear(std::ios::badbit | is.rdstate());
338 std::cerr << "Unexpected caching state keyword of RandGauss:" << c2
339 << "\nistream is left in the badbit state\n";
340 }
341 return is;
342} // get
343
344 // Static save and restore to/from streams
345
346std::ostream & RandGauss::saveDistState ( std::ostream & os ) {
347 long prec = os.precision(20);
348 std::vector<unsigned long> t(2);
349 os << distributionName() << "\n";
350 os << "Uvec\n";
351 if ( getFlag() ) {
353 os << "nextGauss_st " << getVal() << " " << t[0] << " " << t[1] << "\n";
354 } else {
355 os << "no_cached_nextGauss_st \n";
356 }
357 os.precision(prec);
358 return os;
359}
360
361std::istream & RandGauss::restoreDistState ( std::istream & is ) {
362 std::string inName;
363 is >> inName;
364 if (inName != distributionName()) {
365 is.clear(std::ios::badbit | is.rdstate());
366 std::cerr << "Mismatch when expecting to read static state of a "
367 << distributionName() << " distribution\n"
368 << "Name found was " << inName
369 << "\nistream is left in the badbit state\n";
370 return is;
371 }
372 std::string c1;
373 std::string c2;
374 if (possibleKeywordInput(is, "Uvec", c1)) {
375 std::vector<unsigned long> t(2);
376 std::string ng;
377 is >> ng;
378 setFlag (false);
379 if (ng == "nextGauss_st") {
380 is >> nextGauss_st >> t[0] >> t[1];
381 nextGauss_st = DoubConv::longs2double(t);
382 setFlag (true);
383 }
384 return is;
385 }
386 // is >> c1 encompassed by possibleKeywordInput
387 is >> c2 >> nextGauss_st;
388 if ( (!is) || (c1 != "RANDGAUSS") ) {
389 is.clear(std::ios::badbit | is.rdstate());
390 std::cerr << "Failure when reading caching state of static RandGauss\n";
391 return is;
392 }
393 if (c2 == "CACHED_GAUSSIAN:") {
394 setFlag(true);
395 } else if (c2 == "NO_CACHED_GAUSSIAN:") {
396 setFlag(false);
397 } else {
398 is.clear(std::ios::badbit | is.rdstate());
399 std::cerr << "Unexpected caching state keyword of static RandGauss:" << c2
400 << "\nistream is left in the badbit state\n";
401 }
402 return is;
403}
404
405std::ostream & RandGauss::saveFullState ( std::ostream & os ) {
407 saveDistState(os);
408 return os;
409}
410
411std::istream & RandGauss::restoreFullState ( std::istream & is ) {
414 return is;
415}
416
417} // namespace CLHEP
418
static double longs2double(const std::vector< unsigned long > &v)
Definition: DoubConv.cc:110
static std::vector< unsigned long > dto2longs(double d)
Definition: DoubConv.cc:94
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:270
static std::ostream & saveFullState(std::ostream &os)
Definition: Random.cc:290
static std::istream & restoreFullState(std::istream &is)
Definition: Random.cc:295
static std::ostream & saveDistState(std::ostream &os)
Definition: RandGauss.cc:346
std::string name() const
Definition: RandGauss.cc:46
static std::istream & restoreFullState(std::istream &is)
Definition: RandGauss.cc:411
static void restoreEngineStatus(const char filename[]="Config.conf")
Definition: RandGauss.cc:213
static double shoot()
Definition: RandGauss.cc:64
static bool getFlag()
Definition: RandGauss.cc:173
static double getVal()
Definition: RandGauss.cc:183
std::istream & get(std::istream &is)
Definition: RandGauss.cc:285
double defaultStdDev
Definition: RandGauss.h:154
std::ostream & put(std::ostream &os) const
Definition: RandGauss.cc:260
void fireArray(const int size, double *vect)
Definition: RandGauss.cc:160
static void shootArray(const int size, double *vect, double mean=0.0, double stdDev=1.0)
Definition: RandGauss.cc:93
static void setVal(double nextVal)
Definition: RandGauss.cc:188
HepRandomEngine & engine()
Definition: RandGauss.cc:47
static std::ostream & saveFullState(std::ostream &os)
Definition: RandGauss.cc:405
double normal()
Definition: RandGauss.cc:134
double defaultMean
Definition: RandGauss.h:153
static void setFlag(bool val)
Definition: RandGauss.cc:178
static std::string distributionName()
Definition: RandGauss.h:101
std::shared_ptr< HepRandomEngine > localEngine
Definition: RandGauss.h:156
virtual ~RandGauss()
Definition: RandGauss.cc:53
static std::istream & restoreDistState(std::istream &is)
Definition: RandGauss.cc:361
virtual double operator()()
Definition: RandGauss.cc:56
static void saveEngineStatus(const char filename[]="Config.conf")
Definition: RandGauss.cc:193
bool possibleKeywordInput(IS &is, const std::string &key, T &t)
Definition: RandomEngine.h:168