Geant4  10.00.p02
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"
40 #include "CLHEP/Random/JamesRandom.h"
41 #include "CLHEP/Random/engineIDulong.h"
42 #include "CLHEP/Random/DoubConv.h"
43 #include <string.h> // for strcmp
44 #include <cmath>
45 #include <cstdlib>
46 
47 namespace CLHEP {
48 
49 static const int MarkerLen = 64; // Enough room to hold a begin or end marker.
50 
51 std::string HepJamesRandom::name() const {return "HepJamesRandom";}
52 
53 // Number of instances with automatic seed selection
54 int HepJamesRandom::numEngines = 0;
55 
56 // Maximum index into the seed table
57 int HepJamesRandom::maxIndex = 215;
58 
59 HepJamesRandom::HepJamesRandom(long seed)
60 : HepRandomEngine()
61 {
62  setSeed(seed,0);
63  setSeeds(&theSeed,0);
64 }
65 
66 HepJamesRandom::HepJamesRandom() // 15 Feb. 1998 JMM
67 : HepRandomEngine()
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 
82 HepJamesRandom::HepJamesRandom(int rowIndex, int colIndex) // 15 Feb. 1998 JMM
83 : HepRandomEngine()
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 
98 HepJamesRandom::HepJamesRandom(std::istream& is)
99 : HepRandomEngine()
100 {
101  is >> *this;
102 }
103 
104 HepJamesRandom::~HepJamesRandom() {}
105 
106 void 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 
119 void 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 
157 void HepJamesRandom::showStatus() const
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 
173 void 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 
225 void HepJamesRandom::setSeeds(const long* seeds, int)
226 {
227  setSeed(seeds ? *seeds : 19780503L, 0);
228  theSeeds = seeds;
229 }
230 
231 double HepJamesRandom::flat()
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 
256 void 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 
266 HepJamesRandom::operator unsigned int() {
267  return ((unsigned int)(flat() * exponent_bit_32()) & 0xffffffff ) |
268  (((unsigned int)( u[i97] * exponent_bit_32())>>16) & 0xff);
269 }
270 
271 std::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 
281 std::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 
300 std::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 
317 std::string HepJamesRandom::beginTag ( ) {
318  return "JamesRandom-begin";
319 }
320 
321 std::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 
365 bool 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 
374 bool 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 const double cm
Definition: G4SIunits.hh:106
static const int MarkerLen
Definition: DualRand.cc:60
std::ofstream outFile
Definition: GammaRayTel.cc:68
G4String name
Definition: TRTMaterials.hh:40
static const G4double cd
static const G4int L[nN]
static const double s
Definition: G4SIunits.hh:150
const G4int n
double flat()
Definition: G4AblaRandom.cc:47
static const double m
Definition: G4SIunits.hh:110
static const double mm
Definition: G4SIunits.hh:102
void setSeeds(const SeedVector &sv)
Set the seeds of the current generator.
Definition: G4INCLRandom.cc:66