Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
JamesRandom.cc
Go to the documentation of this file.
1// $Id:$
2// -*- C++ -*-
3//
4// -----------------------------------------------------------------------
5// HEP Random
6// --- HepJamesRandom ---
7// class implementation file
8// -----------------------------------------------------------------------
9// This file is part of Geant4 (simulation toolkit for HEP).
10//
11// This algorithm implements the original universal random number generator
12// as proposed by Marsaglia & Zaman in report FSU-SCRI-87-50 and coded
13// in FORTRAN77 by Fred James as the RANMAR generator, part of the MATHLIB
14// HEP library.
15
16// =======================================================================
17// Gabriele Cosmo - Created: 5th September 1995
18// - Fixed a bug in setSeed(): 26th February 1996
19// - Minor corrections: 31st October 1996
20// - Added methods for engine status: 19th November 1996
21// - Fixed bug in setSeeds(): 15th September 1997
22// J.Marraffino - Added stream operators and related constructor.
23// Added automatic seed selection from seed table and
24// engine counter: 16th Feb 1998
25// Ken Smith - Added conversion operators: 6th Aug 1998
26// J. Marraffino - Remove dependence on hepString class 13 May 1999
27// V. Innocente - changed pointers to indices 3 may 2000
28// M. Fischler - In restore, checkFile for file not found 03 Dec 2004
29// M. Fischler - Methods for distrib. instacne save/restore 12/8/04
30// M. Fischler - split get() into tag validation and
31// getState() for anonymous restores 12/27/04
32// M. Fischler - Enforcement that seeds be non-negative
33// (lest the sequence be non-random) 2/14/05
34// M. Fischler - put/get for vectors of ulongs 3/14/05
35// M. Fischler - State-saving using only ints, for portability 4/12/05
36//
37// =======================================================================
38
39#include "CLHEP/Random/Random.h"
43#include <string.h> // for strcmp
44#include <cmath>
45#include <cstdlib>
46
47namespace CLHEP {
48
49static const int MarkerLen = 64; // Enough room to hold a begin or end marker.
50
51std::string HepJamesRandom::name() const {return "HepJamesRandom";}
52
53// Number of instances with automatic seed selection
54int HepJamesRandom::numEngines = 0;
55
56// Maximum index into the seed table
57int HepJamesRandom::maxIndex = 215;
58
61{
62 setSeed(seed,0);
63 setSeeds(&theSeed,0);
64}
65
66HepJamesRandom::HepJamesRandom() // 15 Feb. 1998 JMM
68{
69 long seeds[2];
70 long seed;
71
72 int cycle = std::abs(int(numEngines/maxIndex));
73 int curIndex = std::abs(int(numEngines%maxIndex));
74 ++numEngines;
75 long mask = ((cycle & 0x007fffff) << 8);
76 HepRandom::getTheTableSeeds( seeds, curIndex );
77 seed = seeds[0]^mask;
78 setSeed(seed,0);
79 setSeeds(&theSeed,0);
80}
81
82HepJamesRandom::HepJamesRandom(int rowIndex, int colIndex) // 15 Feb. 1998 JMM
84{
85 long seed;
86 long seeds[2];
87
88 int cycle = std::abs(int(rowIndex/maxIndex));
89 int row = std::abs(int(rowIndex%maxIndex));
90 int col = std::abs(int(colIndex%2));
91 long mask = ((cycle & 0x000007ff) << 20);
92 HepRandom::getTheTableSeeds( seeds, row );
93 seed = (seeds[col])^mask;
94 setSeed(seed,0);
95 setSeeds(&theSeed,0);
96}
97
100{
101 is >> *this;
102}
103
105
106void HepJamesRandom::saveStatus( const char filename[] ) const
107{
108 std::ofstream outFile( filename, std::ios::out ) ;
109
110 if (!outFile.bad()) {
111 outFile << "Uvec\n";
112 std::vector<unsigned long> v = put();
113 for (unsigned int i=0; i<v.size(); ++i) {
114 outFile << v[i] << "\n";
115 }
116 }
117}
118
119void HepJamesRandom::restoreStatus( const char filename[] )
120{
121 int ipos, jpos;
122 std::ifstream inFile( filename, std::ios::in);
123 if (!checkFile ( inFile, filename, engineName(), "restoreStatus" )) {
124 std::cerr << " -- Engine state remains unchanged\n";
125 return;
126 }
127 if ( possibleKeywordInput ( inFile, "Uvec", theSeed ) ) {
128 std::vector<unsigned long> v;
129 unsigned long xin;
130 for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) {
131 inFile >> xin;
132 if (!inFile) {
133 inFile.clear(std::ios::badbit | inFile.rdstate());
134 std::cerr << "\nJamesRandom state (vector) description improper."
135 << "\nrestoreStatus has failed."
136 << "\nInput stream is probably mispositioned now." << std::endl;
137 return;
138 }
139 v.push_back(xin);
140 }
141 getState(v);
142 return;
143 }
144
145 if (!inFile.bad() && !inFile.eof()) {
146// inFile >> theSeed; removed -- encompased by possibleKeywordInput
147 for (int i=0; i<97; ++i)
148 inFile >> u[i];
149 inFile >> c; inFile >> cd; inFile >> cm;
150 inFile >> jpos;
151 ipos = (64+jpos)%97;
152 i97 = ipos;
153 j97 = jpos;
154 }
155}
156
158{
159 std::cout << std::endl;
160 std::cout << "----- HepJamesRandom engine status -----" << std::endl;
161 std::cout << " Initial seed = " << theSeed << std::endl;
162 std::cout << " u[] = ";
163 for (int i=0; i<97; ++i)
164 std::cout << u[i] << " ";
165 std::cout << std::endl;
166 std::cout << " c = " << c << ", cd = " << cd << ", cm = " << cm
167 << std::endl;
168 std::cout << " i97 = " << i97 << ", u[i97] = " << u[i97] << std::endl;
169 std::cout << " j97 = " << j97 << ", u[j97] = " << u[j97] << std::endl;
170 std::cout << "----------------------------------------" << std::endl;
171}
172
173void HepJamesRandom::setSeed(long seed, int)
174{
175 // The input value for "seed" should be within the range [0,900000000]
176 //
177 // Negative seeds result in serious flaws in the randomness;
178 // seeds above 900000000 are OK because of the %177 in the expression for i,
179 // but may have the same effect as other seeds below 900000000.
180
181 int m, n;
182 float s, t;
183 long mm;
184
185 if (seed < 0) {
186 std::cout << "Seed for HepJamesRandom must be non-negative\n"
187 << "Seed value supplied was " << seed
188 << "\nUsing its absolute value instead\n";
189 seed = -seed;
190 }
191
192 long ij = seed/30082;
193 long kl = seed - 30082*ij;
194 long i = (ij/177) % 177 + 2;
195 long j = ij % 177 + 2;
196 long k = (kl/169) % 178 + 1;
197 long l = kl % 169;
198
199 theSeed = seed;
200
201 for ( n = 1 ; n < 98 ; n++ ) {
202 s = 0.0;
203 t = 0.5;
204 for ( m = 1 ; m < 25 ; m++) {
205 mm = ( ( (i*j) % 179 ) * k ) % 179;
206 i = j;
207 j = k;
208 k = mm;
209 l = ( 53 * l + 1 ) % 169;
210 if ( (l*mm % 64 ) >= 32 )
211 s += t;
212 t *= 0.5;
213 }
214 u[n-1] = s;
215 }
216 c = 362436.0 / 16777216.0;
217 cd = 7654321.0 / 16777216.0;
218 cm = 16777213.0 / 16777216.0;
219
220 i97 = 96;
221 j97 = 32;
222
223}
224
225void HepJamesRandom::setSeeds(const long* seeds, int)
226{
227 setSeed(seeds ? *seeds : 19780503L, 0);
228 theSeeds = seeds;
229}
230
232{
233 double uni;
234
235 do {
236 uni = u[i97] - u[j97];
237 if ( uni < 0.0 ) uni++;
238 u[i97] = uni;
239
240 if (i97 == 0) i97 = 96;
241 else i97--;
242
243 if (j97 == 0) j97 = 96;
244 else j97--;
245
246 c -= cd;
247 if (c < 0.0) c += cm;
248
249 uni -= c;
250 if (uni < 0.0) uni += 1.0;
251 } while ( uni <= 0.0 || uni >= 1.0 );
252
253 return uni;
254}
255
256void HepJamesRandom::flatArray(const int size, double* vect)
257{
258// double uni;
259 int i;
260
261 for (i=0; i<size; ++i) {
262 vect[i] = flat();
263 }
264}
265
266HepJamesRandom::operator unsigned int() {
267 return ((unsigned int)(flat() * exponent_bit_32()) & 0xffffffff ) |
268 (((unsigned int)( u[i97] * exponent_bit_32())>>16) & 0xff);
269}
270
271std::ostream & HepJamesRandom::put ( std::ostream& os ) const {
272 char beginMarker[] = "JamesRandom-begin";
273 os << beginMarker << "\nUvec\n";
274 std::vector<unsigned long> v = put();
275 for (unsigned int i=0; i<v.size(); ++i) {
276 os << v[i] << "\n";
277 }
278 return os;
279}
280
281std::vector<unsigned long> HepJamesRandom::put () const {
282 std::vector<unsigned long> v;
283 v.push_back (engineIDulong<HepJamesRandom>());
284 std::vector<unsigned long> t;
285 for (int i=0; i<97; ++i) {
286 t = DoubConv::dto2longs(u[i]);
287 v.push_back(t[0]); v.push_back(t[1]);
288 }
289 t = DoubConv::dto2longs(c);
290 v.push_back(t[0]); v.push_back(t[1]);
291 t = DoubConv::dto2longs(cd);
292 v.push_back(t[0]); v.push_back(t[1]);
293 t = DoubConv::dto2longs(cm);
294 v.push_back(t[0]); v.push_back(t[1]);
295 v.push_back(static_cast<unsigned long>(j97));
296 return v;
297}
298
299
300std::istream & HepJamesRandom::get ( std::istream& is) {
301 char beginMarker [MarkerLen];
302 is >> std::ws;
303 is.width(MarkerLen); // causes the next read to the char* to be <=
304 // that many bytes, INCLUDING A TERMINATION \0
305 // (Stroustrup, section 21.3.2)
306 is >> beginMarker;
307 if (strcmp(beginMarker,"JamesRandom-begin")) {
308 is.clear(std::ios::badbit | is.rdstate());
309 std::cerr << "\nInput stream mispositioned or"
310 << "\nJamesRandom state description missing or"
311 << "\nwrong engine type found." << std::endl;
312 return is;
313 }
314 return getState(is);
315}
316
317std::string HepJamesRandom::beginTag ( ) {
318 return "JamesRandom-begin";
319}
320
321std::istream & HepJamesRandom::getState ( std::istream& is) {
322 if ( possibleKeywordInput ( is, "Uvec", theSeed ) ) {
323 std::vector<unsigned long> v;
324 unsigned long uu;
325 for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) {
326 is >> uu;
327 if (!is) {
328 is.clear(std::ios::badbit | is.rdstate());
329 std::cerr << "\nJamesRandom state (vector) description improper."
330 << "\ngetState() has failed."
331 << "\nInput stream is probably mispositioned now." << std::endl;
332 return is;
333 }
334 v.push_back(uu);
335 }
336 getState(v);
337 return (is);
338 }
339
340// is >> theSeed; Removed, encompassed by possibleKeywordInput()
341
342 int ipos, jpos;
343 char endMarker [MarkerLen];
344 for (int i=0; i<97; ++i) {
345 is >> u[i];
346 }
347 is >> c; is >> cd; is >> cm;
348 is >> jpos;
349 is >> std::ws;
350 is.width(MarkerLen);
351 is >> endMarker;
352 if(strcmp(endMarker,"JamesRandom-end")) {
353 is.clear(std::ios::badbit | is.rdstate());
354 std::cerr << "\nJamesRandom state description incomplete."
355 << "\nInput stream is probably mispositioned now." << std::endl;
356 return is;
357 }
358
359 ipos = (64+jpos)%97;
360 i97 = ipos;
361 j97 = jpos;
362 return is;
363}
364
365bool HepJamesRandom::get (const std::vector<unsigned long> & v) {
366 if ( (v[0] & 0xffffffffUL) != engineIDulong<HepJamesRandom>()) {
367 std::cerr <<
368 "\nHepJamesRandom get:state vector has wrong ID word - state unchanged\n";
369 return false;
370 }
371 return getState(v);
372}
373
374bool HepJamesRandom::getState (const std::vector<unsigned long> & v) {
375 if (v.size() != VECTOR_STATE_SIZE ) {
376 std::cerr <<
377 "\nHepJamesRandom get:state vector has wrong length - state unchanged\n";
378 return false;
379 }
380 std::vector<unsigned long> t(2);
381 for (int i=0; i<97; ++i) {
382 t[0] = v[2*i+1]; t[1] = v[2*i+2];
383 u[i] = DoubConv::longs2double(t);
384 }
385 t[0] = v[195]; t[1] = v[196]; c = DoubConv::longs2double(t);
386 t[0] = v[197]; t[1] = v[198]; cd = DoubConv::longs2double(t);
387 t[0] = v[199]; t[1] = v[200]; cm = DoubConv::longs2double(t);
388 j97 = v[201];
389 i97 = (64+j97)%97;
390 return true;
391}
392
393} // namespace CLHEP
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
void flatArray(const int size, double *vect)
Definition: JamesRandom.cc:256
static std::string beginTag()
Definition: JamesRandom.cc:317
static std::string engineName()
Definition: JamesRandom.h:88
void setSeeds(const long *seeds, int dum=0)
Definition: JamesRandom.cc:225
virtual std::istream & getState(std::istream &is)
Definition: JamesRandom.cc:321
std::string name() const
Definition: JamesRandom.cc:51
std::vector< unsigned long > put() const
Definition: JamesRandom.cc:281
void setSeed(long seed, int dum=0)
Definition: JamesRandom.cc:173
virtual std::istream & get(std::istream &is)
Definition: JamesRandom.cc:300
void saveStatus(const char filename[]="JamesRand.conf") const
Definition: JamesRandom.cc:106
void restoreStatus(const char filename[]="JamesRand.conf")
Definition: JamesRandom.cc:119
static const unsigned int VECTOR_STATE_SIZE
Definition: JamesRandom.h:94
void showStatus() const
Definition: JamesRandom.cc:157
static bool checkFile(std::istream &file, const std::string &filename, const std::string &classname, const std::string &methodname)
Definition: RandomEngine.cc:45
static void getTheTableSeeds(long *seeds, int index)
Definition: Random.cc:151
Definition: DoubConv.h:17
bool possibleKeywordInput(IS &is, const std::string &key, T &t)
Definition: RandomEngine.h:167