mirror of
https://github.com/boostorg/random.git
synced 2026-01-19 04:22:17 +00:00
Update the last tests left in random_test.cpp and move them to the appropriate places.
[SVN r69991]
This commit is contained in:
@@ -10,7 +10,6 @@ import testing ;
|
||||
|
||||
project /boost/random/test ;
|
||||
|
||||
run random_test.cpp ;
|
||||
run test_const_mod.cpp /boost//unit_test_framework ;
|
||||
run test_generate_canonical.cpp /boost//unit_test_framework ;
|
||||
run test_random_number_generator.cpp /boost//unit_test_framework ;
|
||||
|
||||
@@ -1,291 +0,0 @@
|
||||
/* boost random_test.cpp various tests
|
||||
*
|
||||
* Copyright Jens Maurer 2000
|
||||
* 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$
|
||||
*/
|
||||
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
|
||||
#pragma warning( disable : 4786 )
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
#include <boost/random.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <boost/test/test_tools.hpp>
|
||||
#include <boost/test/included/test_exec_monitor.hpp>
|
||||
|
||||
#ifdef BOOST_NO_STDC_NAMESPACE
|
||||
namespace std { using ::abs; using ::fabs; using ::pow; }
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* General portability note:
|
||||
* MSVC mis-compiles explicit function template instantiations.
|
||||
* For example, f<A>() and f<B>() are both compiled to call f<A>().
|
||||
* BCC is unable to implicitly convert a "const char *" to a std::string
|
||||
* when using explicit function template instantiations.
|
||||
*
|
||||
* Therefore, avoid explicit function template instantiations.
|
||||
*/
|
||||
|
||||
/*
|
||||
* A few equidistribution tests
|
||||
*/
|
||||
|
||||
// yet to come...
|
||||
|
||||
template<class Generator>
|
||||
void check_uniform_int(Generator & gen, int iter)
|
||||
{
|
||||
std::cout << "testing uniform_int(" << (gen.min)() << "," << (gen.max)()
|
||||
<< ")" << std::endl;
|
||||
int range = (gen.max)()-(gen.min)()+1;
|
||||
std::vector<int> bucket(range);
|
||||
for(int j = 0; j < iter; j++) {
|
||||
int result = gen();
|
||||
if(result < (gen.min)() || result > (gen.max)())
|
||||
std::cerr << " ... delivers " << result << std::endl;
|
||||
else
|
||||
bucket[result-(gen.min)()]++;
|
||||
}
|
||||
int sum = 0;
|
||||
// use a different variable name "k", because MSVC has broken "for" scoping
|
||||
for(int k = 0; k < range; k++)
|
||||
sum += bucket[k];
|
||||
double avg = static_cast<double>(sum)/range;
|
||||
double p = 1 / static_cast<double>(range);
|
||||
double threshold = 2*std::sqrt(static_cast<double>(iter)*p*(1-p));
|
||||
for(int i = 0; i < range; i++) {
|
||||
if(std::fabs(bucket[i] - avg) > threshold) {
|
||||
// 95% confidence interval
|
||||
std::cout << " ... has bucket[" << i << "] = " << bucket[i]
|
||||
<< " (distance " << (bucket[i] - avg) << ")"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class Generator>
|
||||
void test_uniform_int(Generator & gen)
|
||||
{
|
||||
typedef boost::uniform_int<int> int_gen;
|
||||
|
||||
// large range => small range (modulo case)
|
||||
typedef boost::variate_generator<Generator&, int_gen> 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::variate_generator<level_one&, int_gen> 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::variate_generator<level_two&, int_gen> level_three;
|
||||
level_three uint1_4(uint05, int_gen(1, 4));
|
||||
check_uniform_int(uint1_4, 100000);
|
||||
|
||||
typedef boost::uniform_int<boost::uint8_t> int8_gen;
|
||||
typedef boost::variate_generator<Generator&, int8_gen> 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::variate_generator<gen8_t, int8_gen> 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::variate_generator<gen8_t, int_gen> uniform_uint_from8;
|
||||
uniform_uint_from8 uint0300(gen8_03, int_gen(0, 300));
|
||||
check_uniform_int(uint0300, 100000);
|
||||
}
|
||||
|
||||
#if defined(BOOST_MSVC) && _MSC_VER < 1300
|
||||
|
||||
// These explicit instantiations are necessary, otherwise MSVC does
|
||||
// not find the <boost/operators.hpp> inline friends.
|
||||
// We ease the typing with a suitable preprocessor macro.
|
||||
#define INSTANT(x) \
|
||||
template class boost::uniform_smallint<x>; \
|
||||
template class boost::uniform_int<x>; \
|
||||
template class boost::uniform_real<x>; \
|
||||
template class boost::bernoulli_distribution<x>; \
|
||||
template class boost::geometric_distribution<x>; \
|
||||
template class boost::triangle_distribution<x>; \
|
||||
template class boost::exponential_distribution<x>; \
|
||||
template class boost::normal_distribution<x>; \
|
||||
template class boost::uniform_on_sphere<x>; \
|
||||
template class boost::lognormal_distribution<x>;
|
||||
|
||||
INSTANT(boost::minstd_rand0)
|
||||
INSTANT(boost::minstd_rand)
|
||||
INSTANT(boost::ecuyer1988)
|
||||
INSTANT(boost::kreutzer1986)
|
||||
INSTANT(boost::hellekalek1995)
|
||||
INSTANT(boost::mt19937)
|
||||
INSTANT(boost::mt11213b)
|
||||
|
||||
#undef INSTANT
|
||||
#endif
|
||||
|
||||
#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<result_type>::max BOOST_PREVENT_MACRO_SUBSTITUTION (); }
|
||||
result_type operator()() { return state--; }
|
||||
private:
|
||||
result_type state;
|
||||
};
|
||||
|
||||
void test_overflow_range()
|
||||
{
|
||||
ruetti_gen gen;
|
||||
boost::variate_generator<ruetti_gen, boost::uniform_int<> >
|
||||
rng(gen, boost::uniform_int<>(0, 10));
|
||||
for (int i=0;i<10;i++)
|
||||
(void) rng();
|
||||
}
|
||||
#else
|
||||
void test_overflow_range()
|
||||
{ }
|
||||
#endif
|
||||
|
||||
template <typename EngineT>
|
||||
struct rand_for_random_shuffle
|
||||
{
|
||||
explicit rand_for_random_shuffle(EngineT &engine)
|
||||
: m_engine(engine)
|
||||
{ }
|
||||
|
||||
template <typename IntT>
|
||||
IntT operator()(IntT upperBound)
|
||||
{
|
||||
assert(upperBound > 0);
|
||||
|
||||
if (upperBound == 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef boost::uniform_int<IntT> distribution_type;
|
||||
typedef boost::variate_generator<EngineT &, distribution_type> generator_type;
|
||||
|
||||
return generator_type(m_engine, distribution_type(0, upperBound - 1))();
|
||||
}
|
||||
|
||||
EngineT &m_engine;
|
||||
|
||||
};
|
||||
|
||||
// Test that uniform_int<> can be used with std::random_shuffle
|
||||
// Author: Jos Hickson
|
||||
void test_random_shuffle()
|
||||
{
|
||||
typedef boost::uniform_int<> distribution_type;
|
||||
typedef boost::variate_generator<boost::mt19937 &, distribution_type> generator_type;
|
||||
|
||||
boost::mt19937 engine1(1234);
|
||||
boost::mt19937 engine2(1234);
|
||||
|
||||
rand_for_random_shuffle<boost::mt19937> referenceRand(engine1);
|
||||
|
||||
distribution_type dist(0,10);
|
||||
generator_type testRand(engine2, dist);
|
||||
|
||||
std::vector<int> referenceVec;
|
||||
|
||||
for (int i = 0; i < 200; ++i)
|
||||
{
|
||||
referenceVec.push_back(i);
|
||||
}
|
||||
|
||||
std::vector<int> testVec(referenceVec);
|
||||
|
||||
std::random_shuffle(referenceVec.begin(), referenceVec.end(), referenceRand);
|
||||
std::random_shuffle(testVec.begin(), testVec.end(), testRand);
|
||||
|
||||
typedef std::vector<int>::iterator iter_type;
|
||||
iter_type theEnd(referenceVec.end());
|
||||
|
||||
for (iter_type referenceIter(referenceVec.begin()), testIter(testVec.begin());
|
||||
referenceIter != theEnd;
|
||||
++referenceIter, ++testIter)
|
||||
{
|
||||
BOOST_CHECK_EQUAL(*referenceIter, *testIter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int test_main(int, char*[])
|
||||
{
|
||||
|
||||
#if !defined(__INTEL_COMPILER) || !defined(_MSC_VER) || __INTEL_COMPILER > 700
|
||||
boost::mt19937 mt;
|
||||
test_uniform_int(mt);
|
||||
|
||||
// bug report from Ken Mahler: This used to lead to an endless loop.
|
||||
typedef boost::uniform_int<unsigned int> uint_dist;
|
||||
boost::minstd_rand mr;
|
||||
boost::variate_generator<boost::minstd_rand, uint_dist> 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<boost::minstd_rand, boost::uniform_int<> > x(mr, boost::uniform_int<>(0, 8361));
|
||||
(void) x();
|
||||
|
||||
// bug report from Alan Stokes and others: this throws an assertion
|
||||
boost::variate_generator<boost::minstd_rand, boost::uniform_int<> > y(mr, boost::uniform_int<>(1,1));
|
||||
std::cout << "uniform_int(1,1) " << y() << ", " << y() << ", " << y()
|
||||
<< std::endl;
|
||||
|
||||
test_overflow_range();
|
||||
test_random_shuffle();
|
||||
|
||||
return 0;
|
||||
#else
|
||||
std::cout << "Intel 7.00 on Win32 loops, so the test is disabled\n";
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
@@ -36,3 +36,41 @@
|
||||
#define BOOST_RANDOM_TEST2_MAX 19
|
||||
|
||||
#include "test_distribution.ipp"
|
||||
|
||||
#define BOOST_RANDOM_UNIFORM_INT boost::uniform_int
|
||||
|
||||
#include "test_uniform_int.ipp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/random/random_number_generator.hpp>
|
||||
|
||||
// Test that uniform_int<> can be used with std::random_shuffle
|
||||
// Author: Jos Hickson
|
||||
BOOST_AUTO_TEST_CASE(test_random_shuffle)
|
||||
{
|
||||
typedef boost::uniform_int<> distribution_type;
|
||||
typedef boost::variate_generator<boost::mt19937 &, distribution_type> generator_type;
|
||||
|
||||
boost::mt19937 engine1(1234);
|
||||
boost::mt19937 engine2(1234);
|
||||
|
||||
boost::random::random_number_generator<boost::mt19937> referenceRand(engine1);
|
||||
|
||||
distribution_type dist(0,10);
|
||||
generator_type testRand(engine2, dist);
|
||||
|
||||
std::vector<int> referenceVec;
|
||||
|
||||
for (int i = 0; i < 200; ++i) {
|
||||
referenceVec.push_back(i);
|
||||
}
|
||||
|
||||
std::vector<int> testVec(referenceVec);
|
||||
|
||||
std::random_shuffle(referenceVec.begin(), referenceVec.end(), referenceRand);
|
||||
std::random_shuffle(testVec.begin(), testVec.end(), testRand);
|
||||
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(
|
||||
testVec.begin(), testVec.end(),
|
||||
referenceVec.begin(), referenceVec.end());
|
||||
}
|
||||
|
||||
149
test/test_uniform_int.ipp
Normal file
149
test/test_uniform_int.ipp
Normal file
@@ -0,0 +1,149 @@
|
||||
/* 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 <numeric>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/random/mersenne_twister.hpp>
|
||||
#include <boost/random/linear_congruential.hpp>
|
||||
#include <boost/random/lagged_fibonacci.hpp>
|
||||
#include <boost/random/variate_generator.hpp>
|
||||
#include "chi_squared_test.hpp"
|
||||
|
||||
#define BOOST_TEST_MAIN
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
template<class Generator>
|
||||
void check_uniform_int(Generator & gen, int iter)
|
||||
{
|
||||
int range = (gen.max)()-(gen.min)()+1;
|
||||
std::vector<int> 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<double> 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> int_gen;
|
||||
|
||||
// large range => small range (modulo case)
|
||||
typedef boost::random::variate_generator<boost::random::mt19937&, int_gen> 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_one&, int_gen> 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_two&, int_gen> level_three;
|
||||
level_three uint1_4(uint05, int_gen(1, 4));
|
||||
check_uniform_int(uint1_4, 100000);
|
||||
|
||||
typedef BOOST_RANDOM_UNIFORM_INT<boost::uint8_t> int8_gen;
|
||||
typedef boost::random::variate_generator<boost::random::mt19937&, int8_gen> 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<gen8_t, int8_gen> 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<gen8_t, int_gen> 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<result_type>::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<unsigned int> uint_dist;
|
||||
boost::minstd_rand mr;
|
||||
boost::variate_generator<boost::minstd_rand, uint_dist> 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<boost::minstd_rand, BOOST_RANDOM_DISTRIBUTION > x(mr, BOOST_RANDOM_DISTRIBUTION(0, 8361));
|
||||
x();
|
||||
|
||||
// bug report from Alan Stokes and others: this throws an assertion
|
||||
boost::variate_generator<boost::minstd_rand, BOOST_RANDOM_DISTRIBUTION > y(mr, BOOST_RANDOM_DISTRIBUTION(1,1));
|
||||
y();
|
||||
y();
|
||||
y();
|
||||
}
|
||||
@@ -36,3 +36,7 @@
|
||||
#define BOOST_RANDOM_TEST2_MAX 19
|
||||
|
||||
#include "test_distribution.ipp"
|
||||
|
||||
#define BOOST_RANDOM_UNIFORM_INT boost::random::uniform_int_distribution
|
||||
|
||||
#include "test_uniform_int.ipp"
|
||||
|
||||
Reference in New Issue
Block a user