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