test_root_finding_concepts.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. // Copyright John Maddock 2014
  2. // Use, modification and distribution are subject to the
  3. // Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt
  5. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #define BOOST_TEST_MAIN
  7. #include <boost/test/unit_test.hpp> // Boost.Test
  8. #include <boost/test/results_collector.hpp>
  9. #include <boost/test/unit_test.hpp>
  10. #include <boost/test/tools/floating_point_comparison.hpp>
  11. #include <boost/tuple/tuple.hpp>
  12. #include <boost/fusion/include/tuple.hpp>
  13. #include <boost/fusion/include/std_pair.hpp>
  14. #ifndef BOOST_NO_CXX11_HDR_TUPLE
  15. #include <tuple>
  16. #endif
  17. #include <iostream>
  18. #include <iomanip>
  19. using std::cout;
  20. using std::endl;
  21. using std::setprecision;
  22. #include <boost/math/tools/roots.hpp>
  23. //
  24. // We'll use cbrt as an example:
  25. //
  26. struct cbtr_functor_1
  27. {
  28. cbtr_functor_1(double x) : m_target(x) {}
  29. double operator()(double x)
  30. {
  31. return x * x * x - m_target;
  32. }
  33. private:
  34. double m_target;
  35. };
  36. struct cbtr_functor_2a
  37. {
  38. cbtr_functor_2a(double x) : m_target(x) {}
  39. std::pair<double, double> operator()(double x)
  40. {
  41. return std::make_pair(x * x * x - m_target, 3 * x * x);
  42. }
  43. private:
  44. double m_target;
  45. };
  46. #ifndef BOOST_NO_CXX11_HDR_TUPLE
  47. struct cbtr_functor_2b
  48. {
  49. cbtr_functor_2b(double x) : m_target(x) {}
  50. std::tuple<double, double> operator()(double x)
  51. {
  52. return std::tuple<double, double>(x * x * x - m_target, 3 * x * x);
  53. }
  54. private:
  55. double m_target;
  56. };
  57. #endif
  58. struct cbtr_functor_2c
  59. {
  60. cbtr_functor_2c(double x) : m_target(x) {}
  61. boost::tuple<double, double> operator()(double x)
  62. {
  63. return boost::tuple<double, double>(x * x * x - m_target, 3 * x * x);
  64. }
  65. private:
  66. double m_target;
  67. };
  68. struct cbtr_functor_2d
  69. {
  70. cbtr_functor_2d(double x) : m_target(x) {}
  71. boost::fusion::tuple<double, double> operator()(double x)
  72. {
  73. return boost::fusion::tuple<double, double>(x * x * x - m_target, 3 * x * x);
  74. }
  75. private:
  76. double m_target;
  77. };
  78. #ifndef BOOST_NO_CXX11_HDR_TUPLE
  79. struct cbtr_functor_3b
  80. {
  81. cbtr_functor_3b(double x) : m_target(x) {}
  82. std::tuple<double, double, double> operator()(double x)
  83. {
  84. return std::tuple<double, double, double>(x * x * x - m_target, 3 * x * x, 6 * x);
  85. }
  86. private:
  87. double m_target;
  88. };
  89. #endif
  90. struct cbtr_functor_3c
  91. {
  92. cbtr_functor_3c(double x) : m_target(x) {}
  93. boost::tuple<double, double, double> operator()(double x)
  94. {
  95. return boost::tuple<double, double, double>(x * x * x - m_target, 3 * x * x, 6 * x);
  96. }
  97. private:
  98. double m_target;
  99. };
  100. struct cbtr_functor_3d
  101. {
  102. cbtr_functor_3d(double x) : m_target(x) {}
  103. boost::fusion::tuple<double, double, double> operator()(double x)
  104. {
  105. return boost::fusion::tuple<double, double, double>(x * x * x - m_target, 3 * x * x, 6 * x);
  106. }
  107. private:
  108. double m_target;
  109. };
  110. BOOST_AUTO_TEST_CASE( test_main )
  111. {
  112. double x = 27;
  113. double expected = 3;
  114. double result;
  115. double tolerance = std::numeric_limits<double>::epsilon() * 5;
  116. std::pair<double, double> p;
  117. //
  118. // Start by trying the unary functors, bisect first:
  119. //
  120. cbtr_functor_1 f1(x);
  121. boost::math::tools::eps_tolerance<double> t(std::numeric_limits<double>::digits - 1);
  122. p = boost::math::tools::bisect(f1, 0.0, x, t);
  123. result = (p.first + p.second) / 2;
  124. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  125. //
  126. // bracket_and_solve_root:
  127. //
  128. boost::uintmax_t max_iter = boost::math::policies::get_max_root_iterations<boost::math::policies::policy<> >();
  129. p = boost::math::tools::bracket_and_solve_root(f1, x, 2.0, true, t, max_iter);
  130. result = (p.first + p.second) / 2;
  131. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  132. //
  133. // toms748_solve:
  134. //
  135. max_iter = boost::math::policies::get_max_root_iterations<boost::math::policies::policy<> >();
  136. p = boost::math::tools::toms748_solve(f1, 0.0, x, t, max_iter);
  137. result = (p.first + p.second) / 2;
  138. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  139. #ifndef BOOST_NO_CXX11_LAMBDAS
  140. //
  141. // Now try again with C++11 lambda's
  142. //
  143. p = boost::math::tools::bisect([x](double z){ return z * z * z - x; }, 0.0, x, t);
  144. result = (p.first + p.second) / 2;
  145. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  146. //
  147. // bracket_and_solve_root:
  148. //
  149. max_iter = boost::math::policies::get_max_root_iterations<boost::math::policies::policy<> >();
  150. p = boost::math::tools::bracket_and_solve_root([x](double z){ return z * z * z - x; }, x, 2.0, true, t, max_iter);
  151. result = (p.first + p.second) / 2;
  152. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  153. //
  154. // toms748_solve:
  155. //
  156. max_iter = boost::math::policies::get_max_root_iterations<boost::math::policies::policy<> >();
  157. p = boost::math::tools::toms748_solve([x](double z){ return z * z * z - x; }, 0.0, x, t, max_iter);
  158. result = (p.first + p.second) / 2;
  159. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  160. #endif
  161. cbtr_functor_2a f2(x);
  162. #ifndef BOOST_NO_CXX11_HDR_TUPLE
  163. cbtr_functor_2b f3(x);
  164. #endif
  165. cbtr_functor_2c f4(x);
  166. cbtr_functor_2d f5(x);
  167. //
  168. // Binary Functors - newton_raphson_iterate - test each possible tuple type:
  169. //
  170. #ifndef BOOST_NO_CXX11_HDR_TUPLE
  171. result = boost::math::tools::newton_raphson_iterate(f2, x, 0.0, x, std::numeric_limits<double>::digits - 1);
  172. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  173. result = boost::math::tools::newton_raphson_iterate(f3, x, 0.0, x, std::numeric_limits<double>::digits - 1);
  174. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  175. #endif
  176. result = boost::math::tools::newton_raphson_iterate(f4, x, 0.0, x, std::numeric_limits<double>::digits - 1);
  177. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  178. result = boost::math::tools::newton_raphson_iterate(f5, x, 0.0, x, std::numeric_limits<double>::digits - 1);
  179. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  180. //
  181. // And again but with lambdas:
  182. //
  183. #ifndef BOOST_NO_CXX11_LAMBDAS
  184. result = boost::math::tools::newton_raphson_iterate([x](double z){ return std::make_pair(z * z * z - x, 3 * z * z); }, x, 0.0, x, std::numeric_limits<double>::digits - 1);
  185. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  186. #ifndef BOOST_NO_CXX11_HDR_TUPLE
  187. result = boost::math::tools::newton_raphson_iterate([x](double z){ return std::make_tuple(z * z * z - x, 3 * z * z); }, x, 0.0, x, std::numeric_limits<double>::digits - 1);
  188. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  189. #endif
  190. result = boost::math::tools::newton_raphson_iterate([x](double z){ return boost::tuple<double, double>(z * z * z - x, 3 * z * z); }, x, 0.0, x, std::numeric_limits<double>::digits - 1);
  191. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  192. result = boost::math::tools::newton_raphson_iterate([x](double z){ return boost::fusion::tuple<double, double>(z * z * z - x, 3 * z * z); }, x, 0.0, x, std::numeric_limits<double>::digits - 1);
  193. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  194. #endif
  195. #ifndef BOOST_NO_CXX11_HDR_TUPLE
  196. cbtr_functor_3b f6(x);
  197. #endif
  198. cbtr_functor_3c f7(x);
  199. cbtr_functor_3d f8(x);
  200. //
  201. // Ternary functors:
  202. //
  203. #ifndef BOOST_NO_CXX11_HDR_TUPLE
  204. result = boost::math::tools::halley_iterate(f6, x, 0.0, x, std::numeric_limits<double>::digits - 1);
  205. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  206. #endif
  207. result = boost::math::tools::halley_iterate(f7, x, 0.0, x, std::numeric_limits<double>::digits - 1);
  208. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  209. result = boost::math::tools::halley_iterate(f8, x, 0.0, x, std::numeric_limits<double>::digits - 1);
  210. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  211. #ifndef BOOST_NO_CXX11_LAMBDAS
  212. #ifndef BOOST_NO_CXX11_HDR_TUPLE
  213. result = boost::math::tools::halley_iterate([x](double z){ return std::make_tuple(z * z * z - x, 3 * z * z, 6 * z); }, x, 0.0, x, std::numeric_limits<double>::digits - 1);
  214. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  215. #endif
  216. result = boost::math::tools::halley_iterate([x](double z){ return boost::tuple<double, double, double>(z * z * z - x, 3 * z * z, 6 * z); }, x, 0.0, x, std::numeric_limits<double>::digits - 1);
  217. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  218. result = boost::math::tools::halley_iterate([x](double z){ return boost::fusion::tuple<double, double, double>(z * z * z - x, 3 * z * z, 6 * z); }, x, 0.0, x, std::numeric_limits<double>::digits - 1);
  219. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  220. #endif
  221. #ifndef BOOST_NO_CXX11_HDR_TUPLE
  222. result = boost::math::tools::schroder_iterate(f6, x, 0.0, x, std::numeric_limits<double>::digits - 1);
  223. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  224. #endif
  225. result = boost::math::tools::schroder_iterate(f7, x, 0.0, x, std::numeric_limits<double>::digits - 1);
  226. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  227. result = boost::math::tools::schroder_iterate(f8, x, 0.0, x, std::numeric_limits<double>::digits - 1);
  228. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  229. #ifndef BOOST_NO_CXX11_LAMBDAS
  230. #ifndef BOOST_NO_CXX11_HDR_TUPLE
  231. result = boost::math::tools::schroder_iterate([x](double z){ return std::make_tuple(z * z * z - x, 3 * z * z, 6 * z); }, x, 0.0, x, std::numeric_limits<double>::digits - 1);
  232. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  233. #endif
  234. result = boost::math::tools::schroder_iterate([x](double z){ return boost::tuple<double, double, double>(z * z * z - x, 3 * z * z, 6 * z); }, x, 0.0, x, std::numeric_limits<double>::digits - 1);
  235. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  236. result = boost::math::tools::schroder_iterate([x](double z){ return boost::fusion::tuple<double, double, double>(z * z * z - x, 3 * z * z, 6 * z); }, x, 0.0, x, std::numeric_limits<double>::digits - 1);
  237. BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
  238. #endif
  239. } // BOOST_AUTO_TEST_CASE( test_main )