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