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
40namespace CLHEP {
41
42static const int MarkerLen = 64; // Enough room to hold a begin or end marker.
43
44std::string RanshiEngine::name() const {return "RanshiEngine";}
45
46// Number of instances with automatic seed selection
47int RanshiEngine::numEngines = 0;
48
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
66 halfBuff(0), numFlats(0)
67{
68 is >> *this;
69}
70
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
86RanshiEngine::RanshiEngine(int rowIndex, int colIndex)
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
117void RanshiEngine::flatArray(const int size, double* vect) {
118 for (int i = 0; i < size; ++i) {
119 vect[i] = flat();
120 }
121}
122
123void RanshiEngine::setSeed(long seed, int) {
124 *this = RanshiEngine(seed);
125}
126
127void 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
144void 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
174void 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
228RanshiEngine::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
240RanshiEngine::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
252std::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
277std::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
289std::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
306std::string RanshiEngine::beginTag ( ) {
307 return "RanshiEngine-begin";
308}
309
310std::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
348bool 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
357bool 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
static double twoToMinus_32()
static double twoToMinus_53()
static double nearlyTwoToMinus_54()
static bool checkFile(std::istream &file, const std::string &filename, const std::string &classname, const std::string &methodname)
Definition: RandomEngine.cc:46
std::string name() const
Definition: RanshiEngine.cc:44
virtual std::istream & getState(std::istream &is)
static std::string beginTag()
void flatArray(const int size, double *vect)
virtual std::istream & get(std::istream &is)
void saveStatus(const char filename[]="RanshiEngine.conf") const
std::vector< unsigned long > put() const
void restoreStatus(const char filename[]="RanshiEngine.conf")
void setSeeds(const long *seeds, int)
void setSeed(long seed, int)
void showStatus() const
bool possibleKeywordInput(IS &is, const std::string &key, T &t)