StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
JamesRandom.cc
1 /***************************************************************************
2  *
3  * $Id: JamesRandom.cc,v 1.4 2016/01/22 17:10:49 smirnovd Exp $
4  *
5  * Author: Gabriele Cosmo - Created: 5th September 1995
6  * modified for SCL bl
7  ***************************************************************************
8  *
9  * Description:
10  * -----------------------------------------------------------------------
11  * HEP Random
12  * --- HepJamesRandom ---
13  * class implementation file
14  * -----------------------------------------------------------------------
15  * This file is part of Geant4 (simulation toolkit for HEP).
16  *
17  * This algorithm implements the original universal random number generator
18  * as proposed by Marsaglia & Zaman in report FSU-SCRI-87-50 and coded
19  * in FORTRAN77 by Fred James as the RANMAR generator, part of the MATHLIB
20  * HEP library.
21  *
22  ***************************************************************************
23  *
24  * $Log: JamesRandom.cc,v $
25  * Revision 1.4 2016/01/22 17:10:49 smirnovd
26  * StarClassLibrary: Removed deprecated storage class specifier 'register'
27  *
28  * This keyword is deprecated since C++11 and serves no purpose
29  *
30  * "
31  * The register specifier is only allowed for objects declared at block scope and
32  * in function parameter lists. It indicates automatic storage duration, which is
33  * the default for these kinds of declarations. Additionally, the presence of this
34  * keyword may be used as a hint for the optimizer to store the value of this
35  * variable in a CPU register.
36  * "
37  *
38  * Revision 1.3 2012/06/11 15:29:26 fisyak
39  * std namespace
40  *
41  * Revision 1.2 1999/12/07 23:43:03 ullrich
42  * Modified to get rid of warnings on Linux.
43  *
44  * Revision 1.1 1999/01/30 03:58:59 fisyak
45  * Root Version of StarClassLibrary
46  *
47  * Revision 1.1 1999/01/23 00:29:02 ullrich
48  * Initial Revision
49  *
50  **************************************************************************/
51 
52 #include "JamesRandom.h"
53 
54 HepJamesRandom::HepJamesRandom(long seed)
55 {
56  setSeed(seed,0);
57  setSeeds(&theSeed,0);
58 }
59 
60 HepJamesRandom::~HepJamesRandom() {}
61 
62 HepJamesRandom::HepJamesRandom(const HepJamesRandom &p)
63 {
64  HepInt ipos, jpos;
65  if ((this != &p) && (&p)) {
66  theSeed = p.getSeed();
67  setSeeds(&theSeed,0);
68  for (HepInt i=0; i<97; ++i)
69  u[i] = p.u[i];
70  c = p.c; cd = p.cd; cm = p.cm;
71  jpos = HepInt(p.pj97-p.u);
72  ipos = (64+jpos)%97;
73  pi97 = &u[ipos]; pj97 = &u[jpos];
74  }
75 }
76 
77 HepJamesRandom & HepJamesRandom::operator = (const HepJamesRandom &p)
78 {
79  HepInt ipos, jpos;
80  if ((this != &p) && (&p)) {
81  theSeed = p.getSeed();
82  setSeeds(&theSeed,0);
83  for (HepInt i=0; i<97; ++i)
84  u[i] = p.u[i];
85  c = p.c; cd = p.cd; cm = p.cm;
86  jpos = HepInt(p.pj97-p.u);
87  ipos = (64+jpos)%97;
88  pi97 = &u[ipos]; pj97 = &u[jpos];
89  }
90  return *this;
91 }
92 
93 void HepJamesRandom::saveStatus() const
94 {
95  ofstream outFile("JamesRand.conf", std::ios::out ) ;
96 
97  if (!outFile.bad()) {
98  HepInt pos = HepInt(pj97-u);
99  outFile << theSeed << endl;
100  for (HepInt i=0; i<97; ++i)
101  outFile << u[i] << " ";
102  outFile << endl;
103  outFile << c << " " << cd << " " << cm << endl;
104  outFile << pos << endl;
105  }
106 }
107 
108 void HepJamesRandom::restoreStatus()
109 {
110  HepInt ipos, jpos;
111  ifstream inFile("JamesRand.conf", std::ios::in);
112 
113  if (!inFile.bad() && !inFile.eof()) {
114  inFile >> theSeed;
115  for (HepInt i=0; i<97; ++i)
116  inFile >> u[i];
117  inFile >> c; inFile >> cd; inFile >> cm;
118  inFile >> jpos;
119  ipos = (64+jpos)%97;
120  pi97 = &u[ipos];
121  pj97 = &u[jpos];
122  }
123 }
124 
125 void HepJamesRandom::showStatus() const
126 {
127  cout << endl;
128  cout << "----- HepJamesRandom engine status -----" << endl;
129  cout << " Initial seed = " << theSeed << endl;
130  cout << " u[] = ";
131  for (HepInt i=0; i<97; ++i)
132  cout << u[i] << " ";
133  cout << endl;
134  cout << " c = " << c << ", cd = " << cd << ", cm = " << cm << endl;
135  cout << " pi97 = " << pi97 << ", *pi97 = " << *pi97 << endl;
136  cout << " pj97 = " << pj97 << ", *pj97 = " << *pj97 << endl;
137  cout << "----------------------------------------" << endl;
138 }
139 
140 void HepJamesRandom::setSeed(long seed, HepInt)
141 {
142  // The input value for "seed" should be within the range [0,900000000]
143 
144  HepInt m, n;
145  HepFloat s, t;
146  long mm;
147 
148  long ij = seed/30082;
149  long kl = seed - 30082*ij;
150  long i = (ij/177) % 177 + 2;
151  long j = ij % 177 + 2;
152  long k = (kl/169) % 178 + 1;
153  long l = kl % 169;
154 
155  theSeed = seed;
156 
157  for ( n = 1 ; n < 98 ; n++ ) {
158  s = 0.0;
159  t = 0.5;
160  for ( m = 1 ; m < 25 ; m++) {
161  mm = ( ( (i*j) % 179 ) * k ) % 179;
162  i = j;
163  j = k;
164  k = mm;
165  l = ( 53 * l + 1 ) % 169;
166  if ( (l*mm % 64 ) >= 32 )
167  s += t;
168  t *= 0.5;
169  }
170  u[n-1] = s;
171  }
172  c = 362436.0 / 16777216.0;
173  cd = 7654321.0 / 16777216.0;
174  cm = 16777213.0 / 16777216.0;
175  pi97 = &u[96];
176  pj97 = &u[32];
177 }
178 
179 void HepJamesRandom::setSeeds(const long* seeds, HepInt)
180 {
181  setSeed(seeds ? *seeds : 19780503, 0);
182  theSeeds = seeds;
183 }
184 
185 HepDouble HepJamesRandom::flat()
186 {
187  HepDouble uni;
188 
189  do {
190  uni = *pi97 - *pj97;
191  if ( uni < 0.0 ) uni++;
192  *pi97 = uni;
193 
194  if (pi97 == u) pi97 += 96;
195  else pi97--;
196 
197  if (pj97 == u) pj97 += 96;
198  else pj97--;
199 
200  c -= cd;
201  if (c < 0.0) c += cm;
202 
203  uni -= c;
204  if (uni < 0.0) uni += 1.0;
205  } while ( uni <= 0.0 || uni >= 1.0 );
206 
207  return uni;
208 }
209 
210 void HepJamesRandom::flatArray(const HepInt size, HepDouble* vect)
211 {
212  HepDouble uni;
213  HepInt i;
214 
215  for (i=0; i<size; ++i) {
216  do {
217  uni = *pi97 - *pj97;
218  if ( uni < 0.0 ) uni++;
219  *pi97 = uni;
220 
221  if (pi97 == u) pi97 += 96;
222  else pi97--;
223 
224  if (pj97 == u) pj97 += 96;
225  else pj97--;
226 
227  c -= cd;
228  if (c < 0.0) c += cm;
229 
230  uni -= c;
231  if (uni < 0.0) uni += 1.0;
232  } while ( uni <= 0.0 || uni >= 1.0 );
233  vect[i] = uni;
234  }
235 }
236 
237 void
238 #ifndef ST_NO_TEMPLATE_DEF_ARGS
239 HepJamesRandom::flatArray(vector<HepDouble>& vec)
240 #else
241 HepJamesRandom::flatArray(vector<HepDouble,allocator<HepDouble> >& vec)
242 #endif
243 {
244  HepDouble uni;
245 
246  for (unsigned int i=0; i<vec.size(); ++i) {
247  do {
248  uni = *pi97 - *pj97;
249  if ( uni < 0.0 ) uni++;
250  *pi97 = uni;
251 
252  if (pi97 == u) pi97 += 96;
253  else pi97--;
254 
255  if (pj97 == u) pj97 += 96;
256  else pj97--;
257 
258  c -= cd;
259  if (c < 0.0) c += cm;
260 
261  uni -= c;
262  if (uni < 0.0) uni += 1.0;
263  } while ( uni <= 0.0 || uni >= 1.0 );
264  vec[i] = uni;
265  }
266 }