Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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, (int)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)
static void getTheTableSeeds(long *seeds, int index)
Definition Random.cc:254
void restoreStatus(const char filename[]="Ranecu.conf")
static const int shift1
void saveStatus(const char filename[]="Ranecu.conf") const
static const int ecuyer_b
static const int ecuyer_e
static std::string engineName()
static const int ecuyer_f
void showStatus() const
std::vector< unsigned long > put() const
void setSeed(long index, int dum=0)
static const int ecuyer_d
virtual std::istream & get(std::istream &is)
std::string name() const
void flatArray(const int size, double *vect)
virtual std::istream & getState(std::istream &is)
void setIndex(long index)
static const int ecuyer_a
static const unsigned int VECTOR_STATE_SIZE
static const int shift2
static const int ecuyer_c
void setSeeds(const long *seeds, int index=-1)
static std::string beginTag()
bool possibleKeywordInput(IS &is, const std::string &key, T &t)
unsigned long engineIDulong()