]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/math/test/test_root_iterations.cpp
1 // (C) Copyright John Maddock 2015.
2 // Use, modification and distribution are subject to the
3 // Boost Software License, Version 1.0. (See accompanying file
4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 #ifndef BOOST_NO_CXX11_HDR_TUPLE
10 #define BOOST_TEST_MAIN
11 #include <boost/test/unit_test.hpp>
12 #include <boost/test/floating_point_comparison.hpp>
13 #include <boost/math/tools/roots.hpp>
14 #include <boost/test/results_collector.hpp>
15 #include <boost/test/unit_test.hpp>
16 #include <boost/math/special_functions/cbrt.hpp>
21 // No derivatives - using TOMS748 internally.
22 struct cbrt_functor_noderiv
23 { // cube root of x using only function - no derivatives.
24 cbrt_functor_noderiv ( double to_find_root_of
) : a ( to_find_root_of
)
25 { // Constructor just stores value a to find root of.
27 double operator ()( double x
)
29 double fx
= x
* x
* x
- a
; // Difference (estimate x^3 - a).
33 double a
; // to be 'cube_rooted'.
34 }; // template <class T> struct cbrt_functor_noderiv
36 // Using 1st derivative only Newton-Raphson
37 struct cbrt_functor_deriv
38 { // Functor also returning 1st derviative.
39 cbrt_functor_deriv ( double const & to_find_root_of
) : a ( to_find_root_of
)
40 { // Constructor stores value a to find root of,
41 // for example: calling cbrt_functor_deriv<double>(x) to use to get cube root of x.
43 std :: pair
< double , double > operator ()( double const & x
)
44 { // Return both f(x) and f'(x).
45 double fx
= x
* x
* x
- a
; // Difference (estimate x^3 - value).
46 double dx
= 3 * x
* x
; // 1st derivative = 3x^2.
47 return std :: make_pair ( fx
, dx
); // 'return' both fx and dx.
50 double a
; // to be 'cube_rooted'.
52 // Using 1st and 2nd derivatives with Halley algorithm.
53 struct cbrt_functor_2deriv
54 { // Functor returning both 1st and 2nd derivatives.
55 cbrt_functor_2deriv ( double const & to_find_root_of
) : a ( to_find_root_of
)
56 { // Constructor stores value a to find root of, for example:
57 // calling cbrt_functor_2deriv<double>(x) to get cube root of x,
59 std :: tuple
< double , double , double > operator ()( double const & x
)
60 { // Return both f(x) and f'(x) and f''(x).
61 double fx
= x
* x
* x
- a
; // Difference (estimate x^3 - value).
62 double dx
= 3 * x
* x
; // 1st derivative = 3x^2.
63 double d2x
= 6 * x
; // 2nd derivative = 6x.
64 return std :: make_tuple ( fx
, dx
, d2x
); // 'return' fx, dx and d2x.
67 double a
; // to be 'cube_rooted'.
70 BOOST_AUTO_TEST_CASE ( test_main
)
72 int newton_limits
= static_cast < int >( std :: numeric_limits
< double >:: digits
* 0.6 );
77 double result
= boost :: math :: cbrt ( arg
);
79 // Start with a really bad guess 5 times below the result:
81 double guess
= result
/ 5 ;
82 boost :: uintmax_t iters
= 1000 ;
84 std :: pair
< double , double > r
= boost :: math :: tools :: bracket_and_solve_root ( cbrt_functor_noderiv ( arg
), guess
, 2.0 , true , boost :: math :: tools :: eps_tolerance
< double >(), iters
);
85 BOOST_CHECK_CLOSE_FRACTION (( r
. first
+ r
. second
) / 2 , result
, std :: numeric_limits
< double >:: epsilon () * 4 );
86 BOOST_CHECK_LE ( iters
, 14 );
89 double dr
= boost :: math :: tools :: newton_raphson_iterate ( cbrt_functor_deriv ( arg
), guess
, guess
/ 2 , result
* 10 , newton_limits
, iters
);
90 BOOST_CHECK_CLOSE_FRACTION ( dr
, result
, std :: numeric_limits
< double >:: epsilon () * 2 );
91 BOOST_CHECK_LE ( iters
, 12 );
94 dr
= boost :: math :: tools :: halley_iterate ( cbrt_functor_2deriv ( arg
), guess
, result
/ 10 , result
* 10 , newton_limits
, iters
);
95 BOOST_CHECK_CLOSE_FRACTION ( dr
, result
, std :: numeric_limits
< double >:: epsilon () * 2 );
96 BOOST_CHECK_LE ( iters
, 7 );
99 dr
= boost :: math :: tools :: schroder_iterate ( cbrt_functor_2deriv ( arg
), guess
, result
/ 10 , result
* 10 , newton_limits
, iters
);
100 BOOST_CHECK_CLOSE_FRACTION ( dr
, result
, std :: numeric_limits
< double >:: epsilon () * 2 );
101 BOOST_CHECK_LE ( iters
, 11 );
103 // Over again with a bad guess 5 times larger than the result:
107 r
= boost :: math :: tools :: bracket_and_solve_root ( cbrt_functor_noderiv ( arg
), guess
, 2.0 , true , boost :: math :: tools :: eps_tolerance
< double >(), iters
);
108 BOOST_CHECK_CLOSE_FRACTION (( r
. first
+ r
. second
) / 2 , result
, std :: numeric_limits
< double >:: epsilon () * 4 );
109 BOOST_CHECK_LE ( iters
, 14 );
112 dr
= boost :: math :: tools :: newton_raphson_iterate ( cbrt_functor_deriv ( arg
), guess
, result
/ 10 , result
* 10 , newton_limits
, iters
);
113 BOOST_CHECK_CLOSE_FRACTION ( dr
, result
, std :: numeric_limits
< double >:: epsilon () * 2 );
114 BOOST_CHECK_LE ( iters
, 12 );
117 dr
= boost :: math :: tools :: halley_iterate ( cbrt_functor_2deriv ( arg
), guess
, result
/ 10 , result
* 10 , newton_limits
, iters
);
118 BOOST_CHECK_CLOSE_FRACTION ( dr
, result
, std :: numeric_limits
< double >:: epsilon () * 2 );
119 BOOST_CHECK_LE ( iters
, 7 );
122 dr
= boost :: math :: tools :: schroder_iterate ( cbrt_functor_2deriv ( arg
), guess
, result
/ 10 , result
* 10 , newton_limits
, iters
);
123 BOOST_CHECK_CLOSE_FRACTION ( dr
, result
, std :: numeric_limits
< double >:: epsilon () * 2 );
124 BOOST_CHECK_LE ( iters
, 11 );
126 // A much better guess, 1% below result:
129 guess
= result
* 0.9 ;
130 r
= boost :: math :: tools :: bracket_and_solve_root ( cbrt_functor_noderiv ( arg
), guess
, 2.0 , true , boost :: math :: tools :: eps_tolerance
< double >(), iters
);
131 BOOST_CHECK_CLOSE_FRACTION (( r
. first
+ r
. second
) / 2 , result
, std :: numeric_limits
< double >:: epsilon () * 4 );
132 BOOST_CHECK_LE ( iters
, 12 );
135 dr
= boost :: math :: tools :: newton_raphson_iterate ( cbrt_functor_deriv ( arg
), guess
, result
/ 10 , result
* 10 , newton_limits
, iters
);
136 BOOST_CHECK_CLOSE_FRACTION ( dr
, result
, std :: numeric_limits
< double >:: epsilon () * 2 );
137 BOOST_CHECK_LE ( iters
, 5 );
140 dr
= boost :: math :: tools :: halley_iterate ( cbrt_functor_2deriv ( arg
), guess
, result
/ 10 , result
* 10 , newton_limits
, iters
);
141 BOOST_CHECK_CLOSE_FRACTION ( dr
, result
, std :: numeric_limits
< double >:: epsilon () * 2 );
142 BOOST_CHECK_LE ( iters
, 3 );
145 dr
= boost :: math :: tools :: schroder_iterate ( cbrt_functor_2deriv ( arg
), guess
, result
/ 10 , result
* 10 , newton_limits
, iters
);
146 BOOST_CHECK_CLOSE_FRACTION ( dr
, result
, std :: numeric_limits
< double >:: epsilon () * 2 );
147 BOOST_CHECK_LE ( iters
, 4 );
149 // A much better guess, 1% above result:
152 guess
= result
* 1.1 ;
153 r
= boost :: math :: tools :: bracket_and_solve_root ( cbrt_functor_noderiv ( arg
), guess
, 2.0 , true , boost :: math :: tools :: eps_tolerance
< double >(), iters
);
154 BOOST_CHECK_CLOSE_FRACTION (( r
. first
+ r
. second
) / 2 , result
, std :: numeric_limits
< double >:: epsilon () * 4 );
155 BOOST_CHECK_LE ( iters
, 12 );
158 dr
= boost :: math :: tools :: newton_raphson_iterate ( cbrt_functor_deriv ( arg
), guess
, result
/ 10 , result
* 10 , newton_limits
, iters
);
159 BOOST_CHECK_CLOSE_FRACTION ( dr
, result
, std :: numeric_limits
< double >:: epsilon () * 2 );
160 BOOST_CHECK_LE ( iters
, 5 );
163 dr
= boost :: math :: tools :: halley_iterate ( cbrt_functor_2deriv ( arg
), guess
, result
/ 10 , result
* 10 , newton_limits
, iters
);
164 BOOST_CHECK_CLOSE_FRACTION ( dr
, result
, std :: numeric_limits
< double >:: epsilon () * 2 );
165 BOOST_CHECK_LE ( iters
, 3 );
168 dr
= boost :: math :: tools :: schroder_iterate ( cbrt_functor_2deriv ( arg
), guess
, result
/ 10 , result
* 10 , newton_limits
, iters
);
169 BOOST_CHECK_CLOSE_FRACTION ( dr
, result
, std :: numeric_limits
< double >:: epsilon () * 2 );
170 BOOST_CHECK_LE ( iters
, 4 );
178 int main () { return 0 ; }