/* test_real_distribution.ipp * * 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$ * */ #ifndef BOOST_MATH_DISTRIBUTION_INIT #ifdef BOOST_RANDOM_ARG2_TYPE #define BOOST_MATH_DISTRIBUTION_INIT (BOOST_RANDOM_ARG1_NAME, BOOST_RANDOM_ARG2_NAME) #else #define BOOST_MATH_DISTRIBUTION_INIT (BOOST_RANDOM_ARG1_NAME) #endif #endif #ifndef BOOST_RANDOM_DISTRIBUTION_INIT #ifdef BOOST_RANDOM_ARG2_TYPE #define BOOST_RANDOM_DISTRIBUTION_INIT (BOOST_RANDOM_ARG1_NAME, BOOST_RANDOM_ARG2_NAME) #else #define BOOST_RANDOM_DISTRIBUTION_INIT (BOOST_RANDOM_ARG1_NAME) #endif #endif #ifndef BOOST_RANDOM_P_CUTOFF #define BOOST_RANDOM_P_CUTOFF 0.99 #endif #include #include #include #include #include #include #include #include #include "statistic_tests.hpp" #include "chi_squared_test.hpp" bool do_test(BOOST_RANDOM_ARG1_TYPE BOOST_RANDOM_ARG1_NAME, #ifdef BOOST_RANDOM_ARG2_TYPE BOOST_RANDOM_ARG2_TYPE BOOST_RANDOM_ARG2_NAME, #endif long long max, boost::mt19937& gen) { std::cout << "running " BOOST_PP_STRINGIZE(BOOST_RANDOM_DISTRIBUTION_NAME) "(" << BOOST_RANDOM_ARG1_NAME; #ifdef BOOST_RANDOM_ARG2_NAME std::cout << ", " << BOOST_RANDOM_ARG2_NAME; #endif std::cout << ")" << " " << max << " times: " << std::flush; BOOST_MATH_DISTRIBUTION expected BOOST_MATH_DISTRIBUTION_INIT; BOOST_RANDOM_DISTRIBUTION dist BOOST_RANDOM_DISTRIBUTION_INIT; #ifdef BOOST_RANDOM_DISTRIBUTION_MAX BOOST_RANDOM_DISTRIBUTION::result_type max_value = BOOST_RANDOM_DISTRIBUTION_MAX; std::vector expected_pdf(max_value+1); { for(int i = 0; i <= max_value; ++i) { expected_pdf[i] = pdf(expected, i); } expected_pdf.back() += 1 - boost::accumulate(expected_pdf, 0.0); } std::vector results(max_value + 1); for(long long i = 0; i < max; ++i) { ++results[(std::min)(dist(gen), max_value)]; } long long sum = boost::accumulate(results, 0ll); if(sum != max) { std::cout << "*** Failed: incorrect total: " << sum << " ***" << std::endl; return false; } double prob = chi_squared_test(results, expected_pdf, max); #else kolmogorov_experiment test(boost::numeric_cast(max)); boost::variate_generator vgen(gen, dist); double prob = test.probability(test.run(vgen, expected)); #endif bool result = prob < BOOST_RANDOM_P_CUTOFF; const char* err = result? "" : "*"; std::cout << std::setprecision(17) << prob << err << std::endl; std::cout << std::setprecision(6); return result; } template bool do_tests(int repeat, Dist1 d1, #ifdef BOOST_RANDOM_ARG2_NAME Dist2 d2, #endif long long trials) { boost::mt19937 gen; int errors = 0; for(int i = 0; i < repeat; ++i) { if(!do_test(d1(gen), #ifdef BOOST_RANDOM_ARG2_NAME d2(gen), #endif trials, gen)) { ++errors; } } if(errors != 0) { std::cout << "*** " << errors << " errors detected ***" << std::endl; } return errors == 0; } int usage() { std::cerr << "Usage: test_" BOOST_PP_STRINGIZE(BOOST_RANDOM_DISTRIBUTION_NAME) " -r " " -" BOOST_PP_STRINGIZE(BOOST_RANDOM_ARG1_NAME) " " #ifdef BOOST_RANDOM_ARG2_NAME " -" BOOST_PP_STRINGIZE(BOOST_RANDOM_ARG2_NAME) " " #endif " -t " << std::endl; return 2; } template bool handle_option(int& argc, char**& argv, const char* opt, T& value) { if(std::strcmp(argv[0], opt) == 0 && argc > 1) { --argc; ++argv; value = boost::lexical_cast(argv[0]); return true; } else { return false; } } int main(int argc, char** argv) { int repeat = 1; BOOST_RANDOM_ARG1_TYPE max_arg1 = BOOST_RANDOM_ARG1_DEFAULT; #ifdef BOOST_RANDOM_ARG2_TYPE BOOST_RANDOM_ARG2_TYPE max_arg2 = BOOST_RANDOM_ARG2_DEFAULT; #endif long long trials = 100000; if(argc > 0) { --argc; ++argv; } while(argc > 0) { if(argv[0][0] != '-') return usage(); else if(!handle_option(argc, argv, "-r", repeat) && !handle_option(argc, argv, "-" BOOST_PP_STRINGIZE(BOOST_RANDOM_ARG1_NAME), max_arg1) #ifdef BOOST_RANDOM_ARG2_TYPE && !handle_option(argc, argv, "-" BOOST_PP_STRINGIZE(BOOST_RANDOM_ARG2_NAME), max_arg2) #endif && !handle_option(argc, argv, "-t", trials)) { return usage(); } --argc; ++argv; } try { if(do_tests(repeat, BOOST_RANDOM_ARG1_DISTRIBUTION(max_arg1), #ifdef BOOST_RANDOM_ARG2_TYPE BOOST_RANDOM_ARG2_DISTRIBUTION(max_arg2), #endif trials)) { return 0; } else { return EXIT_FAILURE; } } catch(...) { std::cerr << boost::current_exception_diagnostic_information() << std::endl; return EXIT_FAILURE; } }