diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
commit | 483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch) | |
tree | e5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/boost/libs/math/example/brent_minimise_example.cpp | |
parent | Initial commit. (diff) | |
download | ceph-upstream.tar.xz ceph-upstream.zip |
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/math/example/brent_minimise_example.cpp')
-rw-r--r-- | src/boost/libs/math/example/brent_minimise_example.cpp | 730 |
1 files changed, 730 insertions, 0 deletions
diff --git a/src/boost/libs/math/example/brent_minimise_example.cpp b/src/boost/libs/math/example/brent_minimise_example.cpp new file mode 100644 index 00000000..09053bd0 --- /dev/null +++ b/src/boost/libs/math/example/brent_minimise_example.cpp @@ -0,0 +1,730 @@ +//! \file +//! \brief Brent_minimise_example.cpp + +// Copyright Paul A. Bristow 2015, 2018. + +// 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) + +// Note that this file contains Quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +// For some diagnostic information: +//#define BOOST_MATH_INSTRUMENT +// If quadmath float128 is available: +//#define BOOST_HAVE_QUADMATH + +// Example of finding minimum of a function with Brent's method. +//[brent_minimise_include_1 +#include <boost/math/tools/minima.hpp> +//] [/brent_minimise_include_1] + +#include <boost/math/special_functions/next.hpp> +#include <boost/multiprecision/cpp_dec_float.hpp> +#include <boost/math/special_functions/pow.hpp> +#include <boost/math/constants/constants.hpp> +#include <boost/test/tools/floating_point_comparison.hpp> // For is_close_at)tolerance and is_small + +//[brent_minimise_mp_include_0 +#include <boost/multiprecision/cpp_dec_float.hpp> // For decimal boost::multiprecision::cpp_dec_float_50. +#include <boost/multiprecision/cpp_bin_float.hpp> // For binary boost::multiprecision::cpp_bin_float_50; +//] [/brent_minimise_mp_include_0] + +//#ifndef _MSC_VER // float128 is not yet supported by Microsoft compiler at 2018. +#ifdef BOOST_HAVE_QUADMATH // Define only if GCC or Intel, and have quadmath.lib or .dll library available. +# include <boost/multiprecision/float128.hpp> +#endif + +#include <iostream> +// using std::cout; using std::endl; +#include <iomanip> +// using std::setw; using std::setprecision; +#include <limits> +using std::numeric_limits; +#include <tuple> +#include <utility> // pair, make_pair +#include <type_traits> +#include <typeinfo> + + //typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<50>, + // boost::multiprecision::et_off> + // cpp_dec_float_50_et_off; + // + // typedef boost::multiprecision::number<boost::multiprecision::cpp_bin_float<50>, + // boost::multiprecision::et_off> + // cpp_bin_float_50_et_off; + +// 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); +} + +//[brent_minimise_double_functor +struct funcdouble +{ + double operator()(double const& x) + { + return (x + 3) * (x - 1) * (x - 1); // (x + 3)(x - 1)^2 + } +}; +//] [/brent_minimise_double_functor] + +//[brent_minimise_T_functor +struct func +{ + template <class T> + T operator()(T const& x) + { + return (x + 3) * (x - 1) * (x - 1); // (x + 3)(x - 1)^2 + } +}; +//] [/brent_minimise_T_functor] + +//! Test if two values are close within a given tolerance. +template<typename FPT> +inline bool +is_close_to(FPT left, FPT right, FPT tolerance) +{ + return boost::math::fpc::close_at_tolerance<FPT>(tolerance) (left, right); +} + +//[brent_minimise_close + +//! Compare if value got is close to expected, +//! checking first if expected is very small +//! (to avoid divide by tiny or zero during comparison) +//! before comparing expect with value got. + +template <class T> +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<T>(expect, tolerance)) + { + return is_small<T>(got, tolerance); + } + + return close_at_tolerance<T>(tolerance, FPC_STRONG) (expect, got); +} // bool is_close(T expect, T got, T tolerance) + +//] [/brent_minimise_close] + +//[brent_minimise_T_show + +//! Example template function to find and show minima. +//! \tparam T floating-point or fixed_point type. +template <class T> +void show_minima() +{ + using boost::math::tools::brent_find_minima; + using std::sqrt; + try + { // Always use try'n'catch blocks with Boost.Math to ensure you get any error messages. + + int bits = std::numeric_limits<T>::digits/2; // Maximum is digits/2; + std::streamsize prec = static_cast<int>(2 + sqrt((double)bits)); // Number of significant decimal digits. + std::streamsize precision = std::cout.precision(prec); // Save and set. + + std::cout << "\n\nFor type: " << typeid(T).name() + << ",\n epsilon = " << std::numeric_limits<T>::epsilon() + // << ", precision of " << bits << " bits" + << ",\n the maximum theoretical precision from Brent's minimization is " + << sqrt(std::numeric_limits<T>::epsilon()) + << "\n Displaying to std::numeric_limits<T>::digits10 " << prec << ", significant decimal digits." + << std::endl; + + const boost::uintmax_t maxit = 20; + boost::uintmax_t it = maxit; + // Construct using string, not double, avoids loss of precision. + //T bracket_min = static_cast<T>("-4"); + //T bracket_max = static_cast<T>("1.3333333333333333333333333333333333333333333333333"); + + // 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<T>(-4); + T bracket_max = static_cast<T>(1.3333333333333333333333333333333333333333333333333); + + std::pair<T, T> r = brent_find_minima<func, T>(func(), bracket_min, bracket_max, bits, it); + + std::cout << " x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second; + if (it < maxit) + { + std::cout << ",\n met " << bits << " bits precision" << ", after " << it << " iterations." << std::endl; + } + else + { + std::cout << ",\n did NOT meet " << bits << " bits precision" << " after " << it << " iterations!" << std::endl; + } + // Check that result is that expected (compared to theoretical uncertainty). + T uncertainty = sqrt(std::numeric_limits<T>::epsilon()); + std::cout << std::boolalpha << "x == 1 (compared to uncertainty " << uncertainty << ") is " + << is_close(static_cast<T>(1), r.first, uncertainty) << std::endl; + std::cout << std::boolalpha << "f(x) == (0 compared to uncertainty " << uncertainty << ") is " + << is_close(static_cast<T>(0), r.second, uncertainty) << std::endl; + // Problems with this using multiprecision with expression template on? + std::cout.precision(precision); // Restore. + } + catch (const std::exception& e) + { // Always useful to include try & catch blocks because default policies + // are to throw exceptions on arguments that cause errors like underflow, overflow. + // Lacking try & catch blocks, the program will abort without a message below, + // which may give some helpful clues as to the cause of the exception. + std::cout << + "\n""Message from thrown exception was:\n " << e.what() << std::endl; + } +} // void show_minima() + +//] [/brent_minimise_T_show] + +int main() +{ + using boost::math::tools::brent_find_minima; + using std::sqrt; + std::cout << "Brent's minimisation examples." << std::endl; + std::cout << std::boolalpha << std::endl; + std::cout << std::showpoint << std::endl; // Show trailing zeros. + + // Tip - using + // std::cout.precision(std::numeric_limits<T>::digits10); + // 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 (unwise?). + { + std::cout << "\nType double - unlimited iterations (unwise?)" << std::endl; + //[brent_minimise_double_1 + const int double_bits = std::numeric_limits<double>::digits; + std::pair<double, double> r = brent_find_minima(funcdouble(), -4., 4. / 3, double_bits); + + std::streamsize precision_1 = std::cout.precision(std::numeric_limits<double>::digits10); + // Show all double precision decimal digits and trailing zeros. + std::cout << "x at minimum = " << r.first + << ", f(" << r.first << ") = " << r.second << std::endl; + //] [/brent_minimise_double_1] + std::cout << "x at minimum = " << (r.first - 1.) / r.first << std::endl; + // x at minimum = 1.00000000112345, f(1.00000000112345) = 5.04852568272458e-018 + double uncertainty = sqrt(std::numeric_limits<double>::epsilon()); + std::cout << "Uncertainty sqrt(epsilon) = " << uncertainty << std::endl; + // sqrt(epsilon) = 1.49011611938477e-008 + // (epsilon is always > 0, so no need to take abs value). + + std::cout.precision(precision_1); // Restore. + //[brent_minimise_double_1a + + using boost::math::fpc::close_at_tolerance; + using boost::math::fpc::is_small; + + 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 +//] [/brent_minimise_double_1a] + + } + std::cout << "\nType double with limited iterations." << std::endl; + { + const int bits = std::numeric_limits<double>::digits; + // Specific type double - limit maxit to 20 iterations. + std::cout << "Precision bits = " << bits << std::endl; + //[brent_minimise_double_2 + const boost::uintmax_t maxit = 20; + boost::uintmax_t it = maxit; + std::pair<double, double> r = brent_find_minima(funcdouble(), -4., 4. / 3, bits, it); + std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second + << " after " << it << " iterations. " << std::endl; + //] [/brent_minimise_double_2] + // x at minimum = 1.00000000112345, f(1.00000000112345) = 5.04852568272458e-018 +//[brent_minimise_double_3 + std::streamsize prec = static_cast<int>(2 + sqrt((double)bits)); // Number of significant decimal digits. + std::streamsize precision_3 = std::cout.precision(prec); // Save and set new precision. + std::cout << "Showing " << bits << " bits " + "precision with " << prec + << " decimal digits from tolerance " << sqrt(std::numeric_limits<double>::epsilon()) + << std::endl; + + std::cout << "x at minimum = " << r.first + << ", f(" << r.first << ") = " << r.second + << " after " << it << " iterations. " << std::endl; + std::cout.precision(precision_3); // Restore. +//] [/brent_minimise_double_3] + // Showing 53 bits precision with 9 decimal digits from tolerance 1.49011611938477e-008 + // x at minimum = 1, f(1) = 5.04852568e-018 + } + + std::cout << "\nType double with limited iterations and half double bits." << std::endl; + { + +//[brent_minimise_double_4 + const int bits_div_2 = std::numeric_limits<double>::digits / 2; // Half digits precision (effective maximum). + double epsilon_2 = boost::math::pow<-(std::numeric_limits<double>::digits/2 - 1), double>(2); + std::streamsize prec = static_cast<int>(2 + sqrt((double)bits_div_2)); // Number of significant decimal digits. + + std::cout << "Showing " << bits_div_2 << " bits precision with " << prec + << " decimal digits from tolerance " << sqrt(epsilon_2) + << std::endl; + std::streamsize precision_4 = std::cout.precision(prec); // Save. + const boost::uintmax_t maxit = 20; + boost::uintmax_t it_4 = maxit; + std::pair<double, double> r = brent_find_minima(funcdouble(), -4., 4. / 3, bits_div_2, it_4); + std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second << std::endl; + std::cout << it_4 << " iterations. " << std::endl; + std::cout.precision(precision_4); // Restore. + +//] [/brent_minimise_double_4] + } + // x at minimum = 1, f(1) = 5.04852568e-018 + + { + std::cout << "\nType double with limited iterations and quarter double bits." << std::endl; + //[brent_minimise_double_5 + const int bits_div_4 = std::numeric_limits<double>::digits / 4; // Quarter precision. + double epsilon_4 = boost::math::pow<-(std::numeric_limits<double>::digits / 4 - 1), double>(2); + std::streamsize prec = static_cast<int>(2 + sqrt((double)bits_div_4)); // Number of significant decimal digits. + std::cout << "Showing " << bits_div_4 << " bits precision with " << prec + << " decimal digits from tolerance " << sqrt(epsilon_4) + << std::endl; + std::streamsize precision_5 = std::cout.precision(prec); // Save & set. + const boost::uintmax_t maxit = 20; + + boost::uintmax_t it_5 = maxit; + std::pair<double, double> r = brent_find_minima(funcdouble(), -4., 4. / 3, bits_div_4, it_5); + std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second + << ", after " << it_5 << " iterations. " << std::endl; + std::cout.precision(precision_5); // Restore. + + //] [/brent_minimise_double_5] + } + + // Showing 13 bits precision with 9 decimal digits from tolerance 0.015625 + // x at minimum = 0.9999776, f(0.9999776) = 2.0069572e-009 + // 7 iterations. + + { + std::cout << "\nType long double with limited iterations and all long double bits." << std::endl; +//[brent_minimise_template_1 + std::streamsize precision_t1 = std::cout.precision(std::numeric_limits<long double>::digits10); // Save & set. + long double bracket_min = -4.; + long double bracket_max = 4. / 3; + const int bits = std::numeric_limits<long double>::digits; + const boost::uintmax_t maxit = 20; + boost::uintmax_t it = maxit; + + std::pair<long double, long double> r = brent_find_minima(func(), bracket_min, bracket_max, bits, it); + std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second + << ", after " << it << " iterations. " << std::endl; + std::cout.precision(precision_t1); // Restore. +//] [/brent_minimise_template_1] + } + + // Show use of built-in type Template versions. + // (Will not work if construct bracket min and max from string). + +//[brent_minimise_template_fd + show_minima<float>(); + show_minima<double>(); + show_minima<long double>(); + + //] [/brent_minimise_template_fd] + +//[brent_minimise_mp_include_1 +#ifdef BOOST_HAVE_QUADMATH // Defined only if GCC or Intel and have quadmath.lib or .dll library available. + using boost::multiprecision::float128; +#endif +//] [/brent_minimise_mp_include_1] + +//[brent_minimise_template_quad +#ifdef BOOST_HAVE_QUADMATH // Defined only if GCC or Intel and have quadmath.lib or .dll library available. + show_minima<float128>(); // Needs quadmath_snprintf, sqrtQ, fabsq that are in in quadmath library. +#endif +//] [/brent_minimise_template_quad + + // User-defined floating-point template. + +//[brent_minimise_mp_typedefs + using boost::multiprecision::cpp_bin_float_50; // binary multiprecision typedef. + using boost::multiprecision::cpp_dec_float_50; // decimal multiprecision typedef. + + // One might also need typedefs like these to switch expression templates off and on (default is on). + typedef boost::multiprecision::number<boost::multiprecision::cpp_bin_float<50>, + boost::multiprecision::et_on> + cpp_bin_float_50_et_on; // et_on is default so is same as cpp_bin_float_50. + + typedef boost::multiprecision::number<boost::multiprecision::cpp_bin_float<50>, + boost::multiprecision::et_off> + cpp_bin_float_50_et_off; + + typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<50>, + boost::multiprecision::et_on> // et_on is default so is same as cpp_dec_float_50. + cpp_dec_float_50_et_on; + + typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<50>, + boost::multiprecision::et_off> + cpp_dec_float_50_et_off; +//] [/brent_minimise_mp_typedefs] + + { // binary ET on by default. +//[brent_minimise_mp_1 + std::cout.precision(std::numeric_limits<cpp_bin_float_50>::digits10); + int bits = std::numeric_limits<cpp_bin_float_50>::digits / 2 - 2; + cpp_bin_float_50 bracket_min = static_cast<cpp_bin_float_50>("-4"); + cpp_bin_float_50 bracket_max = static_cast<cpp_bin_float_50>("1.3333333333333333333333333333333333333333333333333"); + + std::cout << "Bracketing " << bracket_min << " to " << bracket_max << std::endl; + const boost::uintmax_t maxit = 20; + boost::uintmax_t it = maxit; // Will be updated with actual iteration count. + std::pair<cpp_bin_float_50, cpp_bin_float_50> r + = brent_find_minima(func(), bracket_min, bracket_max, bits, it); + + std::cout << "x at minimum = " << r.first << ",\n f(" << r.first << ") = " << r.second + // x at minimum = 1, f(1) = 5.04853e-018 + << ", after " << it << " iterations. " << std::endl; + + is_close_to(static_cast<cpp_bin_float_50>("1"), r.first, sqrt(std::numeric_limits<cpp_bin_float_50>::epsilon())); + is_close_to(static_cast<cpp_bin_float_50>("0"), r.second, sqrt(std::numeric_limits<cpp_bin_float_50>::epsilon())); + +//] [/brent_minimise_mp_1] + +/* +//[brent_minimise_mp_output_1 +For type class boost::multiprecision::number<class boost::multiprecision::backends::cpp_bin_float<50,10,void,int,0,0>,1>, +epsilon = 5.3455294202e-51, +the maximum theoretical precision from Brent minimization is 7.311312755e-26 +Displaying to std::numeric_limits<T>::digits10 11 significant decimal digits. +x at minimum = 1, f(1) = 5.6273022713e-58, +met 84 bits precision, after 14 iterations. +x == 1 (compared to uncertainty 7.311312755e-26) is true +f(x) == (0 compared to uncertainty 7.311312755e-26) is true +-4 1.3333333333333333333333333333333333333333333333333 +x at minimum = 0.99999999999999999999999999998813903221565569205253, +f(0.99999999999999999999999999998813903221565569205253) = + 5.6273022712501408640665300316078046703496236636624e-58 +14 iterations +//] [/brent_minimise_mp_output_1] +*/ +//[brent_minimise_mp_2 + show_minima<cpp_bin_float_50_et_on>(); // +//] [/brent_minimise_mp_2] + +/* +//[brent_minimise_mp_output_2 + For type class boost::multiprecision::number<class boost::multiprecision::backends::cpp_bin_float<50, 10, void, int, 0, 0>, 1>, + +//] [/brent_minimise_mp_output_1] +*/ + } + + { // binary ET on explicit + std::cout.precision(std::numeric_limits<cpp_bin_float_50_et_on>::digits10); + + int bits = std::numeric_limits<cpp_bin_float_50_et_on>::digits / 2 - 2; + + cpp_bin_float_50_et_on bracket_min = static_cast<cpp_bin_float_50_et_on>("-4"); + cpp_bin_float_50_et_on bracket_max = static_cast<cpp_bin_float_50_et_on>("1.3333333333333333333333333333333333333333333333333"); + + std::cout << bracket_min << " " << bracket_max << std::endl; + const boost::uintmax_t maxit = 20; + boost::uintmax_t it = maxit; + std::pair<cpp_bin_float_50_et_on, cpp_bin_float_50_et_on> r = brent_find_minima(func(), bracket_min, bracket_max, bits, it); + + std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second << std::endl; + // x at minimum = 1, f(1) = 5.04853e-018 + std::cout << it << " iterations. " << std::endl; + + show_minima<cpp_bin_float_50_et_on>(); // + + } + return 0; + + // Some examples of switching expression templates on and off follow. + + { // binary ET off + std::cout.precision(std::numeric_limits<cpp_bin_float_50_et_off>::digits10); + + int bits = std::numeric_limits<cpp_bin_float_50_et_off>::digits / 2 - 2; + cpp_bin_float_50_et_off bracket_min = static_cast<cpp_bin_float_50_et_off>("-4"); + cpp_bin_float_50_et_off bracket_max = static_cast<cpp_bin_float_50_et_off>("1.3333333333333333333333333333333333333333333333333"); + + std::cout << bracket_min << " " << bracket_max << std::endl; + const boost::uintmax_t maxit = 20; + boost::uintmax_t it = maxit; + std::pair<cpp_bin_float_50_et_off, cpp_bin_float_50_et_off> r = brent_find_minima(func(), bracket_min, bracket_max, bits, it); + + std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second << std::endl; + // x at minimum = 1, f(1) = 5.04853e-018 + std::cout << it << " iterations. " << std::endl; + + show_minima<cpp_bin_float_50_et_off>(); // + } + + { // decimal ET on by default + std::cout.precision(std::numeric_limits<cpp_dec_float_50>::digits10); + + int bits = std::numeric_limits<cpp_dec_float_50>::digits / 2 - 2; + + cpp_dec_float_50 bracket_min = static_cast<cpp_dec_float_50>("-4"); + cpp_dec_float_50 bracket_max = static_cast<cpp_dec_float_50>("1.3333333333333333333333333333333333333333333333333"); + + std::cout << bracket_min << " " << bracket_max << std::endl; + const boost::uintmax_t maxit = 20; + boost::uintmax_t it = maxit; + std::pair<cpp_dec_float_50, cpp_dec_float_50> r = brent_find_minima(func(), bracket_min, bracket_max, bits, it); + + std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second << std::endl; + // x at minimum = 1, f(1) = 5.04853e-018 + std::cout << it << " iterations. " << std::endl; + + show_minima<cpp_dec_float_50>(); + } + + { // decimal ET on + std::cout.precision(std::numeric_limits<cpp_dec_float_50_et_on>::digits10); + + int bits = std::numeric_limits<cpp_dec_float_50_et_on>::digits / 2 - 2; + + cpp_dec_float_50_et_on bracket_min = static_cast<cpp_dec_float_50_et_on>("-4"); + cpp_dec_float_50_et_on bracket_max = static_cast<cpp_dec_float_50_et_on>("1.3333333333333333333333333333333333333333333333333"); + std::cout << bracket_min << " " << bracket_max << std::endl; + const boost::uintmax_t maxit = 20; + boost::uintmax_t it = maxit; + std::pair<cpp_dec_float_50_et_on, cpp_dec_float_50_et_on> r = brent_find_minima(func(), bracket_min, bracket_max, bits, it); + + std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second << std::endl; + // x at minimum = 1, f(1) = 5.04853e-018 + std::cout << it << " iterations. " << std::endl; + + show_minima<cpp_dec_float_50_et_on>(); + + } + + { // decimal ET off + std::cout.precision(std::numeric_limits<cpp_dec_float_50_et_off>::digits10); + + int bits = std::numeric_limits<cpp_dec_float_50_et_off>::digits / 2 - 2; + + cpp_dec_float_50_et_off bracket_min = static_cast<cpp_dec_float_50_et_off>("-4"); + cpp_dec_float_50_et_off bracket_max = static_cast<cpp_dec_float_50_et_off>("1.3333333333333333333333333333333333333333333333333"); + + std::cout << bracket_min << " " << bracket_max << std::endl; + const boost::uintmax_t maxit = 20; + boost::uintmax_t it = maxit; + std::pair<cpp_dec_float_50_et_off, cpp_dec_float_50_et_off> r = brent_find_minima(func(), bracket_min, bracket_max, bits, it); + + std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second << std::endl; + // x at minimum = 1, f(1) = 5.04853e-018 + std::cout << it << " iterations. " << std::endl; + + show_minima<cpp_dec_float_50_et_off>(); + } + + return 0; +} // int main() + + +/* + +Typical output MSVC 15.7.3 + +brent_minimise_example.cpp +Generating code +7 of 2746 functions ( 0.3%) were compiled, the rest were copied from previous compilation. +0 functions were new in current compilation +1 functions had inline decision re-evaluated but remain unchanged +Finished generating code +brent_minimise_example.vcxproj -> J:\Cpp\MathToolkit\test\Math_test\Release\brent_minimise_example.exe +Autorun "J:\Cpp\MathToolkit\test\Math_test\Release\brent_minimise_example.exe" +Brent's minimisation examples. + + + +Type double - unlimited iterations (unwise?) +x at minimum = 1.00000000112345, f(1.00000000112345) = 5.04852568272458e-18 +x at minimum = 1.12344622367552e-09 +Uncertainty sqrt(epsilon) = 1.49011611938477e-08 +x = 1.00000, f(x) = 5.04853e-18 +x == 1 (compared to uncertainty 1.49012e-08) is true +f(x) == 0 (compared to uncertainty 1.49012e-08) is true + +Type double with limited iterations. +Precision bits = 53 +x at minimum = 1.00000, f(1.00000) = 5.04853e-18 after 10 iterations. +Showing 53 bits precision with 9 decimal digits from tolerance 1.49011612e-08 +x at minimum = 1.00000000, f(1.00000000) = 5.04852568e-18 after 10 iterations. + +Type double with limited iterations and half double bits. +Showing 26 bits precision with 7 decimal digits from tolerance 0.000172633 +x at minimum = 1.000000, f(1.000000) = 5.048526e-18 +10 iterations. + +Type double with limited iterations and quarter double bits. +Showing 13 bits precision with 5 decimal digits from tolerance 0.0156250 +x at minimum = 0.99998, f(0.99998) = 2.0070e-09, after 7 iterations. + +Type long double with limited iterations and all long double bits. +x at minimum = 1.00000000112345, f(1.00000000112345) = 5.04852568272458e-18, after 10 iterations. + + +For type: float, +epsilon = 1.1921e-07, +the maximum theoretical precision from Brent's minimization is 0.00034527 +Displaying to std::numeric_limits<T>::digits10 5, significant decimal digits. +x at minimum = 1.0002, f(1.0002) = 1.9017e-07, +met 12 bits precision, after 7 iterations. +x == 1 (compared to uncertainty 0.00034527) is true +f(x) == (0 compared to uncertainty 0.00034527) is true + + +For type: double, +epsilon = 2.220446e-16, +the maximum theoretical precision from Brent's minimization is 1.490116e-08 +Displaying to std::numeric_limits<T>::digits10 7, significant decimal digits. +x at minimum = 1.000000, f(1.000000) = 5.048526e-18, +met 26 bits precision, after 10 iterations. +x == 1 (compared to uncertainty 1.490116e-08) is true +f(x) == (0 compared to uncertainty 1.490116e-08) is true + + +For type: long double, +epsilon = 2.220446e-16, +the maximum theoretical precision from Brent's minimization is 1.490116e-08 +Displaying to std::numeric_limits<T>::digits10 7, significant decimal digits. +x at minimum = 1.000000, f(1.000000) = 5.048526e-18, +met 26 bits precision, after 10 iterations. +x == 1 (compared to uncertainty 1.490116e-08) is true +f(x) == (0 compared to uncertainty 1.490116e-08) is true +Bracketing -4.0000000000000000000000000000000000000000000000000 to 1.3333333333333333333333333333333333333333333333333 +x at minimum = 0.99999999999999999999999999998813903221565569205253, +f(0.99999999999999999999999999998813903221565569205253) = 5.6273022712501408640665300316078046703496236636624e-58, after 14 iterations. + + +For type: class boost::multiprecision::number<class boost::multiprecision::backends::cpp_bin_float<50,10,void,int,0,0>,1>, +epsilon = 5.3455294202e-51, +the maximum theoretical precision from Brent's minimization is 7.3113127550e-26 +Displaying to std::numeric_limits<T>::digits10 11, significant decimal digits. +x at minimum = 1.0000000000, f(1.0000000000) = 5.6273022713e-58, +met 84 bits precision, after 14 iterations. +x == 1 (compared to uncertainty 7.3113127550e-26) is true +f(x) == (0 compared to uncertainty 7.3113127550e-26) is true +-4.0000000000000000000000000000000000000000000000000 1.3333333333333333333333333333333333333333333333333 +x at minimum = 0.99999999999999999999999999998813903221565569205253, f(0.99999999999999999999999999998813903221565569205253) = 5.6273022712501408640665300316078046703496236636624e-58 +14 iterations. + + +For type: class boost::multiprecision::number<class boost::multiprecision::backends::cpp_bin_float<50,10,void,int,0,0>,1>, +epsilon = 5.3455294202e-51, +the maximum theoretical precision from Brent's minimization is 7.3113127550e-26 +Displaying to std::numeric_limits<T>::digits10 11, significant decimal digits. +x at minimum = 1.0000000000, f(1.0000000000) = 5.6273022713e-58, +met 84 bits precision, after 14 iterations. +x == 1 (compared to uncertainty 7.3113127550e-26) is true +f(x) == (0 compared to uncertainty 7.3113127550e-26) is true + + +============================================================================================================ + + // GCC 7.2.0 with quadmath + +Brent's minimisation examples. + +Type double - unlimited iterations (unwise?) +x at minimum = 1.00000000112345, f(1.00000000112345) = 5.04852568272458e-018 +x at minimum = 1.12344622367552e-009 +Uncertainty sqrt(epsilon) = 1.49011611938477e-008 +x = 1.00000, f(x) = 5.04853e-018 +x == 1 (compared to uncertainty 1.49012e-008) is true +f(x) == 0 (compared to uncertainty 1.49012e-008) is true + +Type double with limited iterations. +Precision bits = 53 +x at minimum = 1.00000, f(1.00000) = 5.04853e-018 after 10 iterations. +Showing 53 bits precision with 9 decimal digits from tolerance 1.49011612e-008 +x at minimum = 1.00000000, f(1.00000000) = 5.04852568e-018 after 10 iterations. + +Type double with limited iterations and half double bits. +Showing 26 bits precision with 7 decimal digits from tolerance 0.000172633 +x at minimum = 1.000000, f(1.000000) = 5.048526e-018 +10 iterations. + +Type double with limited iterations and quarter double bits. +Showing 13 bits precision with 5 decimal digits from tolerance 0.0156250 +x at minimum = 0.99998, f(0.99998) = 2.0070e-009, after 7 iterations. + +Type long double with limited iterations and all long double bits. +x at minimum = 1.00000000000137302, f(1.00000000000137302) = 7.54079013697311930e-024, after 10 iterations. + + +For type: f, +epsilon = 1.1921e-007, +the maximum theoretical precision from Brent's minimization is 0.00034527 +Displaying to std::numeric_limits<T>::digits10 5, significant decimal digits. +x at minimum = 1.0002, f(1.0002) = 1.9017e-007, +met 12 bits precision, after 7 iterations. +x == 1 (compared to uncertainty 0.00034527) is true +f(x) == (0 compared to uncertainty 0.00034527) is true + + +For type: d, +epsilon = 2.220446e-016, +the maximum theoretical precision from Brent's minimization is 1.490116e-008 +Displaying to std::numeric_limits<T>::digits10 7, significant decimal digits. +x at minimum = 1.000000, f(1.000000) = 5.048526e-018, +met 26 bits precision, after 10 iterations. +x == 1 (compared to uncertainty 1.490116e-008) is true +f(x) == (0 compared to uncertainty 1.490116e-008) is true + + +For type: e, +epsilon = 1.084202e-019, +the maximum theoretical precision from Brent's minimization is 3.292723e-010 +Displaying to std::numeric_limits<T>::digits10 7, significant decimal digits. +x at minimum = 1.000000, f(1.000000) = 7.540790e-024, +met 32 bits precision, after 10 iterations. +x == 1 (compared to uncertainty 3.292723e-010) is true +f(x) == (0 compared to uncertainty 3.292723e-010) is true + + +For type: N5boost14multiprecision6numberINS0_8backends16float128_backendELNS0_26expression_template_optionE0EEE, +epsilon = 1.92592994e-34, +the maximum theoretical precision from Brent's minimization is 1.38777878e-17 +Displaying to std::numeric_limits<T>::digits10 9, significant decimal digits. +x at minimum = 1.00000000, f(1.00000000) = 1.48695468e-43, +met 56 bits precision, after 12 iterations. +x == 1 (compared to uncertainty 1.38777878e-17) is true +f(x) == (0 compared to uncertainty 1.38777878e-17) is true +Bracketing -4.0000000000000000000000000000000000000000000000000 to 1.3333333333333333333333333333333333333333333333333 +x at minimum = 0.99999999999999999999999999998813903221565569205253, +f(0.99999999999999999999999999998813903221565569205253) = 5.6273022712501408640665300316078046703496236636624e-58, after 14 iterations. + + +For type: N5boost14multiprecision6numberINS0_8backends13cpp_bin_floatILj50ELNS2_15digit_base_typeE10EviLi0ELi0EEELNS0_26expression_template_optionE1EEE, +epsilon = 5.3455294202e-51, +the maximum theoretical precision from Brent's minimization is 7.3113127550e-26 +Displaying to std::numeric_limits<T>::digits10 11, significant decimal digits. +x at minimum = 1.0000000000, f(1.0000000000) = 5.6273022713e-58, +met 84 bits precision, after 14 iterations. +x == 1 (compared to uncertainty 7.3113127550e-26) is true +f(x) == (0 compared to uncertainty 7.3113127550e-26) is true +-4.0000000000000000000000000000000000000000000000000 1.3333333333333333333333333333333333333333333333333 +x at minimum = 0.99999999999999999999999999998813903221565569205253, f(0.99999999999999999999999999998813903221565569205253) = 5.6273022712501408640665300316078046703496236636624e-58 +14 iterations. + + +For type: N5boost14multiprecision6numberINS0_8backends13cpp_bin_floatILj50ELNS2_15digit_base_typeE10EviLi0ELi0EEELNS0_26expression_template_optionE1EEE, +epsilon = 5.3455294202e-51, +the maximum theoretical precision from Brent's minimization is 7.3113127550e-26 +Displaying to std::numeric_limits<T>::digits10 11, significant decimal digits. +x at minimum = 1.0000000000, f(1.0000000000) = 5.6273022713e-58, +met 84 bits precision, after 14 iterations. +x == 1 (compared to uncertainty 7.3113127550e-26) is true +f(x) == (0 compared to uncertainty 7.3113127550e-26) is true + +*/ |