ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RanshiEngine.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file RanshiEngine.cc
1 // -*- C++ -*-
2 //
3 // -----------------------------------------------------------------------
4 // HEP Random
5 // --- RanshiEngine ---
6 // class implementation file
7 // -----------------------------------------------------------------------
8 //
9 // This algorithm implements the random number generator as proposed by
10 // "F. Gutbrod, Comp. Phys. Comm. 87 (1995) 291-306".
11 //
12 // =======================================================================
13 // Ken Smith - Created: 9th June 1998
14 // - Removed std::pow() from flat method: 21st Jul 1998
15 // - Added conversion operators: 6th Aug 1998
16 // J. Marraffino - Added some explicit casts to deal with
17 // machines where sizeof(int) != sizeof(long) 22 Aug 1998
18 // M. Fischler - Modified constructors taking seeds to not
19 // depend on numEngines (same seeds should
20 // produce same sequences). Default still
21 // depends on numEngines. 16 Sep 1998
22 // - Modified use of the various exponents of 2
23 // to avoid per-instance space overhead and
24 // correct the rounding procedure 16 Sep 1998
25 // J. Marraffino - Remove dependence on hepString class 13 May 1999
26 // M. Fischler - In restore, checkFile for file not found 03 Dec 2004
27 // M. Fischler - Methods for instance save/restore 12/8/04
28 // M. Fischler - split get() into tag validation and
29 // getState() for anonymous restores 12/27/04
30 // M. Fischler - State-saving using only ints, for portability 4/12/05
31 // L. Garren - use explicit 32bit mask to avoid compiler warnings 6/6/2014
32 // L. Garren - adding pragma for 32bit gcc 4.9 11/20/2014
33 //
34 // =======================================================================
35 
39 
40 #include <string.h> // for strcmp
41 #include <iostream>
42 
43 // don't generate warnings about agressive loop optimization
44 #if defined __GNUC__
45  #if __GNUC__ > 3 && __GNUC_MINOR__ > 8
46  #pragma GCC diagnostic push
47  #pragma GCC diagnostic ignored "-Waggressive-loop-optimizations"
48  #endif
49 #endif
50 
51 namespace CLHEP {
52 
53 namespace {
54  // Number of instances with automatic seed selection
55  CLHEP_ATOMIC_INT_TYPE numberOfEngines(0);
56 }
57 
58 static const int MarkerLen = 64; // Enough room to hold a begin or end marker.
59 
60 std::string RanshiEngine::name() const {return "RanshiEngine";}
61 
63 : HepRandomEngine(),
64  halfBuff(0), numFlats(0)
65 {
66  int numEngines = numberOfEngines++;
67  int i = 0;
68  while (i < numBuff) {
69  buffer[i] = (unsigned int)((numEngines+19780503L*(i+1))& 0xffffffff);
70  ++i;
71  }
72  theSeed = numEngines+19780503L*++i;
73  redSpin = (unsigned int)(theSeed & 0xffffffff);
74 
75  for( i = 0; i < 10000; ++i) flat(); // Warm-up by running thorugh 10000 nums
76 }
77 
78 RanshiEngine::RanshiEngine(std::istream& is)
79 : HepRandomEngine(),
80  halfBuff(0), numFlats(0)
81 {
82  is >> *this;
83 }
84 
86 : HepRandomEngine(),
87  halfBuff(0), numFlats(0)
88 {
89  for (int i = 0; i < numBuff; ++i) {
90  buffer[i] = (unsigned int)seed&0xffffffff;
91  }
92  theSeed = seed;
93  redSpin = (unsigned int)(theSeed & 0xffffffff);
94  int j;
95  for (j = 0; j < numBuff*20; ++j) { // "warm-up" for engine to hit
96  flat(); // every ball on average 20X.
97  }
98 }
99 
100 RanshiEngine::RanshiEngine(int rowIndex, int colIndex)
101 : HepRandomEngine(),
102  halfBuff(0), numFlats(0)
103 {
104  int i = 0;
105  while( i < numBuff ) {
106  buffer[i] = (unsigned int)((rowIndex + (i+1)*(colIndex+8))&0xffffffff);
107  ++i;
108  }
109  theSeed = rowIndex;
110  redSpin = colIndex & 0xffffffff;
111  for( i = 0; i < 100; ++i) flat(); // Warm-up by running thorugh 100 nums
112 }
113 
115 
117  unsigned int redAngle = (((numBuff/2) - 1) & redSpin) + halfBuff;
118  unsigned int blkSpin = buffer[redAngle] & 0xffffffff;
119  unsigned int boostResult = blkSpin ^ redSpin;
120 
121  buffer[redAngle] = ((blkSpin << 17) | (blkSpin >> (32-17))) ^ redSpin;
122 
123  redSpin = (blkSpin + numFlats++) & 0xffffffff;
124  halfBuff = numBuff/2 - halfBuff;
125 
126  return ( blkSpin * twoToMinus_32() + // most significant part
127  (boostResult>>11) * twoToMinus_53() + // fill in remaining bits
128  nearlyTwoToMinus_54()); // non-zero
129 }
130 
131 void RanshiEngine::flatArray(const int size, double* vect) {
132  for (int i = 0; i < size; ++i) {
133  vect[i] = flat();
134  }
135 }
136 
137 void RanshiEngine::setSeed(long seed, int) {
138  *this = RanshiEngine(seed);
139 }
140 
141 void RanshiEngine::setSeeds(const long* seeds, int) {
142  if (*seeds) {
143  int i = 0;
144  while (seeds[i] && i < numBuff) {
145  buffer[i] = (unsigned int)seeds[i];
146  ++i;
147  }
148  while (i < numBuff) {
149  buffer[i] = buffer[i-1];
150  ++i;
151  }
152  theSeed = seeds[0];
153  redSpin = (unsigned int)theSeed;
154  }
155  theSeeds = seeds;
156 }
157 
158 void RanshiEngine::saveStatus(const char filename[]) const {
159  std::ofstream outFile(filename, std::ios::out);
160  if (!outFile.bad()) {
161  outFile << "Uvec\n";
162  std::vector<unsigned long> v = put();
163  for (unsigned int i=0; i<v.size(); ++i) {
164  outFile << v[i] << "\n";
165  }
166  }
167 }
168 
170  std::ifstream inFile(filename, std::ios::in);
171  if (!checkFile ( inFile, filename, engineName(), "restoreStatus" )) {
172  std::cerr << " -- Engine state remains unchanged\n";
173  return;
174  }
175  if ( possibleKeywordInput ( inFile, "Uvec", theSeed ) ) {
176  std::vector<unsigned long> v;
177  unsigned long xin;
178  for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) {
179  inFile >> xin;
180  if (!inFile) {
181  inFile.clear(std::ios::badbit | inFile.rdstate());
182  std::cerr << "\nRanshiEngine state (vector) description improper."
183  << "\nrestoreStatus has failed."
184  << "\nInput stream is probably mispositioned now." << std::endl;
185  return;
186  }
187  v.push_back(xin);
188  }
189  getState(v);
190  return;
191  }
192 
193  if (!inFile.bad()) {
194 // inFile >> theSeed; removed -- encompased by possibleKeywordInput
195  for (int i = 0; i < numBuff; ++i) {
196  inFile >> buffer[i];
197  }
198  inFile >> redSpin >> numFlats >> halfBuff;
199  }
200 }
201 
203  std::cout << std::setprecision(20) << std::endl;
204  std::cout << "----------- Ranshi engine status ----------" << std::endl;
205  std::cout << "Initial seed = " << theSeed << std::endl;
206  std::cout << "Current red spin = " << redSpin << std::endl;
207  std::cout << "Values produced = " << numFlats << std::endl;
208  std::cout << "Side of buffer = " << (halfBuff ? "upper" : "lower")
209  << std::endl;
210  std::cout << "Current buffer = " << std::endl;
211  for (int i = 0; i < numBuff; i+=4) {
212  std::cout << std::setw(10) << std::setiosflags(std::ios::right)
213  << buffer[i] << std::setw(11) << buffer[i+1] << std::setw(11)
214  << buffer[i+2] << std::setw(11) << buffer[i+3] << std::endl;
215  }
216  std::cout << "-------------------------------------------" << std::endl;
217 }
218 
219 RanshiEngine::operator double() {
220  return flat();
221 }
222 
223 RanshiEngine::operator float() {
224  unsigned int redAngle = (((numBuff/2) - 1) & redSpin) + halfBuff;
225  unsigned int blkSpin = buffer[redAngle] & 0xffffffff;
226 
227  buffer[redAngle] = ((blkSpin << 17) | (blkSpin >> (32-17))) ^ redSpin;
228 
229  redSpin = (blkSpin + numFlats++) & 0xffffffff;
230  halfBuff = numBuff/2 - halfBuff;
231 
232  return float(blkSpin * twoToMinus_32());
233 }
234 
235 RanshiEngine::operator unsigned int() {
236  unsigned int redAngle = (((numBuff/2) - 1) & redSpin) + halfBuff;
237  unsigned int blkSpin = buffer[redAngle] & 0xffffffff;
238 
239  buffer[redAngle] = ((blkSpin << 17) | (blkSpin >> (32-17))) ^ redSpin;
240 
241  redSpin = (blkSpin + numFlats++) & 0xffffffff;
242  halfBuff = numBuff/2 - halfBuff;
243 
244  return blkSpin;
245 }
246 
247 std::ostream& RanshiEngine::put (std::ostream& os ) const {
248  char beginMarker[] = "RanshiEngine-begin";
249  os << beginMarker << "\nUvec\n";
250  std::vector<unsigned long> v = put();
251  for (unsigned int i=0; i<v.size(); ++i) {
252  os << v[i] << "\n";
253  }
254  return os;
255 }
256 
257 std::vector<unsigned long> RanshiEngine::put () const {
258  std::vector<unsigned long> v;
259  v.push_back (engineIDulong<RanshiEngine>());
260  for (int i = 0; i < numBuff; ++i) {
261  v.push_back(static_cast<unsigned long>(buffer[i]));
262  }
263  v.push_back(static_cast<unsigned long>(redSpin));
264  v.push_back(static_cast<unsigned long>(numFlats));
265  v.push_back(static_cast<unsigned long>(halfBuff));
266  return v;
267 }
268 
269 std::istream& RanshiEngine::get (std::istream& is) {
270  char beginMarker [MarkerLen];
271  is >> std::ws;
272  is.width(MarkerLen); // causes the next read to the char* to be <=
273  // that many bytes, INCLUDING A TERMINATION \0
274  // (Stroustrup, section 21.3.2)
275  is >> beginMarker;
276  if (strcmp(beginMarker,"RanshiEngine-begin")) {
277  is.clear(std::ios::badbit | is.rdstate());
278  std::cerr << "\nInput mispositioned or"
279  << "\nRanshiEngine state description missing or"
280  << "\nwrong engine type found." << std::endl;
281  return is;
282  }
283  return getState(is);
284 }
285 
286 std::string RanshiEngine::beginTag ( ) {
287  return "RanshiEngine-begin";
288 }
289 
290 std::istream& RanshiEngine::getState (std::istream& is) {
291  if ( possibleKeywordInput ( is, "Uvec", theSeed ) ) {
292  std::vector<unsigned long> v;
293  unsigned long uu;
294  for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) {
295  is >> uu;
296  if (!is) {
297  is.clear(std::ios::badbit | is.rdstate());
298  std::cerr << "\nRanshiEngine state (vector) description improper."
299  << "\ngetState() has failed."
300  << "\nInput stream is probably mispositioned now." << std::endl;
301  return is;
302  }
303  v.push_back(uu);
304  }
305  getState(v);
306  return (is);
307  }
308 
309 // is >> theSeed; Removed, encompassed by possibleKeywordInput()
310 
311  char endMarker [MarkerLen];
312  for (int i = 0; i < numBuff; ++i) {
313  is >> buffer[i];
314  }
315  is >> redSpin >> numFlats >> halfBuff;
316  is >> std::ws;
317  is.width(MarkerLen);
318  is >> endMarker;
319  if (strcmp(endMarker,"RanshiEngine-end")) {
320  is.clear(std::ios::badbit | is.rdstate());
321  std::cerr << "\nRanshiEngine state description incomplete."
322  << "\nInput stream is probably mispositioned now." << std::endl;
323  return is;
324  }
325  return is;
326 }
327 
328 bool RanshiEngine::get (const std::vector<unsigned long> & v) {
329  if ((v[0] & 0xffffffffUL) != engineIDulong<RanshiEngine>()) {
330  std::cerr <<
331  "\nRanshiEngine get:state vector has wrong ID word - state unchanged\n";
332  return false;
333  }
334  return getState(v);
335 }
336 
337 bool RanshiEngine::getState (const std::vector<unsigned long> & v) {
338  if (v.size() != VECTOR_STATE_SIZE ) {
339  std::cerr <<
340  "\nRanshiEngine get:state vector has wrong length - state unchanged\n";
341  return false;
342  }
343  for (int i = 0; i < numBuff; ++i) {
344  buffer[i] = v[i+1];
345  }
346  redSpin = v[numBuff+1];
347  numFlats = v[numBuff+2];
348  halfBuff = v[numBuff+3];
349  return true;
350 }
351 
352 } // namespace CLHEP
353 
354 #if defined __GNUC__
355  #if __GNUC__ > 3 && __GNUC_MINOR__ > 8
356  #pragma GCC diagnostic pop
357  #endif
358 #endif