CLHEP VERSION Reference Documentation
   
CLHEP Home Page     CLHEP Documentation     CLHEP Bug Reports

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