X-Git-Url: https://git.donarmstrong.com/?p=rsem.git;a=blobdiff_plain;f=boost%2Fmath%2Ftools%2Froots.hpp;h=7ef7d9951867848df88fa0e015e9fbd9ed3ea43e;hp=ce0cfe0b8403b3c2a40cc5308db96d5d1fd38449;hb=2d71eb92104693ca9baa5a2e1c23eeca776d8fd3;hpb=a95154919f950f86de9104b2b9dcf1f0c7e83387 diff --git a/boost/math/tools/roots.hpp b/boost/math/tools/roots.hpp index ce0cfe0..7ef7d99 100644 --- a/boost/math/tools/roots.hpp +++ b/boost/math/tools/roots.hpp @@ -14,7 +14,6 @@ #include #include -#include #include #include #include @@ -24,7 +23,7 @@ #pragma warning(push) #pragma warning(disable: 4512) #endif -#include +#include #ifdef BOOST_MSVC #pragma warning(pop) #endif @@ -39,7 +38,7 @@ namespace detail{ template inline void unpack_0(const Tuple& t, T& val) -{ val = std::tr1::get<0>(t); } +{ val = boost::math::get<0>(t); } template void handle_zero_derivative(F f, @@ -64,7 +63,6 @@ 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) @@ -201,7 +199,7 @@ T newton_raphson_iterate(F f, T guess, T min, T max, int digits, boost::uintmax_ 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) @@ -296,7 +294,7 @@ T halley_iterate(F f, T guess, T min, T max, int digits, boost::uintmax_t& max_i 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); @@ -331,8 +329,18 @@ T halley_iterate(F f, T guess, T min, T max, int digits, boost::uintmax_t& max_i 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 @@ -446,7 +454,7 @@ T schroeder_iterate(F f, T guess, T min, T max, int digits, boost::uintmax_t& ma 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))