#include <boost/config/no_tr1/cmath.hpp>
#include <stdexcept>
-#include <boost/tr1/tuple.hpp>
#include <boost/math/tools/config.hpp>
#include <boost/cstdint.hpp>
#include <boost/assert.hpp>
#pragma warning(push)
#pragma warning(disable: 4512)
#endif
-#include <boost/tr1/tuple.hpp>
+#include <boost/math/tools/tuple.hpp>
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
template <class Tuple, class T>
inline void unpack_0(const Tuple& t, T& val)
-{ val = std::tr1::get<0>(t); }
+{ val = boost::math::get<0>(t); }
template <class F, class T>
void handle_zero_derivative(F f,
guess = min;
}
unpack_0(f(guess), last_f0);
- //last_f0 = std::tr1::get<0>(f(guess));
delta = guess - result;
}
if(sign(last_f0) * sign(f0) < 0)
last_f0 = f0;
delta2 = delta1;
delta1 = delta;
- std::tr1::tie(f0, f1) = f(result);
+ boost::math::tie(f0, f1) = f(result);
if(0 == f0)
break;
if(f1 == 0)
last_f0 = f0;
delta2 = delta1;
delta1 = delta;
- std::tr1::tie(f0, f1, f2) = f(result);
+ boost::math::tie(f0, f1, f2) = f(result);
BOOST_MATH_INSTRUMENT_VARIABLE(f0);
BOOST_MATH_INSTRUMENT_VARIABLE(f1);
delta = denom / num;
if(delta * f1 / f0 < 0)
{
- // probably cancellation error, try a Newton step instead:
+ // Oh dear, we have a problem as Newton and Halley steps
+ // disagree about which way we should move. Probably
+ // there is cancelation error in the calculation of the
+ // Halley step, or else the derivatives are so small
+ // that their values are basically trash. We will move
+ // in the direction indicated by a Newton step, but
+ // by no more than twice the current guess value, otherwise
+ // we can jump way out of bounds if we're not careful.
+ // See https://svn.boost.org/trac/boost/ticket/8314.
delta = f0 / f1;
+ if(fabs(delta) > 2 * fabs(guess))
+ delta = (delta < 0 ? -1 : 1) * 2 * fabs(guess);
}
}
else
last_f0 = f0;
delta2 = delta1;
delta1 = delta;
- std::tr1::tie(f0, f1, f2) = f(result);
+ boost::math::tie(f0, f1, f2) = f(result);
if(0 == f0)
break;
if((f1 == 0) && (f2 == 0))