// Copyright John Maddock 2007. // 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) #include "required_defines.hpp" #include <map> #include <set> #include <iostream> #include <iomanip> #include <string> #include <cstring> #include <boost/math/tools/config.hpp> #include <boost/regex.hpp> #include <boost/type_traits/is_same.hpp> #include "performance_measure.hpp" #include <boost/math/policies/policy.hpp> #ifdef TEST_GSL #include <gsl/gsl_errno.h> #include <gsl/gsl_message.h> #endif extern void reference_evaluate(); std::map<std::string, double> times; std::set<test_info> tests; double total = 0; int call_count = 0; bool compiler_prefix = false; std::set<test_info>& all_tests() { static std::set<test_info> i; return i; } void add_new_test(test_info i) { all_tests().insert(i); } void set_call_count(int i) { call_count = i; } void show_help() { std::cout << "Specify on the command line which functions to test.\n" "Available options are:\n"; std::set<test_info>::const_iterator i(all_tests().begin()), j(all_tests().end()); while(i != j) { std::cout << " --" << (*i).name << std::endl; ++i; } std::cout << "Or use --all to test everything." << std::endl; std::cout << "You can also specify what to test as a regular expression,\n" " for example --dist.* to test all the distributions." << std::endl; } void run_tests() { // Get time for empty proceedure: double reference_time = performance_measure(reference_evaluate); std::set<test_info>::const_iterator i, j; for(i = tests.begin(), j = tests.end(); i != j; ++i) { std::string name; if(compiler_prefix) { #if defined(BOOST_MSVC) && !defined(_DEBUG) && !defined(__ICL) name = "msvc-"; #elif defined(BOOST_MSVC) && defined(_DEBUG) && !defined(__ICL) name = "msvc-debug-"; #elif defined(__GNUC__) name = "gcc-"; #elif defined(__ICL) name = "intel-"; #elif defined(__ICC) name = "intel-linux-"; #endif } name += i->name; set_call_count(1); std::cout << "Testing " << std::left << std::setw(50) << name << std::flush; double time = performance_measure(i->proc) - reference_time; time /= call_count; std::cout << std::setprecision(3) << std::scientific << time << std::endl; } } bool add_named_test(const char* name) { bool found = false; boost::regex e(name); std::set<test_info>::const_iterator a(all_tests().begin()), b(all_tests().end()); while(a != b) { if(regex_match((*a).name, e)) { found = true; tests.insert(*a); } ++a; } return found; } void print_current_config() { std::cout << "Currently, polynomial evaluation uses method " << BOOST_MATH_POLY_METHOD << std::endl; std::cout << "Currently, rational function evaluation uses method " << BOOST_MATH_RATIONAL_METHOD << std::endl; if(BOOST_MATH_POLY_METHOD + BOOST_MATH_RATIONAL_METHOD > 0) std::cout << "Currently, the largest order of polynomial or rational function" " that uses a method other than 0, is " << BOOST_MATH_MAX_POLY_ORDER << std::endl; bool uses_mixed_tables = boost::is_same<BOOST_MATH_INT_TABLE_TYPE(double, int), int>::value; if(uses_mixed_tables) std::cout << "Currently, rational functions with integer coefficients are evaluated using mixed integer/real arithmetic" << std::endl; else std::cout << "Currently, rational functions with integer coefficients are evaluated using all real arithmetic (integer coefficients are actually stored as reals)" << std::endl << std::endl; std::cout << "Policies are currently set as follows:\n\n"; std::cout << "Policy Value\n"; std::cout << "BOOST_MATH_DOMAIN_ERROR_POLICY " << BOOST_STRINGIZE(BOOST_MATH_DOMAIN_ERROR_POLICY) << std::endl; std::cout << "BOOST_MATH_POLE_ERROR_POLICY " << BOOST_STRINGIZE(BOOST_MATH_POLE_ERROR_POLICY) << std::endl; std::cout << "BOOST_MATH_OVERFLOW_ERROR_POLICY " << BOOST_STRINGIZE(BOOST_MATH_OVERFLOW_ERROR_POLICY) << std::endl; std::cout << "BOOST_MATH_UNDERFLOW_ERROR_POLICY " << BOOST_STRINGIZE(BOOST_MATH_UNDERFLOW_ERROR_POLICY) << std::endl; std::cout << "BOOST_MATH_DENORM_ERROR_POLICY " << BOOST_STRINGIZE(BOOST_MATH_DENORM_ERROR_POLICY) << std::endl; std::cout << "BOOST_MATH_EVALUATION_ERROR_POLICY " << BOOST_STRINGIZE(BOOST_MATH_EVALUATION_ERROR_POLICY) << std::endl; std::cout << "BOOST_MATH_DIGITS10_POLICY " << BOOST_STRINGIZE(BOOST_MATH_DIGITS10_POLICY) << std::endl; std::cout << "BOOST_MATH_PROMOTE_FLOAT_POLICY " << BOOST_STRINGIZE(BOOST_MATH_PROMOTE_FLOAT_POLICY) << std::endl; std::cout << "BOOST_MATH_PROMOTE_DOUBLE_POLICY " << BOOST_STRINGIZE(BOOST_MATH_PROMOTE_DOUBLE_POLICY) << std::endl; std::cout << "BOOST_MATH_DISCRETE_QUANTILE_POLICY " << BOOST_STRINGIZE(BOOST_MATH_DISCRETE_QUANTILE_POLICY) << std::endl; std::cout << "BOOST_MATH_ASSERT_UNDEFINED_POLICY " << BOOST_STRINGIZE(BOOST_MATH_ASSERT_UNDEFINED_POLICY) << std::endl; std::cout << "BOOST_MATH_MAX_SERIES_ITERATION_POLICY " << BOOST_STRINGIZE(BOOST_MATH_MAX_SERIES_ITERATION_POLICY) << std::endl; std::cout << "BOOST_MATH_MAX_ROOT_ITERATION_POLICY " << BOOST_STRINGIZE(BOOST_MATH_MAX_ROOT_ITERATION_POLICY) << std::endl; } extern void sanity_check(); int main(int argc, const char** argv) { //sanity_check(); try{ #ifdef TEST_GSL gsl_set_error_handler_off(); #endif if(argc >= 2) { for(int i = 1; i < argc; ++i) { if(std::strcmp(argv[i], "--help") == 0) { show_help(); } else if(std::strcmp(argv[i], "--tune") == 0) { print_current_config(); add_named_test("Polynomial-method-0"); add_named_test("Polynomial-method-1"); add_named_test("Polynomial-method-2"); add_named_test("Polynomial-method-3"); add_named_test("Polynomial-mixed-method-0"); add_named_test("Polynomial-mixed-method-1"); add_named_test("Polynomial-mixed-method-2"); add_named_test("Polynomial-mixed-method-3"); add_named_test("Rational-method-0"); add_named_test("Rational-method-1"); add_named_test("Rational-method-2"); add_named_test("Rational-method-3"); add_named_test("Rational-mixed-method-0"); add_named_test("Rational-mixed-method-1"); add_named_test("Rational-mixed-method-2"); add_named_test("Rational-mixed-method-3"); } else if(std::strcmp(argv[i], "--all") == 0) { print_current_config(); std::set<test_info>::const_iterator a(all_tests().begin()), b(all_tests().end()); while(a != b) { tests.insert(*a); ++a; } } else if(std::strcmp(argv[i], "--compiler-prefix") == 0) { compiler_prefix = true; } else { bool found = false; if((argv[i][0] == '-') && (argv[i][1] == '-')) { found = add_named_test(argv[i] + 2); } if(!found) { std::cerr << "Unknown option: " << argv[i] << std::endl; show_help(); return 1; } } } run_tests(); } else { show_help(); } // // This is just to confuse the optimisers: // if(argc == 100000) { std::cerr << total << std::endl; } } catch(const std::exception& e) { std::cerr << e.what() << std::endl; } return 0; } void consume_result(double x) { // Do nothing proceedure, don't let whole program optimisation // optimise this away - doing so may cause false readings.... total += x; }