annotate DEPENDENCIES/generic/include/boost/math/tools/toms748_solve.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
rev   line source
Chris@16 1 // (C) Copyright John Maddock 2006.
Chris@16 2 // Use, modification and distribution are subject to the
Chris@16 3 // Boost Software License, Version 1.0. (See accompanying file
Chris@16 4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 5
Chris@16 6 #ifndef BOOST_MATH_TOOLS_SOLVE_ROOT_HPP
Chris@16 7 #define BOOST_MATH_TOOLS_SOLVE_ROOT_HPP
Chris@16 8
Chris@16 9 #ifdef _MSC_VER
Chris@16 10 #pragma once
Chris@16 11 #endif
Chris@16 12
Chris@16 13 #include <boost/math/tools/precision.hpp>
Chris@16 14 #include <boost/math/policies/error_handling.hpp>
Chris@16 15 #include <boost/math/tools/config.hpp>
Chris@16 16 #include <boost/math/special_functions/sign.hpp>
Chris@16 17 #include <boost/cstdint.hpp>
Chris@16 18 #include <limits>
Chris@16 19
Chris@16 20 namespace boost{ namespace math{ namespace tools{
Chris@16 21
Chris@16 22 template <class T>
Chris@16 23 class eps_tolerance
Chris@16 24 {
Chris@16 25 public:
Chris@16 26 eps_tolerance(unsigned bits)
Chris@16 27 {
Chris@16 28 BOOST_MATH_STD_USING
Chris@16 29 eps = (std::max)(T(ldexp(1.0F, 1-bits)), T(4 * tools::epsilon<T>()));
Chris@16 30 }
Chris@16 31 bool operator()(const T& a, const T& b)
Chris@16 32 {
Chris@16 33 BOOST_MATH_STD_USING
Chris@16 34 return fabs(a - b) <= (eps * (std::min)(fabs(a), fabs(b)));
Chris@16 35 }
Chris@16 36 private:
Chris@16 37 T eps;
Chris@16 38 };
Chris@16 39
Chris@16 40 struct equal_floor
Chris@16 41 {
Chris@16 42 equal_floor(){}
Chris@16 43 template <class T>
Chris@16 44 bool operator()(const T& a, const T& b)
Chris@16 45 {
Chris@16 46 BOOST_MATH_STD_USING
Chris@16 47 return floor(a) == floor(b);
Chris@16 48 }
Chris@16 49 };
Chris@16 50
Chris@16 51 struct equal_ceil
Chris@16 52 {
Chris@16 53 equal_ceil(){}
Chris@16 54 template <class T>
Chris@16 55 bool operator()(const T& a, const T& b)
Chris@16 56 {
Chris@16 57 BOOST_MATH_STD_USING
Chris@16 58 return ceil(a) == ceil(b);
Chris@16 59 }
Chris@16 60 };
Chris@16 61
Chris@16 62 struct equal_nearest_integer
Chris@16 63 {
Chris@16 64 equal_nearest_integer(){}
Chris@16 65 template <class T>
Chris@16 66 bool operator()(const T& a, const T& b)
Chris@16 67 {
Chris@16 68 BOOST_MATH_STD_USING
Chris@16 69 return floor(a + 0.5f) == floor(b + 0.5f);
Chris@16 70 }
Chris@16 71 };
Chris@16 72
Chris@16 73 namespace detail{
Chris@16 74
Chris@16 75 template <class F, class T>
Chris@16 76 void bracket(F f, T& a, T& b, T c, T& fa, T& fb, T& d, T& fd)
Chris@16 77 {
Chris@16 78 //
Chris@16 79 // Given a point c inside the existing enclosing interval
Chris@16 80 // [a, b] sets a = c if f(c) == 0, otherwise finds the new
Chris@16 81 // enclosing interval: either [a, c] or [c, b] and sets
Chris@16 82 // d and fd to the point that has just been removed from
Chris@16 83 // the interval. In other words d is the third best guess
Chris@16 84 // to the root.
Chris@16 85 //
Chris@16 86 BOOST_MATH_STD_USING // For ADL of std math functions
Chris@16 87 T tol = tools::epsilon<T>() * 2;
Chris@16 88 //
Chris@16 89 // If the interval [a,b] is very small, or if c is too close
Chris@16 90 // to one end of the interval then we need to adjust the
Chris@16 91 // location of c accordingly:
Chris@16 92 //
Chris@16 93 if((b - a) < 2 * tol * a)
Chris@16 94 {
Chris@16 95 c = a + (b - a) / 2;
Chris@16 96 }
Chris@16 97 else if(c <= a + fabs(a) * tol)
Chris@16 98 {
Chris@16 99 c = a + fabs(a) * tol;
Chris@16 100 }
Chris@16 101 else if(c >= b - fabs(b) * tol)
Chris@16 102 {
Chris@16 103 c = b - fabs(a) * tol;
Chris@16 104 }
Chris@16 105 //
Chris@16 106 // OK, lets invoke f(c):
Chris@16 107 //
Chris@16 108 T fc = f(c);
Chris@16 109 //
Chris@16 110 // if we have a zero then we have an exact solution to the root:
Chris@16 111 //
Chris@16 112 if(fc == 0)
Chris@16 113 {
Chris@16 114 a = c;
Chris@16 115 fa = 0;
Chris@16 116 d = 0;
Chris@16 117 fd = 0;
Chris@16 118 return;
Chris@16 119 }
Chris@16 120 //
Chris@16 121 // Non-zero fc, update the interval:
Chris@16 122 //
Chris@16 123 if(boost::math::sign(fa) * boost::math::sign(fc) < 0)
Chris@16 124 {
Chris@16 125 d = b;
Chris@16 126 fd = fb;
Chris@16 127 b = c;
Chris@16 128 fb = fc;
Chris@16 129 }
Chris@16 130 else
Chris@16 131 {
Chris@16 132 d = a;
Chris@16 133 fd = fa;
Chris@16 134 a = c;
Chris@16 135 fa= fc;
Chris@16 136 }
Chris@16 137 }
Chris@16 138
Chris@16 139 template <class T>
Chris@16 140 inline T safe_div(T num, T denom, T r)
Chris@16 141 {
Chris@16 142 //
Chris@16 143 // return num / denom without overflow,
Chris@16 144 // return r if overflow would occur.
Chris@16 145 //
Chris@16 146 BOOST_MATH_STD_USING // For ADL of std math functions
Chris@16 147
Chris@16 148 if(fabs(denom) < 1)
Chris@16 149 {
Chris@16 150 if(fabs(denom * tools::max_value<T>()) <= fabs(num))
Chris@16 151 return r;
Chris@16 152 }
Chris@16 153 return num / denom;
Chris@16 154 }
Chris@16 155
Chris@16 156 template <class T>
Chris@16 157 inline T secant_interpolate(const T& a, const T& b, const T& fa, const T& fb)
Chris@16 158 {
Chris@16 159 //
Chris@16 160 // Performs standard secant interpolation of [a,b] given
Chris@16 161 // function evaluations f(a) and f(b). Performs a bisection
Chris@16 162 // if secant interpolation would leave us very close to either
Chris@16 163 // a or b. Rationale: we only call this function when at least
Chris@16 164 // one other form of interpolation has already failed, so we know
Chris@16 165 // that the function is unlikely to be smooth with a root very
Chris@16 166 // close to a or b.
Chris@16 167 //
Chris@16 168 BOOST_MATH_STD_USING // For ADL of std math functions
Chris@16 169
Chris@16 170 T tol = tools::epsilon<T>() * 5;
Chris@16 171 T c = a - (fa / (fb - fa)) * (b - a);
Chris@16 172 if((c <= a + fabs(a) * tol) || (c >= b - fabs(b) * tol))
Chris@16 173 return (a + b) / 2;
Chris@16 174 return c;
Chris@16 175 }
Chris@16 176
Chris@16 177 template <class T>
Chris@16 178 T quadratic_interpolate(const T& a, const T& b, T const& d,
Chris@16 179 const T& fa, const T& fb, T const& fd,
Chris@16 180 unsigned count)
Chris@16 181 {
Chris@16 182 //
Chris@16 183 // Performs quadratic interpolation to determine the next point,
Chris@16 184 // takes count Newton steps to find the location of the
Chris@16 185 // quadratic polynomial.
Chris@16 186 //
Chris@16 187 // Point d must lie outside of the interval [a,b], it is the third
Chris@16 188 // best approximation to the root, after a and b.
Chris@16 189 //
Chris@16 190 // Note: this does not guarentee to find a root
Chris@16 191 // inside [a, b], so we fall back to a secant step should
Chris@16 192 // the result be out of range.
Chris@16 193 //
Chris@16 194 // Start by obtaining the coefficients of the quadratic polynomial:
Chris@16 195 //
Chris@16 196 T B = safe_div(T(fb - fa), T(b - a), tools::max_value<T>());
Chris@16 197 T A = safe_div(T(fd - fb), T(d - b), tools::max_value<T>());
Chris@16 198 A = safe_div(T(A - B), T(d - a), T(0));
Chris@16 199
Chris@16 200 if(A == 0)
Chris@16 201 {
Chris@16 202 // failure to determine coefficients, try a secant step:
Chris@16 203 return secant_interpolate(a, b, fa, fb);
Chris@16 204 }
Chris@16 205 //
Chris@16 206 // Determine the starting point of the Newton steps:
Chris@16 207 //
Chris@16 208 T c;
Chris@16 209 if(boost::math::sign(A) * boost::math::sign(fa) > 0)
Chris@16 210 {
Chris@16 211 c = a;
Chris@16 212 }
Chris@16 213 else
Chris@16 214 {
Chris@16 215 c = b;
Chris@16 216 }
Chris@16 217 //
Chris@16 218 // Take the Newton steps:
Chris@16 219 //
Chris@16 220 for(unsigned i = 1; i <= count; ++i)
Chris@16 221 {
Chris@16 222 //c -= safe_div(B * c, (B + A * (2 * c - a - b)), 1 + c - a);
Chris@16 223 c -= safe_div(T(fa+(B+A*(c-b))*(c-a)), T(B + A * (2 * c - a - b)), T(1 + c - a));
Chris@16 224 }
Chris@16 225 if((c <= a) || (c >= b))
Chris@16 226 {
Chris@16 227 // Oops, failure, try a secant step:
Chris@16 228 c = secant_interpolate(a, b, fa, fb);
Chris@16 229 }
Chris@16 230 return c;
Chris@16 231 }
Chris@16 232
Chris@16 233 template <class T>
Chris@16 234 T cubic_interpolate(const T& a, const T& b, const T& d,
Chris@16 235 const T& e, const T& fa, const T& fb,
Chris@16 236 const T& fd, const T& fe)
Chris@16 237 {
Chris@16 238 //
Chris@16 239 // Uses inverse cubic interpolation of f(x) at points
Chris@16 240 // [a,b,d,e] to obtain an approximate root of f(x).
Chris@16 241 // Points d and e lie outside the interval [a,b]
Chris@16 242 // and are the third and forth best approximations
Chris@16 243 // to the root that we have found so far.
Chris@16 244 //
Chris@16 245 // Note: this does not guarentee to find a root
Chris@16 246 // inside [a, b], so we fall back to quadratic
Chris@16 247 // interpolation in case of an erroneous result.
Chris@16 248 //
Chris@16 249 BOOST_MATH_INSTRUMENT_CODE(" a = " << a << " b = " << b
Chris@16 250 << " d = " << d << " e = " << e << " fa = " << fa << " fb = " << fb
Chris@16 251 << " fd = " << fd << " fe = " << fe);
Chris@16 252 T q11 = (d - e) * fd / (fe - fd);
Chris@16 253 T q21 = (b - d) * fb / (fd - fb);
Chris@16 254 T q31 = (a - b) * fa / (fb - fa);
Chris@16 255 T d21 = (b - d) * fd / (fd - fb);
Chris@16 256 T d31 = (a - b) * fb / (fb - fa);
Chris@16 257 BOOST_MATH_INSTRUMENT_CODE(
Chris@16 258 "q11 = " << q11 << " q21 = " << q21 << " q31 = " << q31
Chris@16 259 << " d21 = " << d21 << " d31 = " << d31);
Chris@16 260 T q22 = (d21 - q11) * fb / (fe - fb);
Chris@16 261 T q32 = (d31 - q21) * fa / (fd - fa);
Chris@16 262 T d32 = (d31 - q21) * fd / (fd - fa);
Chris@16 263 T q33 = (d32 - q22) * fa / (fe - fa);
Chris@16 264 T c = q31 + q32 + q33 + a;
Chris@16 265 BOOST_MATH_INSTRUMENT_CODE(
Chris@16 266 "q22 = " << q22 << " q32 = " << q32 << " d32 = " << d32
Chris@16 267 << " q33 = " << q33 << " c = " << c);
Chris@16 268
Chris@16 269 if((c <= a) || (c >= b))
Chris@16 270 {
Chris@16 271 // Out of bounds step, fall back to quadratic interpolation:
Chris@16 272 c = quadratic_interpolate(a, b, d, fa, fb, fd, 3);
Chris@16 273 BOOST_MATH_INSTRUMENT_CODE(
Chris@16 274 "Out of bounds interpolation, falling back to quadratic interpolation. c = " << c);
Chris@16 275 }
Chris@16 276
Chris@16 277 return c;
Chris@16 278 }
Chris@16 279
Chris@16 280 } // namespace detail
Chris@16 281
Chris@16 282 template <class F, class T, class Tol, class Policy>
Chris@16 283 std::pair<T, T> toms748_solve(F f, const T& ax, const T& bx, const T& fax, const T& fbx, Tol tol, boost::uintmax_t& max_iter, const Policy& pol)
Chris@16 284 {
Chris@16 285 //
Chris@16 286 // Main entry point and logic for Toms Algorithm 748
Chris@16 287 // root finder.
Chris@16 288 //
Chris@16 289 BOOST_MATH_STD_USING // For ADL of std math functions
Chris@16 290
Chris@16 291 static const char* function = "boost::math::tools::toms748_solve<%1%>";
Chris@16 292
Chris@16 293 boost::uintmax_t count = max_iter;
Chris@16 294 T a, b, fa, fb, c, u, fu, a0, b0, d, fd, e, fe;
Chris@16 295 static const T mu = 0.5f;
Chris@16 296
Chris@16 297 // initialise a, b and fa, fb:
Chris@16 298 a = ax;
Chris@16 299 b = bx;
Chris@16 300 if(a >= b)
Chris@16 301 policies::raise_domain_error(
Chris@16 302 function,
Chris@16 303 "Parameters a and b out of order: a=%1%", a, pol);
Chris@16 304 fa = fax;
Chris@16 305 fb = fbx;
Chris@16 306
Chris@16 307 if(tol(a, b) || (fa == 0) || (fb == 0))
Chris@16 308 {
Chris@16 309 max_iter = 0;
Chris@16 310 if(fa == 0)
Chris@16 311 b = a;
Chris@16 312 else if(fb == 0)
Chris@16 313 a = b;
Chris@16 314 return std::make_pair(a, b);
Chris@16 315 }
Chris@16 316
Chris@16 317 if(boost::math::sign(fa) * boost::math::sign(fb) > 0)
Chris@16 318 policies::raise_domain_error(
Chris@16 319 function,
Chris@16 320 "Parameters a and b do not bracket the root: a=%1%", a, pol);
Chris@16 321 // dummy value for fd, e and fe:
Chris@16 322 fe = e = fd = 1e5F;
Chris@16 323
Chris@16 324 if(fa != 0)
Chris@16 325 {
Chris@16 326 //
Chris@16 327 // On the first step we take a secant step:
Chris@16 328 //
Chris@16 329 c = detail::secant_interpolate(a, b, fa, fb);
Chris@16 330 detail::bracket(f, a, b, c, fa, fb, d, fd);
Chris@16 331 --count;
Chris@16 332 BOOST_MATH_INSTRUMENT_CODE(" a = " << a << " b = " << b);
Chris@16 333
Chris@16 334 if(count && (fa != 0) && !tol(a, b))
Chris@16 335 {
Chris@16 336 //
Chris@16 337 // On the second step we take a quadratic interpolation:
Chris@16 338 //
Chris@16 339 c = detail::quadratic_interpolate(a, b, d, fa, fb, fd, 2);
Chris@16 340 e = d;
Chris@16 341 fe = fd;
Chris@16 342 detail::bracket(f, a, b, c, fa, fb, d, fd);
Chris@16 343 --count;
Chris@16 344 BOOST_MATH_INSTRUMENT_CODE(" a = " << a << " b = " << b);
Chris@16 345 }
Chris@16 346 }
Chris@16 347
Chris@16 348 while(count && (fa != 0) && !tol(a, b))
Chris@16 349 {
Chris@16 350 // save our brackets:
Chris@16 351 a0 = a;
Chris@16 352 b0 = b;
Chris@16 353 //
Chris@16 354 // Starting with the third step taken
Chris@16 355 // we can use either quadratic or cubic interpolation.
Chris@16 356 // Cubic interpolation requires that all four function values
Chris@16 357 // fa, fb, fd, and fe are distinct, should that not be the case
Chris@16 358 // then variable prof will get set to true, and we'll end up
Chris@16 359 // taking a quadratic step instead.
Chris@16 360 //
Chris@16 361 T min_diff = tools::min_value<T>() * 32;
Chris@16 362 bool prof = (fabs(fa - fb) < min_diff) || (fabs(fa - fd) < min_diff) || (fabs(fa - fe) < min_diff) || (fabs(fb - fd) < min_diff) || (fabs(fb - fe) < min_diff) || (fabs(fd - fe) < min_diff);
Chris@16 363 if(prof)
Chris@16 364 {
Chris@16 365 c = detail::quadratic_interpolate(a, b, d, fa, fb, fd, 2);
Chris@16 366 BOOST_MATH_INSTRUMENT_CODE("Can't take cubic step!!!!");
Chris@16 367 }
Chris@16 368 else
Chris@16 369 {
Chris@16 370 c = detail::cubic_interpolate(a, b, d, e, fa, fb, fd, fe);
Chris@16 371 }
Chris@16 372 //
Chris@16 373 // re-bracket, and check for termination:
Chris@16 374 //
Chris@16 375 e = d;
Chris@16 376 fe = fd;
Chris@16 377 detail::bracket(f, a, b, c, fa, fb, d, fd);
Chris@16 378 if((0 == --count) || (fa == 0) || tol(a, b))
Chris@16 379 break;
Chris@16 380 BOOST_MATH_INSTRUMENT_CODE(" a = " << a << " b = " << b);
Chris@16 381 //
Chris@16 382 // Now another interpolated step:
Chris@16 383 //
Chris@16 384 prof = (fabs(fa - fb) < min_diff) || (fabs(fa - fd) < min_diff) || (fabs(fa - fe) < min_diff) || (fabs(fb - fd) < min_diff) || (fabs(fb - fe) < min_diff) || (fabs(fd - fe) < min_diff);
Chris@16 385 if(prof)
Chris@16 386 {
Chris@16 387 c = detail::quadratic_interpolate(a, b, d, fa, fb, fd, 3);
Chris@16 388 BOOST_MATH_INSTRUMENT_CODE("Can't take cubic step!!!!");
Chris@16 389 }
Chris@16 390 else
Chris@16 391 {
Chris@16 392 c = detail::cubic_interpolate(a, b, d, e, fa, fb, fd, fe);
Chris@16 393 }
Chris@16 394 //
Chris@16 395 // Bracket again, and check termination condition, update e:
Chris@16 396 //
Chris@16 397 detail::bracket(f, a, b, c, fa, fb, d, fd);
Chris@16 398 if((0 == --count) || (fa == 0) || tol(a, b))
Chris@16 399 break;
Chris@16 400 BOOST_MATH_INSTRUMENT_CODE(" a = " << a << " b = " << b);
Chris@16 401 //
Chris@16 402 // Now we take a double-length secant step:
Chris@16 403 //
Chris@16 404 if(fabs(fa) < fabs(fb))
Chris@16 405 {
Chris@16 406 u = a;
Chris@16 407 fu = fa;
Chris@16 408 }
Chris@16 409 else
Chris@16 410 {
Chris@16 411 u = b;
Chris@16 412 fu = fb;
Chris@16 413 }
Chris@16 414 c = u - 2 * (fu / (fb - fa)) * (b - a);
Chris@16 415 if(fabs(c - u) > (b - a) / 2)
Chris@16 416 {
Chris@16 417 c = a + (b - a) / 2;
Chris@16 418 }
Chris@16 419 //
Chris@16 420 // Bracket again, and check termination condition:
Chris@16 421 //
Chris@16 422 e = d;
Chris@16 423 fe = fd;
Chris@16 424 detail::bracket(f, a, b, c, fa, fb, d, fd);
Chris@16 425 BOOST_MATH_INSTRUMENT_CODE(" a = " << a << " b = " << b);
Chris@16 426 BOOST_MATH_INSTRUMENT_CODE(" tol = " << T((fabs(a) - fabs(b)) / fabs(a)));
Chris@16 427 if((0 == --count) || (fa == 0) || tol(a, b))
Chris@16 428 break;
Chris@16 429 //
Chris@16 430 // And finally... check to see if an additional bisection step is
Chris@16 431 // to be taken, we do this if we're not converging fast enough:
Chris@16 432 //
Chris@16 433 if((b - a) < mu * (b0 - a0))
Chris@16 434 continue;
Chris@16 435 //
Chris@16 436 // bracket again on a bisection:
Chris@16 437 //
Chris@16 438 e = d;
Chris@16 439 fe = fd;
Chris@16 440 detail::bracket(f, a, b, T(a + (b - a) / 2), fa, fb, d, fd);
Chris@16 441 --count;
Chris@16 442 BOOST_MATH_INSTRUMENT_CODE("Not converging: Taking a bisection!!!!");
Chris@16 443 BOOST_MATH_INSTRUMENT_CODE(" a = " << a << " b = " << b);
Chris@16 444 } // while loop
Chris@16 445
Chris@16 446 max_iter -= count;
Chris@16 447 if(fa == 0)
Chris@16 448 {
Chris@16 449 b = a;
Chris@16 450 }
Chris@16 451 else if(fb == 0)
Chris@16 452 {
Chris@16 453 a = b;
Chris@16 454 }
Chris@16 455 return std::make_pair(a, b);
Chris@16 456 }
Chris@16 457
Chris@16 458 template <class F, class T, class Tol>
Chris@16 459 inline std::pair<T, T> toms748_solve(F f, const T& ax, const T& bx, const T& fax, const T& fbx, Tol tol, boost::uintmax_t& max_iter)
Chris@16 460 {
Chris@16 461 return toms748_solve(f, ax, bx, fax, fbx, tol, max_iter, policies::policy<>());
Chris@16 462 }
Chris@16 463
Chris@16 464 template <class F, class T, class Tol, class Policy>
Chris@16 465 inline std::pair<T, T> toms748_solve(F f, const T& ax, const T& bx, Tol tol, boost::uintmax_t& max_iter, const Policy& pol)
Chris@16 466 {
Chris@16 467 max_iter -= 2;
Chris@16 468 std::pair<T, T> r = toms748_solve(f, ax, bx, f(ax), f(bx), tol, max_iter, pol);
Chris@16 469 max_iter += 2;
Chris@16 470 return r;
Chris@16 471 }
Chris@16 472
Chris@16 473 template <class F, class T, class Tol>
Chris@16 474 inline std::pair<T, T> toms748_solve(F f, const T& ax, const T& bx, Tol tol, boost::uintmax_t& max_iter)
Chris@16 475 {
Chris@16 476 return toms748_solve(f, ax, bx, tol, max_iter, policies::policy<>());
Chris@16 477 }
Chris@16 478
Chris@16 479 template <class F, class T, class Tol, class Policy>
Chris@16 480 std::pair<T, T> bracket_and_solve_root(F f, const T& guess, T factor, bool rising, Tol tol, boost::uintmax_t& max_iter, const Policy& pol)
Chris@16 481 {
Chris@16 482 BOOST_MATH_STD_USING
Chris@16 483 static const char* function = "boost::math::tools::bracket_and_solve_root<%1%>";
Chris@16 484 //
Chris@16 485 // Set up inital brackets:
Chris@16 486 //
Chris@16 487 T a = guess;
Chris@16 488 T b = a;
Chris@16 489 T fa = f(a);
Chris@16 490 T fb = fa;
Chris@16 491 //
Chris@16 492 // Set up invocation count:
Chris@16 493 //
Chris@16 494 boost::uintmax_t count = max_iter - 1;
Chris@16 495
Chris@16 496 if((fa < 0) == (guess < 0 ? !rising : rising))
Chris@16 497 {
Chris@16 498 //
Chris@16 499 // Zero is to the right of b, so walk upwards
Chris@16 500 // until we find it:
Chris@16 501 //
Chris@16 502 while((boost::math::sign)(fb) == (boost::math::sign)(fa))
Chris@16 503 {
Chris@16 504 if(count == 0)
Chris@16 505 policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", b, pol);
Chris@16 506 //
Chris@16 507 // Heuristic: every 20 iterations we double the growth factor in case the
Chris@16 508 // initial guess was *really* bad !
Chris@16 509 //
Chris@16 510 if((max_iter - count) % 20 == 0)
Chris@16 511 factor *= 2;
Chris@16 512 //
Chris@16 513 // Now go ahead and move our guess by "factor":
Chris@16 514 //
Chris@16 515 a = b;
Chris@16 516 fa = fb;
Chris@16 517 b *= factor;
Chris@16 518 fb = f(b);
Chris@16 519 --count;
Chris@16 520 BOOST_MATH_INSTRUMENT_CODE("a = " << a << " b = " << b << " fa = " << fa << " fb = " << fb << " count = " << count);
Chris@16 521 }
Chris@16 522 }
Chris@16 523 else
Chris@16 524 {
Chris@16 525 //
Chris@16 526 // Zero is to the left of a, so walk downwards
Chris@16 527 // until we find it:
Chris@16 528 //
Chris@16 529 while((boost::math::sign)(fb) == (boost::math::sign)(fa))
Chris@16 530 {
Chris@16 531 if(fabs(a) < tools::min_value<T>())
Chris@16 532 {
Chris@16 533 // Escape route just in case the answer is zero!
Chris@16 534 max_iter -= count;
Chris@16 535 max_iter += 1;
Chris@16 536 return a > 0 ? std::make_pair(T(0), T(a)) : std::make_pair(T(a), T(0));
Chris@16 537 }
Chris@16 538 if(count == 0)
Chris@16 539 policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", a, pol);
Chris@16 540 //
Chris@16 541 // Heuristic: every 20 iterations we double the growth factor in case the
Chris@16 542 // initial guess was *really* bad !
Chris@16 543 //
Chris@16 544 if((max_iter - count) % 20 == 0)
Chris@16 545 factor *= 2;
Chris@16 546 //
Chris@16 547 // Now go ahead and move are guess by "factor":
Chris@16 548 //
Chris@16 549 b = a;
Chris@16 550 fb = fa;
Chris@16 551 a /= factor;
Chris@16 552 fa = f(a);
Chris@16 553 --count;
Chris@16 554 BOOST_MATH_INSTRUMENT_CODE("a = " << a << " b = " << b << " fa = " << fa << " fb = " << fb << " count = " << count);
Chris@16 555 }
Chris@16 556 }
Chris@16 557 max_iter -= count;
Chris@16 558 max_iter += 1;
Chris@16 559 std::pair<T, T> r = toms748_solve(
Chris@16 560 f,
Chris@16 561 (a < 0 ? b : a),
Chris@16 562 (a < 0 ? a : b),
Chris@16 563 (a < 0 ? fb : fa),
Chris@16 564 (a < 0 ? fa : fb),
Chris@16 565 tol,
Chris@16 566 count,
Chris@16 567 pol);
Chris@16 568 max_iter += count;
Chris@16 569 BOOST_MATH_INSTRUMENT_CODE("max_iter = " << max_iter << " count = " << count);
Chris@16 570 return r;
Chris@16 571 }
Chris@16 572
Chris@16 573 template <class F, class T, class Tol>
Chris@16 574 inline std::pair<T, T> bracket_and_solve_root(F f, const T& guess, const T& factor, bool rising, Tol tol, boost::uintmax_t& max_iter)
Chris@16 575 {
Chris@16 576 return bracket_and_solve_root(f, guess, factor, rising, tol, max_iter, policies::policy<>());
Chris@16 577 }
Chris@16 578
Chris@16 579 } // namespace tools
Chris@16 580 } // namespace math
Chris@16 581 } // namespace boost
Chris@16 582
Chris@16 583
Chris@16 584 #endif // BOOST_MATH_TOOLS_SOLVE_ROOT_HPP
Chris@16 585