Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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] = v[i+1];
348 }
349 redSpin = v[numBuff+1];
350 numFlats = v[numBuff+2];
351 halfBuff = 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)
Definition: RandomEngine.cc:47
std::string name() const
Definition: RanshiEngine.cc:63
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()
Definition: RanshiEngine.h:95
void restoreStatus(const char filename[]="RanshiEngine.conf")
void setSeeds(const long *seeds, int)
void setSeed(long seed, int)
void showStatus() const
Definition: DoubConv.h:17
bool possibleKeywordInput(IS &is, const std::string &key, T &t)
Definition: RandomEngine.h:166