CLHEP 2.4.6.4
C++ Class Library for High Energy Physics
Loading...
Searching...
No Matches
RanecuEngine.cc
Go to the documentation of this file.
1//
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/defs.h"
41#include "CLHEP/Random/Random.h"
42#include "CLHEP/Random/RanecuEngine.h"
43#include "CLHEP/Random/engineIDulong.h"
44#include "CLHEP/Utility/atomic_int.h"
45
46#include <atomic>
47#include <cstdlib>
48#include <cmath>
49#include <iostream>
50#include <string>
51#include <string.h> // for strcmp
52#include <vector>
53
54
55namespace CLHEP {
56
57namespace {
58 // Number of instances with automatic seed selection
59 CLHEP_ATOMIC_INT_TYPE numberOfEngines(0);
60}
61
62static const int MarkerLen = 64; // Enough room to hold a begin or end marker.
63
64static const double prec = 4.6566128E-10;
65
66std::string RanecuEngine::name() const {return "RanecuEngine";}
67
68void RanecuEngine::further_randomize (int seq1, int col, int index, int modulus)
69{
70 table[seq1][col] -= (index&0x3FFFFFFF);
71 while (table[seq1][col] <= 0) table[seq1][col] += (modulus-1);
72} // mf 6/22/10
73
76{
77 int numEngines = numberOfEngines++;
78 int cycle = std::abs(int(numEngines/maxSeq));
79 seq = std::abs(int(numEngines%maxSeq));
80
81 theSeed = seq;
82 long mask = ((cycle & 0x007fffff) << 8);
83 for (int i=0; i<2; ++i) {
84 for (int j=0; j<maxSeq; ++j) {
86 table[j][i] ^= mask;
87 }
88 }
89 theSeeds = &table[seq][0];
90}
91
94{
95 int cycle = std::abs(int(index/maxSeq));
96 seq = std::abs(int(index%maxSeq));
97 theSeed = seq;
98 long mask = ((cycle & 0x000007ff) << 20);
99 for (int j=0; j<maxSeq; ++j) {
100 HepRandom::getTheTableSeeds(table[j],j);
101 table[j][0] ^= mask;
102 table[j][1] ^= mask;
103 }
104 theSeeds = &table[seq][0];
105 further_randomize (seq, 0, index, shift1); // mf 6/22/10
106}
107
110{
111 is >> *this;
112}
113
115
116void RanecuEngine::setSeed(long index, int dum)
117{
118 seq = std::abs(int(index%maxSeq));
119 theSeed = seq;
120 HepRandom::getTheTableSeeds(table[seq],seq);
121 theSeeds = &table[seq][0];
122 further_randomize (seq, 0, (int)index, shift1); // mf 6/22/10
123 further_randomize (seq, 1, dum, shift2); // mf 6/22/10
124}
125
126void RanecuEngine::setSeeds(const long* seeds, int pos)
127{
128 if (pos != -1) {
129 seq = std::abs(int(pos%maxSeq));
130 theSeed = seq;
131 }
132 // only positive seeds are allowed
133 table[seq][0] = std::abs(seeds[0])%shift1;
134 table[seq][1] = std::abs(seeds[1])%shift2;
135 theSeeds = &table[seq][0];
136}
137
139{
140 seq = std::abs(int(index%maxSeq));
141 theSeed = seq;
142 theSeeds = &table[seq][0];
143}
144
145void RanecuEngine::saveStatus( const char filename[] ) const
146{
147 std::ofstream outFile( filename, std::ios::out ) ;
148
149 if (!outFile.bad()) {
150 outFile << "Uvec\n";
151 std::vector<unsigned long> v = put();
152 #ifdef TRACE_IO
153 std::cout << "Result of v = put() is:\n";
154 #endif
155 for (unsigned int i=0; i<v.size(); ++i) {
156 outFile << v[i] << "\n";
157 #ifdef TRACE_IO
158 std::cout << v[i] << " ";
159 if (i%6==0) std::cout << "\n";
160 #endif
161 }
162 #ifdef TRACE_IO
163 std::cout << "\n";
164 #endif
165 }
166#ifdef REMOVED
167 if (!outFile.bad()) {
168 outFile << theSeed << std::endl;
169 for (int i=0; i<2; ++i)
170 outFile << table[theSeed][i] << " ";
171 outFile << std::endl;
172 }
173#endif
174}
175
176void RanecuEngine::restoreStatus( const char filename[] )
177{
178 std::ifstream inFile( filename, std::ios::in);
179 if (!checkFile ( inFile, filename, engineName(), "restoreStatus" )) {
180 std::cerr << " -- Engine state remains unchanged\n";
181 return;
182 }
183 if ( possibleKeywordInput ( inFile, "Uvec", theSeed ) ) {
184 std::vector<unsigned long> v;
185 unsigned long xin;
186 for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) {
187 inFile >> xin;
188 #ifdef TRACE_IO
189 std::cout << "ivec = " << ivec << " xin = " << xin << " ";
190 if (ivec%3 == 0) std::cout << "\n";
191 #endif
192 if (!inFile) {
193 inFile.clear(std::ios::badbit | inFile.rdstate());
194 std::cerr << "\nJamesRandom state (vector) description improper."
195 << "\nrestoreStatus has failed."
196 << "\nInput stream is probably mispositioned now." << std::endl;
197 return;
198 }
199 v.push_back(xin);
200 }
201 getState(v);
202 return;
203 }
204
205 if (!inFile.bad() && !inFile.eof()) {
206// inFile >> theSeed; removed -- encompased by possibleKeywordInput
207 for (int i=0; i<2; ++i)
208 inFile >> table[theSeed][i];
209 seq = int(theSeed);
210 }
211}
212
214{
215 std::cout << std::endl;
216 std::cout << "--------- Ranecu engine status ---------" << std::endl;
217 std::cout << " Initial seed (index) = " << theSeed << std::endl;
218 std::cout << " Current couple of seeds = "
219 << table[theSeed][0] << ", "
220 << table[theSeed][1] << std::endl;
221 std::cout << "----------------------------------------" << std::endl;
222}
223
225{
226 const int index = seq;
227 long seed1 = table[index][0];
228 long seed2 = table[index][1];
229
230 int k1 = (int)(seed1/ecuyer_b);
231 int k2 = (int)(seed2/ecuyer_e);
232
233 seed1 = ecuyer_a*(seed1-k1*ecuyer_b)-k1*ecuyer_c;
234 if (seed1 < 0) seed1 += shift1;
235 seed2 = ecuyer_d*(seed2-k2*ecuyer_e)-k2*ecuyer_f;
236 if (seed2 < 0) seed2 += shift2;
237
238 table[index][0] = seed1;
239 table[index][1] = seed2;
240
241 long diff = seed1-seed2;
242
243 if (diff <= 0) diff += (shift1-1);
244 return (double)(diff*prec);
245}
246
247void RanecuEngine::flatArray(const int size, double* vect)
248{
249 const int index = seq;
250 long seed1 = table[index][0];
251 long seed2 = table[index][1];
252 int k1, k2;
253 int i;
254
255 for (i=0; i<size; ++i)
256 {
257 k1 = (int)(seed1/ecuyer_b);
258 k2 = (int)(seed2/ecuyer_e);
259
260 seed1 = ecuyer_a*(seed1-k1*ecuyer_b)-k1*ecuyer_c;
261 if (seed1 < 0) seed1 += shift1;
262 seed2 = ecuyer_d*(seed2-k2*ecuyer_e)-k2*ecuyer_f;
263 if (seed2 < 0) seed2 += shift2;
264
265 long diff = seed1-seed2;
266 if (diff <= 0) diff += (shift1-1);
267
268 vect[i] = (double)(diff*prec);
269 }
270 table[index][0] = seed1;
271 table[index][1] = seed2;
272}
273
274RanecuEngine::operator double() {
275 return flat();
276}
277
278RanecuEngine::operator float() {
279 return float( flat() );
280}
281
282RanecuEngine::operator unsigned int() {
283 const int index = seq;
284 long seed1 = table[index][0];
285 long seed2 = table[index][1];
286
287 int k1 = (int)(seed1/ecuyer_b);
288 int k2 = (int)(seed2/ecuyer_e);
289
290 seed1 = ecuyer_a*(seed1-k1*ecuyer_b)-k1*ecuyer_c;
291 if (seed1 < 0) seed1 += shift1;
292 seed2 = ecuyer_d*(seed2-k2*ecuyer_e)-k2*ecuyer_f;
293 if (seed2 < 0) seed2 += shift2;
294
295 table[index][0] = seed1;
296 table[index][1] = seed2;
297 long diff = seed1-seed2;
298 if( diff <= 0 ) diff += (shift1-1);
299
300 return ((diff << 1) | (seed1&1))& 0xffffffff;
301}
302
303std::ostream & RanecuEngine::put( std::ostream& os ) const
304{
305 char beginMarker[] = "RanecuEngine-begin";
306 os << beginMarker << "\nUvec\n";
307 std::vector<unsigned long> v = put();
308 for (unsigned int i=0; i<v.size(); ++i) {
309 os << v[i] << "\n";
310 }
311 return os;
312#ifdef REMOVED
313 char endMarker[] = "RanecuEngine-end";
314 os << " " << beginMarker << "\n";
315 os << theSeed << " ";
316 for (int i=0; i<2; ++i) {
317 os << table[theSeed][i] << "\n";
318 }
319 os << endMarker << "\n";
320 return os;
321#endif
322}
323
324std::vector<unsigned long> RanecuEngine::put () const {
325 std::vector<unsigned long> v;
326 v.push_back (engineIDulong<RanecuEngine>());
327 v.push_back(static_cast<unsigned long>(theSeed));
328 v.push_back(static_cast<unsigned long>(table[theSeed][0]));
329 v.push_back(static_cast<unsigned long>(table[theSeed][1]));
330 return v;
331}
332
333std::istream & RanecuEngine::get ( std::istream& is )
334{
335 char beginMarker [MarkerLen];
336
337 is >> std::ws;
338 is.width(MarkerLen); // causes the next read to the char* to be <=
339 // that many bytes, INCLUDING A TERMINATION \0
340 // (Stroustrup, section 21.3.2)
341 is >> beginMarker;
342 if (strcmp(beginMarker,"RanecuEngine-begin")) {
343 is.clear(std::ios::badbit | is.rdstate());
344 std::cerr << "\nInput stream mispositioned or"
345 << "\nRanecuEngine state description missing or"
346 << "\nwrong engine type found." << std::endl;
347 return is;
348 }
349 return getState(is);
350}
351
352std::string RanecuEngine::beginTag ( ) {
353 return "RanecuEngine-begin";
354}
355
356std::istream & RanecuEngine::getState ( std::istream& is )
357{
358 if ( possibleKeywordInput ( is, "Uvec", theSeed ) ) {
359 std::vector<unsigned long> v;
360 unsigned long uu;
361 for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) {
362 is >> uu;
363 if (!is) {
364 is.clear(std::ios::badbit | is.rdstate());
365 std::cerr << "\nRanecuEngine state (vector) description improper."
366 << "\ngetState() has failed."
367 << "\nInput stream is probably mispositioned now." << std::endl;
368 return is;
369 }
370 v.push_back(uu);
371 }
372 getState(v);
373 return (is);
374 }
375
376// is >> theSeed; Removed, encompassed by possibleKeywordInput()
377 char endMarker [MarkerLen];
378 for (int i=0; i<2; ++i) {
379 is >> table[theSeed][i];
380 }
381 is >> std::ws;
382 is.width(MarkerLen);
383 is >> endMarker;
384 if (strcmp(endMarker,"RanecuEngine-end")) {
385 is.clear(std::ios::badbit | is.rdstate());
386 std::cerr << "\nRanecuEngine state description incomplete."
387 << "\nInput stream is probably mispositioned now." << std::endl;
388 return is;
389 }
390
391 seq = int(theSeed);
392 return is;
393}
394
395bool RanecuEngine::get (const std::vector<unsigned long> & v) {
396 if ((v[0] & 0xffffffffUL) != engineIDulong<RanecuEngine>()) {
397 std::cerr <<
398 "\nRanecuEngine get:state vector has wrong ID word - state unchanged\n";
399 return false;
400 }
401 return getState(v);
402}
403
404bool RanecuEngine::getState (const std::vector<unsigned long> & v) {
405 if (v.size() != VECTOR_STATE_SIZE ) {
406 std::cerr <<
407 "\nRanecuEngine get:state vector has wrong length - state unchanged\n";
408 return false;
409 }
410 theSeed = v[1];
411 table[theSeed][0] = v[2];
412 table[theSeed][1] = v[3];
413 seq = int(theSeed);
414 return true;
415}
416
417
418} // namespace CLHEP
#define CLHEP_ATOMIC_INT_TYPE
Definition: atomic_int.h:25
static bool checkFile(std::istream &file, const std::string &filename, const std::string &classname, const std::string &methodname)
Definition: RandomEngine.cc:49
static void getTheTableSeeds(long *seeds, int index)
Definition: Random.cc:256
void restoreStatus(const char filename[]="Ranecu.conf")
static const int shift1
Definition: RanecuEngine.h:117
void saveStatus(const char filename[]="Ranecu.conf") const
static const int ecuyer_b
Definition: RanecuEngine.h:112
static const int ecuyer_e
Definition: RanecuEngine.h:115
static std::string engineName()
Definition: RanecuEngine.h:101
static const int ecuyer_f
Definition: RanecuEngine.h:116
void showStatus() const
std::vector< unsigned long > put() const
void setSeed(long index, int dum=0)
static const int ecuyer_d
Definition: RanecuEngine.h:114
virtual std::istream & get(std::istream &is)
std::string name() const
Definition: RanecuEngine.cc:66
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:111
static const unsigned int VECTOR_STATE_SIZE
Definition: RanecuEngine.h:120
static const int shift2
Definition: RanecuEngine.h:118
static const int ecuyer_c
Definition: RanecuEngine.h:113
void setSeeds(const long *seeds, int index=-1)
static std::string beginTag()
#define double(obj)
Definition: excDblThrow.cc:32
bool possibleKeywordInput(IS &is, const std::string &key, T &t)
Definition: RandomEngine.h:168