Geant4  10.00.p02
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 
35 #include "CLHEP/Random/RanshiEngine.h"
36 #include "CLHEP/Random/engineIDulong.h"
37 #include <string.h> // for strcmp
38 
39 namespace CLHEP {
40 
41 static const int MarkerLen = 64; // Enough room to hold a begin or end marker.
42 
43 std::string RanshiEngine::name() const {return "RanshiEngine";}
44 
45 // Number of instances with automatic seed selection
46 int RanshiEngine::numEngines = 0;
47 
48 RanshiEngine::RanshiEngine()
49 : HepRandomEngine(),
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 
63 RanshiEngine::RanshiEngine(std::istream& is)
64 : HepRandomEngine(),
65  halfBuff(0), numFlats(0)
66 {
67  is >> *this;
68 }
69 
70 RanshiEngine::RanshiEngine(long seed)
71 : HepRandomEngine(),
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 
85 RanshiEngine::RanshiEngine(int rowIndex, int colIndex)
86 : HepRandomEngine(),
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 
99 RanshiEngine::~RanshiEngine() { }
100 
101 double RanshiEngine::flat() {
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 
116 void RanshiEngine::flatArray(const int size, double* vect) {
117  for (int i = 0; i < size; ++i) {
118  vect[i] = flat();
119  }
120 }
121 
122 void RanshiEngine::setSeed(long seed, int) {
123  *this = RanshiEngine(seed);
124 }
125 
126 void 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 
143 void 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 
154 void 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 
187 void RanshiEngine::showStatus() const {
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 
204 RanshiEngine::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 
216 RanshiEngine::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 
228 std::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 
238 std::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 
250 std::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 
267 std::string RanshiEngine::beginTag ( ) {
268  return "RanshiEngine-begin";
269 }
270 
271 std::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 
309 bool 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 
318 bool 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 const int MarkerLen
Definition: DualRand.cc:60
std::ofstream outFile
Definition: GammaRayTel.cc:68
G4String name
Definition: TRTMaterials.hh:40
#define buffer
Definition: xmlparse.cc:611
static const G4int L[nN]
double flat()
Definition: G4AblaRandom.cc:47
void setSeeds(const SeedVector &sv)
Set the seeds of the current generator.
Definition: G4INCLRandom.cc:66