diff --git a/example/brent_minimise_example.cpp b/example/brent_minimise_example.cpp index a80919855..474f98ee7 100644 --- a/example/brent_minimise_example.cpp +++ b/example/brent_minimise_example.cpp @@ -1,7 +1,7 @@ //! \file //! \brief Brent_minimise_example.cpp -// Copyright Paul A. Bristow 2015. +// Copyright Paul A. Bristow 2015, 2018. // Use, modification and distribution are subject to the // Boost Software License, Version 1.0. @@ -25,7 +25,7 @@ #include #include #include -#include // For is_close_to and is_small +#include // For is_close_at)tolerance and is_small //[brent_minimise_mp_include_0 #include // For decimal boost::multiprecision::cpp_dec_float_50. @@ -58,6 +58,7 @@ using std::numeric_limits; // http://en.wikipedia.org/wiki/Brent%27s_method Brent's method +// An example of a function for which we want to find a minimum. double f(double x) { return (x + 3) * (x - 1) * (x - 1); @@ -85,22 +86,33 @@ struct func //] [/brent_minimise_T_functor] //[brent_minimise_close -// -template -bool close(T expect, T got, T tolerance) + +template +inline bool +is_close_to(FPT left, FPT right, FPT tolerance) { - using boost::math::fpc::is_close_to; + return boost::math::fpc::close_at_tolerance(tolerance) (left, right); +} + +//! Compare if value got is close to expected, +//! checking first if expected is very small +//! (to avoid divide by zero during comparison) +//! before comparing expect with value got. + +template +bool is_close(T expect, T got, T tolerance) +{ + using boost::math::fpc::close_at_tolerance; using boost::math::fpc::is_small; + using boost::math::fpc::FPC_STRONG; if (is_small(expect, tolerance)) { return is_small(got, tolerance); } - else - { - return is_close_to(expect, got, tolerance); - } -} + + return close_at_tolerance(tolerance, FPC_STRONG) (expect, got); +} // bool is_close(T expect, T got, T tolerance) //] [/brent_minimise_close] @@ -111,7 +123,7 @@ void show_minima() { using boost::math::tools::brent_find_minima; try - { // Always use try'n'catch blocks with Boost.Math to get any error messages. + { // Always use try'n'catch blocks with Boost.Math to ensure you get any error messages. int bits = std::numeric_limits::digits/2; // Maximum is digits/2; std::streamsize prec = static_cast(2 + sqrt(bits)); // Number of significant decimal digits. @@ -130,7 +142,7 @@ void show_minima() //T bracket_min = static_cast("-4"); //T bracket_max = static_cast("1.3333333333333333333333333333333333333333333333333"); - // Construction from double may cause loss of precision for multiprecision types like cpp_bin_float. + // Construction from double may cause loss of precision for multiprecision types like cpp_bin_float, // but brackets values are good enough for using Brent minimization. T bracket_min = static_cast(-4); T bracket_max = static_cast(1.3333333333333333333333333333333333333333333333333); @@ -148,8 +160,8 @@ void show_minima() } // Check that result is that expected (compared to theoretical uncertainty). T uncertainty = sqrt(std::numeric_limits::epsilon()); - //std::cout << std::boolalpha << "x == 1 (compared to uncertainty " << uncertainty << ") is " << close(static_cast(1), r.first, uncertainty) << std::endl; - //std::cout << std::boolalpha << "f(x) == (0 compared to uncertainty " << uncertainty << ") is " << close(static_cast(0), r.second, uncertainty) << std::endl; + std::cout << std::boolalpha << "x == 1 (compared to uncertainty " << uncertainty << ") is " << is_close(static_cast(1), r.first, uncertainty) << std::endl; + std::cout << std::boolalpha << "f(x) == (0 compared to uncertainty " << uncertainty << ") is " << is_close(static_cast(0), r.second, uncertainty) << std::endl; // Problems with this using multiprecision with expression template on? std::cout.precision(precision); // Restore. } @@ -169,14 +181,15 @@ int main() { std::cout << "Brent's minimisation example." << std::endl; std::cout << std::boolalpha << std::endl; + using boost::math::tools::brent_find_minima; // Tip - using // std::cout.precision(std::numeric_limits::digits10); - // during debugging is wise because it shows if construction of multiprecision involves conversion from double - // by finding random or zero digits after 17. + // during debugging is wise because it warns + // if construction of multiprecision involves conversion from double + // by finding random or zero digits after 17th decimal digit. - // Specific type double - unlimited iterations. - using boost::math::tools::brent_find_minima; + // Specific type double - unlimited iterations (unwise?). //[brent_minimise_double_1 int bits = std::numeric_limits::digits; @@ -195,14 +208,12 @@ int main() // sqrt(epsilon) = 1.49011611938477e-008 // (epsilon is always > 0, so no need to take abs value). - using boost::math::fpc::is_close_to; - using boost::math::fpc::is_small; + using boost::math::fpc::close_at_tolerance; + using boost::math::fpc::is_small; - std::cout << is_close_to(1., r.first, uncertainty) << std::endl; - std::cout << is_small(r.second, uncertainty) << std::endl; - - std::cout << std::boolalpha << "x == 1 (compared to uncertainty " << uncertainty << ") is " << close(1., r.first, uncertainty) << std::endl; - std::cout << std::boolalpha << "f(x) == (0 compared to uncertainty " << uncertainty << ") is " << close(0., r.second, uncertainty) << std::endl; + std::cout << "x = " << r.first << ", f(x) = " << r.second << std::endl; + std::cout << std::boolalpha << "x == 1 (compared to uncertainty " << uncertainty << ") is " << is_close(1., r.first, uncertainty) << std::endl; // true + std::cout << std::boolalpha << "f(x) == 0 (compared to uncertainty " << uncertainty << ") is " << is_close(0., r.second, uncertainty) << std::endl; // true // Specific type double - limit maxit to 20 iterations. std::cout << "Precision bits = " << bits << std::endl; @@ -357,7 +368,7 @@ int main() // x at minimum = 1, f(1) = 5.04853e-018 << ", after " << it << " iterations. " << std::endl; - close(static_cast(1), r.first, sqrt(std::numeric_limits::epsilon())); + is_close_to(static_cast(1), r.first, sqrt(std::numeric_limits::epsilon())); //] [/brent_minimise_mp_1]