Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
RanshiEngine.cc
Go to the documentation of this file.
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 <atomic>
41#include <string.h> // for strcmp
42#include <iostream>
43#include <string>
44#include <vector>
45
46// don't generate warnings about agressive loop optimization
47#if defined __GNUC__
48 #if __GNUC__ > 3 && __GNUC_MINOR__ > 8
49 #pragma GCC diagnostic push
50 #pragma GCC diagnostic ignored "-Waggressive-loop-optimizations"
51 #endif
52#endif
53
54namespace CLHEP {
55
56namespace {
57 // Number of instances with automatic seed selection
58 CLHEP_ATOMIC_INT_TYPE numberOfEngines(0);
59}
60
61static const int MarkerLen = 64; // Enough room to hold a begin or end marker.
62
63std::string RanshiEngine::name() const {return "RanshiEngine";}
64
67 halfBuff(0), numFlats(0)
68{
69 int numEngines = numberOfEngines++;
70 int i = 0;
71 while (i < numBuff) {
72 buffer[i] = (unsigned int)((numEngines+19780503L*(i+1))& 0xffffffff);
73 ++i;
74 }
75 theSeed = numEngines+19780503L*++i;
76 redSpin = (unsigned int)(theSeed & 0xffffffff);
77
78 for( i = 0; i < 10000; ++i) flat(); // Warm-up by running thorugh 10000 nums
79}
80
83 halfBuff(0), numFlats(0)
84{
85 is >> *this;
86}
87
90 halfBuff(0), numFlats(0)
91{
92 for (int i = 0; i < numBuff; ++i) {
93 buffer[i] = (unsigned int)seed&0xffffffff;
94 }
95 theSeed = seed;
96 redSpin = (unsigned int)(theSeed & 0xffffffff);
97 int j;
98 for (j = 0; j < numBuff*20; ++j) { // "warm-up" for engine to hit
99 flat(); // every ball on average 20X.
100 }
101}
102
103RanshiEngine::RanshiEngine(int rowIndex, int colIndex)
105 halfBuff(0), numFlats(0)
106{
107 int i = 0;
108 while( i < numBuff ) {
109 buffer[i] = (unsigned int)((rowIndex + (i+1)*(colIndex+8))&0xffffffff);
110 ++i;
111 }
112 theSeed = rowIndex;
113 redSpin = colIndex & 0xffffffff;
114 for( i = 0; i < 100; ++i) flat(); // Warm-up by running thorugh 100 nums
115}
116
118
120 unsigned int redAngle = (((numBuff/2) - 1) & redSpin) + halfBuff;
121 unsigned int blkSpin = buffer[redAngle] & 0xffffffff;
122 unsigned int boostResult = blkSpin ^ redSpin;
123
124 buffer[redAngle] = ((blkSpin << 17) | (blkSpin >> (32-17))) ^ redSpin;
125
126 redSpin = (blkSpin + numFlats++) & 0xffffffff;
127 halfBuff = numBuff/2 - halfBuff;
128
129 return ( blkSpin * twoToMinus_32() + // most significant part
130 (boostResult>>11) * twoToMinus_53() + // fill in remaining bits
131 nearlyTwoToMinus_54()); // non-zero
132}
133
134void RanshiEngine::flatArray(const int size, double* vect) {
135 for (int i = 0; i < size; ++i) {
136 vect[i] = flat();
137 }
138}
139
140void RanshiEngine::setSeed(long seed, int) {
141 *this = RanshiEngine(seed);
142}
143
144void RanshiEngine::setSeeds(const long* seeds, int) {
145 if (*seeds) {
146 int i = 0;
147 while (seeds[i] && i < numBuff) {
148 buffer[i] = (unsigned int)seeds[i];
149 ++i;
150 }
151 while (i < numBuff) {
152 buffer[i] = buffer[i-1];
153 ++i;
154 }
155 theSeed = seeds[0];
156 redSpin = (unsigned int)theSeed;
157 }
158 theSeeds = seeds;
159}
160
161void RanshiEngine::saveStatus(const char filename[]) const {
162 std::ofstream outFile(filename, std::ios::out);
163 if (!outFile.bad()) {
164 outFile << "Uvec\n";
165 std::vector<unsigned long> v = put();
166 for (unsigned int i=0; i<v.size(); ++i) {
167 outFile << v[i] << "\n";
168 }
169 }
170}
171
172void RanshiEngine::restoreStatus(const char filename[]) {
173 std::ifstream inFile(filename, std::ios::in);
174 if (!checkFile ( inFile, filename, engineName(), "restoreStatus" )) {
175 std::cerr << " -- Engine state remains unchanged\n";
176 return;
177 }
178 if ( possibleKeywordInput ( inFile, "Uvec", theSeed ) ) {
179 std::vector<unsigned long> v;
180 unsigned long xin;
181 for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) {
182 inFile >> xin;
183 if (!inFile) {
184 inFile.clear(std::ios::badbit | inFile.rdstate());
185 std::cerr << "\nRanshiEngine state (vector) description improper."
186 << "\nrestoreStatus has failed."
187 << "\nInput stream is probably mispositioned now." << std::endl;
188 return;
189 }
190 v.push_back(xin);
191 }
192 getState(v);
193 return;
194 }
195
196 if (!inFile.bad()) {
197// inFile >> theSeed; removed -- encompased by possibleKeywordInput
198 for (int i = 0; i < numBuff; ++i) {
199 inFile >> buffer[i];
200 }
201 inFile >> redSpin >> numFlats >> halfBuff;
202 }
203}
204
206 std::cout << std::setprecision(20) << std::endl;
207 std::cout << "----------- Ranshi engine status ----------" << std::endl;
208 std::cout << "Initial seed = " << theSeed << std::endl;
209 std::cout << "Current red spin = " << redSpin << std::endl;
210 std::cout << "Values produced = " << numFlats << std::endl;
211 std::cout << "Side of buffer = " << (halfBuff ? "upper" : "lower")
212 << std::endl;
213 std::cout << "Current buffer = " << std::endl;
214 for (int i = 0; i < numBuff; i+=4) {
215 std::cout << std::setw(10) << std::setiosflags(std::ios::right)
216 << buffer[i] << std::setw(11) << buffer[i+1] << std::setw(11)
217 << buffer[i+2] << std::setw(11) << buffer[i+3] << std::endl;
218 }
219 std::cout << "-------------------------------------------" << std::endl;
220}
221
222RanshiEngine::operator double() {
223 return flat();
224}
225
226RanshiEngine::operator float() {
227 unsigned int redAngle = (((numBuff/2) - 1) & redSpin) + halfBuff;
228 unsigned int blkSpin = buffer[redAngle] & 0xffffffff;
229
230 buffer[redAngle] = ((blkSpin << 17) | (blkSpin >> (32-17))) ^ redSpin;
231
232 redSpin = (blkSpin + numFlats++) & 0xffffffff;
233 halfBuff = numBuff/2 - halfBuff;
234
235 return float(blkSpin * twoToMinus_32());
236}
237
238RanshiEngine::operator unsigned int() {
239 unsigned int redAngle = (((numBuff/2) - 1) & redSpin) + halfBuff;
240 unsigned int blkSpin = buffer[redAngle] & 0xffffffff;
241
242 buffer[redAngle] = ((blkSpin << 17) | (blkSpin >> (32-17))) ^ redSpin;
243
244 redSpin = (blkSpin + numFlats++) & 0xffffffff;
245 halfBuff = numBuff/2 - halfBuff;
246
247 return blkSpin;
248}
249
250std::ostream& RanshiEngine::put (std::ostream& os ) const {
251 char beginMarker[] = "RanshiEngine-begin";
252 os << beginMarker << "\nUvec\n";
253 std::vector<unsigned long> v = put();
254 for (unsigned int i=0; i<v.size(); ++i) {
255 os << v[i] << "\n";
256 }
257 return os;
258}
259
260std::vector<unsigned long> RanshiEngine::put () const {
261 std::vector<unsigned long> v;
262 v.push_back (engineIDulong<RanshiEngine>());
263 for (int i = 0; i < numBuff; ++i) {
264 v.push_back(static_cast<unsigned long>(buffer[i]));
265 }
266 v.push_back(static_cast<unsigned long>(redSpin));
267 v.push_back(static_cast<unsigned long>(numFlats));
268 v.push_back(static_cast<unsigned long>(halfBuff));
269 return v;
270}
271
272std::istream& RanshiEngine::get (std::istream& is) {
273 char beginMarker [MarkerLen];
274 is >> std::ws;
275 is.width(MarkerLen); // causes the next read to the char* to be <=
276 // that many bytes, INCLUDING A TERMINATION \0
277 // (Stroustrup, section 21.3.2)
278 is >> beginMarker;
279 if (strcmp(beginMarker,"RanshiEngine-begin")) {
280 is.clear(std::ios::badbit | is.rdstate());
281 std::cerr << "\nInput mispositioned or"
282 << "\nRanshiEngine state description missing or"
283 << "\nwrong engine type found." << std::endl;
284 return is;
285 }
286 return getState(is);
287}
288
289std::string RanshiEngine::beginTag ( ) {
290 return "RanshiEngine-begin";
291}
292
293std::istream& RanshiEngine::getState (std::istream& is) {
294 if ( possibleKeywordInput ( is, "Uvec", theSeed ) ) {
295 std::vector<unsigned long> v;
296 unsigned long uu;
297 for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) {
298 is >> uu;
299 if (!is) {
300 is.clear(std::ios::badbit | is.rdstate());
301 std::cerr << "\nRanshiEngine state (vector) description improper."
302 << "\ngetState() has failed."
303 << "\nInput stream is probably mispositioned now." << std::endl;
304 return is;
305 }
306 v.push_back(uu);
307 }
308 getState(v);
309 return (is);
310 }
311
312// is >> theSeed; Removed, encompassed by possibleKeywordInput()
313
314 char endMarker [MarkerLen];
315 for (int i = 0; i < numBuff; ++i) {
316 is >> buffer[i];
317 }
318 is >> redSpin >> numFlats >> halfBuff;
319 is >> std::ws;
320 is.width(MarkerLen);
321 is >> endMarker;
322 if (strcmp(endMarker,"RanshiEngine-end")) {
323 is.clear(std::ios::badbit | is.rdstate());
324 std::cerr << "\nRanshiEngine state description incomplete."
325 << "\nInput stream is probably mispositioned now." << std::endl;
326 return is;
327 }
328 return is;
329}
330
331bool RanshiEngine::get (const std::vector<unsigned long> & v) {
332 if ((v[0] & 0xffffffffUL) != engineIDulong<RanshiEngine>()) {
333 std::cerr <<
334 "\nRanshiEngine get:state vector has wrong ID word - state unchanged\n";
335 return false;
336 }
337 return getState(v);
338}
339
340bool RanshiEngine::getState (const std::vector<unsigned long> & v) {
341 if (v.size() != VECTOR_STATE_SIZE ) {
342 std::cerr <<
343 "\nRanshiEngine get:state vector has wrong length - state unchanged\n";
344 return false;
345 }
346 for (int i = 0; i < numBuff; ++i) {
347 buffer[i] = (unsigned int)v[i+1];
348 }
349 redSpin = (unsigned int)v[numBuff+1];
350 numFlats = (unsigned int)v[numBuff+2];
351 halfBuff = (unsigned int)v[numBuff+3];
352 return true;
353}
354
355} // namespace CLHEP
356
357#if defined __GNUC__
358 #if __GNUC__ > 3 && __GNUC_MINOR__ > 8
359 #pragma GCC diagnostic pop
360 #endif
361#endif
#define CLHEP_ATOMIC_INT_TYPE
Definition atomic_int.h:14
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)
std::string name() const
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
static std::string engineName()
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)
unsigned long engineIDulong()