CLHEP 2.4.6.4
C++ Class Library for High Energy Physics
Loading...
Searching...
No Matches
Hurd160Engine.cc
Go to the documentation of this file.
1//
2// -*- C++ -*-
3//
4// -----------------------------------------------------------------------
5// HEP Random
6// Ken Smith - Initial draft started: 23rd Jul 1998
7// - Added conversion operators: 6th Aug 1998
8// J. Marraffino - Added some explicit casts to deal with
9// machines where sizeof(int) != sizeof(long) 22 Aug 1998
10// M. Fischler - Modified use of the various exponents of 2
11// to avoid per-instance space overhead and
12// correct the rounding procedure 15 Sep 1998
13// - Modified various methods to avoid any
14// possibility of predicting the next number
15// based on the last several: We skip one
16// 32-bit word per cycle. 15 Sep 1998
17// - modify word[0] in two of the constructors
18// so that no sequence can ever accidentally
19// be produced by differnt seeds. 15 Sep 1998
20// J. Marraffino - Remove dependence on hepStrings class 13 May 1999
21// M. Fischler - Put endl at end of a save 10 Apr 2001
22// M. Fischler - In restore, checkFile for file not found 03 Dec 2004
23// M. Fischler - Methods put, get for instance save/restore 12/8/04
24// M. Fischler - split get() into tag validation and
25// getState() for anonymous restores 12/27/04
26// M. Fischler - put/get for vectors of ulongs 3/14/05
27// M. Fischler - State-saving using only ints, for portability 4/12/05
28//
29// =======================================================================
30
31#include "CLHEP/Random/defs.h"
32#include "CLHEP/Random/Random.h"
33#include "CLHEP/Random/Hurd160Engine.h"
34#include "CLHEP/Random/engineIDulong.h"
35#include "CLHEP/Utility/atomic_int.h"
36
37#include <atomic>
38#include <cstdlib> // for std::abs(int)
39#include <iostream>
40#include <ostream>
41#include <string.h>
42#include <string>
43#include <vector>
44
45namespace CLHEP {
46
47namespace {
48 // Number of instances with automatic seed selection
49 CLHEP_ATOMIC_INT_TYPE numberOfEngines(0);
50
51 // Maximum index into the seed table
52 const int maxIndex = 215;
53}
54
55static const int MarkerLen = 64; // Enough room to hold a begin or end marker.
56
57std::string Hurd160Engine::name() const {return "Hurd160Engine";}
58
59static inline unsigned int f160(unsigned int a, unsigned int b, unsigned int c)
60{
61 return ( ((b<<2) & 0x7c) | ((a<<2) & ~0x7c) | (a>>30) ) ^ ( (c<<1)|(c>>31) );
62}
63
66{
67 int numEngines = numberOfEngines++;
68 int cycle = std::abs(int(numEngines/maxIndex));
69 int curIndex = std::abs(int(numEngines%maxIndex));
70 long mask = ((cycle & 0x007fffff) << 8);
71 HepRandom::getTheTableSeeds(seeds_, curIndex);
72 seeds_[0] ^= mask;
73 setSeeds(seeds_, 0);
74 words[0] ^= 0x1324abcd; // To make unique vs long or two unsigned
75 if (words[0]==0) words[0] = 1; // ints in the constructor
76
77 for( int i=0; i < 100; ++i ) flat(); // warm-up just a bit
78}
79
82{
83 is >> *this;
84}
85
88{
89 seeds_[0] = seed;
90 setSeeds(seeds_, 0);
91 words[0] ^= 0xa5482134; // To make unique vs default two unsigned
92 if (words[0]==0) words[0] = 1; // ints in the constructor
93 for( int i=0; i < 100; ++i ) flat(); // warm-up just a bit
94}
95
96Hurd160Engine::Hurd160Engine( int rowIndex, int colIndex )
98{
99 int cycle = std::abs(int(rowIndex/maxIndex));
100 int row = std::abs(int(rowIndex%maxIndex));
101 int col = colIndex & 0x1;
102 long mask = (( cycle & 0x000007ff ) << 20 );
103 HepRandom::getTheTableSeeds( seeds_, row );
104 // NOTE: is that really the seed wanted (PGC) ??
105 seeds_[0] = seeds_[col]^mask;
106 setSeeds(seeds_, 0);
107 for( int i=0; i < 100; ++i ) flat(); // warm-up just a bit
108}
109
111
112void Hurd160Engine::advance() {
113 unsigned int W0, W1, W2, W3, W4;
114
115 W0 = words[0];
116 W1 = words[1];
117 W2 = words[2];
118 W3 = words[3];
119 W4 = words[4];
120 W1 ^= W0; W0 = f160(W4, W3, W0);
121 W2 ^= W1; W1 = f160(W0, W4, W1);
122 W3 ^= W2; W2 = f160(W1, W0, W2);
123 W4 ^= W3; W3 = f160(W2, W1, W3);
124 W0 ^= W4; W4 = f160(W3, W2, W4);
125 words[0] = W0 & 0xffffffff;
126 words[1] = W1 & 0xffffffff;
127 words[2] = W2 & 0xffffffff;
128 words[3] = W3 & 0xffffffff;
129 words[4] = W4 & 0xffffffff;
130 wordIndex = 5;
131
132} // advance();
133
135
136 if( wordIndex <= 2 ) { // MF 9/15/98:
137 // skip word 0 and use two words per flat
138 advance();
139 }
140
141 // LG 6/30/2010
142 // define the order of execution for --wordIndex
143 double x = words[--wordIndex] * twoToMinus_32() ; // most significant part
144 double y = (words[--wordIndex]>>11) * twoToMinus_53() + // fill in rest of bits
145 nearlyTwoToMinus_54(); // make sure non-zero
146 return x + y ;
147}
148
149void Hurd160Engine::flatArray( const int size, double* vect ) {
150 for (int i = 0; i < size; ++i) {
151 vect[i] = flat();
152 }
153}
154
155void Hurd160Engine::setSeed( long seed, int ) {
156 seeds_[0] = seed;
157 seeds_[1] = 0;
158 theSeed = seeds_[0];
159 words[0] = (unsigned int)seed;
160 for (wordIndex = 1; wordIndex < 5; ++wordIndex) {
161 words[wordIndex] = 69607 * words[wordIndex-1] + 54329;
162 }
163}
164
165void Hurd160Engine::setSeeds( const long* seeds, int ) {
166 theSeeds = seeds;
167 setSeed( *seeds ? *seeds : 32767, 0 );
168}
169
170void Hurd160Engine::saveStatus( const char filename[] ) const {
171 std::ofstream outFile(filename, std::ios::out);
172 if( !outFile.bad() ) {
173 outFile << "Uvec\n";
174 std::vector<unsigned long> v = put();
175 #ifdef TRACE_IO
176 std::cout << "Result of v = put() is:\n";
177 #endif
178 for (unsigned int i=0; i<v.size(); ++i) {
179 outFile << v[i] << "\n";
180 #ifdef TRACE_IO
181 std::cout << v[i] << " ";
182 if (i%6==0) std::cout << "\n";
183 #endif
184 }
185 #ifdef TRACE_IO
186 std::cout << "\n";
187 #endif
188 }
189#ifdef REMOVED
190 outFile << std::setprecision(20) << theSeed << " ";
191 outFile << wordIndex << " ";
192 for( int i = 0; i < 5; ++i ) {
193 outFile << words[i] << " ";
194 }
195 outFile << std::endl;
196#endif
197}
198
199void Hurd160Engine::restoreStatus( const char filename[] ) {
200 std::ifstream inFile(filename, std::ios::in);
201 if (!checkFile ( inFile, filename, engineName(), "restoreStatus" )) {
202 std::cerr << " -- Engine state remains unchanged\n";
203 return;
204 }
205 if ( possibleKeywordInput ( inFile, "Uvec", theSeed ) ) {
206 std::vector<unsigned long> v;
207 unsigned long xin;
208 for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) {
209 inFile >> xin;
210 #ifdef TRACE_IO
211 std::cout << "ivec = " << ivec << " xin = " << xin << " ";
212 if (ivec%3 == 0) std::cout << "\n";
213 #endif
214 if (!inFile) {
215 inFile.clear(std::ios::badbit | inFile.rdstate());
216 std::cerr << "\nHurd160Engine state (vector) description improper."
217 << "\nrestoreStatus has failed."
218 << "\nInput stream is probably mispositioned now." << std::endl;
219 return;
220 }
221 v.push_back(xin);
222 }
223 getState(v);
224 return;
225 }
226
227 if( !inFile.bad() ) {
228// inFile >> theSeed; removed -- encompased by possibleKeywordInput
229 inFile >> wordIndex;
230 for( int i = 0; i < 5; ++i ) {
231 inFile >> words[i];
232 }
233 }
234}
235
237 long pr = std::cout.precision(20);
238 std::cout << std::endl;
239 std::cout << "----------- Hurd engine status ----------" << std::endl;
240 std::cout << "Initial seed = " << theSeed << std::endl;
241 std::cout << "Current index = " << wordIndex << std::endl;
242 std::cout << "Current words = " << std::endl;
243 for( int i = 0; i < 5 ; ++i ) {
244 std::cout << " " << words[i] << std::endl;
245 }
246 std::cout << "------------------------------------------" << std::endl;
247 std::cout.precision(pr);
248}
249
250Hurd160Engine::operator double() {
251 return flat();
252}
253
254Hurd160Engine::operator float() {
255 if( wordIndex <= 1 ) { // MF 9/15/98: skip word 0
256 advance();
257 }
258 return words[--wordIndex ] * twoToMinus_32();
259}
260
261Hurd160Engine::operator unsigned int() {
262 if( wordIndex <= 1 ) { // MF 9/15/98: skip word 0
263 advance();
264 }
265 return words[--wordIndex];
266}
267
268std::ostream& Hurd160Engine::put(std::ostream& os) const {
269 char beginMarker[] = "Hurd160Engine-begin";
270 os << beginMarker << "\nUvec\n";
271 std::vector<unsigned long> v = put();
272 for (unsigned int i=0; i<v.size(); ++i) {
273 os << v[i] << "\n";
274 }
275 return os;
276#ifdef REMOVED
277 char endMarker[] = "Hurd160Engine-end";
278 long pr = os.precision(20);
279 os << " " << beginMarker << " ";
280 os << theSeed << " ";
281 os << wordIndex << " ";
282 for (int i = 0; i < 5; ++i) {
283 os << words[i] << "\n";
284 }
285 os << endMarker << "\n ";
286 os.precision(pr);
287 return os;
288#endif
289}
290
291std::vector<unsigned long> Hurd160Engine::put () const {
292 std::vector<unsigned long> v;
293 v.push_back (engineIDulong<Hurd160Engine>());
294 v.push_back(static_cast<unsigned long>(wordIndex));
295 for (int i = 0; i < 5; ++i) {
296 v.push_back(static_cast<unsigned long>(words[i]));
297 }
298 return v;
299}
300
301
302std::istream& Hurd160Engine::get(std::istream& is) {
303 char beginMarker [MarkerLen];
304 is >> std::ws;
305 is.width(MarkerLen); // causes the next read to the char* to be <=
306 // that many bytes, INCLUDING A TERMINATION \0
307 // (Stroustrup, section 21.3.2)
308 is >> beginMarker;
309 if (strcmp(beginMarker,"Hurd160Engine-begin")) {
310 is.clear(std::ios::badbit | is.rdstate());
311 std::cerr << "\nInput mispositioned or"
312 << "\nHurd160Engine state description missing or"
313 << "\nwrong engine type found." << std::endl;
314 return is;
315 }
316 return getState(is);
317}
318
319std::string Hurd160Engine::beginTag ( ) {
320 return "Hurd160Engine-begin";
321}
322
323std::istream& Hurd160Engine::getState(std::istream& is) {
324 if ( possibleKeywordInput ( is, "Uvec", theSeed ) ) {
325 std::vector<unsigned long> v;
326 unsigned long uu;
327 for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) {
328 is >> uu;
329 if (!is) {
330 is.clear(std::ios::badbit | is.rdstate());
331 std::cerr << "\nHurd160Engine state (vector) description improper."
332 << "\ngetState() has failed."
333 << "\nInput stream is probably mispositioned now." << std::endl;
334 return is;
335 }
336 v.push_back(uu);
337 }
338 getState(v);
339 return (is);
340 }
341
342// is >> theSeed; Removed, encompassed by possibleKeywordInput()
343
344 char endMarker [MarkerLen];
345 is >> wordIndex;
346 for (int i = 0; i < 5; ++i) {
347 is >> words[i];
348 }
349 is >> std::ws;
350 is.width(MarkerLen);
351 is >> endMarker;
352 if (strcmp(endMarker,"Hurd160Engine-end")) {
353 is.clear(std::ios::badbit | is.rdstate());
354 std::cerr << "\nHurd160Engine state description incomplete."
355 << "\nInput stream is probably mispositioned now." << std::endl;
356 return is;
357 }
358 return is;
359}
360
361
362bool Hurd160Engine::get (const std::vector<unsigned long> & v) {
363 if ((v[0] & 0xffffffffUL) != engineIDulong<Hurd160Engine>()) {
364 std::cerr <<
365 "\nHurd160Engine get:state vector has wrong ID word - state unchanged\n";
366 return false;
367 }
368 return getState(v);
369}
370
371bool Hurd160Engine::getState (const std::vector<unsigned long> & v) {
372 if (v.size() != VECTOR_STATE_SIZE ) {
373 std::cerr <<
374 "\nHurd160Engine get:state vector has wrong length - state unchanged\n";
375 return false;
376 }
377 wordIndex = (int)v[1];
378 for (int i = 0; i < 5; ++i) {
379 words[i] = (unsigned int)v[i+2];
380 }
381 return true;
382}
383
384
385} // namespace CLHEP
#define CLHEP_ATOMIC_INT_TYPE
Definition: atomic_int.h:25
static double twoToMinus_32()
static double twoToMinus_53()
static double nearlyTwoToMinus_54()
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
static const unsigned int VECTOR_STATE_SIZE
Definition: Hurd160Engine.h:91
virtual std::istream & get(std::istream &is)
void setSeeds(const long *seeds, int)
void restoreStatus(const char filename[]="Hurd160Engine.conf")
void showStatus() const
virtual std::istream & getState(std::istream &is)
std::vector< unsigned long > put() const
static std::string engineName()
Definition: Hurd160Engine.h:83
void flatArray(const int size, double *vect)
void setSeed(long seed, int)
static std::string beginTag()
void saveStatus(const char filename[]="Hurd160Engine.conf") const
std::string name() const
#define double(obj)
Definition: excDblThrow.cc:32
bool possibleKeywordInput(IS &is, const std::string &key, T &t)
Definition: RandomEngine.h:168