Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
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