CLHEP 2.4.6.4
C++ Class Library for High Energy Physics
Loading...
Searching...
No Matches
testBug58950.cc File Reference
#include "CLHEP/Random/RanecuEngine.h"
#include "CLHEP/Random/Random.h"
#include "pretend.h"
#include <cmath>
#include <iostream>
#include <limits>
#include <stdexcept>
#include <stdlib.h>
#include <vector>

Go to the source code of this file.

Functions

bool printCheck (int &i, double &r, std::ofstream &os)
 
int main ()
 

Function Documentation

◆ main()

int main ( )

Definition at line 29 of file testBug58950.cc.

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

◆ printCheck()

bool printCheck ( int &  i,
double r,
std::ofstream &  os 
)

Definition at line 19 of file testBug58950.cc.

20{
21 os << i << " " << r << std::endl;
22 if (r < 0 || r > 1.0 ) {
23 std::cout << "Error: bad random number " << r << std::endl;
24 return false;
25 }
26 return true;
27}

Referenced by main().