diff options
Diffstat (limited to 'src/boost/libs/math/test/test_toms748_solve.cpp')
-rw-r--r-- | src/boost/libs/math/test/test_toms748_solve.cpp | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/src/boost/libs/math/test/test_toms748_solve.cpp b/src/boost/libs/math/test/test_toms748_solve.cpp new file mode 100644 index 00000000..5a40055c --- /dev/null +++ b/src/boost/libs/math/test/test_toms748_solve.cpp @@ -0,0 +1,273 @@ +// (C) Copyright John Maddock 2006. +// 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 <pch.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> +#include <boost/test/tools/floating_point_comparison.hpp> + +#include <boost/math/tools/toms748_solve.hpp> +#include <boost/math/special_functions/gamma.hpp> +#include <boost/math/special_functions/beta.hpp> +#include <iostream> +#include <iomanip> + +// +// Test functor implements the same test cases as used by +// "Algorithm 748: Enclosing Zeros of Continuous Functions" +// by G.E. Alefeld, F.A. Potra and Yixun Shi. +// +// Plus two more: one for inverting the incomplete gamma, +// and one for inverting the incomplete beta. +// +template <class T> +struct toms748tester +{ + toms748tester(unsigned i) : k(i), ip(0), a(0), b(0){} + toms748tester(unsigned i, int ip_) : k(i), ip(ip_), a(0), b(0){} + toms748tester(unsigned i, T a_, T b_) : k(i), ip(0), a(a_), b(b_){} + + static unsigned total_calls() + { + return invocations; + } + static void reset() + { + invocations = 0; + } + + T operator()(T x) + { + using namespace std; + + ++invocations; + switch(k) + { + case 1: + return sin(x) - x / 2; + case 2: + { + T r = 0; + for(int i = 1; i <= 20; ++i) + { + T p = (2 * i - 5); + T q = x - i * i; + r += p * p / (q * q * q); + } + r *= -2; + return r; + } + case 3: + return a * x * exp(b * x); + case 4: + return pow(x, b) - a; + case 5: + return sin(x) - 0.5; + case 6: + return 2 * x * exp(-T(ip)) - 2 * exp(-ip * x) + 1; + case 7: + return (1 + (1 - ip) * (1 - ip)) * x - (1 - ip * x) * (1 - ip * x); + case 8: + return x * x - pow(1 - x, a); + case 9: + return (1 + (1 - ip) * (1 - ip) * (1 - ip) * (1 - ip)) * x - (1 - ip * x) * (1 - ip * x) * (1 - ip * x) * (1 - ip * x); + case 10: + return exp(-ip * x) * (x - 1) + pow(x, T(ip)); + case 11: + return (ip * x - 1) / ((ip - 1) * x); + case 12: + return pow(x, T(1)/ip) - pow(T(ip), T(1)/ip); + case 13: + return x == 0 ? 0 : x * exp(-1 / (x * x)); + case 14: + return x >= 0 ? (T(ip)/20) * (x / 1.5f + sin(x) - 1) : -T(ip)/20; + case 15: + { + T d = 2e-3f / (1+ip); + if(x > d) + return exp(1.0) - 1.859; + else if(x > 0) + return exp((ip+1)*x*1000 / 2) - 1.859; + return -0.859f; + } + case 16: + { + return boost::math::gamma_q(x, a) - b; + } + case 17: + return boost::math::ibeta(x, a, 0.5) - b; + } + return 0; + } +private: + int k; // index of problem. + int ip; // integer parameter + T a, b; // real parameter + + static unsigned invocations; +}; + +template <class T> +unsigned toms748tester<T>::invocations = 0; + +boost::uintmax_t total = 0; +boost::uintmax_t invocations = 0; + +template <class T> +void run_test(T a, T b, int id) +{ + boost::uintmax_t c = 1000; + std::pair<double, double> r = toms748_solve(toms748tester<double>(id), + a, + b, + boost::math::tools::eps_tolerance<double>(std::numeric_limits<double>::digits), + c); + BOOST_CHECK_EQUAL(c, toms748tester<double>::total_calls()); + total += c; + invocations += toms748tester<double>::total_calls(); + std::cout << "Function " << id << "\nresult={" << r.first << ", " << r.second << "} total calls=" << toms748tester<double>::total_calls() << "\n\n"; + toms748tester<double>::reset(); +} + +template <class T> +void run_test(T a, T b, int id, int p) +{ + boost::uintmax_t c = 1000; + std::pair<double, double> r = toms748_solve(toms748tester<double>(id, p), + a, + b, + boost::math::tools::eps_tolerance<double>(std::numeric_limits<double>::digits), + c); + BOOST_CHECK_EQUAL(c, toms748tester<double>::total_calls()); + total += c; + invocations += toms748tester<double>::total_calls(); + std::cout << "Function " << id << "\nresult={" << r.first << ", " << r.second << "} total calls=" << toms748tester<double>::total_calls() << "\n\n"; + toms748tester<double>::reset(); +} + +template <class T> +void run_test(T a, T b, int id, T p1, T p2) +{ + boost::uintmax_t c = 1000; + std::pair<double, double> r = toms748_solve(toms748tester<double>(id, p1, p2), + a, + b, + boost::math::tools::eps_tolerance<double>(std::numeric_limits<double>::digits), + c); + BOOST_CHECK_EQUAL(c, toms748tester<double>::total_calls()); + total += c; + invocations += toms748tester<double>::total_calls(); + std::cout << "Function " << id << "\n Result={" << r.first << ", " << r.second << "} total calls=" << toms748tester<double>::total_calls() << "\n\n"; + toms748tester<double>::reset(); +} + +BOOST_AUTO_TEST_CASE( test_main ) +{ + std::cout << std::setprecision(18); + run_test(3.14/2, 3.14, 1); + + for(int i = 1; i <= 10; i += 1) + { + run_test(i*i + 1e-9, (i+1)*(i+1) - 1e-9, 2); + } + + run_test(-9.0, 31.0, 3, -40.0, -1.0); + run_test(-9.0, 31.0, 3, -100.0, -2.0); + run_test(-9.0, 31.0, 3, -200.0, -3.0); + + for(int n = 4; n <= 12; n += 2) + { + run_test(0.0, 5.0, 4, 0.2, double(n)); + } + for(int n = 4; n <= 12; n += 2) + { + run_test(0.0, 5.0, 4, 1.0, double(n)); + } + for(int n = 8; n <= 14; n += 2) + { + run_test(-0.95, 4.05, 4, 1.0, double(n)); + } + run_test(0.0, 1.5, 5); + for(int n = 1; n <= 5; ++n) + { + run_test(0.0, 1.0, 6, n); + } + for(int n = 20; n <= 100; n += 20) + { + run_test(0.0, 1.0, 6, n); + } + run_test(0.0, 1.0, 7, 5); + run_test(0.0, 1.0, 7, 10); + run_test(0.0, 1.0, 7, 20); + run_test(0.0, 1.0, 8, 2); + run_test(0.0, 1.0, 8, 5); + run_test(0.0, 1.0, 8, 10); + run_test(0.0, 1.0, 8, 15); + run_test(0.0, 1.0, 8, 20); + run_test(0.0, 1.0, 9, 1); + run_test(0.0, 1.0, 9, 2); + run_test(0.0, 1.0, 9, 4); + run_test(0.0, 1.0, 9, 5); + run_test(0.0, 1.0, 9, 8); + run_test(0.0, 1.0, 9, 15); + run_test(0.0, 1.0, 9, 20); + run_test(0.0, 1.0, 10, 1); + run_test(0.0, 1.0, 10, 5); + run_test(0.0, 1.0, 10, 10); + run_test(0.0, 1.0, 10, 15); + run_test(0.0, 1.0, 10, 20); + + run_test(0.01, 1.0, 11, 2); + run_test(0.01, 1.0, 11, 5); + run_test(0.01, 1.0, 11, 15); + run_test(0.01, 1.0, 11, 20); + + for(int n = 2; n <= 6; ++n) + run_test(1.0, 100.0, 12, n); + for(int n = 7; n <= 33; n+=2) + run_test(1.0, 100.0, 12, n); + + run_test(-1.0, 4.0, 13); + + for(int n = 1; n <= 40; ++n) + run_test(-1e4, 3.14/2, 14, n); + + for(int n = 20; n <= 40; ++n) + run_test(-1e4, 1e-4, 15, n); + + for(int n = 100; n <= 1000; n+=100) + run_test(-1e4, 1e-4, 15, n); + + std::cout << "Total iterations consumed = " << total << std::endl; + std::cout << "Total function invocations consumed = " << invocations << std::endl << std::endl; + + BOOST_CHECK(invocations < 3150); + + std::cout << std::setprecision(18); + + for(int n = 5; n <= 100; n += 10) + run_test(sqrt(double(n)), double(n+1), 16, (double)n, 0.4); + + for(int n = 5; n <= 100; n += 10) + run_test(double(n / 2), double(2*n), 17, (double)n, 0.4); + + + for(int n = 4; n <= 12; n += 2) + { + boost::uintmax_t c = 1000; + std::pair<double, double> r = bracket_and_solve_root(toms748tester<double>(4, 0.2, double(n)), + 2.0, + 2.0, + true, + boost::math::tools::eps_tolerance<double>(std::numeric_limits<double>::digits), + c); + std::cout << std::setprecision(18); + std::cout << "Function " << 4 << "\n Result={" << r.first << ", " << r.second << "} total calls=" << toms748tester<double>::total_calls() << "\n\n"; + toms748tester<double>::reset(); + BOOST_CHECK(c < 20); + } +} + |