]> git.donarmstrong.com Git - rsem.git/blobdiff - boost/math/tools/roots.hpp
Updated boost to v1.55.0
[rsem.git] / boost / math / tools / roots.hpp
index ce0cfe0b8403b3c2a40cc5308db96d5d1fd38449..7ef7d9951867848df88fa0e015e9fbd9ed3ea43e 100644 (file)
@@ -14,7 +14,6 @@
 #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>
@@ -24,7 +23,7 @@
 #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
@@ -39,7 +38,7 @@ namespace detail{
 
 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,
@@ -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))