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