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
RanecuEngine.cc
Go to the documentation of this file.
1// $Id:$
2// -*- C++ -*-
3//
4// -----------------------------------------------------------------------
5// HEP Random
6// --- RanecuEngine ---
7// class implementation file
8// -----------------------------------------------------------------------
9// This file is part of Geant4 (simulation toolkit for HEP).
10//
11// RANECU Random Engine - algorithm originally written in FORTRAN77
12// as part of the MATHLIB HEP library.
13
14// =======================================================================
15// Gabriele Cosmo - Created - 2nd February 1996
16// - Minor corrections: 31st October 1996
17// - Added methods for engine status: 19th November 1996
18// - Added abs for setting seed index: 11th July 1997
19// - Modified setSeeds() to handle default index: 16th Oct 1997
20// - setSeed() now resets the engine status to the original
21// values in the static table of HepRandom: 19th Mar 1998
22// J.Marraffino - Added stream operators and related constructor.
23// Added automatic seed selection from seed table and
24// engine counter: 16th Feb 1998
25// Ken Smith - Added conversion operators: 6th Aug 1998
26// J. Marraffino - Remove dependence on hepString class 13 May 1999
27// M. Fischler - Add endl to the end of saveStatus 10 Apr 2001
28// M. Fischler - In restore, checkFile for file not found 03 Dec 2004
29// M. Fischler - Methods for distrib. instance save/restore 12/8/04
30// M. Fischler - split get() into tag validation and
31// getState() for anonymous restores 12/27/04
32// M. Fischler - put/get for vectors of ulongs 3/14/05
33// M. Fischler - State-saving using only ints, for portability 4/12/05
34// M. Fischler - Modify ctor and setSeed to utilize all info provided
35// and avoid coincidence of same state from different
36// seeds 6/22/10
37//
38// =======================================================================
39
40#include "CLHEP/Random/Random.h"
43#include <string.h> // for strcmp
44#include <cmath>
45#include <cstdlib>
46
47namespace CLHEP {
48
49static const int MarkerLen = 64; // Enough room to hold a begin or end marker.
50
51static const double prec = 4.6566128E-10;
52
53std::string RanecuEngine::name() const {return "RanecuEngine";}
54
55void RanecuEngine::further_randomize (int seq1, int col, int index, int modulus)
56{
57 table[seq1][col] -= (index&0x3FFFFFFF);
58 while (table[seq1][col] <= 0) table[seq1][col] += (modulus-1);
59} // mf 6/22/10
60
61// Number of instances with automatic seed selection
62int RanecuEngine::numEngines = 0;
63
66{
67 int cycle = std::abs(int(numEngines/maxSeq));
68 seq = std::abs(int(numEngines%maxSeq));
69 numEngines += 1;
70 theSeed = seq;
71 long mask = ((cycle & 0x007fffff) << 8);
72 for (int i=0; i<2; ++i) {
73 for (int j=0; j<maxSeq; ++j) {
75 table[j][i] ^= mask;
76 }
77 }
78 theSeeds = &table[seq][0];
79}
80
83{
84 int cycle = std::abs(int(index/maxSeq));
85 seq = std::abs(int(index%maxSeq));
86 theSeed = seq;
87 long mask = ((cycle & 0x000007ff) << 20);
88 for (int j=0; j<maxSeq; ++j) {
90 table[j][0] ^= mask;
91 table[j][1] ^= mask;
92 }
93 theSeeds = &table[seq][0];
94 further_randomize (seq, 0, index, shift1); // mf 6/22/10
95}
96
99{
100 is >> *this;
101}
102
104
105void RanecuEngine::setSeed(long index, int dum)
106{
107 seq = std::abs(int(index%maxSeq));
108 theSeed = seq;
109 HepRandom::getTheTableSeeds(table[seq],seq);
110 theSeeds = &table[seq][0];
111 further_randomize (seq, 0, index, shift1); // mf 6/22/10
112 further_randomize (seq, 1, dum, shift2); // mf 6/22/10
113}
114
115void RanecuEngine::setSeeds(const long* seeds, int pos)
116{
117 if (pos != -1) {
118 seq = std::abs(int(pos%maxSeq));
119 theSeed = seq;
120 }
121 // only positive seeds are allowed
122 table[seq][0] = std::abs(seeds[0])%shift1;
123 table[seq][1] = std::abs(seeds[1])%shift2;
124 theSeeds = &table[seq][0];
125}
126
128{
129 seq = std::abs(int(index%maxSeq));
130 theSeed = seq;
131 theSeeds = &table[seq][0];
132}
133
134void RanecuEngine::saveStatus( const char filename[] ) const
135{
136 std::ofstream outFile( filename, std::ios::out ) ;
137
138 if (!outFile.bad()) {
139 outFile << "Uvec\n";
140 std::vector<unsigned long> v = put();
141 for (unsigned int i=0; i<v.size(); ++i) {
142 outFile << v[i] << "\n";
143 }
144 }
145}
146
147void RanecuEngine::restoreStatus( const char filename[] )
148{
149 std::ifstream inFile( filename, std::ios::in);
150 if (!checkFile ( inFile, filename, engineName(), "restoreStatus" )) {
151 std::cerr << " -- Engine state remains unchanged\n";
152 return;
153 }
154 if ( possibleKeywordInput ( inFile, "Uvec", theSeed ) ) {
155 std::vector<unsigned long> v;
156 unsigned long xin;
157 for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) {
158 inFile >> xin;
159 if (!inFile) {
160 inFile.clear(std::ios::badbit | inFile.rdstate());
161 std::cerr << "\nJamesRandom state (vector) description improper."
162 << "\nrestoreStatus has failed."
163 << "\nInput stream is probably mispositioned now." << std::endl;
164 return;
165 }
166 v.push_back(xin);
167 }
168 getState(v);
169 return;
170 }
171
172 if (!inFile.bad() && !inFile.eof()) {
173// inFile >> theSeed; removed -- encompased by possibleKeywordInput
174 for (int i=0; i<2; ++i)
175 inFile >> table[theSeed][i];
176 seq = int(theSeed);
177 }
178}
179
181{
182 std::cout << std::endl;
183 std::cout << "--------- Ranecu engine status ---------" << std::endl;
184 std::cout << " Initial seed (index) = " << theSeed << std::endl;
185 std::cout << " Current couple of seeds = "
186 << table[theSeed][0] << ", "
187 << table[theSeed][1] << std::endl;
188 std::cout << "----------------------------------------" << std::endl;
189}
190
192{
193 const int index = seq;
194 long seed1 = table[index][0];
195 long seed2 = table[index][1];
196
197 int k1 = (int)(seed1/ecuyer_b);
198 int k2 = (int)(seed2/ecuyer_e);
199
200 seed1 = ecuyer_a*(seed1-k1*ecuyer_b)-k1*ecuyer_c;
201 if (seed1 < 0) seed1 += shift1;
202 seed2 = ecuyer_d*(seed2-k2*ecuyer_e)-k2*ecuyer_f;
203 if (seed2 < 0) seed2 += shift2;
204
205 table[index][0] = seed1;
206 table[index][1] = seed2;
207
208 long diff = seed1-seed2;
209
210 if (diff <= 0) diff += (shift1-1);
211 return (double)(diff*prec);
212}
213
214void RanecuEngine::flatArray(const int size, double* vect)
215{
216 const int index = seq;
217 long seed1 = table[index][0];
218 long seed2 = table[index][1];
219 int k1, k2;
220 register int i;
221
222 for (i=0; i<size; ++i)
223 {
224 k1 = (int)(seed1/ecuyer_b);
225 k2 = (int)(seed2/ecuyer_e);
226
227 seed1 = ecuyer_a*(seed1-k1*ecuyer_b)-k1*ecuyer_c;
228 if (seed1 < 0) seed1 += shift1;
229 seed2 = ecuyer_d*(seed2-k2*ecuyer_e)-k2*ecuyer_f;
230 if (seed2 < 0) seed2 += shift2;
231
232 long diff = seed1-seed2;
233 if (diff <= 0) diff += (shift1-1);
234
235 vect[i] = (double)(diff*prec);
236 }
237 table[index][0] = seed1;
238 table[index][1] = seed2;
239}
240
241RanecuEngine::operator unsigned int() {
242 const int index = seq;
243 long seed1 = table[index][0];
244 long seed2 = table[index][1];
245
246 int k1 = (int)(seed1/ecuyer_b);
247 int k2 = (int)(seed2/ecuyer_e);
248
249 seed1 = ecuyer_a*(seed1-k1*ecuyer_b)-k1*ecuyer_c;
250 if (seed1 < 0) seed1 += shift1;
251 seed2 = ecuyer_d*(seed2-k2*ecuyer_e)-k2*ecuyer_f;
252 if (seed2 < 0) seed2 += shift2;
253
254 table[index][0] = seed1;
255 table[index][1] = seed2;
256 long diff = seed1-seed2;
257 if( diff <= 0 ) diff += (shift1-1);
258
259 return ((diff << 1) | (seed1&1))& 0xffffffff;
260}
261
262std::ostream & RanecuEngine::put( std::ostream& os ) const
263{
264 char beginMarker[] = "RanecuEngine-begin";
265 os << beginMarker << "\nUvec\n";
266 std::vector<unsigned long> v = put();
267 for (unsigned int i=0; i<v.size(); ++i) {
268 os << v[i] << "\n";
269 }
270 return os;
271}
272
273std::vector<unsigned long> RanecuEngine::put () const {
274 std::vector<unsigned long> v;
275 v.push_back (engineIDulong<RanecuEngine>());
276 v.push_back(static_cast<unsigned long>(theSeed));
277 v.push_back(static_cast<unsigned long>(table[theSeed][0]));
278 v.push_back(static_cast<unsigned long>(table[theSeed][1]));
279 return v;
280}
281
282std::istream & RanecuEngine::get ( std::istream& is )
283{
284 char beginMarker [MarkerLen];
285
286 is >> std::ws;
287 is.width(MarkerLen); // causes the next read to the char* to be <=
288 // that many bytes, INCLUDING A TERMINATION \0
289 // (Stroustrup, section 21.3.2)
290 is >> beginMarker;
291 if (strcmp(beginMarker,"RanecuEngine-begin")) {
292 is.clear(std::ios::badbit | is.rdstate());
293 std::cerr << "\nInput stream mispositioned or"
294 << "\nRanecuEngine state description missing or"
295 << "\nwrong engine type found." << std::endl;
296 return is;
297 }
298 return getState(is);
299}
300
301std::string RanecuEngine::beginTag ( ) {
302 return "RanecuEngine-begin";
303}
304
305std::istream & RanecuEngine::getState ( std::istream& is )
306{
307 if ( possibleKeywordInput ( is, "Uvec", theSeed ) ) {
308 std::vector<unsigned long> v;
309 unsigned long uu;
310 for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) {
311 is >> uu;
312 if (!is) {
313 is.clear(std::ios::badbit | is.rdstate());
314 std::cerr << "\nRanecuEngine state (vector) description improper."
315 << "\ngetState() has failed."
316 << "\nInput stream is probably mispositioned now." << std::endl;
317 return is;
318 }
319 v.push_back(uu);
320 }
321 getState(v);
322 return (is);
323 }
324
325// is >> theSeed; Removed, encompassed by possibleKeywordInput()
326 char endMarker [MarkerLen];
327 for (int i=0; i<2; ++i) {
328 is >> table[theSeed][i];
329 }
330 is >> std::ws;
331 is.width(MarkerLen);
332 is >> endMarker;
333 if (strcmp(endMarker,"RanecuEngine-end")) {
334 is.clear(std::ios::badbit | is.rdstate());
335 std::cerr << "\nRanecuEngine state description incomplete."
336 << "\nInput stream is probably mispositioned now." << std::endl;
337 return is;
338 }
339
340 seq = int(theSeed);
341 return is;
342}
343
344bool RanecuEngine::get (const std::vector<unsigned long> & v) {
345 if ((v[0] & 0xffffffffUL) != engineIDulong<RanecuEngine>()) {
346 std::cerr <<
347 "\nRanecuEngine get:state vector has wrong ID word - state unchanged\n";
348 return false;
349 }
350 return getState(v);
351}
352
353bool RanecuEngine::getState (const std::vector<unsigned long> & v) {
354 if (v.size() != VECTOR_STATE_SIZE ) {
355 std::cerr <<
356 "\nRanecuEngine get:state vector has wrong length - state unchanged\n";
357 return false;
358 }
359 theSeed = v[1];
360 table[theSeed][0] = v[2];
361 table[theSeed][1] = v[3];
362 seq = int(theSeed);
363 return true;
364}
365
366
367} // namespace CLHEP
static bool checkFile(std::istream &file, const std::string &filename, const std::string &classname, const std::string &methodname)
Definition: RandomEngine.cc:45
static void getTheTableSeeds(long *seeds, int index)
Definition: Random.cc:151
void restoreStatus(const char filename[]="Ranecu.conf")
static const int shift1
Definition: RanecuEngine.h:112
void saveStatus(const char filename[]="Ranecu.conf") const
static const int ecuyer_b
Definition: RanecuEngine.h:107
static const int ecuyer_e
Definition: RanecuEngine.h:110
static std::string engineName()
Definition: RanecuEngine.h:96
static const int ecuyer_f
Definition: RanecuEngine.h:111
void showStatus() const
std::vector< unsigned long > put() const
void setSeed(long index, int dum=0)
static const int ecuyer_d
Definition: RanecuEngine.h:109
virtual std::istream & get(std::istream &is)
std::string name() const
Definition: RanecuEngine.cc:53
void flatArray(const int size, double *vect)
virtual std::istream & getState(std::istream &is)
void setIndex(long index)
static const int ecuyer_a
Definition: RanecuEngine.h:106
static const unsigned int VECTOR_STATE_SIZE
Definition: RanecuEngine.h:115
static const int shift2
Definition: RanecuEngine.h:113
static const int ecuyer_c
Definition: RanecuEngine.h:108
void setSeeds(const long *seeds, int index=-1)
static std::string beginTag()
Definition: DoubConv.h:17
bool possibleKeywordInput(IS &is, const std::string &key, T &t)
Definition: RandomEngine.h:167