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