comparison DEPENDENCIES/generic/include/boost/math/tools/toms748_solve.hpp @ 101:c530137014c0

Update Boost headers (1.58.0)
author Chris Cannam
date Mon, 07 Sep 2015 11:12:49 +0100
parents 2665513ce2d3
children
comparison
equal deleted inserted replaced
100:793467b5e61c 101:c530137014c0
14 #include <boost/math/policies/error_handling.hpp> 14 #include <boost/math/policies/error_handling.hpp>
15 #include <boost/math/tools/config.hpp> 15 #include <boost/math/tools/config.hpp>
16 #include <boost/math/special_functions/sign.hpp> 16 #include <boost/math/special_functions/sign.hpp>
17 #include <boost/cstdint.hpp> 17 #include <boost/cstdint.hpp>
18 #include <limits> 18 #include <limits>
19
20 #ifdef BOOST_MATH_LOG_ROOT_ITERATIONS
21 # define BOOST_MATH_LOGGER_INCLUDE <boost/math/tools/iteration_logger.hpp>
22 # include BOOST_MATH_LOGGER_INCLUDE
23 # undef BOOST_MATH_LOGGER_INCLUDE
24 #else
25 # define BOOST_MATH_LOG_COUNT(count)
26 #endif
19 27
20 namespace boost{ namespace math{ namespace tools{ 28 namespace boost{ namespace math{ namespace tools{
21 29
22 template <class T> 30 template <class T>
23 class eps_tolerance 31 class eps_tolerance
296 304
297 // initialise a, b and fa, fb: 305 // initialise a, b and fa, fb:
298 a = ax; 306 a = ax;
299 b = bx; 307 b = bx;
300 if(a >= b) 308 if(a >= b)
301 policies::raise_domain_error( 309 return boost::math::detail::pair_from_single(policies::raise_domain_error(
302 function, 310 function,
303 "Parameters a and b out of order: a=%1%", a, pol); 311 "Parameters a and b out of order: a=%1%", a, pol));
304 fa = fax; 312 fa = fax;
305 fb = fbx; 313 fb = fbx;
306 314
307 if(tol(a, b) || (fa == 0) || (fb == 0)) 315 if(tol(a, b) || (fa == 0) || (fb == 0))
308 { 316 {
313 a = b; 321 a = b;
314 return std::make_pair(a, b); 322 return std::make_pair(a, b);
315 } 323 }
316 324
317 if(boost::math::sign(fa) * boost::math::sign(fb) > 0) 325 if(boost::math::sign(fa) * boost::math::sign(fb) > 0)
318 policies::raise_domain_error( 326 return boost::math::detail::pair_from_single(policies::raise_domain_error(
319 function, 327 function,
320 "Parameters a and b do not bracket the root: a=%1%", a, pol); 328 "Parameters a and b do not bracket the root: a=%1%", a, pol));
321 // dummy value for fd, e and fe: 329 // dummy value for fd, e and fe:
322 fe = e = fd = 1e5F; 330 fe = e = fd = 1e5F;
323 331
324 if(fa != 0) 332 if(fa != 0)
325 { 333 {
450 } 458 }
451 else if(fb == 0) 459 else if(fb == 0)
452 { 460 {
453 a = b; 461 a = b;
454 } 462 }
463 BOOST_MATH_LOG_COUNT(max_iter)
455 return std::make_pair(a, b); 464 return std::make_pair(a, b);
456 } 465 }
457 466
458 template <class F, class T, class Tol> 467 template <class F, class T, class Tol>
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) 468 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)
491 // 500 //
492 // Set up invocation count: 501 // Set up invocation count:
493 // 502 //
494 boost::uintmax_t count = max_iter - 1; 503 boost::uintmax_t count = max_iter - 1;
495 504
505 int step = 32;
506
496 if((fa < 0) == (guess < 0 ? !rising : rising)) 507 if((fa < 0) == (guess < 0 ? !rising : rising))
497 { 508 {
498 // 509 //
499 // Zero is to the right of b, so walk upwards 510 // Zero is to the right of b, so walk upwards
500 // until we find it: 511 // until we find it:
501 // 512 //
502 while((boost::math::sign)(fb) == (boost::math::sign)(fa)) 513 while((boost::math::sign)(fb) == (boost::math::sign)(fa))
503 { 514 {
504 if(count == 0) 515 if(count == 0)
505 policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", b, pol); 516 return boost::math::detail::pair_from_single(policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", b, pol));
506 // 517 //
507 // Heuristic: every 20 iterations we double the growth factor in case the 518 // Heuristic: normally it's best not to increase the step sizes as we'll just end up
508 // initial guess was *really* bad ! 519 // with a really wide range to search for the root. However, if the initial guess was *really*
509 // 520 // bad then we need to speed up the search otherwise we'll take forever if we're orders of
510 if((max_iter - count) % 20 == 0) 521 // magnitude out. This happens most often if the guess is a small value (say 1) and the result
522 // we're looking for is close to std::numeric_limits<T>::min().
523 //
524 if((max_iter - count) % step == 0)
525 {
511 factor *= 2; 526 factor *= 2;
527 if(step > 1) step /= 2;
528 }
512 // 529 //
513 // Now go ahead and move our guess by "factor": 530 // Now go ahead and move our guess by "factor":
514 // 531 //
515 a = b; 532 a = b;
516 fa = fb; 533 fa = fb;
534 max_iter -= count; 551 max_iter -= count;
535 max_iter += 1; 552 max_iter += 1;
536 return a > 0 ? std::make_pair(T(0), T(a)) : std::make_pair(T(a), T(0)); 553 return a > 0 ? std::make_pair(T(0), T(a)) : std::make_pair(T(a), T(0));
537 } 554 }
538 if(count == 0) 555 if(count == 0)
539 policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", a, pol); 556 return boost::math::detail::pair_from_single(policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", a, pol));
540 // 557 //
541 // Heuristic: every 20 iterations we double the growth factor in case the 558 // Heuristic: normally it's best not to increase the step sizes as we'll just end up
542 // initial guess was *really* bad ! 559 // with a really wide range to search for the root. However, if the initial guess was *really*
543 // 560 // bad then we need to speed up the search otherwise we'll take forever if we're orders of
544 if((max_iter - count) % 20 == 0) 561 // magnitude out. This happens most often if the guess is a small value (say 1) and the result
562 // we're looking for is close to std::numeric_limits<T>::min().
563 //
564 if((max_iter - count) % step == 0)
565 {
545 factor *= 2; 566 factor *= 2;
567 if(step > 1) step /= 2;
568 }
546 // 569 //
547 // Now go ahead and move are guess by "factor": 570 // Now go ahead and move are guess by "factor":
548 // 571 //
549 b = a; 572 b = a;
550 fb = fa; 573 fb = fa;
565 tol, 588 tol,
566 count, 589 count,
567 pol); 590 pol);
568 max_iter += count; 591 max_iter += count;
569 BOOST_MATH_INSTRUMENT_CODE("max_iter = " << max_iter << " count = " << count); 592 BOOST_MATH_INSTRUMENT_CODE("max_iter = " << max_iter << " count = " << count);
593 BOOST_MATH_LOG_COUNT(max_iter)
570 return r; 594 return r;
571 } 595 }
572 596
573 template <class F, class T, class Tol> 597 template <class F, class T, class Tol>
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) 598 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)