1 // Copyright John Maddock 2014
3 // Use, modification and distribution are subject to the
4 // Boost Software License, Version 1.0.
5 // (See accompanying file LICENSE_1_0.txt
6 // or copy at http://www.boost.org/LICENSE_1_0.txt)
8 #define BOOST_TEST_MAIN
9 #include <boost/test/unit_test.hpp> // Boost.Test
10 #include <boost/test/results_collector.hpp>
11 #include <boost/test/unit_test.hpp>
12 #include <boost/test/tools/floating_point_comparison.hpp>
13 #include <boost/tuple/tuple.hpp>
14 #include <boost/fusion/include/tuple.hpp>
15 #include <boost/fusion/include/std_pair.hpp>
16 #ifndef BOOST_NO_CXX11_HDR_TUPLE
24 using std::setprecision;
26 #include <boost/math/tools/roots.hpp>
29 // We'll use cbrt as an example:
33 cbtr_functor_1(double x) : m_target(x) {}
34 double operator()(double x)
36 return x * x * x - m_target;
42 struct cbtr_functor_2a
44 cbtr_functor_2a(double x) : m_target(x) {}
45 std::pair<double, double> operator()(double x)
47 return std::make_pair(x * x * x - m_target, 3 * x * x);
52 #ifndef BOOST_NO_CXX11_HDR_TUPLE
53 struct cbtr_functor_2b
55 cbtr_functor_2b(double x) : m_target(x) {}
56 std::tuple<double, double> operator()(double x)
58 return std::tuple<double, double>(x * x * x - m_target, 3 * x * x);
64 struct cbtr_functor_2c
66 cbtr_functor_2c(double x) : m_target(x) {}
67 boost::tuple<double, double> operator()(double x)
69 return boost::tuple<double, double>(x * x * x - m_target, 3 * x * x);
74 struct cbtr_functor_2d
76 cbtr_functor_2d(double x) : m_target(x) {}
77 boost::fusion::tuple<double, double> operator()(double x)
79 return boost::fusion::tuple<double, double>(x * x * x - m_target, 3 * x * x);
85 #ifndef BOOST_NO_CXX11_HDR_TUPLE
86 struct cbtr_functor_3b
88 cbtr_functor_3b(double x) : m_target(x) {}
89 std::tuple<double, double, double> operator()(double x)
91 return std::tuple<double, double, double>(x * x * x - m_target, 3 * x * x, 6 * x);
97 struct cbtr_functor_3c
99 cbtr_functor_3c(double x) : m_target(x) {}
100 boost::tuple<double, double, double> operator()(double x)
102 return boost::tuple<double, double, double>(x * x * x - m_target, 3 * x * x, 6 * x);
107 struct cbtr_functor_3d
109 cbtr_functor_3d(double x) : m_target(x) {}
110 boost::fusion::tuple<double, double, double> operator()(double x)
112 return boost::fusion::tuple<double, double, double>(x * x * x - m_target, 3 * x * x, 6 * x);
119 BOOST_AUTO_TEST_CASE( test_main )
124 double tolerance = std::numeric_limits<double>::epsilon() * 5;
125 std::pair<double, double> p;
127 // Start by trying the unary functors, bisect first:
129 cbtr_functor_1 f1(x);
130 boost::math::tools::eps_tolerance<double> t(std::numeric_limits<double>::digits - 1);
131 p = boost::math::tools::bisect(f1, 0.0, x, t);
132 result = (p.first + p.second) / 2;
133 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
135 // bracket_and_solve_root:
137 boost::uintmax_t max_iter = boost::math::policies::get_max_root_iterations<boost::math::policies::policy<> >();
138 p = boost::math::tools::bracket_and_solve_root(f1, x, 2.0, true, t, max_iter);
139 result = (p.first + p.second) / 2;
140 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
144 max_iter = boost::math::policies::get_max_root_iterations<boost::math::policies::policy<> >();
145 p = boost::math::tools::toms748_solve(f1, 0.0, x, t, max_iter);
146 result = (p.first + p.second) / 2;
147 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
149 #ifndef BOOST_NO_CXX11_LAMBDAS
151 // Now try again with C++11 lambda's
153 p = boost::math::tools::bisect([x](double z){ return z * z * z - x; }, 0.0, x, t);
154 result = (p.first + p.second) / 2;
155 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
157 // bracket_and_solve_root:
159 max_iter = boost::math::policies::get_max_root_iterations<boost::math::policies::policy<> >();
160 p = boost::math::tools::bracket_and_solve_root([x](double z){ return z * z * z - x; }, x, 2.0, true, t, max_iter);
161 result = (p.first + p.second) / 2;
162 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
166 max_iter = boost::math::policies::get_max_root_iterations<boost::math::policies::policy<> >();
167 p = boost::math::tools::toms748_solve([x](double z){ return z * z * z - x; }, 0.0, x, t, max_iter);
168 result = (p.first + p.second) / 2;
169 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
172 cbtr_functor_2a f2(x);
173 #ifndef BOOST_NO_CXX11_HDR_TUPLE
174 cbtr_functor_2b f3(x);
176 cbtr_functor_2c f4(x);
177 cbtr_functor_2d f5(x);
180 // Binary Functors - newton_raphson_iterate - test each possible tuple type:
182 #ifndef BOOST_NO_CXX11_HDR_TUPLE
183 result = boost::math::tools::newton_raphson_iterate(f2, x, 0.0, x, std::numeric_limits<double>::digits - 1);
184 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
185 result = boost::math::tools::newton_raphson_iterate(f3, x, 0.0, x, std::numeric_limits<double>::digits - 1);
186 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
188 result = boost::math::tools::newton_raphson_iterate(f4, x, 0.0, x, std::numeric_limits<double>::digits - 1);
189 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
190 result = boost::math::tools::newton_raphson_iterate(f5, x, 0.0, x, std::numeric_limits<double>::digits - 1);
191 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
193 // And again but with lambdas:
195 #ifndef BOOST_NO_CXX11_LAMBDAS
196 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);
197 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
198 #ifndef BOOST_NO_CXX11_HDR_TUPLE
199 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);
200 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
202 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);
203 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
204 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);
205 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
208 #ifndef BOOST_NO_CXX11_HDR_TUPLE
209 cbtr_functor_3b f6(x);
211 cbtr_functor_3c f7(x);
212 cbtr_functor_3d f8(x);
217 #ifndef BOOST_NO_CXX11_HDR_TUPLE
218 result = boost::math::tools::halley_iterate(f6, x, 0.0, x, std::numeric_limits<double>::digits - 1);
219 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
221 result = boost::math::tools::halley_iterate(f7, x, 0.0, x, std::numeric_limits<double>::digits - 1);
222 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
223 result = boost::math::tools::halley_iterate(f8, x, 0.0, x, std::numeric_limits<double>::digits - 1);
224 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
225 #ifndef BOOST_NO_CXX11_LAMBDAS
226 #ifndef BOOST_NO_CXX11_HDR_TUPLE
227 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);
228 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
230 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);
231 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
232 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);
233 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
235 #ifndef BOOST_NO_CXX11_HDR_TUPLE
236 result = boost::math::tools::schroder_iterate(f6, x, 0.0, x, std::numeric_limits<double>::digits - 1);
237 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
239 result = boost::math::tools::schroder_iterate(f7, x, 0.0, x, std::numeric_limits<double>::digits - 1);
240 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
241 result = boost::math::tools::schroder_iterate(f8, x, 0.0, x, std::numeric_limits<double>::digits - 1);
242 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
243 #ifndef BOOST_NO_CXX11_LAMBDAS
244 #ifndef BOOST_NO_CXX11_HDR_TUPLE
245 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);
246 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
248 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);
249 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
250 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);
251 BOOST_CHECK_CLOSE_FRACTION(expected, result, tolerance);
253 } // BOOST_AUTO_TEST_CASE( test_main )