| // 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; |
| } |