1 // $Id: RandFlat.cc,v 1.6 2010/06/16 17:24:53 garren Exp $
2 // -*- C++ -*-
3 //
4 // -----------------------------------------------------------------------
5 // HEP Random
6 // --- RandFlat ---
7 // class implementation file
8 // -----------------------------------------------------------------------
9 // This file is part of Geant4 (simulation toolkit for HEP).
10
11 // =======================================================================
12 // Gabriele Cosmo - Created: 17th May 1995
13 // - Added methods to shoot arrays: 28th July 1997
14 // - Added operator(): 24th Jul 1997
15 // J.Marraffino - Added default arguments as attributes and
16 // operator() with arguments: 16th Feb 1998
17 // M Fischler - Copy constructor should supply right engine to HepRandom:
18 // 1/26/00.
19 // M Fischler - Semi-fix to the saveEngineStatus misbehavior causing
20 // non-reproducing shootBit() 3/1/00.
21 // M Fischler - Avoiding hang when file not found in restoreEngineStatus
22 // 12/3/04
23 // M Fischler - put and get to/from streams 12/10/04
24 // M Fischler - save and restore dist to streams 12/20/04
25 // M Fischler - put/get to/from streams uses pairs of ulongs when
26 // + storing doubles avoid problems with precision
27 // 4/14/05
28 // =======================================================================
29
30 #include "CLHEP/Random/defs.h"
31 #include "CLHEP/Random/RandFlat.h"
32 #include "CLHEP/Random/DoubConv.hh"
33 #include <string.h> // for strcmp
34
35 namespace CLHEP {
36
37 const int RandFlat::MSBBits= 15;
38 const unsigned long RandFlat::MSB= 1ul<<RandFlat::MSBBits;
39 CLHEP_THREAD_LOCAL unsigned long RandFlat::staticRandomInt= 0;
40 CLHEP_THREAD_LOCAL unsigned long RandFlat::staticFirstUnusedBit= 0;
41
name() const42 std::string RandFlat::name() const {return "RandFlat";}
engine()43 HepRandomEngine & RandFlat::engine() {return *localEngine;}
44
~RandFlat()45 RandFlat::~RandFlat() {
46 }
47
operator ()()48 double RandFlat::operator()() {
49 return fire( defaultA, defaultB );
50 }
51
operator ()(double w)52 double RandFlat::operator()( double w ) {
53 return fire( w );
54 }
55
operator ()(double a,double b)56 double RandFlat::operator()( double a, double b ) {
57 return fire( a, b );
58 }
59
shoot()60 double RandFlat::shoot() {
61 return HepRandom::getTheEngine()->flat();
62 }
63
shootArray(const int size,double * vect)64 void RandFlat::shootArray(const int size, double* vect) {
65 HepRandom::getTheEngine()->flatArray(size,vect);
66 }
67
shootArray(const int size,double * vect,double lx,double dx)68 void RandFlat::shootArray( const int size, double* vect,
69 double lx, double dx )
70 {
71 int i;
72
73 for (i=0; i<size; ++i)
74 vect[i] = shoot(lx,dx);
75 }
76
shootArray(HepRandomEngine * anEngine,const int size,double * vect,double lx,double dx)77 void RandFlat::shootArray( HepRandomEngine* anEngine,
78 const int size, double* vect,
79 double lx, double dx )
80 {
81 int i;
82
83 for (i=0; i<size; ++i)
84 vect[i] = shoot(anEngine,lx,dx);
85 }
86
fireArray(const int size,double * vect)87 void RandFlat::fireArray( const int size, double* vect)
88 {
89 int i;
90
91 for (i=0; i<size; ++i)
92 vect[i] = fire( defaultA, defaultB );
93 }
94
fireArray(const int size,double * vect,double lx,double dx)95 void RandFlat::fireArray( const int size, double* vect,
96 double lx, double dx )
97 {
98 int i;
99
100 for (i=0; i<size; ++i)
101 vect[i] = fire( lx, dx );
102 }
103
saveEngineStatus(const char filename[])104 void RandFlat::saveEngineStatus ( const char filename[] ) {
105
106 // First save the engine status just like the base class would do:
107 getTheEngine()->saveStatus( filename );
108
109 // Now append the cached random Int, and first unused bit:
110
111 std::ofstream outfile ( filename, std::ios::app );
112
113 outfile << "RANDFLAT staticRandomInt: " << staticRandomInt
114 << " staticFirstUnusedBit: " << staticFirstUnusedBit << "\n";
115
116 } // saveEngineStatus
117
118
restoreEngineStatus(const char filename[])119 void RandFlat::restoreEngineStatus( const char filename[] ) {
120
121 // First restore the engine status just like the base class would do:
122 getTheEngine()->restoreStatus( filename );
123
124 // Now find the line describing the cached data:
125
126 std::ifstream infile ( filename, std::ios::in );
127 if (!infile) return;
128 char inputword[] = "NO_KEYWORD "; // leaves room for 14 characters plus \0
129 while (true) {
130 infile.width(13);
131 infile >> inputword;
132 if (strcmp(inputword,"RANDFLAT")==0) break;
133 if (infile.eof()) break;
134 // If the file ends without the RANDFLAT line, that means this
135 // was a file produced by an earlier version of RandFlat. We will
136 // replicate the old behavior in that case: staticFirstUnusedBit
137 // and staticRandomInt retain their existing values.
138 }
139
140 // Then read and use the caching info:
141
142 if (strcmp(inputword,"RANDFLAT")==0) {
143 char setword[40]; // the longest, staticFirstUnusedBit: has length 21
144 infile.width(39);
145 infile >> setword;
146 // setword should be staticRandomInt:
147 infile >> staticRandomInt;
148 infile.width(39);
149 infile >> setword;
150 // setword should be staticFirstUnusedBit:
151 infile >> staticFirstUnusedBit;
152 }
153
154 } // restoreEngineStatus
155
put(std::ostream & os) const156 std::ostream & RandFlat::put ( std::ostream & os ) const {
157 int pr=os.precision(20);
158 std::vector<unsigned long> t(2);
159 os << " " << name() << "\n";
160 os << "Uvec" << "\n";
161 os << randomInt << " " << firstUnusedBit << "\n";
162 t = DoubConv::dto2longs(defaultWidth);
163 os << defaultWidth << " " << t[0] << " " << t[1] << "\n";
164 t = DoubConv::dto2longs(defaultA);
165 os << defaultA << " " << t[0] << " " << t[1] << "\n";
166 t = DoubConv::dto2longs(defaultB);
167 os << defaultB << " " << t[0] << " " << t[1] << "\n";
168 #ifdef TRACE_IO
169 std::cout << "RandFlat::put(): randomInt = " << randomInt
170 << " firstUnusedBit = " << firstUnusedBit
171 << "\ndefaultWidth = " << defaultWidth
172 << " defaultA = " << defaultA
173 << " defaultB = " << defaultB << "\n";
174 #endif
175 os.precision(pr);
176 return os;
177 #ifdef REMOVED
178 int pr=os.precision(20);
179 os << " " << name() << "\n";
180 os << randomInt << " " << firstUnusedBit << "\n";
181 os << defaultWidth << " " << defaultA << " " << defaultB << "\n";
182 os.precision(pr);
183 return os;
184 #endif
185 }
186
get(std::istream & is)187 std::istream & RandFlat::get ( std::istream & is ) {
188 std::string inName;
189 is >> inName;
190 if (inName != name()) {
191 is.clear(std::ios::badbit | is.rdstate());
192 std::cerr << "Mismatch when expecting to read state of a "
193 << name() << " distribution\n"
194 << "Name found was " << inName
195 << "\nistream is left in the badbit state\n";
196 return is;
197 }
198 if (possibleKeywordInput(is, "Uvec", randomInt)) {
199 std::vector<unsigned long> t(2);
200 is >> randomInt >> firstUnusedBit;
201 is >> defaultWidth >>t[0]>>t[1]; defaultWidth = DoubConv::longs2double(t);
202 is >> defaultA >> t[0] >> t[1]; defaultA = DoubConv::longs2double(t);
203 is >> defaultB >> t[0] >> t[1]; defaultB = DoubConv::longs2double(t);
204 #ifdef TRACE_IO
205 std::cout << "RandFlat::get(): randomInt = " << randomInt
206 << " firstUnusedBit = " << firstUnusedBit
207 << "\ndefaultWidth = " << defaultWidth
208 << " defaultA = " << defaultA
209 << " defaultB = " << defaultB << "\n";
210 #endif
211 if (!is) {
212 is.clear(std::ios::badbit | is.rdstate());
213 std::cerr << "\nRandFlat input failed"
214 << "\nInput stream is probably mispositioned now." << std::endl;
215 return is;
216 }
217 return is;
218 }
219 // is >> randomInt encompassed by possibleKeywordInput
220 is >> firstUnusedBit;
221 is >> defaultWidth >> defaultA >> defaultB;
222 return is;
223 }
224
saveDistState(std::ostream & os)225 std::ostream & RandFlat::saveDistState ( std::ostream & os ) {
226 os << distributionName() << "\n";
227 int prec = os.precision(20);
228 os << "RANDFLAT staticRandomInt: " << staticRandomInt
229 << " staticFirstUnusedBit: " << staticFirstUnusedBit << "\n";
230 os.precision(prec);
231 return os;
232 }
233
restoreDistState(std::istream & is)234 std::istream & RandFlat::restoreDistState ( std::istream & is ) {
235 std::string inName;
236 is >> inName;
237 if (inName != distributionName()) {
238 is.clear(std::ios::badbit | is.rdstate());
239 std::cerr << "Mismatch when expecting to read static state of a "
240 << distributionName() << " distribution\n"
241 << "Name found was " << inName
242 << "\nistream is left in the badbit state\n";
243 return is;
244 }
245 std::string keyword;
246 std::string c1;
247 std::string c2;
248 is >> keyword;
249 if (keyword!="RANDFLAT") {
250 is.clear(std::ios::badbit | is.rdstate());
251 std::cerr << "Mismatch when expecting to read RANDFLAT bit cache info: "
252 << keyword << "\n";
253 return is;
254 }
255 is >> c1 >> staticRandomInt >> c2 >> staticFirstUnusedBit;
256 return is;
257 }
258
saveFullState(std::ostream & os)259 std::ostream & RandFlat::saveFullState ( std::ostream & os ) {
260 HepRandom::saveFullState(os);
261 saveDistState(os);
262 return os;
263 }
264
restoreFullState(std::istream & is)265 std::istream & RandFlat::restoreFullState ( std::istream & is ) {
266 HepRandom::restoreFullState(is);
267 restoreDistState(is);
268 return is;
269 }
270
271
272 } // namespace CLHEP
273
274