summaryrefslogtreecommitdiff
path: root/boost/math/tools/toms748_solve.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/math/tools/toms748_solve.hpp')
-rw-r--r--boost/math/tools/toms748_solve.hpp50
1 files changed, 37 insertions, 13 deletions
diff --git a/boost/math/tools/toms748_solve.hpp b/boost/math/tools/toms748_solve.hpp
index f0c42324e8..48737a821a 100644
--- a/boost/math/tools/toms748_solve.hpp
+++ b/boost/math/tools/toms748_solve.hpp
@@ -17,6 +17,14 @@
#include <boost/cstdint.hpp>
#include <limits>
+#ifdef BOOST_MATH_LOG_ROOT_ITERATIONS
+# define BOOST_MATH_LOGGER_INCLUDE <boost/math/tools/iteration_logger.hpp>
+# include BOOST_MATH_LOGGER_INCLUDE
+# undef BOOST_MATH_LOGGER_INCLUDE
+#else
+# define BOOST_MATH_LOG_COUNT(count)
+#endif
+
namespace boost{ namespace math{ namespace tools{
template <class T>
@@ -197,7 +205,7 @@ T quadratic_interpolate(const T& a, const T& b, T const& d,
T A = safe_div(T(fd - fb), T(d - b), tools::max_value<T>());
A = safe_div(T(A - B), T(d - a), T(0));
- if(a == 0)
+ if(A == 0)
{
// failure to determine coefficients, try a secant step:
return secant_interpolate(a, b, fa, fb);
@@ -298,9 +306,9 @@ std::pair<T, T> toms748_solve(F f, const T& ax, const T& bx, const T& fax, const
a = ax;
b = bx;
if(a >= b)
- policies::raise_domain_error(
+ return boost::math::detail::pair_from_single(policies::raise_domain_error(
function,
- "Parameters a and b out of order: a=%1%", a, pol);
+ "Parameters a and b out of order: a=%1%", a, pol));
fa = fax;
fb = fbx;
@@ -315,9 +323,9 @@ std::pair<T, T> toms748_solve(F f, const T& ax, const T& bx, const T& fax, const
}
if(boost::math::sign(fa) * boost::math::sign(fb) > 0)
- policies::raise_domain_error(
+ return boost::math::detail::pair_from_single(policies::raise_domain_error(
function,
- "Parameters a and b do not bracket the root: a=%1%", a, pol);
+ "Parameters a and b do not bracket the root: a=%1%", a, pol));
// dummy value for fd, e and fe:
fe = e = fd = 1e5F;
@@ -452,6 +460,7 @@ std::pair<T, T> toms748_solve(F f, const T& ax, const T& bx, const T& fax, const
{
a = b;
}
+ BOOST_MATH_LOG_COUNT(max_iter)
return std::make_pair(a, b);
}
@@ -493,6 +502,8 @@ std::pair<T, T> bracket_and_solve_root(F f, const T& guess, T factor, bool risin
//
boost::uintmax_t count = max_iter - 1;
+ int step = 32;
+
if((fa < 0) == (guess < 0 ? !rising : rising))
{
//
@@ -502,13 +513,19 @@ std::pair<T, T> bracket_and_solve_root(F f, const T& guess, T factor, bool risin
while((boost::math::sign)(fb) == (boost::math::sign)(fa))
{
if(count == 0)
- policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", b, pol);
+ return boost::math::detail::pair_from_single(policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", b, pol));
//
- // Heuristic: every 20 iterations we double the growth factor in case the
- // initial guess was *really* bad !
+ // Heuristic: normally it's best not to increase the step sizes as we'll just end up
+ // with a really wide range to search for the root. However, if the initial guess was *really*
+ // bad then we need to speed up the search otherwise we'll take forever if we're orders of
+ // magnitude out. This happens most often if the guess is a small value (say 1) and the result
+ // we're looking for is close to std::numeric_limits<T>::min().
//
- if((max_iter - count) % 20 == 0)
+ if((max_iter - count) % step == 0)
+ {
factor *= 2;
+ if(step > 1) step /= 2;
+ }
//
// Now go ahead and move our guess by "factor":
//
@@ -536,13 +553,19 @@ std::pair<T, T> bracket_and_solve_root(F f, const T& guess, T factor, bool risin
return a > 0 ? std::make_pair(T(0), T(a)) : std::make_pair(T(a), T(0));
}
if(count == 0)
- policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", a, pol);
+ return boost::math::detail::pair_from_single(policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", a, pol));
//
- // Heuristic: every 20 iterations we double the growth factor in case the
- // initial guess was *really* bad !
+ // Heuristic: normally it's best not to increase the step sizes as we'll just end up
+ // with a really wide range to search for the root. However, if the initial guess was *really*
+ // bad then we need to speed up the search otherwise we'll take forever if we're orders of
+ // magnitude out. This happens most often if the guess is a small value (say 1) and the result
+ // we're looking for is close to std::numeric_limits<T>::min().
//
- if((max_iter - count) % 20 == 0)
+ if((max_iter - count) % step == 0)
+ {
factor *= 2;
+ if(step > 1) step /= 2;
+ }
//
// Now go ahead and move are guess by "factor":
//
@@ -567,6 +590,7 @@ std::pair<T, T> bracket_and_solve_root(F f, const T& guess, T factor, bool risin
pol);
max_iter += count;
BOOST_MATH_INSTRUMENT_CODE("max_iter = " << max_iter << " count = " << count);
+ BOOST_MATH_LOG_COUNT(max_iter)
return r;
}