brent_minimise_example.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. //! \file
  2. //! \brief Brent_minimise_example.cpp
  3. // Copyright Paul A. Bristow 2015, 2018.
  4. // Use, modification and distribution are subject to the
  5. // Boost Software License, Version 1.0.
  6. // (See accompanying file LICENSE_1_0.txt
  7. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  8. // Note that this file contains Quickbook mark-up as well as code
  9. // and comments, don't change any of the special comment mark-ups!
  10. // For some diagnostic information:
  11. //#define BOOST_MATH_INSTRUMENT
  12. // If quadmath float128 is available:
  13. //#define BOOST_HAVE_QUADMATH
  14. // Example of finding minimum of a function with Brent's method.
  15. //[brent_minimise_include_1
  16. #include <boost/math/tools/minima.hpp>
  17. //] [/brent_minimise_include_1]
  18. #include <boost/math/special_functions/next.hpp>
  19. #include <boost/multiprecision/cpp_dec_float.hpp>
  20. #include <boost/math/special_functions/pow.hpp>
  21. #include <boost/math/constants/constants.hpp>
  22. #include <boost/test/tools/floating_point_comparison.hpp> // For is_close_at)tolerance and is_small
  23. //[brent_minimise_mp_include_0
  24. #include <boost/multiprecision/cpp_dec_float.hpp> // For decimal boost::multiprecision::cpp_dec_float_50.
  25. #include <boost/multiprecision/cpp_bin_float.hpp> // For binary boost::multiprecision::cpp_bin_float_50;
  26. //] [/brent_minimise_mp_include_0]
  27. //#ifndef _MSC_VER // float128 is not yet supported by Microsoft compiler at 2018.
  28. #ifdef BOOST_HAVE_QUADMATH // Define only if GCC or Intel, and have quadmath.lib or .dll library available.
  29. # include <boost/multiprecision/float128.hpp>
  30. #endif
  31. #include <iostream>
  32. // using std::cout; using std::endl;
  33. #include <iomanip>
  34. // using std::setw; using std::setprecision;
  35. #include <limits>
  36. using std::numeric_limits;
  37. #include <tuple>
  38. #include <utility> // pair, make_pair
  39. #include <type_traits>
  40. #include <typeinfo>
  41. //typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<50>,
  42. // boost::multiprecision::et_off>
  43. // cpp_dec_float_50_et_off;
  44. //
  45. // typedef boost::multiprecision::number<boost::multiprecision::cpp_bin_float<50>,
  46. // boost::multiprecision::et_off>
  47. // cpp_bin_float_50_et_off;
  48. // http://en.wikipedia.org/wiki/Brent%27s_method Brent's method
  49. // An example of a function for which we want to find a minimum.
  50. double f(double x)
  51. {
  52. return (x + 3) * (x - 1) * (x - 1);
  53. }
  54. //[brent_minimise_double_functor
  55. struct funcdouble
  56. {
  57. double operator()(double const& x)
  58. {
  59. return (x + 3) * (x - 1) * (x - 1); // (x + 3)(x - 1)^2
  60. }
  61. };
  62. //] [/brent_minimise_double_functor]
  63. //[brent_minimise_T_functor
  64. struct func
  65. {
  66. template <class T>
  67. T operator()(T const& x)
  68. {
  69. return (x + 3) * (x - 1) * (x - 1); // (x + 3)(x - 1)^2
  70. }
  71. };
  72. //] [/brent_minimise_T_functor]
  73. //! Test if two values are close within a given tolerance.
  74. template<typename FPT>
  75. inline bool
  76. is_close_to(FPT left, FPT right, FPT tolerance)
  77. {
  78. return boost::math::fpc::close_at_tolerance<FPT>(tolerance) (left, right);
  79. }
  80. //[brent_minimise_close
  81. //! Compare if value got is close to expected,
  82. //! checking first if expected is very small
  83. //! (to avoid divide by tiny or zero during comparison)
  84. //! before comparing expect with value got.
  85. template <class T>
  86. bool is_close(T expect, T got, T tolerance)
  87. {
  88. using boost::math::fpc::close_at_tolerance;
  89. using boost::math::fpc::is_small;
  90. using boost::math::fpc::FPC_STRONG;
  91. if (is_small<T>(expect, tolerance))
  92. {
  93. return is_small<T>(got, tolerance);
  94. }
  95. return close_at_tolerance<T>(tolerance, FPC_STRONG) (expect, got);
  96. } // bool is_close(T expect, T got, T tolerance)
  97. //] [/brent_minimise_close]
  98. //[brent_minimise_T_show
  99. //! Example template function to find and show minima.
  100. //! \tparam T floating-point or fixed_point type.
  101. template <class T>
  102. void show_minima()
  103. {
  104. using boost::math::tools::brent_find_minima;
  105. using std::sqrt;
  106. try
  107. { // Always use try'n'catch blocks with Boost.Math to ensure you get any error messages.
  108. int bits = std::numeric_limits<T>::digits/2; // Maximum is digits/2;
  109. std::streamsize prec = static_cast<int>(2 + sqrt((double)bits)); // Number of significant decimal digits.
  110. std::streamsize precision = std::cout.precision(prec); // Save and set.
  111. std::cout << "\n\nFor type: " << typeid(T).name()
  112. << ",\n epsilon = " << std::numeric_limits<T>::epsilon()
  113. // << ", precision of " << bits << " bits"
  114. << ",\n the maximum theoretical precision from Brent's minimization is "
  115. << sqrt(std::numeric_limits<T>::epsilon())
  116. << "\n Displaying to std::numeric_limits<T>::digits10 " << prec << ", significant decimal digits."
  117. << std::endl;
  118. const boost::uintmax_t maxit = 20;
  119. boost::uintmax_t it = maxit;
  120. // Construct using string, not double, avoids loss of precision.
  121. //T bracket_min = static_cast<T>("-4");
  122. //T bracket_max = static_cast<T>("1.3333333333333333333333333333333333333333333333333");
  123. // Construction from double may cause loss of precision for multiprecision types like cpp_bin_float,
  124. // but brackets values are good enough for using Brent minimization.
  125. T bracket_min = static_cast<T>(-4);
  126. T bracket_max = static_cast<T>(1.3333333333333333333333333333333333333333333333333);
  127. std::pair<T, T> r = brent_find_minima<func, T>(func(), bracket_min, bracket_max, bits, it);
  128. std::cout << " x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second;
  129. if (it < maxit)
  130. {
  131. std::cout << ",\n met " << bits << " bits precision" << ", after " << it << " iterations." << std::endl;
  132. }
  133. else
  134. {
  135. std::cout << ",\n did NOT meet " << bits << " bits precision" << " after " << it << " iterations!" << std::endl;
  136. }
  137. // Check that result is that expected (compared to theoretical uncertainty).
  138. T uncertainty = sqrt(std::numeric_limits<T>::epsilon());
  139. std::cout << std::boolalpha << "x == 1 (compared to uncertainty " << uncertainty << ") is "
  140. << is_close(static_cast<T>(1), r.first, uncertainty) << std::endl;
  141. std::cout << std::boolalpha << "f(x) == (0 compared to uncertainty " << uncertainty << ") is "
  142. << is_close(static_cast<T>(0), r.second, uncertainty) << std::endl;
  143. // Problems with this using multiprecision with expression template on?
  144. std::cout.precision(precision); // Restore.
  145. }
  146. catch (const std::exception& e)
  147. { // Always useful to include try & catch blocks because default policies
  148. // are to throw exceptions on arguments that cause errors like underflow, overflow.
  149. // Lacking try & catch blocks, the program will abort without a message below,
  150. // which may give some helpful clues as to the cause of the exception.
  151. std::cout <<
  152. "\n""Message from thrown exception was:\n " << e.what() << std::endl;
  153. }
  154. } // void show_minima()
  155. //] [/brent_minimise_T_show]
  156. int main()
  157. {
  158. using boost::math::tools::brent_find_minima;
  159. using std::sqrt;
  160. std::cout << "Brent's minimisation examples." << std::endl;
  161. std::cout << std::boolalpha << std::endl;
  162. std::cout << std::showpoint << std::endl; // Show trailing zeros.
  163. // Tip - using
  164. // std::cout.precision(std::numeric_limits<T>::digits10);
  165. // during debugging is wise because it warns
  166. // if construction of multiprecision involves conversion from double
  167. // by finding random or zero digits after 17th decimal digit.
  168. // Specific type double - unlimited iterations (unwise?).
  169. {
  170. std::cout << "\nType double - unlimited iterations (unwise?)" << std::endl;
  171. //[brent_minimise_double_1
  172. const int double_bits = std::numeric_limits<double>::digits;
  173. std::pair<double, double> r = brent_find_minima(funcdouble(), -4., 4. / 3, double_bits);
  174. std::streamsize precision_1 = std::cout.precision(std::numeric_limits<double>::digits10);
  175. // Show all double precision decimal digits and trailing zeros.
  176. std::cout << "x at minimum = " << r.first
  177. << ", f(" << r.first << ") = " << r.second << std::endl;
  178. //] [/brent_minimise_double_1]
  179. std::cout << "x at minimum = " << (r.first - 1.) / r.first << std::endl;
  180. // x at minimum = 1.00000000112345, f(1.00000000112345) = 5.04852568272458e-018
  181. double uncertainty = sqrt(std::numeric_limits<double>::epsilon());
  182. std::cout << "Uncertainty sqrt(epsilon) = " << uncertainty << std::endl;
  183. // sqrt(epsilon) = 1.49011611938477e-008
  184. // (epsilon is always > 0, so no need to take abs value).
  185. std::cout.precision(precision_1); // Restore.
  186. //[brent_minimise_double_1a
  187. using boost::math::fpc::close_at_tolerance;
  188. using boost::math::fpc::is_small;
  189. std::cout << "x = " << r.first << ", f(x) = " << r.second << std::endl;
  190. std::cout << std::boolalpha << "x == 1 (compared to uncertainty "
  191. << uncertainty << ") is " << is_close(1., r.first, uncertainty) << std::endl; // true
  192. std::cout << std::boolalpha << "f(x) == 0 (compared to uncertainty "
  193. << uncertainty << ") is " << is_close(0., r.second, uncertainty) << std::endl; // true
  194. //] [/brent_minimise_double_1a]
  195. }
  196. std::cout << "\nType double with limited iterations." << std::endl;
  197. {
  198. const int bits = std::numeric_limits<double>::digits;
  199. // Specific type double - limit maxit to 20 iterations.
  200. std::cout << "Precision bits = " << bits << std::endl;
  201. //[brent_minimise_double_2
  202. const boost::uintmax_t maxit = 20;
  203. boost::uintmax_t it = maxit;
  204. std::pair<double, double> r = brent_find_minima(funcdouble(), -4., 4. / 3, bits, it);
  205. std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second
  206. << " after " << it << " iterations. " << std::endl;
  207. //] [/brent_minimise_double_2]
  208. // x at minimum = 1.00000000112345, f(1.00000000112345) = 5.04852568272458e-018
  209. //[brent_minimise_double_3
  210. std::streamsize prec = static_cast<int>(2 + sqrt((double)bits)); // Number of significant decimal digits.
  211. std::streamsize precision_3 = std::cout.precision(prec); // Save and set new precision.
  212. std::cout << "Showing " << bits << " bits "
  213. "precision with " << prec
  214. << " decimal digits from tolerance " << sqrt(std::numeric_limits<double>::epsilon())
  215. << std::endl;
  216. std::cout << "x at minimum = " << r.first
  217. << ", f(" << r.first << ") = " << r.second
  218. << " after " << it << " iterations. " << std::endl;
  219. std::cout.precision(precision_3); // Restore.
  220. //] [/brent_minimise_double_3]
  221. // Showing 53 bits precision with 9 decimal digits from tolerance 1.49011611938477e-008
  222. // x at minimum = 1, f(1) = 5.04852568e-018
  223. }
  224. std::cout << "\nType double with limited iterations and half double bits." << std::endl;
  225. {
  226. //[brent_minimise_double_4
  227. const int bits_div_2 = std::numeric_limits<double>::digits / 2; // Half digits precision (effective maximum).
  228. double epsilon_2 = boost::math::pow<-(std::numeric_limits<double>::digits/2 - 1), double>(2);
  229. std::streamsize prec = static_cast<int>(2 + sqrt((double)bits_div_2)); // Number of significant decimal digits.
  230. std::cout << "Showing " << bits_div_2 << " bits precision with " << prec
  231. << " decimal digits from tolerance " << sqrt(epsilon_2)
  232. << std::endl;
  233. std::streamsize precision_4 = std::cout.precision(prec); // Save.
  234. const boost::uintmax_t maxit = 20;
  235. boost::uintmax_t it_4 = maxit;
  236. std::pair<double, double> r = brent_find_minima(funcdouble(), -4., 4. / 3, bits_div_2, it_4);
  237. std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second << std::endl;
  238. std::cout << it_4 << " iterations. " << std::endl;
  239. std::cout.precision(precision_4); // Restore.
  240. //] [/brent_minimise_double_4]
  241. }
  242. // x at minimum = 1, f(1) = 5.04852568e-018
  243. {
  244. std::cout << "\nType double with limited iterations and quarter double bits." << std::endl;
  245. //[brent_minimise_double_5
  246. const int bits_div_4 = std::numeric_limits<double>::digits / 4; // Quarter precision.
  247. double epsilon_4 = boost::math::pow<-(std::numeric_limits<double>::digits / 4 - 1), double>(2);
  248. std::streamsize prec = static_cast<int>(2 + sqrt((double)bits_div_4)); // Number of significant decimal digits.
  249. std::cout << "Showing " << bits_div_4 << " bits precision with " << prec
  250. << " decimal digits from tolerance " << sqrt(epsilon_4)
  251. << std::endl;
  252. std::streamsize precision_5 = std::cout.precision(prec); // Save & set.
  253. const boost::uintmax_t maxit = 20;
  254. boost::uintmax_t it_5 = maxit;
  255. std::pair<double, double> r = brent_find_minima(funcdouble(), -4., 4. / 3, bits_div_4, it_5);
  256. std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second
  257. << ", after " << it_5 << " iterations. " << std::endl;
  258. std::cout.precision(precision_5); // Restore.
  259. //] [/brent_minimise_double_5]
  260. }
  261. // Showing 13 bits precision with 9 decimal digits from tolerance 0.015625
  262. // x at minimum = 0.9999776, f(0.9999776) = 2.0069572e-009
  263. // 7 iterations.
  264. {
  265. std::cout << "\nType long double with limited iterations and all long double bits." << std::endl;
  266. //[brent_minimise_template_1
  267. std::streamsize precision_t1 = std::cout.precision(std::numeric_limits<long double>::digits10); // Save & set.
  268. long double bracket_min = -4.;
  269. long double bracket_max = 4. / 3;
  270. const int bits = std::numeric_limits<long double>::digits;
  271. const boost::uintmax_t maxit = 20;
  272. boost::uintmax_t it = maxit;
  273. std::pair<long double, long double> r = brent_find_minima(func(), bracket_min, bracket_max, bits, it);
  274. std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second
  275. << ", after " << it << " iterations. " << std::endl;
  276. std::cout.precision(precision_t1); // Restore.
  277. //] [/brent_minimise_template_1]
  278. }
  279. // Show use of built-in type Template versions.
  280. // (Will not work if construct bracket min and max from string).
  281. //[brent_minimise_template_fd
  282. show_minima<float>();
  283. show_minima<double>();
  284. show_minima<long double>();
  285. //] [/brent_minimise_template_fd]
  286. //[brent_minimise_mp_include_1
  287. #ifdef BOOST_HAVE_QUADMATH // Defined only if GCC or Intel and have quadmath.lib or .dll library available.
  288. using boost::multiprecision::float128;
  289. #endif
  290. //] [/brent_minimise_mp_include_1]
  291. //[brent_minimise_template_quad
  292. #ifdef BOOST_HAVE_QUADMATH // Defined only if GCC or Intel and have quadmath.lib or .dll library available.
  293. show_minima<float128>(); // Needs quadmath_snprintf, sqrtQ, fabsq that are in in quadmath library.
  294. #endif
  295. //] [/brent_minimise_template_quad
  296. // User-defined floating-point template.
  297. //[brent_minimise_mp_typedefs
  298. using boost::multiprecision::cpp_bin_float_50; // binary multiprecision typedef.
  299. using boost::multiprecision::cpp_dec_float_50; // decimal multiprecision typedef.
  300. // One might also need typedefs like these to switch expression templates off and on (default is on).
  301. typedef boost::multiprecision::number<boost::multiprecision::cpp_bin_float<50>,
  302. boost::multiprecision::et_on>
  303. cpp_bin_float_50_et_on; // et_on is default so is same as cpp_bin_float_50.
  304. typedef boost::multiprecision::number<boost::multiprecision::cpp_bin_float<50>,
  305. boost::multiprecision::et_off>
  306. cpp_bin_float_50_et_off;
  307. typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<50>,
  308. boost::multiprecision::et_on> // et_on is default so is same as cpp_dec_float_50.
  309. cpp_dec_float_50_et_on;
  310. typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<50>,
  311. boost::multiprecision::et_off>
  312. cpp_dec_float_50_et_off;
  313. //] [/brent_minimise_mp_typedefs]
  314. { // binary ET on by default.
  315. //[brent_minimise_mp_1
  316. std::cout.precision(std::numeric_limits<cpp_bin_float_50>::digits10);
  317. int bits = std::numeric_limits<cpp_bin_float_50>::digits / 2 - 2;
  318. cpp_bin_float_50 bracket_min = static_cast<cpp_bin_float_50>("-4");
  319. cpp_bin_float_50 bracket_max = static_cast<cpp_bin_float_50>("1.3333333333333333333333333333333333333333333333333");
  320. std::cout << "Bracketing " << bracket_min << " to " << bracket_max << std::endl;
  321. const boost::uintmax_t maxit = 20;
  322. boost::uintmax_t it = maxit; // Will be updated with actual iteration count.
  323. std::pair<cpp_bin_float_50, cpp_bin_float_50> r
  324. = brent_find_minima(func(), bracket_min, bracket_max, bits, it);
  325. std::cout << "x at minimum = " << r.first << ",\n f(" << r.first << ") = " << r.second
  326. // x at minimum = 1, f(1) = 5.04853e-018
  327. << ", after " << it << " iterations. " << std::endl;
  328. is_close_to(static_cast<cpp_bin_float_50>("1"), r.first, sqrt(std::numeric_limits<cpp_bin_float_50>::epsilon()));
  329. is_close_to(static_cast<cpp_bin_float_50>("0"), r.second, sqrt(std::numeric_limits<cpp_bin_float_50>::epsilon()));
  330. //] [/brent_minimise_mp_1]
  331. /*
  332. //[brent_minimise_mp_output_1
  333. For type class boost::multiprecision::number<class boost::multiprecision::backends::cpp_bin_float<50,10,void,int,0,0>,1>,
  334. epsilon = 5.3455294202e-51,
  335. the maximum theoretical precision from Brent minimization is 7.311312755e-26
  336. Displaying to std::numeric_limits<T>::digits10 11 significant decimal digits.
  337. x at minimum = 1, f(1) = 5.6273022713e-58,
  338. met 84 bits precision, after 14 iterations.
  339. x == 1 (compared to uncertainty 7.311312755e-26) is true
  340. f(x) == (0 compared to uncertainty 7.311312755e-26) is true
  341. -4 1.3333333333333333333333333333333333333333333333333
  342. x at minimum = 0.99999999999999999999999999998813903221565569205253,
  343. f(0.99999999999999999999999999998813903221565569205253) =
  344. 5.6273022712501408640665300316078046703496236636624e-58
  345. 14 iterations
  346. //] [/brent_minimise_mp_output_1]
  347. */
  348. //[brent_minimise_mp_2
  349. show_minima<cpp_bin_float_50_et_on>(); //
  350. //] [/brent_minimise_mp_2]
  351. /*
  352. //[brent_minimise_mp_output_2
  353. For type class boost::multiprecision::number<class boost::multiprecision::backends::cpp_bin_float<50, 10, void, int, 0, 0>, 1>,
  354. //] [/brent_minimise_mp_output_1]
  355. */
  356. }
  357. { // binary ET on explicit
  358. std::cout.precision(std::numeric_limits<cpp_bin_float_50_et_on>::digits10);
  359. int bits = std::numeric_limits<cpp_bin_float_50_et_on>::digits / 2 - 2;
  360. cpp_bin_float_50_et_on bracket_min = static_cast<cpp_bin_float_50_et_on>("-4");
  361. cpp_bin_float_50_et_on bracket_max = static_cast<cpp_bin_float_50_et_on>("1.3333333333333333333333333333333333333333333333333");
  362. std::cout << bracket_min << " " << bracket_max << std::endl;
  363. const boost::uintmax_t maxit = 20;
  364. boost::uintmax_t it = maxit;
  365. 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);
  366. std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second << std::endl;
  367. // x at minimum = 1, f(1) = 5.04853e-018
  368. std::cout << it << " iterations. " << std::endl;
  369. show_minima<cpp_bin_float_50_et_on>(); //
  370. }
  371. return 0;
  372. // Some examples of switching expression templates on and off follow.
  373. { // binary ET off
  374. std::cout.precision(std::numeric_limits<cpp_bin_float_50_et_off>::digits10);
  375. int bits = std::numeric_limits<cpp_bin_float_50_et_off>::digits / 2 - 2;
  376. cpp_bin_float_50_et_off bracket_min = static_cast<cpp_bin_float_50_et_off>("-4");
  377. cpp_bin_float_50_et_off bracket_max = static_cast<cpp_bin_float_50_et_off>("1.3333333333333333333333333333333333333333333333333");
  378. std::cout << bracket_min << " " << bracket_max << std::endl;
  379. const boost::uintmax_t maxit = 20;
  380. boost::uintmax_t it = maxit;
  381. 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);
  382. std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second << std::endl;
  383. // x at minimum = 1, f(1) = 5.04853e-018
  384. std::cout << it << " iterations. " << std::endl;
  385. show_minima<cpp_bin_float_50_et_off>(); //
  386. }
  387. { // decimal ET on by default
  388. std::cout.precision(std::numeric_limits<cpp_dec_float_50>::digits10);
  389. int bits = std::numeric_limits<cpp_dec_float_50>::digits / 2 - 2;
  390. cpp_dec_float_50 bracket_min = static_cast<cpp_dec_float_50>("-4");
  391. cpp_dec_float_50 bracket_max = static_cast<cpp_dec_float_50>("1.3333333333333333333333333333333333333333333333333");
  392. std::cout << bracket_min << " " << bracket_max << std::endl;
  393. const boost::uintmax_t maxit = 20;
  394. boost::uintmax_t it = maxit;
  395. std::pair<cpp_dec_float_50, cpp_dec_float_50> r = brent_find_minima(func(), bracket_min, bracket_max, bits, it);
  396. std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second << std::endl;
  397. // x at minimum = 1, f(1) = 5.04853e-018
  398. std::cout << it << " iterations. " << std::endl;
  399. show_minima<cpp_dec_float_50>();
  400. }
  401. { // decimal ET on
  402. std::cout.precision(std::numeric_limits<cpp_dec_float_50_et_on>::digits10);
  403. int bits = std::numeric_limits<cpp_dec_float_50_et_on>::digits / 2 - 2;
  404. cpp_dec_float_50_et_on bracket_min = static_cast<cpp_dec_float_50_et_on>("-4");
  405. cpp_dec_float_50_et_on bracket_max = static_cast<cpp_dec_float_50_et_on>("1.3333333333333333333333333333333333333333333333333");
  406. std::cout << bracket_min << " " << bracket_max << std::endl;
  407. const boost::uintmax_t maxit = 20;
  408. boost::uintmax_t it = maxit;
  409. 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);
  410. std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second << std::endl;
  411. // x at minimum = 1, f(1) = 5.04853e-018
  412. std::cout << it << " iterations. " << std::endl;
  413. show_minima<cpp_dec_float_50_et_on>();
  414. }
  415. { // decimal ET off
  416. std::cout.precision(std::numeric_limits<cpp_dec_float_50_et_off>::digits10);
  417. int bits = std::numeric_limits<cpp_dec_float_50_et_off>::digits / 2 - 2;
  418. cpp_dec_float_50_et_off bracket_min = static_cast<cpp_dec_float_50_et_off>("-4");
  419. cpp_dec_float_50_et_off bracket_max = static_cast<cpp_dec_float_50_et_off>("1.3333333333333333333333333333333333333333333333333");
  420. std::cout << bracket_min << " " << bracket_max << std::endl;
  421. const boost::uintmax_t maxit = 20;
  422. boost::uintmax_t it = maxit;
  423. 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);
  424. std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second << std::endl;
  425. // x at minimum = 1, f(1) = 5.04853e-018
  426. std::cout << it << " iterations. " << std::endl;
  427. show_minima<cpp_dec_float_50_et_off>();
  428. }
  429. return 0;
  430. } // int main()
  431. /*
  432. Typical output MSVC 15.7.3
  433. brent_minimise_example.cpp
  434. Generating code
  435. 7 of 2746 functions ( 0.3%) were compiled, the rest were copied from previous compilation.
  436. 0 functions were new in current compilation
  437. 1 functions had inline decision re-evaluated but remain unchanged
  438. Finished generating code
  439. brent_minimise_example.vcxproj -> J:\Cpp\MathToolkit\test\Math_test\Release\brent_minimise_example.exe
  440. Autorun "J:\Cpp\MathToolkit\test\Math_test\Release\brent_minimise_example.exe"
  441. Brent's minimisation examples.
  442. Type double - unlimited iterations (unwise?)
  443. x at minimum = 1.00000000112345, f(1.00000000112345) = 5.04852568272458e-18
  444. x at minimum = 1.12344622367552e-09
  445. Uncertainty sqrt(epsilon) = 1.49011611938477e-08
  446. x = 1.00000, f(x) = 5.04853e-18
  447. x == 1 (compared to uncertainty 1.49012e-08) is true
  448. f(x) == 0 (compared to uncertainty 1.49012e-08) is true
  449. Type double with limited iterations.
  450. Precision bits = 53
  451. x at minimum = 1.00000, f(1.00000) = 5.04853e-18 after 10 iterations.
  452. Showing 53 bits precision with 9 decimal digits from tolerance 1.49011612e-08
  453. x at minimum = 1.00000000, f(1.00000000) = 5.04852568e-18 after 10 iterations.
  454. Type double with limited iterations and half double bits.
  455. Showing 26 bits precision with 7 decimal digits from tolerance 0.000172633
  456. x at minimum = 1.000000, f(1.000000) = 5.048526e-18
  457. 10 iterations.
  458. Type double with limited iterations and quarter double bits.
  459. Showing 13 bits precision with 5 decimal digits from tolerance 0.0156250
  460. x at minimum = 0.99998, f(0.99998) = 2.0070e-09, after 7 iterations.
  461. Type long double with limited iterations and all long double bits.
  462. x at minimum = 1.00000000112345, f(1.00000000112345) = 5.04852568272458e-18, after 10 iterations.
  463. For type: float,
  464. epsilon = 1.1921e-07,
  465. the maximum theoretical precision from Brent's minimization is 0.00034527
  466. Displaying to std::numeric_limits<T>::digits10 5, significant decimal digits.
  467. x at minimum = 1.0002, f(1.0002) = 1.9017e-07,
  468. met 12 bits precision, after 7 iterations.
  469. x == 1 (compared to uncertainty 0.00034527) is true
  470. f(x) == (0 compared to uncertainty 0.00034527) is true
  471. For type: double,
  472. epsilon = 2.220446e-16,
  473. the maximum theoretical precision from Brent's minimization is 1.490116e-08
  474. Displaying to std::numeric_limits<T>::digits10 7, significant decimal digits.
  475. x at minimum = 1.000000, f(1.000000) = 5.048526e-18,
  476. met 26 bits precision, after 10 iterations.
  477. x == 1 (compared to uncertainty 1.490116e-08) is true
  478. f(x) == (0 compared to uncertainty 1.490116e-08) is true
  479. For type: long double,
  480. epsilon = 2.220446e-16,
  481. the maximum theoretical precision from Brent's minimization is 1.490116e-08
  482. Displaying to std::numeric_limits<T>::digits10 7, significant decimal digits.
  483. x at minimum = 1.000000, f(1.000000) = 5.048526e-18,
  484. met 26 bits precision, after 10 iterations.
  485. x == 1 (compared to uncertainty 1.490116e-08) is true
  486. f(x) == (0 compared to uncertainty 1.490116e-08) is true
  487. Bracketing -4.0000000000000000000000000000000000000000000000000 to 1.3333333333333333333333333333333333333333333333333
  488. x at minimum = 0.99999999999999999999999999998813903221565569205253,
  489. f(0.99999999999999999999999999998813903221565569205253) = 5.6273022712501408640665300316078046703496236636624e-58, after 14 iterations.
  490. For type: class boost::multiprecision::number<class boost::multiprecision::backends::cpp_bin_float<50,10,void,int,0,0>,1>,
  491. epsilon = 5.3455294202e-51,
  492. the maximum theoretical precision from Brent's minimization is 7.3113127550e-26
  493. Displaying to std::numeric_limits<T>::digits10 11, significant decimal digits.
  494. x at minimum = 1.0000000000, f(1.0000000000) = 5.6273022713e-58,
  495. met 84 bits precision, after 14 iterations.
  496. x == 1 (compared to uncertainty 7.3113127550e-26) is true
  497. f(x) == (0 compared to uncertainty 7.3113127550e-26) is true
  498. -4.0000000000000000000000000000000000000000000000000 1.3333333333333333333333333333333333333333333333333
  499. x at minimum = 0.99999999999999999999999999998813903221565569205253, f(0.99999999999999999999999999998813903221565569205253) = 5.6273022712501408640665300316078046703496236636624e-58
  500. 14 iterations.
  501. For type: class boost::multiprecision::number<class boost::multiprecision::backends::cpp_bin_float<50,10,void,int,0,0>,1>,
  502. epsilon = 5.3455294202e-51,
  503. the maximum theoretical precision from Brent's minimization is 7.3113127550e-26
  504. Displaying to std::numeric_limits<T>::digits10 11, significant decimal digits.
  505. x at minimum = 1.0000000000, f(1.0000000000) = 5.6273022713e-58,
  506. met 84 bits precision, after 14 iterations.
  507. x == 1 (compared to uncertainty 7.3113127550e-26) is true
  508. f(x) == (0 compared to uncertainty 7.3113127550e-26) is true
  509. ============================================================================================================
  510. // GCC 7.2.0 with quadmath
  511. Brent's minimisation examples.
  512. Type double - unlimited iterations (unwise?)
  513. x at minimum = 1.00000000112345, f(1.00000000112345) = 5.04852568272458e-018
  514. x at minimum = 1.12344622367552e-009
  515. Uncertainty sqrt(epsilon) = 1.49011611938477e-008
  516. x = 1.00000, f(x) = 5.04853e-018
  517. x == 1 (compared to uncertainty 1.49012e-008) is true
  518. f(x) == 0 (compared to uncertainty 1.49012e-008) is true
  519. Type double with limited iterations.
  520. Precision bits = 53
  521. x at minimum = 1.00000, f(1.00000) = 5.04853e-018 after 10 iterations.
  522. Showing 53 bits precision with 9 decimal digits from tolerance 1.49011612e-008
  523. x at minimum = 1.00000000, f(1.00000000) = 5.04852568e-018 after 10 iterations.
  524. Type double with limited iterations and half double bits.
  525. Showing 26 bits precision with 7 decimal digits from tolerance 0.000172633
  526. x at minimum = 1.000000, f(1.000000) = 5.048526e-018
  527. 10 iterations.
  528. Type double with limited iterations and quarter double bits.
  529. Showing 13 bits precision with 5 decimal digits from tolerance 0.0156250
  530. x at minimum = 0.99998, f(0.99998) = 2.0070e-009, after 7 iterations.
  531. Type long double with limited iterations and all long double bits.
  532. x at minimum = 1.00000000000137302, f(1.00000000000137302) = 7.54079013697311930e-024, after 10 iterations.
  533. For type: f,
  534. epsilon = 1.1921e-007,
  535. the maximum theoretical precision from Brent's minimization is 0.00034527
  536. Displaying to std::numeric_limits<T>::digits10 5, significant decimal digits.
  537. x at minimum = 1.0002, f(1.0002) = 1.9017e-007,
  538. met 12 bits precision, after 7 iterations.
  539. x == 1 (compared to uncertainty 0.00034527) is true
  540. f(x) == (0 compared to uncertainty 0.00034527) is true
  541. For type: d,
  542. epsilon = 2.220446e-016,
  543. the maximum theoretical precision from Brent's minimization is 1.490116e-008
  544. Displaying to std::numeric_limits<T>::digits10 7, significant decimal digits.
  545. x at minimum = 1.000000, f(1.000000) = 5.048526e-018,
  546. met 26 bits precision, after 10 iterations.
  547. x == 1 (compared to uncertainty 1.490116e-008) is true
  548. f(x) == (0 compared to uncertainty 1.490116e-008) is true
  549. For type: e,
  550. epsilon = 1.084202e-019,
  551. the maximum theoretical precision from Brent's minimization is 3.292723e-010
  552. Displaying to std::numeric_limits<T>::digits10 7, significant decimal digits.
  553. x at minimum = 1.000000, f(1.000000) = 7.540790e-024,
  554. met 32 bits precision, after 10 iterations.
  555. x == 1 (compared to uncertainty 3.292723e-010) is true
  556. f(x) == (0 compared to uncertainty 3.292723e-010) is true
  557. For type: N5boost14multiprecision6numberINS0_8backends16float128_backendELNS0_26expression_template_optionE0EEE,
  558. epsilon = 1.92592994e-34,
  559. the maximum theoretical precision from Brent's minimization is 1.38777878e-17
  560. Displaying to std::numeric_limits<T>::digits10 9, significant decimal digits.
  561. x at minimum = 1.00000000, f(1.00000000) = 1.48695468e-43,
  562. met 56 bits precision, after 12 iterations.
  563. x == 1 (compared to uncertainty 1.38777878e-17) is true
  564. f(x) == (0 compared to uncertainty 1.38777878e-17) is true
  565. Bracketing -4.0000000000000000000000000000000000000000000000000 to 1.3333333333333333333333333333333333333333333333333
  566. x at minimum = 0.99999999999999999999999999998813903221565569205253,
  567. f(0.99999999999999999999999999998813903221565569205253) = 5.6273022712501408640665300316078046703496236636624e-58, after 14 iterations.
  568. For type: N5boost14multiprecision6numberINS0_8backends13cpp_bin_floatILj50ELNS2_15digit_base_typeE10EviLi0ELi0EEELNS0_26expression_template_optionE1EEE,
  569. epsilon = 5.3455294202e-51,
  570. the maximum theoretical precision from Brent's minimization is 7.3113127550e-26
  571. Displaying to std::numeric_limits<T>::digits10 11, significant decimal digits.
  572. x at minimum = 1.0000000000, f(1.0000000000) = 5.6273022713e-58,
  573. met 84 bits precision, after 14 iterations.
  574. x == 1 (compared to uncertainty 7.3113127550e-26) is true
  575. f(x) == (0 compared to uncertainty 7.3113127550e-26) is true
  576. -4.0000000000000000000000000000000000000000000000000 1.3333333333333333333333333333333333333333333333333
  577. x at minimum = 0.99999999999999999999999999998813903221565569205253, f(0.99999999999999999999999999998813903221565569205253) = 5.6273022712501408640665300316078046703496236636624e-58
  578. 14 iterations.
  579. For type: N5boost14multiprecision6numberINS0_8backends13cpp_bin_floatILj50ELNS2_15digit_base_typeE10EviLi0ELi0EEELNS0_26expression_template_optionE1EEE,
  580. epsilon = 5.3455294202e-51,
  581. the maximum theoretical precision from Brent's minimization is 7.3113127550e-26
  582. Displaying to std::numeric_limits<T>::digits10 11, significant decimal digits.
  583. x at minimum = 1.0000000000, f(1.0000000000) = 5.6273022713e-58,
  584. met 84 bits precision, after 14 iterations.
  585. x == 1 (compared to uncertainty 7.3113127550e-26) is true
  586. f(x) == (0 compared to uncertainty 7.3113127550e-26) is true
  587. */