// Copyright John Maddock 2015. // Use, modification and distribution are subject to 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) #ifdef _MSC_VER # pragma warning (disable : 4224) #endif #define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error #define DISTRIBUTIONS_TEST #include #include #include #include "../../test/table_type.hpp" #include "table_helper.hpp" #include "performance.hpp" #include #ifdef TEST_GSL #include #endif class distribution_tester { std::string distro_name; static const double quantiles[19]; double sum; struct param_info { std::vector params; std::vector x_values; }; std::vector tests; double sanitize_x(double x) { if(x > boost::math::tools::max_value() / 2) return boost::math::tools::max_value() / 2; if(x < -boost::math::tools::max_value() / 2) return -boost::math::tools::max_value() / 2; return x; } public: distribution_tester(const char* name) : distro_name(name), sum(0) {} template void add_test_case(F f) { tests.push_back(param_info()); for(unsigned i = 0; i < sizeof(quantiles) / sizeof(quantiles[0]); ++i) { tests.back().x_values.push_back(sanitize_x(f(quantiles[i]))); } } template void add_test_case(double p1, F f) { tests.push_back(param_info()); tests.back().params.push_back(p1); for(unsigned i = 0; i < sizeof(quantiles) / sizeof(quantiles[0]); ++i) { tests.back().x_values.push_back(sanitize_x(f(p1, quantiles[i]))); } } template void add_test_case(double p1, double p2, F f) { tests.push_back(param_info()); tests.back().params.push_back(p1); tests.back().params.push_back(p2); for(unsigned i = 0; i < sizeof(quantiles) / sizeof(quantiles[0]); ++i) { tests.back().x_values.push_back(sanitize_x(f(p1, p2, quantiles[i]))); } } template void add_test_case(double p1, double p2, double p3, F f) { tests.push_back(param_info()); tests.back().params.push_back(p1); tests.back().params.push_back(p2); tests.back().params.push_back(p3); for(unsigned i = 0; i < sizeof(quantiles) / sizeof(quantiles[0]); ++i) { tests.back().x_values.push_back(sanitize_x(f(p1, p2, p3, quantiles[i]))); } } enum { main_table = 1, boost_only_table = 2, both_tables = 3 }; template void run_timed_tests(F f, std::string sub_name, std::string column, bool p_value = false, int where = main_table) { std::cout << "Testing " << distro_name + " (" + std::string(sub_name) + ")" << " with library " << column << std::endl; try{ double t = 0; unsigned repeats = 1; unsigned data_size; do{ data_size = 0; stopwatch w; for(unsigned count = 0; count < repeats; ++count) { for(unsigned i = 0; i < tests.size(); ++i) { for(unsigned j = 0; j < tests[i].x_values.size(); ++j) { if((boost::math::isfinite)(tests[i].x_values[j])) sum += f(tests[i].params, p_value ? quantiles[j] : tests[i].x_values[j]); ++data_size; } } } t = boost::chrono::duration_cast>(w.elapsed()).count(); if(t < 0.5) repeats *= 2; } while(t < 0.5); static const std::string main_table_name = std::string("Distribution performance comparison with ") + compiler_name() + std::string(" on ") + platform_name(); static const std::string boost_table_name = std::string("Distribution performance comparison for different performance options with ") + compiler_name() + std::string(" on ") + platform_name(); if (where & 1) { report_execution_time( t / data_size, main_table_name, distro_name + " (" + std::string(sub_name) + ")", column); } if (where & 2) { report_execution_time( t / data_size, boost_table_name, distro_name + " (" + std::string(sub_name) + ")", column); } } catch(const std::exception& e) { std::cerr << "Aborting due to exception: " << e.what() << std::endl; std::cerr << "In " << distro_name + " (" + std::string(sub_name) + ")" << std::endl; report_execution_time( (std::numeric_limits::max)(), std::string("Distribution performance comparison with ") + compiler_name() + std::string(" on ") + platform_name(), distro_name + " (" + std::string(sub_name) + ")", column); } } }; const double distribution_tester::quantiles[19] = { 0.000001, 0.00001, 0.0001, 0.001, 0.01, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.99, 0.999, 0.9999, 0.99999, 0.999999 }; template struct three_param_quantile { template double operator()(T x, U y, V z, X q)const { return quantile(D(x, y, z), q); } }; template struct two_param_quantile { template double operator()(T x, U y, V q)const { return quantile(D(x, y), q); } }; template struct one_param_quantile { template double operator()(T x, V q)const { return quantile(D(x), q); } }; template