/* boost test_uniform_int.ipp * * Copyright Jens Maurer 2000 * Copyright Steven Watanabe 2011 * Distributed under the Boost Software License, Version 1.0. (See * accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * * $Id$ */ #include #include #include #include #include #include #include #include #include #include #include "chi_squared_test.hpp" #define BOOST_TEST_MAIN #include template void check_uniform_int(Generator & gen, int iter) { int range = (gen.max)()-(gen.min)()+1; std::vector bucket(range); for(int j = 0; j < iter; j++) { int result = gen(); BOOST_CHECK_GE(result, (gen.min)()); BOOST_CHECK_LE(result, (gen.max)()); if(result >= (gen.min)() && result <= (gen.max)()) { bucket[result-(gen.min)()]++; } } int sum = std::accumulate(bucket.begin(), bucket.end(), 0); std::vector expected(range, 1.0 / range); BOOST_CHECK_LT(chi_squared_test(bucket, expected, sum), 0.99); } BOOST_AUTO_TEST_CASE(test_uniform_int) { boost::random::mt19937 gen; typedef BOOST_RANDOM_UNIFORM_INT int_gen; // large range => small range (modulo case) typedef boost::random::variate_generator level_one; level_one uint12(gen, int_gen(1,2)); BOOST_CHECK((uint12.distribution().min)() == 1); BOOST_CHECK((uint12.distribution().max)() == 2); check_uniform_int(uint12, 100000); level_one uint16(gen, int_gen(1,6)); check_uniform_int(uint16, 100000); // test chaining to get all cases in operator() // identity map typedef boost::random::variate_generator level_two; level_two uint01(uint12, int_gen(0, 1)); check_uniform_int(uint01, 100000); // small range => larger range level_two uint05(uint12, int_gen(-3, 2)); check_uniform_int(uint05, 100000); // small range => larger range level_two uint099(uint12, int_gen(0, 99)); check_uniform_int(uint099, 100000); // larger => small range, rejection case typedef boost::random::variate_generator level_three; level_three uint1_4(uint05, int_gen(1, 4)); check_uniform_int(uint1_4, 100000); typedef BOOST_RANDOM_UNIFORM_INT int8_gen; typedef boost::random::variate_generator gen8_t; gen8_t gen8_03(gen, int8_gen(0, 3)); // use the full range of the type, where the destination // range is a power of the source range typedef boost::random::variate_generator uniform_uint8; uniform_uint8 uint8_0255(gen8_03, int8_gen(0, 255)); check_uniform_int(uint8_0255, 100000); // use the full range, but a generator whose range is not // a root of the destination range. gen8_t gen8_02(gen, int8_gen(0, 2)); uniform_uint8 uint8_0255_2(gen8_02, int8_gen(0, 255)); check_uniform_int(uint8_0255_2, 100000); // expand the range to a larger type. typedef boost::random::variate_generator uniform_uint_from8; uniform_uint_from8 uint0300(gen8_03, int_gen(0, 300)); check_uniform_int(uint0300, 100000); } #if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T) // testcase by Mario Rutti class ruetti_gen { public: ruetti_gen() : state((max)() - 1) {} typedef boost::uint64_t result_type; result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 0; } result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION (); } result_type operator()() { return state--; } private: result_type state; }; BOOST_AUTO_TEST_CASE(test_overflow_range) { ruetti_gen gen; BOOST_RANDOM_DISTRIBUTION dist(0, 10); for (int i=0;i<10;i++) { dist(gen); } } #endif BOOST_AUTO_TEST_CASE(test_misc) { // bug report from Ken Mahler: This used to lead to an endless loop. typedef BOOST_RANDOM_UNIFORM_INT uint_dist; boost::minstd_rand mr; boost::variate_generator r2(mr, uint_dist(0, 0xffffffff)); r2(); r2(); // bug report from Fernando Cacciola: This used to lead to an endless loop. // also from Douglas Gregor boost::variate_generator x(mr, BOOST_RANDOM_DISTRIBUTION(0, 8361)); x(); // bug report from Alan Stokes and others: this throws an assertion boost::variate_generator y(mr, BOOST_RANDOM_DISTRIBUTION(1,1)); y(); y(); y(); }