1 | /* boost random_test.cpp various tests |
---|
2 | * |
---|
3 | * Copyright Jens Maurer 2000 |
---|
4 | * Distributed under the Boost Software License, Version 1.0. (See |
---|
5 | * accompanying file LICENSE_1_0.txt or copy at |
---|
6 | * http://www.boost.org/LICENSE_1_0.txt) |
---|
7 | * |
---|
8 | * $Id: random_test.cpp,v 1.57 2005/06/16 09:56:21 johnmaddock Exp $ |
---|
9 | */ |
---|
10 | |
---|
11 | #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 |
---|
12 | #pragma warning( disable : 4786 ) |
---|
13 | #endif |
---|
14 | |
---|
15 | #include <iostream> |
---|
16 | #include <sstream> |
---|
17 | #include <string> |
---|
18 | #include <cmath> |
---|
19 | #include <iterator> |
---|
20 | #include <vector> |
---|
21 | #include <boost/random.hpp> |
---|
22 | #include <boost/config.hpp> |
---|
23 | |
---|
24 | #include <boost/test/test_tools.hpp> |
---|
25 | #include <boost/test/included/test_exec_monitor.hpp> |
---|
26 | |
---|
27 | #ifdef BOOST_NO_STDC_NAMESPACE |
---|
28 | namespace std { using ::abs; using ::fabs; using ::pow; } |
---|
29 | #endif |
---|
30 | |
---|
31 | |
---|
32 | /* |
---|
33 | * General portability note: |
---|
34 | * MSVC mis-compiles explicit function template instantiations. |
---|
35 | * For example, f<A>() and f<B>() are both compiled to call f<A>(). |
---|
36 | * BCC is unable to implicitly convert a "const char *" to a std::string |
---|
37 | * when using explicit function template instantiations. |
---|
38 | * |
---|
39 | * Therefore, avoid explicit function template instantiations. |
---|
40 | */ |
---|
41 | |
---|
42 | /* |
---|
43 | * Validate correct implementation |
---|
44 | */ |
---|
45 | |
---|
46 | // own run |
---|
47 | bool check(unsigned long x, const boost::mt11213b&) { return x == 3809585648U; } |
---|
48 | |
---|
49 | // validation by experiment from mt19937.c |
---|
50 | bool check(unsigned long x, const boost::mt19937&) { return x == 4123659995U; } |
---|
51 | |
---|
52 | // validation values from the publications |
---|
53 | bool check(int x, const boost::minstd_rand0&) { return x == 1043618065; } |
---|
54 | |
---|
55 | // validation values from the publications |
---|
56 | bool check(int x, const boost::minstd_rand&) { return x == 399268537; } |
---|
57 | |
---|
58 | #if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T) |
---|
59 | // by experiment from lrand48() |
---|
60 | bool check(unsigned long x, const boost::rand48&) { return x == 1993516219; } |
---|
61 | #endif |
---|
62 | |
---|
63 | // ???? |
---|
64 | bool check(unsigned long x, const boost::taus88&) { return x == 3535848941U; } |
---|
65 | |
---|
66 | // ???? |
---|
67 | bool check(int x, const boost::ecuyer1988&) { return x == 2060321752; } |
---|
68 | |
---|
69 | // validation by experiment from Harry Erwin's generator.h (private e-mail) |
---|
70 | bool check(unsigned int x, const boost::kreutzer1986&) { return x == 139726; } |
---|
71 | |
---|
72 | bool check(double x, const boost::lagged_fibonacci607&) { return std::abs(x-0.401269) < 1e-5; } |
---|
73 | |
---|
74 | // principal operation validated with CLHEP, values by experiment |
---|
75 | bool check(unsigned long x, const boost::ranlux3&) { return x == 5957620; } |
---|
76 | bool check(unsigned long x, const boost::ranlux4&) { return x == 8587295; } |
---|
77 | |
---|
78 | bool check(float x, const boost::ranlux3_01&) |
---|
79 | { return std::abs(x-5957620/std::pow(2.0f,24)) < 1e-6; } |
---|
80 | bool check(float x, const boost::ranlux4_01&) |
---|
81 | { return std::abs(x-8587295/std::pow(2.0f,24)) < 1e-6; } |
---|
82 | |
---|
83 | bool check(double x, const boost::ranlux64_3_01&) |
---|
84 | { return std::abs(x-0.838413) < 1e-6; } |
---|
85 | bool check(double x, const boost::ranlux64_4_01&) |
---|
86 | { return std::abs(x-0.59839) < 1e-6; } |
---|
87 | |
---|
88 | template<class PRNG> |
---|
89 | void validate(const std::string & name, const PRNG &) |
---|
90 | { |
---|
91 | std::cout << "validating " << name << ": "; |
---|
92 | PRNG rng; // default ctor |
---|
93 | for(int i = 0; i < 9999; i++) |
---|
94 | rng(); |
---|
95 | typename PRNG::result_type val = rng(); |
---|
96 | // make sure the validation function is a static member |
---|
97 | bool result = check(val, rng); |
---|
98 | |
---|
99 | // allow for a simple eyeball check for MSVC instantiation brokenness |
---|
100 | // (if the numbers for all generators are the same, it's obviously broken) |
---|
101 | std::cout << val << std::endl; |
---|
102 | BOOST_CHECK(result); |
---|
103 | } |
---|
104 | |
---|
105 | void validate_all() |
---|
106 | { |
---|
107 | using namespace boost; |
---|
108 | #if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T) |
---|
109 | validate("rand48", rand48()); |
---|
110 | #endif |
---|
111 | validate("minstd_rand", minstd_rand()); |
---|
112 | validate("minstd_rand0", minstd_rand0()); |
---|
113 | validate("ecuyer combined", ecuyer1988()); |
---|
114 | validate("mt11213b", mt11213b()); |
---|
115 | validate("mt19937", mt19937()); |
---|
116 | validate("kreutzer1986", kreutzer1986()); |
---|
117 | validate("ranlux3", ranlux3()); |
---|
118 | validate("ranlux4", ranlux4()); |
---|
119 | validate("ranlux3_01", ranlux3_01()); |
---|
120 | validate("ranlux4_01", ranlux4_01()); |
---|
121 | validate("ranlux64_3_01", ranlux64_3_01()); |
---|
122 | validate("ranlux64_4_01", ranlux64_4_01()); |
---|
123 | validate("taus88", taus88()); |
---|
124 | validate("lagged_fibonacci607", lagged_fibonacci607()); |
---|
125 | } |
---|
126 | |
---|
127 | |
---|
128 | /* |
---|
129 | * Check function signatures |
---|
130 | */ |
---|
131 | |
---|
132 | #if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x570) ) |
---|
133 | #pragma warn -par |
---|
134 | #endif |
---|
135 | template<class URNG, class Dist> |
---|
136 | void instantiate_dist(URNG& urng, const char * name, const Dist& dist) |
---|
137 | { |
---|
138 | // this makes a copy of urng |
---|
139 | boost::variate_generator<URNG, Dist> gen(urng, dist); |
---|
140 | |
---|
141 | // this keeps a reference to urng |
---|
142 | boost::variate_generator<URNG&, Dist> genref(urng, dist); |
---|
143 | |
---|
144 | #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
---|
145 | // and here is a pointer to (a copy of) the urng |
---|
146 | URNG copy = urng; |
---|
147 | boost::variate_generator<URNG*, Dist> genptr(©, dist); |
---|
148 | #endif |
---|
149 | |
---|
150 | for(int i = 0; i < 1000; ++i) { |
---|
151 | (void) gen(); |
---|
152 | (void) genref(); |
---|
153 | #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
---|
154 | (void) genptr(); |
---|
155 | #endif |
---|
156 | } |
---|
157 | typename Dist::result_type g = gen(); |
---|
158 | BOOST_CHECK(std::abs(g - genref()) < 1e-6); |
---|
159 | #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
---|
160 | BOOST_CHECK(std::abs(g - genptr()) < 1e-6); |
---|
161 | #endif |
---|
162 | |
---|
163 | (void) gen.engine(); |
---|
164 | gen.distribution().reset(); |
---|
165 | |
---|
166 | Dist d = dist; // copy ctor |
---|
167 | d = dist; // copy assignment |
---|
168 | |
---|
169 | #if !defined(BOOST_NO_OPERATORS_IN_NAMESPACE) && !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) |
---|
170 | { |
---|
171 | std::ostringstream file; |
---|
172 | file << urng << std::endl; |
---|
173 | file << d; |
---|
174 | std::istringstream input(file.str()); |
---|
175 | // std::cout << file.str() << std::endl; |
---|
176 | URNG restored_engine; |
---|
177 | input >> restored_engine; |
---|
178 | input >> std::ws; |
---|
179 | Dist restored_dist; |
---|
180 | input >> restored_dist; |
---|
181 | #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // MSVC brokenness |
---|
182 | boost::variate_generator<URNG, Dist> old(urng, d); |
---|
183 | boost::variate_generator<URNG, Dist> restored(restored_engine, restored_dist); |
---|
184 | // advance some more so that state is exercised |
---|
185 | for(int i = 0; i < 1000; ++i) { |
---|
186 | (void) old(); |
---|
187 | (void) restored(); |
---|
188 | } |
---|
189 | BOOST_CHECK_MESSAGE((std::abs(old()-restored()) < 0.0001), |
---|
190 | (std::string(name) + " old == restored_dist")); |
---|
191 | #endif // BOOST_MSVC |
---|
192 | } |
---|
193 | #endif // BOOST_NO_OPERATORS_IN_NAMESPACE |
---|
194 | } |
---|
195 | |
---|
196 | template<class URNG, class RealType> |
---|
197 | void instantiate_real_dist(URNG& urng, RealType /* ignored */) |
---|
198 | { |
---|
199 | instantiate_dist(urng, "uniform_real", |
---|
200 | boost::uniform_real<RealType>(0, 2.1)); |
---|
201 | instantiate_dist(urng, "triangle_distribution", |
---|
202 | boost::triangle_distribution<RealType>(1, 1.5, 7)); |
---|
203 | instantiate_dist(urng, "exponential_distribution", |
---|
204 | boost::exponential_distribution<RealType>(5)); |
---|
205 | instantiate_dist(urng, "normal_distribution", |
---|
206 | boost::normal_distribution<RealType>()); |
---|
207 | instantiate_dist(urng, "lognormal_distribution", |
---|
208 | boost::lognormal_distribution<RealType>(1, 1)); |
---|
209 | instantiate_dist(urng, "cauchy_distribution", |
---|
210 | boost::cauchy_distribution<RealType>(1)); |
---|
211 | instantiate_dist(urng, "gamma_distribution", |
---|
212 | boost::gamma_distribution<RealType>(1)); |
---|
213 | } |
---|
214 | |
---|
215 | template<class URNG, class ResultType> |
---|
216 | void instantiate_urng(const std::string & s, const URNG &, const ResultType &) |
---|
217 | { |
---|
218 | std::cout << "Basic tests for " << s; |
---|
219 | URNG urng; |
---|
220 | urng.seed(); // seed() member function |
---|
221 | int a[URNG::has_fixed_range ? 5 : 10]; // compile-time constant |
---|
222 | (void) a; // avoid "unused" warning |
---|
223 | typename URNG::result_type x1 = urng(); |
---|
224 | ResultType x2 = x1; |
---|
225 | (void) &x2; // avoid "unused" warning |
---|
226 | |
---|
227 | URNG urng2 = urng; // copy constructor |
---|
228 | #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // MSVC brokenness |
---|
229 | BOOST_CHECK(urng == urng2); // operator== |
---|
230 | BOOST_CHECK(!(urng != urng2)); // operator!= |
---|
231 | urng(); |
---|
232 | urng2 = urng; // copy assignment |
---|
233 | BOOST_CHECK(urng == urng2); |
---|
234 | #endif // BOOST_MSVC |
---|
235 | |
---|
236 | const std::vector<int> v(9999u, 0x41); |
---|
237 | std::vector<int>::const_iterator it = v.begin(); |
---|
238 | std::vector<int>::const_iterator it_end = v.end(); |
---|
239 | URNG urng3(it, it_end); |
---|
240 | BOOST_CHECK(it != v.begin()); |
---|
241 | std::cout << "; seeding uses " << (it - v.begin()) << " words" << std::endl; |
---|
242 | |
---|
243 | bool have_exception = false; |
---|
244 | try { |
---|
245 | // now check that exceptions are thrown |
---|
246 | it = v.end(); |
---|
247 | urng3.seed(it, it_end); |
---|
248 | } catch(std::invalid_argument& x) { |
---|
249 | have_exception = true; |
---|
250 | } |
---|
251 | BOOST_CHECK(have_exception); |
---|
252 | |
---|
253 | // check for min/max members |
---|
254 | ResultType min = (urng3.min)(); |
---|
255 | (void) &min; |
---|
256 | ResultType max = (urng3.max)(); |
---|
257 | (void) &max; |
---|
258 | |
---|
259 | #if !defined(BOOST_NO_OPERATORS_IN_NAMESPACE) && !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) |
---|
260 | // Streamable concept not supported for broken compilers |
---|
261 | |
---|
262 | // advance a little so that state is relatively arbitrary |
---|
263 | for(int i = 0; i < 9307; ++i) |
---|
264 | urng(); |
---|
265 | urng2 = urng; |
---|
266 | |
---|
267 | { |
---|
268 | // narrow stream first |
---|
269 | std::ostringstream file; |
---|
270 | file << urng; |
---|
271 | // move forward |
---|
272 | urng(); |
---|
273 | // restore old state |
---|
274 | std::istringstream input(file.str()); |
---|
275 | input >> urng; |
---|
276 | // std::cout << file.str() << std::endl; |
---|
277 | #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // MSVC brokenness |
---|
278 | // advance some more so that state is exercised |
---|
279 | for(int i = 0; i < 10000; ++i) { |
---|
280 | urng(); |
---|
281 | urng2(); |
---|
282 | } |
---|
283 | BOOST_CHECK(urng == urng2); |
---|
284 | #endif // BOOST_MSVC |
---|
285 | } |
---|
286 | |
---|
287 | urng2 = urng; |
---|
288 | #if !defined(BOOST_NO_STD_WSTREAMBUF) && !defined(BOOST_NO_STD_WSTRING) |
---|
289 | { |
---|
290 | // then wide stream |
---|
291 | std::wostringstream file; |
---|
292 | file << urng; |
---|
293 | // move forward |
---|
294 | urng(); |
---|
295 | std::wistringstream input(file.str()); |
---|
296 | input >> urng; |
---|
297 | #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // MSVC brokenness |
---|
298 | // advance some more so that state is exercised |
---|
299 | for(int i = 0; i < 10000; ++i) { |
---|
300 | urng(); |
---|
301 | urng2(); |
---|
302 | } |
---|
303 | BOOST_CHECK(urng == urng2); |
---|
304 | #endif // BOOST_MSVC |
---|
305 | } |
---|
306 | #endif // BOOST_NO_STD_WSTREAMBUF, BOOST_NO_STD_WSTRING |
---|
307 | #endif // BOOST_NO_OPERATORS_IN_NAMESPACE etc. |
---|
308 | |
---|
309 | // instantiate various distributions with this URNG |
---|
310 | // instantiate_dist(urng, "uniform_smallint", boost::uniform_smallint(0, 11)); |
---|
311 | instantiate_dist(urng, "uniform_int", boost::uniform_int<>(-200, 20000)); |
---|
312 | instantiate_dist(urng, "bernoulli_distribution", |
---|
313 | boost::bernoulli_distribution<>(0.2)); |
---|
314 | instantiate_dist(urng, "binomial_distribution", |
---|
315 | boost::binomial_distribution<>(4, 0.2)); |
---|
316 | instantiate_dist(urng, "geometric_distribution", |
---|
317 | boost::geometric_distribution<>(0.8)); |
---|
318 | instantiate_dist(urng, "poisson_distribution", |
---|
319 | boost::poisson_distribution<>(1)); |
---|
320 | |
---|
321 | instantiate_real_dist(urng, 1.0f); |
---|
322 | instantiate_real_dist(urng, 1.0); |
---|
323 | instantiate_real_dist(urng, 1.0l); |
---|
324 | |
---|
325 | #if 0 |
---|
326 | // We cannot compare the outcomes before/after save with std::abs(x-y) |
---|
327 | instantiate_dist("uniform_on_sphere", |
---|
328 | boost::uniform_on_sphere<URNG>(urng, 2)); |
---|
329 | #endif |
---|
330 | } |
---|
331 | |
---|
332 | void instantiate_all() |
---|
333 | { |
---|
334 | using namespace boost; |
---|
335 | |
---|
336 | #if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T) |
---|
337 | instantiate_urng("rand48", rand48(), 0); |
---|
338 | rand48 rnd(boost::int32_t(5)); |
---|
339 | rand48 rnd2(boost::uint64_t(0x80000000) * 42); |
---|
340 | rnd.seed(boost::int32_t(17)); |
---|
341 | rnd2.seed(boost::uint64_t(0x80000000) * 49); |
---|
342 | #endif |
---|
343 | |
---|
344 | instantiate_urng("minstd_rand0", minstd_rand0(), 0); |
---|
345 | instantiate_urng("minstd_rand", minstd_rand(), 0); |
---|
346 | minstd_rand mstd(42); |
---|
347 | mstd.seed(17); |
---|
348 | |
---|
349 | instantiate_urng("ecuyer1988", ecuyer1988(), 0); |
---|
350 | instantiate_urng("kreutzer1986", kreutzer1986(), 0); |
---|
351 | instantiate_urng("hellekalek1995", hellekalek1995(), 0); |
---|
352 | |
---|
353 | instantiate_urng("mt11213b", mt11213b(), 0u); |
---|
354 | instantiate_urng("mt19937", mt19937(), 0u); |
---|
355 | |
---|
356 | mt19937 mt(boost::uint32_t(17)); // needs to be an exact type match for MSVC |
---|
357 | int i = 42; |
---|
358 | mt.seed(boost::uint32_t(i)); |
---|
359 | mt19937 mt2(mstd); |
---|
360 | mt2.seed(mstd); |
---|
361 | |
---|
362 | |
---|
363 | random_number_generator<mt19937> std_rng(mt2); |
---|
364 | (void) std_rng(10); |
---|
365 | |
---|
366 | instantiate_urng("lagged_fibonacci", |
---|
367 | boost::random::lagged_fibonacci<boost::uint32_t, 24, 607, 273>(), |
---|
368 | 0u); |
---|
369 | instantiate_urng("lagged_fibonacci607", lagged_fibonacci607(), 0.0); |
---|
370 | |
---|
371 | instantiate_urng("ranlux3", ranlux3(), 0u); |
---|
372 | instantiate_urng("ranlux4", ranlux4(), 0u); |
---|
373 | |
---|
374 | instantiate_urng("ranlux3_01", ranlux3_01(), 0.0f); |
---|
375 | instantiate_urng("ranlux4_01", ranlux4_01(), 0.0f); |
---|
376 | |
---|
377 | instantiate_urng("ranlux64_3_01", ranlux64_3_01(), 0.0); |
---|
378 | instantiate_urng("ranlux64_4_01", ranlux64_4_01(), 0.0); |
---|
379 | |
---|
380 | instantiate_urng("taus88", taus88(), 0u); |
---|
381 | } |
---|
382 | |
---|
383 | /* |
---|
384 | * A few equidistribution tests |
---|
385 | */ |
---|
386 | |
---|
387 | // yet to come... |
---|
388 | |
---|
389 | template<class Generator> |
---|
390 | void check_uniform_int(Generator & gen, int iter) |
---|
391 | { |
---|
392 | std::cout << "testing uniform_int(" << (gen.min)() << "," << (gen.max)() |
---|
393 | << ")" << std::endl; |
---|
394 | int range = (gen.max)()-(gen.min)()+1; |
---|
395 | std::vector<int> bucket(range); |
---|
396 | for(int j = 0; j < iter; j++) { |
---|
397 | int result = gen(); |
---|
398 | if(result < (gen.min)() || result > (gen.max)()) |
---|
399 | std::cerr << " ... delivers " << result << std::endl; |
---|
400 | else |
---|
401 | bucket[result-(gen.min)()]++; |
---|
402 | } |
---|
403 | int sum = 0; |
---|
404 | // use a different variable name "k", because MSVC has broken "for" scoping |
---|
405 | for(int k = 0; k < range; k++) |
---|
406 | sum += bucket[k]; |
---|
407 | double avg = static_cast<double>(sum)/range; |
---|
408 | double threshold = 2*avg/std::sqrt(static_cast<double>(iter)); |
---|
409 | for(int i = 0; i < range; i++) { |
---|
410 | if(std::fabs(bucket[i] - avg) > threshold) { |
---|
411 | // 95% confidence interval |
---|
412 | std::cout << " ... has bucket[" << i << "] = " << bucket[i] |
---|
413 | << " (distance " << (bucket[i] - avg) << ")" |
---|
414 | << std::endl; |
---|
415 | } |
---|
416 | } |
---|
417 | } |
---|
418 | |
---|
419 | template<class Generator> |
---|
420 | void test_uniform_int(Generator & gen) |
---|
421 | { |
---|
422 | typedef boost::uniform_int<int> int_gen; |
---|
423 | |
---|
424 | // large range => small range (modulo case) |
---|
425 | typedef boost::variate_generator<Generator&, int_gen> level_one; |
---|
426 | |
---|
427 | level_one uint12(gen, int_gen(1,2)); |
---|
428 | BOOST_CHECK((uint12.distribution().min)() == 1); |
---|
429 | BOOST_CHECK((uint12.distribution().max)() == 2); |
---|
430 | check_uniform_int(uint12, 100000); |
---|
431 | level_one uint16(gen, int_gen(1,6)); |
---|
432 | check_uniform_int(uint16, 100000); |
---|
433 | |
---|
434 | // test chaining to get all cases in operator() |
---|
435 | |
---|
436 | // identity map |
---|
437 | typedef boost::variate_generator<level_one&, int_gen> level_two; |
---|
438 | level_two uint01(uint12, int_gen(0, 1)); |
---|
439 | check_uniform_int(uint01, 100000); |
---|
440 | |
---|
441 | // small range => larger range |
---|
442 | level_two uint05(uint12, int_gen(-3, 2)); |
---|
443 | check_uniform_int(uint05, 100000); |
---|
444 | |
---|
445 | // larger => small range, rejection case |
---|
446 | typedef boost::variate_generator<level_two&, int_gen> level_three; |
---|
447 | level_three uint1_4(uint05, int_gen(1, 4)); |
---|
448 | check_uniform_int(uint1_4, 100000); |
---|
449 | } |
---|
450 | |
---|
451 | #if defined(BOOST_MSVC) && _MSC_VER <= 1200 |
---|
452 | |
---|
453 | // These explicit instantiations are necessary, otherwise MSVC does |
---|
454 | // not find the <boost/operators.hpp> inline friends. |
---|
455 | // We ease the typing with a suitable preprocessor macro. |
---|
456 | #define INSTANT(x) \ |
---|
457 | template class boost::uniform_smallint<x>; \ |
---|
458 | template class boost::uniform_int<x>; \ |
---|
459 | template class boost::uniform_real<x>; \ |
---|
460 | template class boost::bernoulli_distribution<x>; \ |
---|
461 | template class boost::geometric_distribution<x>; \ |
---|
462 | template class boost::triangle_distribution<x>; \ |
---|
463 | template class boost::exponential_distribution<x>; \ |
---|
464 | template class boost::normal_distribution<x>; \ |
---|
465 | template class boost::uniform_on_sphere<x>; \ |
---|
466 | template class boost::lognormal_distribution<x>; |
---|
467 | |
---|
468 | INSTANT(boost::minstd_rand0) |
---|
469 | INSTANT(boost::minstd_rand) |
---|
470 | INSTANT(boost::ecuyer1988) |
---|
471 | INSTANT(boost::kreutzer1986) |
---|
472 | INSTANT(boost::hellekalek1995) |
---|
473 | INSTANT(boost::mt19937) |
---|
474 | INSTANT(boost::mt11213b) |
---|
475 | |
---|
476 | #undef INSTANT |
---|
477 | #endif |
---|
478 | |
---|
479 | #if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T) |
---|
480 | // testcase by Mario R�tti |
---|
481 | class ruetti_gen |
---|
482 | { |
---|
483 | public: |
---|
484 | typedef boost::uint64_t result_type; |
---|
485 | result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 0; } |
---|
486 | result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return std::numeric_limits<result_type>::max BOOST_PREVENT_MACRO_SUBSTITUTION (); } |
---|
487 | result_type operator()() { return (max)()-1; } |
---|
488 | }; |
---|
489 | |
---|
490 | void test_overflow_range() |
---|
491 | { |
---|
492 | ruetti_gen gen; |
---|
493 | boost::variate_generator<ruetti_gen, boost::uniform_int<> > |
---|
494 | rng(gen, boost::uniform_int<>(0, 10)); |
---|
495 | for (int i=0;i<10;i++) |
---|
496 | (void) rng(); |
---|
497 | } |
---|
498 | #else |
---|
499 | void test_overflow_range() |
---|
500 | { } |
---|
501 | #endif |
---|
502 | |
---|
503 | int test_main(int, char*[]) |
---|
504 | { |
---|
505 | |
---|
506 | #if !defined(__INTEL_COMPILER) || !defined(_MSC_VER) || __INTEL_COMPILER > 700 |
---|
507 | instantiate_all(); |
---|
508 | validate_all(); |
---|
509 | boost::mt19937 mt; |
---|
510 | test_uniform_int(mt); |
---|
511 | |
---|
512 | // bug report from Ken Mahler: This used to lead to an endless loop. |
---|
513 | typedef boost::uniform_int<unsigned int> uint_dist; |
---|
514 | boost::minstd_rand mr; |
---|
515 | boost::variate_generator<boost::minstd_rand, uint_dist> r2(mr, |
---|
516 | uint_dist(0, 0xffffffff)); |
---|
517 | r2(); |
---|
518 | r2(); |
---|
519 | |
---|
520 | // bug report from Fernando Cacciola: This used to lead to an endless loop. |
---|
521 | // also from Douglas Gregor |
---|
522 | boost::variate_generator<boost::minstd_rand, boost::uniform_int<> > x(mr, boost::uniform_int<>(0, 8361)); |
---|
523 | (void) x(); |
---|
524 | |
---|
525 | // bug report from Alan Stokes and others: this throws an assertion |
---|
526 | boost::variate_generator<boost::minstd_rand, boost::uniform_int<> > y(mr, boost::uniform_int<>(1,1)); |
---|
527 | std::cout << "uniform_int(1,1) " << y() << ", " << y() << ", " << y() |
---|
528 | << std::endl; |
---|
529 | |
---|
530 | test_overflow_range(); |
---|
531 | |
---|
532 | return 0; |
---|
533 | #else |
---|
534 | std::cout << "Intel 7.00 on Win32 loops, so the test is disabled\n"; |
---|
535 | return 1; |
---|
536 | #endif |
---|
537 | } |
---|