Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
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