CLHEP VERSION Reference Documentation
   
CLHEP Home Page     CLHEP Documentation     CLHEP Bug Reports

testBug58950.cc
Go to the documentation of this file.
1 // ----------------------------------------------------------------------
2 //
3 // testBug58950 -- test problem with RanecuEngine on 64bit machines
4 //
5 // R. Weller 11/11/09 initial test from Vanderbilt
6 // L. Garren 12/1/09 rewritten for test suite
7 //
8 // ----------------------------------------------------------------------
9 #include <iostream>
10 #include <stdexcept>
11 #include <cmath>
12 #include <stdlib.h>
13 #include "CLHEP/Random/RanecuEngine.h"
14 #include "CLHEP/Random/Random.h"
15 #include "pretend.h"
16 
17 bool printCheck( int & i, double & r, std::ofstream & os )
18 {
19  os << i << " " << r << std::endl;
20  if (r < 0 || r > 1.0 ) {
21  std::cout << "Error: bad random number " << r << std::endl;
22  return false;
23  }
24  return true;
25 }
26 
27 int main() {
28 
29  std::ofstream output("testBug58950.cout");
30 
31  output << std::endl << "short " << sizeof(short) << std::endl;
32  output << "int " << sizeof(int) << std::endl;
33  output << "unsigned int " << sizeof(unsigned int) << std::endl;
34  output << "long " << sizeof(long) << std::endl;
35  output << "float " << sizeof(float) << std::endl;
36  output << "double " << sizeof(double) << std::endl;
37  output << "long double " << sizeof(long double) << std::endl << std::endl;
38 
43 
44  long rvals[2];
45  try {
46  std::ifstream in("/dev/urandom", std::ios::in | std::ios::binary);
47  if(in.is_open()) {
48  in.read((char *)(&rvals), 2*sizeof(long));
49  in.close();
50  if(in.fail()) {
51  throw std::runtime_error("File read error");
52  }
53  } else throw std::runtime_error("File open error");
54  } catch(std::runtime_error e) {
55  std::ostringstream dStr;
56  dStr << "Error: " << e.what()
57  << " processing seed from file \"" << "/dev/urandom" << "\".";
58  throw std::runtime_error(dStr.str().c_str());
59  }
60 
61  int nNumbers = 20;
62  int badcount = 0;
63 
64  long seeds[3];
65  const long *pseeds;
66  //***********************************************************************
67  // Seeds are expected to be positive. Therefore, if either seed is
68  // negative then prior to 2.0.4.5 the generator set initial conditions
69  // and generated the same sequence of numbers no matter what the seeds were.
70  seeds[0]=rvals[0];
71  seeds[1]=rvals[1];
72  seeds[2]=0;
73  if( rvals[0] > 0 ) seeds[0] = -rvals[0];
74 
75  double negseq[20] = { 0.154707, 0.587114, 0.702059, 0.566, 0.988325,
76  0.525921, 0.191554, 0.269338, 0.234277, 0.358997,
77  0.549936, 0.296877, 0.162243, 0.227732, 0.528862,
78  0.631571, 0.176462, 0.247858, 0.170025, 0.284483 };
79  double eps = 1.0E-6;
80 
81  output << std::endl << "********************" << std::endl;
82  output << "This is the case that may or may not fail." << std::endl;
83  output << "However, if it has values in (0,1), they are a " << std::endl
84  << "deterministic sequence beginning with 0.154707." << std::endl;
85  output << "seeds[0] = " << seeds[0] << "\n"
86  << "seeds[1] = " << seeds[1] << std::endl << std::endl;
87 
88  g->setTheSeeds(seeds);
89  int rseq = 0;
90  for (int i=0; i < nNumbers; ++i) {
91  double r = g->flat();
92  if( ! printCheck(i,r,output) ) ++badcount;
93  // before the change, the random number sequence was reliably the same
94  if( std::fabs(r-negseq[i]) < eps ) {
95  std::cout << " reproducing sequence " << i << " "
96  << r << " " << negseq[i] << std::endl;
97  ++rseq;
98  }
99  }
100  if( rseq == 20 ) ++badcount;
101  pseeds=g->getTheSeeds();
102  output << "Final seeds[0] = " << pseeds[0] << "\n"
103  << "Final seeds[1] = " << pseeds[1] << std::endl << std::endl;
104 
105  //***********************************************************************
106  // Prior to the 2.0.4.5 bug fix, 64bit seeds resulted in incorrect randoms
107  seeds[0]=labs(rvals[0]);
108  seeds[1]=labs(rvals[1]);
109  seeds[2]=0;
110 
111  output << std::endl << "********************" << std::endl;
112  output << "This is the case that always fails." << std::endl;
113  output << "seeds[0] = " << seeds[0] << "\n"
114  << "seeds[1] = " << seeds[1] << std::endl << std::endl;
115 
116  g->setTheSeeds(seeds);
117  for (int i=0; i < nNumbers; ++i) {
118  double r = g->flat();
119  if( ! printCheck(i,r,output) ) ++badcount;
120  }
121  pseeds=g->getTheSeeds();
122  output << "Final seeds[0] = " << pseeds[0] << "\n"
123  << "Final seeds[1] = " << pseeds[1] << std::endl << std::endl;
124 
125  //***********************************************************************
126  // recover and reuse seeds
127  seeds[0]=labs(rvals[0]);
128  seeds[1]=labs(rvals[1]);
129  seeds[2]=0;
130 
131  output << std::endl << "********************" << std::endl;
132  output << "Check rolling back a random number seed." << std::endl;
133  output << "seeds[0] = " << seeds[0] << "\n"
134  << "seeds[1] = " << seeds[1] << std::endl << std::endl;
135  std::vector<double> v;
136  g->setTheSeeds(seeds);
137 
138  for (int i=0; i < nNumbers; ++i) {
139  double r = g->flat();
140  if( ! printCheck(i,r,output) ) ++badcount;
141  }
142  pseeds=g->getTheSeeds();
143  seeds[0] = pseeds[0];
144  seeds[1] = pseeds[1];
145  output << " pseeds[0] = " << pseeds[0] << "\n"
146  << "pseeds[1] = " << pseeds[1] << std::endl;
147  for (int i=0; i < nNumbers; ++i) {
148  double r = g->flat();
149  v.push_back(r);
150  }
151  g->setTheSeeds(seeds);
152  for (int i=0; i < nNumbers; ++i) {
153  double r = g->flat();
154  if(v[i] != r ) {
155  ++badcount;
156  std::cerr << " rollback fails: i, v[i], r "
157  << i << " " << v[i] << " " << r << std::endl;
158  }
159  }
160  output << std::endl;
161 
162  //***********************************************************************
163  // 4-byte positive integers generate valid sequences, which remain within bounds.
164  seeds[0]= labs(static_cast<int>(rvals[0]));
165  seeds[1]= labs(static_cast<int>(rvals[1]));
166  seeds[2]=0;
167 
168  output << std::endl << "********************" << std::endl;
169  output << "This is the case that works." << std::endl;
170  output << std::endl << "seeds[0] = " << seeds[0] << "\n"
171  << "seeds[1] = " << seeds[1] << "\n"
172  << "seeds[2] = " << seeds[2] << std::endl << std::endl;
173 
174  g->setTheSeeds(seeds);
175  for (int i=0; i < nNumbers; ++i) {
176  double r = g->flat();
177  if( ! printCheck(i,r,output) ) ++badcount;
178  }
179  pseeds=g->getTheSeeds();
180  output << "Final seeds[0] = " << pseeds[0] << "\n"
181  << "Final seeds[1] = " << pseeds[1] << std::endl << std::endl;
182 
183  //***********************************************************************
184  // Before the fix, a bad 64bit sequence would eventually rectify itself.
185  // This starts with seeds that would have failed before the 64bit corrections
186  // were applied and loops until both seeds are positive 32-bit integers.
187  // This looping should no longer occur.
188  seeds[0]=labs(rvals[0]);
189  seeds[1]=labs(rvals[1]);
190  seeds[2]=0;
191 
192  output << std::endl << "********************" << std::endl;
193  output << "This case loops until valid short seeds occur." << std::endl;
194  output << "seeds[0] = " << seeds[0] << "\n"
195  << "seeds[1] = " << seeds[1] << std::endl << std::endl;
196 
197  g->setTheSeeds(seeds);
198  // Loop as long as the values are bad.
199  double r;
200  unsigned int low = ~0;
201  unsigned long mask = (~0) << 31;
202  unsigned long skipcount = 0;
203  output << "low = " << low << " mask = " << mask << std::endl;
204  do {
205  r = g->flat();
206  pretend_to_use( r );
207  pseeds = g->getTheSeeds();
208  ++skipcount;
209  } while((pseeds[0]&mask) || (pseeds[1]&mask));
210  if ( skipcount > 1 ) ++badcount;
211 
212  output << std::endl << "Loop terminates on two short seeds." << std::endl;
213  output << "Skipcount = " << skipcount << std::endl;
214  output << "pseeds[0]&mask = " << (pseeds[0]&mask) << std::endl;
215  output << "pseeds[1]&mask = " << (pseeds[1]&mask) << std::endl;
216  output << "Final seeds[0] = " << pseeds[0] << "\n"
217  << "Final seeds[1] = " << pseeds[1] << std::endl << std::endl;
218 
219  output << "This should be a valid sequence." << std::endl;
220  for (int i=0; i < nNumbers; ++i) {
221  double r1 = g->flat();
222  if( ! printCheck(i,r1,output) ) ++badcount;
223  }
224  pseeds=g->getTheSeeds();
225  output << "seeds[0] = " << pseeds[0] << "\n"
226  << "seeds[1] = " << pseeds[1] << std::endl << std::endl;
227 
228  if( badcount > 0 ) std::cout << "Error count is " << badcount << std::endl;
229  return badcount;
230 }
std::ofstream output("ranRestoreTest.cout")
#define double(obj)
Definition: excDblThrow.cc:32
static const long * getTheSeeds()
Definition: Random.cc:147
static HepRandom * getTheGenerator()
Definition: Random.cc:161
void pretend_to_use(T const &)
Definition: pretend.h:15
static void setTheEngine(HepRandomEngine *theNewEngine)
Definition: Random.cc:171
double flat()
Definition: Random.cc:97
bool printCheck(int &i, double &r, std::ofstream &os)
Definition: testBug58950.cc:17
static void setTheSeeds(const long *seeds, int aux=-1)
Definition: Random.cc:142
int g(shared_ptr< X >)
int main()
Definition: testBug66214.cc:30