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