[29] | 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.58 2005/08/25 16:27:27 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 < 1300 |
---|
| 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 | } |
---|