//! \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 //] [/brent_minimise_include_1] #include #include #include #include #include // For is_close_at)tolerance and is_small //[brent_minimise_mp_include_0 #include // For decimal boost::multiprecision::cpp_dec_float_50. #include // 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 #endif #include // using std::cout; using std::endl; #include // using std::setw; using std::setprecision; #include using std::numeric_limits; #include #include // pair, make_pair #include #include //typedef boost::multiprecision::number, // boost::multiprecision::et_off> // cpp_dec_float_50_et_off; // // typedef boost::multiprecision::number, // 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 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 inline bool is_close_to(FPT left, FPT right, FPT tolerance) { return boost::math::fpc::close_at_tolerance(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 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); } return close_at_tolerance(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 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::digits/2; // Maximum is digits/2; std::streamsize prec = static_cast(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::epsilon() // << ", precision of " << bits << " bits" << ",\n the maximum theoretical precision from Brent's minimization is " << sqrt(std::numeric_limits::epsilon()) << "\n Displaying to std::numeric_limits::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("-4"); //T bracket_max = static_cast("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(-4); T bracket_max = static_cast(1.3333333333333333333333333333333333333333333333333); std::pair r = brent_find_minima(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::epsilon()); 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. } 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::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::digits; std::pair r = brent_find_minima(funcdouble(), -4., 4. / 3, double_bits); std::streamsize precision_1 = std::cout.precision(std::numeric_limits::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::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::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 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(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::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::digits / 2; // Half digits precision (effective maximum). double epsilon_2 = boost::math::pow<-(std::numeric_limits::digits/2 - 1), double>(2); std::streamsize prec = static_cast(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 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::digits / 4; // Quarter precision. double epsilon_4 = boost::math::pow<-(std::numeric_limits::digits / 4 - 1), double>(2); std::streamsize prec = static_cast(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 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::digits10); // Save & set. long double bracket_min = -4.; long double bracket_max = 4. / 3; const int bits = std::numeric_limits::digits; const boost::uintmax_t maxit = 20; boost::uintmax_t it = maxit; std::pair 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(); show_minima(); show_minima(); //] [/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(); // 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::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::et_off> cpp_bin_float_50_et_off; typedef boost::multiprecision::number, 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::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::digits10); int bits = std::numeric_limits::digits / 2 - 2; cpp_bin_float_50 bracket_min = static_cast("-4"); cpp_bin_float_50 bracket_max = static_cast("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 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("1"), r.first, sqrt(std::numeric_limits::epsilon())); is_close_to(static_cast("0"), r.second, sqrt(std::numeric_limits::epsilon())); //] [/brent_minimise_mp_1] /* //[brent_minimise_mp_output_1 For type class boost::multiprecision::number,1>, epsilon = 5.3455294202e-51, the maximum theoretical precision from Brent minimization is 7.311312755e-26 Displaying to std::numeric_limits::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(); // //] [/brent_minimise_mp_2] /* //[brent_minimise_mp_output_2 For type class boost::multiprecision::number, 1>, //] [/brent_minimise_mp_output_1] */ } { // binary ET on explicit std::cout.precision(std::numeric_limits::digits10); int bits = std::numeric_limits::digits / 2 - 2; cpp_bin_float_50_et_on bracket_min = static_cast("-4"); cpp_bin_float_50_et_on bracket_max = static_cast("1.3333333333333333333333333333333333333333333333333"); std::cout << bracket_min << " " << bracket_max << std::endl; const boost::uintmax_t maxit = 20; boost::uintmax_t it = maxit; std::pair 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(); // } return 0; // Some examples of switching expression templates on and off follow. { // binary ET off std::cout.precision(std::numeric_limits::digits10); int bits = std::numeric_limits::digits / 2 - 2; cpp_bin_float_50_et_off bracket_min = static_cast("-4"); cpp_bin_float_50_et_off bracket_max = static_cast("1.3333333333333333333333333333333333333333333333333"); std::cout << bracket_min << " " << bracket_max << std::endl; const boost::uintmax_t maxit = 20; boost::uintmax_t it = maxit; std::pair 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(); // } { // decimal ET on by default std::cout.precision(std::numeric_limits::digits10); int bits = std::numeric_limits::digits / 2 - 2; cpp_dec_float_50 bracket_min = static_cast("-4"); cpp_dec_float_50 bracket_max = static_cast("1.3333333333333333333333333333333333333333333333333"); std::cout << bracket_min << " " << bracket_max << std::endl; const boost::uintmax_t maxit = 20; boost::uintmax_t it = maxit; std::pair 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(); } { // decimal ET on std::cout.precision(std::numeric_limits::digits10); int bits = std::numeric_limits::digits / 2 - 2; cpp_dec_float_50_et_on bracket_min = static_cast("-4"); cpp_dec_float_50_et_on bracket_max = static_cast("1.3333333333333333333333333333333333333333333333333"); std::cout << bracket_min << " " << bracket_max << std::endl; const boost::uintmax_t maxit = 20; boost::uintmax_t it = maxit; std::pair 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(); } { // decimal ET off std::cout.precision(std::numeric_limits::digits10); int bits = std::numeric_limits::digits / 2 - 2; cpp_dec_float_50_et_off bracket_min = static_cast("-4"); cpp_dec_float_50_et_off bracket_max = static_cast("1.3333333333333333333333333333333333333333333333333"); std::cout << bracket_min << " " << bracket_max << std::endl; const boost::uintmax_t maxit = 20; boost::uintmax_t it = maxit; std::pair 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(); } 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::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::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::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,1>, epsilon = 5.3455294202e-51, the maximum theoretical precision from Brent's minimization is 7.3113127550e-26 Displaying to std::numeric_limits::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,1>, epsilon = 5.3455294202e-51, the maximum theoretical precision from Brent's minimization is 7.3113127550e-26 Displaying to std::numeric_limits::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::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::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::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::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::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::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 */