roots.hpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982
  1. // (C) Copyright John Maddock 2006.
  2. // Use, modification and distribution are subject to the
  3. // Boost Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_MATH_TOOLS_NEWTON_SOLVER_HPP
  6. #define BOOST_MATH_TOOLS_NEWTON_SOLVER_HPP
  7. #ifdef _MSC_VER
  8. #pragma once
  9. #endif
  10. #include <boost/math/tools/complex.hpp> // test for multiprecision types in complex Newton
  11. #include <utility>
  12. #include <cmath>
  13. #include <tuple>
  14. #include <boost/math/tools/config.hpp>
  15. #include <boost/cstdint.hpp>
  16. #include <boost/math/tools/cxx03_warn.hpp>
  17. #include <boost/math/special_functions/sign.hpp>
  18. #include <boost/math/special_functions/next.hpp>
  19. #include <boost/math/tools/toms748_solve.hpp>
  20. #include <boost/math/policies/error_handling.hpp>
  21. namespace boost {
  22. namespace math {
  23. namespace tools {
  24. namespace detail {
  25. namespace dummy {
  26. template<int n, class T>
  27. typename T::value_type get(const T&) BOOST_MATH_NOEXCEPT(T);
  28. }
  29. template <class Tuple, class T>
  30. void unpack_tuple(const Tuple& t, T& a, T& b) BOOST_MATH_NOEXCEPT(T)
  31. {
  32. using dummy::get;
  33. // Use ADL to find the right overload for get:
  34. a = get<0>(t);
  35. b = get<1>(t);
  36. }
  37. template <class Tuple, class T>
  38. void unpack_tuple(const Tuple& t, T& a, T& b, T& c) BOOST_MATH_NOEXCEPT(T)
  39. {
  40. using dummy::get;
  41. // Use ADL to find the right overload for get:
  42. a = get<0>(t);
  43. b = get<1>(t);
  44. c = get<2>(t);
  45. }
  46. template <class Tuple, class T>
  47. inline void unpack_0(const Tuple& t, T& val) BOOST_MATH_NOEXCEPT(T)
  48. {
  49. using dummy::get;
  50. // Rely on ADL to find the correct overload of get:
  51. val = get<0>(t);
  52. }
  53. template <class T, class U, class V>
  54. inline void unpack_tuple(const std::pair<T, U>& p, V& a, V& b) BOOST_MATH_NOEXCEPT(T)
  55. {
  56. a = p.first;
  57. b = p.second;
  58. }
  59. template <class T, class U, class V>
  60. inline void unpack_0(const std::pair<T, U>& p, V& a) BOOST_MATH_NOEXCEPT(T)
  61. {
  62. a = p.first;
  63. }
  64. template <class F, class T>
  65. void handle_zero_derivative(F f,
  66. T& last_f0,
  67. const T& f0,
  68. T& delta,
  69. T& result,
  70. T& guess,
  71. const T& min,
  72. const T& max) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(T) && noexcept(std::declval<F>()(std::declval<T>())))
  73. {
  74. if (last_f0 == 0)
  75. {
  76. // this must be the first iteration, pretend that we had a
  77. // previous one at either min or max:
  78. if (result == min)
  79. {
  80. guess = max;
  81. }
  82. else
  83. {
  84. guess = min;
  85. }
  86. unpack_0(f(guess), last_f0);
  87. delta = guess - result;
  88. }
  89. if (sign(last_f0) * sign(f0) < 0)
  90. {
  91. // we've crossed over so move in opposite direction to last step:
  92. if (delta < 0)
  93. {
  94. delta = (result - min) / 2;
  95. }
  96. else
  97. {
  98. delta = (result - max) / 2;
  99. }
  100. }
  101. else
  102. {
  103. // move in same direction as last step:
  104. if (delta < 0)
  105. {
  106. delta = (result - max) / 2;
  107. }
  108. else
  109. {
  110. delta = (result - min) / 2;
  111. }
  112. }
  113. }
  114. } // namespace
  115. template <class F, class T, class Tol, class Policy>
  116. std::pair<T, T> bisect(F f, T min, T max, Tol tol, boost::uintmax_t& max_iter, const Policy& pol) BOOST_NOEXCEPT_IF(policies::is_noexcept_error_policy<Policy>::value&& BOOST_MATH_IS_FLOAT(T) && noexcept(std::declval<F>()(std::declval<T>())))
  117. {
  118. T fmin = f(min);
  119. T fmax = f(max);
  120. if (fmin == 0)
  121. {
  122. max_iter = 2;
  123. return std::make_pair(min, min);
  124. }
  125. if (fmax == 0)
  126. {
  127. max_iter = 2;
  128. return std::make_pair(max, max);
  129. }
  130. //
  131. // Error checking:
  132. //
  133. static const char* function = "boost::math::tools::bisect<%1%>";
  134. if (min >= max)
  135. {
  136. return boost::math::detail::pair_from_single(policies::raise_evaluation_error(function,
  137. "Arguments in wrong order in boost::math::tools::bisect (first arg=%1%)", min, pol));
  138. }
  139. if (fmin * fmax >= 0)
  140. {
  141. return boost::math::detail::pair_from_single(policies::raise_evaluation_error(function,
  142. "No change of sign in boost::math::tools::bisect, either there is no root to find, or there are multiple roots in the interval (f(min) = %1%).", fmin, pol));
  143. }
  144. //
  145. // Three function invocations so far:
  146. //
  147. boost::uintmax_t count = max_iter;
  148. if (count < 3)
  149. count = 0;
  150. else
  151. count -= 3;
  152. while (count && (0 == tol(min, max)))
  153. {
  154. T mid = (min + max) / 2;
  155. T fmid = f(mid);
  156. if ((mid == max) || (mid == min))
  157. break;
  158. if (fmid == 0)
  159. {
  160. min = max = mid;
  161. break;
  162. }
  163. else if (sign(fmid) * sign(fmin) < 0)
  164. {
  165. max = mid;
  166. }
  167. else
  168. {
  169. min = mid;
  170. fmin = fmid;
  171. }
  172. --count;
  173. }
  174. max_iter -= count;
  175. #ifdef BOOST_MATH_INSTRUMENT
  176. std::cout << "Bisection required " << max_iter << " iterations.\n";
  177. #endif
  178. return std::make_pair(min, max);
  179. }
  180. template <class F, class T, class Tol>
  181. inline std::pair<T, T> bisect(F f, T min, T max, Tol tol, boost::uintmax_t& max_iter) BOOST_NOEXCEPT_IF(policies::is_noexcept_error_policy<policies::policy<> >::value&& BOOST_MATH_IS_FLOAT(T) && noexcept(std::declval<F>()(std::declval<T>())))
  182. {
  183. return bisect(f, min, max, tol, max_iter, policies::policy<>());
  184. }
  185. template <class F, class T, class Tol>
  186. inline std::pair<T, T> bisect(F f, T min, T max, Tol tol) BOOST_NOEXCEPT_IF(policies::is_noexcept_error_policy<policies::policy<> >::value&& BOOST_MATH_IS_FLOAT(T) && noexcept(std::declval<F>()(std::declval<T>())))
  187. {
  188. boost::uintmax_t m = (std::numeric_limits<boost::uintmax_t>::max)();
  189. return bisect(f, min, max, tol, m, policies::policy<>());
  190. }
  191. template <class F, class T>
  192. T newton_raphson_iterate(F f, T guess, T min, T max, int digits, boost::uintmax_t& max_iter) BOOST_NOEXCEPT_IF(policies::is_noexcept_error_policy<policies::policy<> >::value&& BOOST_MATH_IS_FLOAT(T) && noexcept(std::declval<F>()(std::declval<T>())))
  193. {
  194. BOOST_MATH_STD_USING
  195. static const char* function = "boost::math::tools::newton_raphson_iterate<%1%>";
  196. if (min > max)
  197. {
  198. return policies::raise_evaluation_error(function, "Range arguments in wrong order in boost::math::tools::newton_raphson_iterate(first arg=%1%)", min, boost::math::policies::policy<>());
  199. }
  200. T f0(0), f1, last_f0(0);
  201. T result = guess;
  202. T factor = static_cast<T>(ldexp(1.0, 1 - digits));
  203. T delta = tools::max_value<T>();
  204. T delta1 = tools::max_value<T>();
  205. T delta2 = tools::max_value<T>();
  206. //
  207. // We use these to sanity check that we do actually bracket a root,
  208. // we update these to the function value when we update the endpoints
  209. // of the range. Then, provided at some point we update both endpoints
  210. // checking that max_range_f * min_range_f <= 0 verifies there is a root
  211. // to be found somewhere. Note that if there is no root, and we approach
  212. // a local minima, then the derivative will go to zero, and hence the next
  213. // step will jump out of bounds (or at least past the minima), so this
  214. // check *should* happen in pathological cases.
  215. //
  216. T max_range_f = 0;
  217. T min_range_f = 0;
  218. boost::uintmax_t count(max_iter);
  219. #ifdef BOOST_MATH_INSTRUMENT
  220. std::cout << "Newton_raphson_iterate, guess = " << guess << ", min = " << min << ", max = " << max
  221. << ", digits = " << digits << ", max_iter = " << max_iter << "\n";
  222. #endif
  223. do {
  224. last_f0 = f0;
  225. delta2 = delta1;
  226. delta1 = delta;
  227. detail::unpack_tuple(f(result), f0, f1);
  228. --count;
  229. if (0 == f0)
  230. break;
  231. if (f1 == 0)
  232. {
  233. // Oops zero derivative!!!
  234. detail::handle_zero_derivative(f, last_f0, f0, delta, result, guess, min, max);
  235. }
  236. else
  237. {
  238. delta = f0 / f1;
  239. }
  240. #ifdef BOOST_MATH_INSTRUMENT
  241. std::cout << "Newton iteration " << max_iter - count << ", delta = " << delta << ", residual = " << f0 << "\n";
  242. #endif
  243. if (fabs(delta * 2) > fabs(delta2))
  244. {
  245. // Last two steps haven't converged.
  246. T shift = (delta > 0) ? (result - min) / 2 : (result - max) / 2;
  247. if ((result != 0) && (fabs(shift) > fabs(result)))
  248. {
  249. delta = sign(delta) * fabs(result) * 1.1f; // Protect against huge jumps!
  250. //delta = sign(delta) * result; // Protect against huge jumps! Failed for negative result. https://github.com/boostorg/math/issues/216
  251. }
  252. else
  253. delta = shift;
  254. // reset delta1/2 so we don't take this branch next time round:
  255. delta1 = 3 * delta;
  256. delta2 = 3 * delta;
  257. }
  258. guess = result;
  259. result -= delta;
  260. if (result <= min)
  261. {
  262. delta = 0.5F * (guess - min);
  263. result = guess - delta;
  264. if ((result == min) || (result == max))
  265. break;
  266. }
  267. else if (result >= max)
  268. {
  269. delta = 0.5F * (guess - max);
  270. result = guess - delta;
  271. if ((result == min) || (result == max))
  272. break;
  273. }
  274. // Update brackets:
  275. if (delta > 0)
  276. {
  277. max = guess;
  278. max_range_f = f0;
  279. }
  280. else
  281. {
  282. min = guess;
  283. min_range_f = f0;
  284. }
  285. //
  286. // Sanity check that we bracket the root:
  287. //
  288. if (max_range_f * min_range_f > 0)
  289. {
  290. return policies::raise_evaluation_error(function, "There appears to be no root to be found in boost::math::tools::newton_raphson_iterate, perhaps we have a local minima near current best guess of %1%", guess, boost::math::policies::policy<>());
  291. }
  292. }while(count && (fabs(result * factor) < fabs(delta)));
  293. max_iter -= count;
  294. #ifdef BOOST_MATH_INSTRUMENT
  295. std::cout << "Newton Raphson required " << max_iter << " iterations\n";
  296. #endif
  297. return result;
  298. }
  299. template <class F, class T>
  300. inline T newton_raphson_iterate(F f, T guess, T min, T max, int digits) BOOST_NOEXCEPT_IF(policies::is_noexcept_error_policy<policies::policy<> >::value&& BOOST_MATH_IS_FLOAT(T) && noexcept(std::declval<F>()(std::declval<T>())))
  301. {
  302. boost::uintmax_t m = (std::numeric_limits<boost::uintmax_t>::max)();
  303. return newton_raphson_iterate(f, guess, min, max, digits, m);
  304. }
  305. namespace detail {
  306. struct halley_step
  307. {
  308. template <class T>
  309. static T step(const T& /*x*/, const T& f0, const T& f1, const T& f2) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(T))
  310. {
  311. using std::fabs;
  312. T denom = 2 * f0;
  313. T num = 2 * f1 - f0 * (f2 / f1);
  314. T delta;
  315. BOOST_MATH_INSTRUMENT_VARIABLE(denom);
  316. BOOST_MATH_INSTRUMENT_VARIABLE(num);
  317. if ((fabs(num) < 1) && (fabs(denom) >= fabs(num) * tools::max_value<T>()))
  318. {
  319. // possible overflow, use Newton step:
  320. delta = f0 / f1;
  321. }
  322. else
  323. delta = denom / num;
  324. return delta;
  325. }
  326. };
  327. template <class F, class T>
  328. T bracket_root_towards_min(F f, T guess, const T& f0, T& min, T& max, boost::uintmax_t& count) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(T) && noexcept(std::declval<F>()(std::declval<T>())));
  329. template <class F, class T>
  330. T bracket_root_towards_max(F f, T guess, const T& f0, T& min, T& max, boost::uintmax_t& count) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(T) && noexcept(std::declval<F>()(std::declval<T>())))
  331. {
  332. using std::fabs;
  333. //
  334. // Move guess towards max until we bracket the root, updating min and max as we go:
  335. //
  336. T guess0 = guess;
  337. T multiplier = 2;
  338. T f_current = f0;
  339. if (fabs(min) < fabs(max))
  340. {
  341. while (--count && ((f_current < 0) == (f0 < 0)))
  342. {
  343. min = guess;
  344. guess *= multiplier;
  345. if (guess > max)
  346. {
  347. guess = max;
  348. f_current = -f_current; // There must be a change of sign!
  349. break;
  350. }
  351. multiplier *= 2;
  352. unpack_0(f(guess), f_current);
  353. }
  354. }
  355. else
  356. {
  357. //
  358. // If min and max are negative we have to divide to head towards max:
  359. //
  360. while (--count && ((f_current < 0) == (f0 < 0)))
  361. {
  362. min = guess;
  363. guess /= multiplier;
  364. if (guess > max)
  365. {
  366. guess = max;
  367. f_current = -f_current; // There must be a change of sign!
  368. break;
  369. }
  370. multiplier *= 2;
  371. unpack_0(f(guess), f_current);
  372. }
  373. }
  374. if (count)
  375. {
  376. max = guess;
  377. if (multiplier > 16)
  378. return (guess0 - guess) + bracket_root_towards_min(f, guess, f_current, min, max, count);
  379. }
  380. return guess0 - (max + min) / 2;
  381. }
  382. template <class F, class T>
  383. T bracket_root_towards_min(F f, T guess, const T& f0, T& min, T& max, boost::uintmax_t& count) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(T) && noexcept(std::declval<F>()(std::declval<T>())))
  384. {
  385. using std::fabs;
  386. //
  387. // Move guess towards min until we bracket the root, updating min and max as we go:
  388. //
  389. T guess0 = guess;
  390. T multiplier = 2;
  391. T f_current = f0;
  392. if (fabs(min) < fabs(max))
  393. {
  394. while (--count && ((f_current < 0) == (f0 < 0)))
  395. {
  396. max = guess;
  397. guess /= multiplier;
  398. if (guess < min)
  399. {
  400. guess = min;
  401. f_current = -f_current; // There must be a change of sign!
  402. break;
  403. }
  404. multiplier *= 2;
  405. unpack_0(f(guess), f_current);
  406. }
  407. }
  408. else
  409. {
  410. //
  411. // If min and max are negative we have to multiply to head towards min:
  412. //
  413. while (--count && ((f_current < 0) == (f0 < 0)))
  414. {
  415. max = guess;
  416. guess *= multiplier;
  417. if (guess < min)
  418. {
  419. guess = min;
  420. f_current = -f_current; // There must be a change of sign!
  421. break;
  422. }
  423. multiplier *= 2;
  424. unpack_0(f(guess), f_current);
  425. }
  426. }
  427. if (count)
  428. {
  429. min = guess;
  430. if (multiplier > 16)
  431. return (guess0 - guess) + bracket_root_towards_max(f, guess, f_current, min, max, count);
  432. }
  433. return guess0 - (max + min) / 2;
  434. }
  435. template <class Stepper, class F, class T>
  436. T second_order_root_finder(F f, T guess, T min, T max, int digits, boost::uintmax_t& max_iter) BOOST_NOEXCEPT_IF(policies::is_noexcept_error_policy<policies::policy<> >::value&& BOOST_MATH_IS_FLOAT(T) && noexcept(std::declval<F>()(std::declval<T>())))
  437. {
  438. BOOST_MATH_STD_USING
  439. #ifdef BOOST_MATH_INSTRUMENT
  440. std::cout << "Second order root iteration, guess = " << guess << ", min = " << min << ", max = " << max
  441. << ", digits = " << digits << ", max_iter = " << max_iter << "\n";
  442. #endif
  443. static const char* function = "boost::math::tools::halley_iterate<%1%>";
  444. if (min >= max)
  445. {
  446. return policies::raise_evaluation_error(function, "Range arguments in wrong order in boost::math::tools::halley_iterate(first arg=%1%)", min, boost::math::policies::policy<>());
  447. }
  448. T f0(0), f1, f2;
  449. T result = guess;
  450. T factor = ldexp(static_cast<T>(1.0), 1 - digits);
  451. T delta = (std::max)(T(10000000 * guess), T(10000000)); // arbitrarily large delta
  452. T last_f0 = 0;
  453. T delta1 = delta;
  454. T delta2 = delta;
  455. bool out_of_bounds_sentry = false;
  456. #ifdef BOOST_MATH_INSTRUMENT
  457. std::cout << "Second order root iteration, limit = " << factor << "\n";
  458. #endif
  459. //
  460. // We use these to sanity check that we do actually bracket a root,
  461. // we update these to the function value when we update the endpoints
  462. // of the range. Then, provided at some point we update both endpoints
  463. // checking that max_range_f * min_range_f <= 0 verifies there is a root
  464. // to be found somewhere. Note that if there is no root, and we approach
  465. // a local minima, then the derivative will go to zero, and hence the next
  466. // step will jump out of bounds (or at least past the minima), so this
  467. // check *should* happen in pathological cases.
  468. //
  469. T max_range_f = 0;
  470. T min_range_f = 0;
  471. boost::uintmax_t count(max_iter);
  472. do {
  473. last_f0 = f0;
  474. delta2 = delta1;
  475. delta1 = delta;
  476. detail::unpack_tuple(f(result), f0, f1, f2);
  477. --count;
  478. BOOST_MATH_INSTRUMENT_VARIABLE(f0);
  479. BOOST_MATH_INSTRUMENT_VARIABLE(f1);
  480. BOOST_MATH_INSTRUMENT_VARIABLE(f2);
  481. if (0 == f0)
  482. break;
  483. if (f1 == 0)
  484. {
  485. // Oops zero derivative!!!
  486. detail::handle_zero_derivative(f, last_f0, f0, delta, result, guess, min, max);
  487. }
  488. else
  489. {
  490. if (f2 != 0)
  491. {
  492. delta = Stepper::step(result, f0, f1, f2);
  493. if (delta * f1 / f0 < 0)
  494. {
  495. // Oh dear, we have a problem as Newton and Halley steps
  496. // disagree about which way we should move. Probably
  497. // there is cancelation error in the calculation of the
  498. // Halley step, or else the derivatives are so small
  499. // that their values are basically trash. We will move
  500. // in the direction indicated by a Newton step, but
  501. // by no more than twice the current guess value, otherwise
  502. // we can jump way out of bounds if we're not careful.
  503. // See https://svn.boost.org/trac/boost/ticket/8314.
  504. delta = f0 / f1;
  505. if (fabs(delta) > 2 * fabs(guess))
  506. delta = (delta < 0 ? -1 : 1) * 2 * fabs(guess);
  507. }
  508. }
  509. else
  510. delta = f0 / f1;
  511. }
  512. #ifdef BOOST_MATH_INSTRUMENT
  513. std::cout << "Second order root iteration, delta = " << delta << ", residual = " << f0 << "\n";
  514. #endif
  515. T convergence = fabs(delta / delta2);
  516. if ((convergence > 0.8) && (convergence < 2))
  517. {
  518. // last two steps haven't converged.
  519. delta = (delta > 0) ? (result - min) / 2 : (result - max) / 2;
  520. if ((result != 0) && (fabs(delta) > result))
  521. delta = sign(delta) * fabs(result) * 0.9f; // protect against huge jumps!
  522. // reset delta2 so that this branch will *not* be taken on the
  523. // next iteration:
  524. delta2 = delta * 3;
  525. delta1 = delta * 3;
  526. BOOST_MATH_INSTRUMENT_VARIABLE(delta);
  527. }
  528. guess = result;
  529. result -= delta;
  530. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  531. // check for out of bounds step:
  532. if (result < min)
  533. {
  534. T diff = ((fabs(min) < 1) && (fabs(result) > 1) && (tools::max_value<T>() / fabs(result) < fabs(min)))
  535. ? T(1000)
  536. : (fabs(min) < 1) && (fabs(tools::max_value<T>() * min) < fabs(result))
  537. ? ((min < 0) != (result < 0)) ? -tools::max_value<T>() : tools::max_value<T>() : T(result / min);
  538. if (fabs(diff) < 1)
  539. diff = 1 / diff;
  540. if (!out_of_bounds_sentry && (diff > 0) && (diff < 3))
  541. {
  542. // Only a small out of bounds step, lets assume that the result
  543. // is probably approximately at min:
  544. delta = 0.99f * (guess - min);
  545. result = guess - delta;
  546. out_of_bounds_sentry = true; // only take this branch once!
  547. }
  548. else
  549. {
  550. if (fabs(float_distance(min, max)) < 2)
  551. {
  552. result = guess = (min + max) / 2;
  553. break;
  554. }
  555. delta = bracket_root_towards_min(f, guess, f0, min, max, count);
  556. result = guess - delta;
  557. guess = min;
  558. continue;
  559. }
  560. }
  561. else if (result > max)
  562. {
  563. T diff = ((fabs(max) < 1) && (fabs(result) > 1) && (tools::max_value<T>() / fabs(result) < fabs(max))) ? T(1000) : T(result / max);
  564. if (fabs(diff) < 1)
  565. diff = 1 / diff;
  566. if (!out_of_bounds_sentry && (diff > 0) && (diff < 3))
  567. {
  568. // Only a small out of bounds step, lets assume that the result
  569. // is probably approximately at min:
  570. delta = 0.99f * (guess - max);
  571. result = guess - delta;
  572. out_of_bounds_sentry = true; // only take this branch once!
  573. }
  574. else
  575. {
  576. if (fabs(float_distance(min, max)) < 2)
  577. {
  578. result = guess = (min + max) / 2;
  579. break;
  580. }
  581. delta = bracket_root_towards_max(f, guess, f0, min, max, count);
  582. result = guess - delta;
  583. guess = min;
  584. continue;
  585. }
  586. }
  587. // update brackets:
  588. if (delta > 0)
  589. {
  590. max = guess;
  591. max_range_f = f0;
  592. }
  593. else
  594. {
  595. min = guess;
  596. min_range_f = f0;
  597. }
  598. //
  599. // Sanity check that we bracket the root:
  600. //
  601. if (max_range_f * min_range_f > 0)
  602. {
  603. return policies::raise_evaluation_error(function, "There appears to be no root to be found in boost::math::tools::newton_raphson_iterate, perhaps we have a local minima near current best guess of %1%", guess, boost::math::policies::policy<>());
  604. }
  605. } while(count && (fabs(result * factor) < fabs(delta)));
  606. max_iter -= count;
  607. #ifdef BOOST_MATH_INSTRUMENT
  608. std::cout << "Second order root finder required " << max_iter << " iterations.\n";
  609. #endif
  610. return result;
  611. }
  612. } // T second_order_root_finder
  613. template <class F, class T>
  614. T halley_iterate(F f, T guess, T min, T max, int digits, boost::uintmax_t& max_iter) BOOST_NOEXCEPT_IF(policies::is_noexcept_error_policy<policies::policy<> >::value&& BOOST_MATH_IS_FLOAT(T) && noexcept(std::declval<F>()(std::declval<T>())))
  615. {
  616. return detail::second_order_root_finder<detail::halley_step>(f, guess, min, max, digits, max_iter);
  617. }
  618. template <class F, class T>
  619. inline T halley_iterate(F f, T guess, T min, T max, int digits) BOOST_NOEXCEPT_IF(policies::is_noexcept_error_policy<policies::policy<> >::value&& BOOST_MATH_IS_FLOAT(T) && noexcept(std::declval<F>()(std::declval<T>())))
  620. {
  621. boost::uintmax_t m = (std::numeric_limits<boost::uintmax_t>::max)();
  622. return halley_iterate(f, guess, min, max, digits, m);
  623. }
  624. namespace detail {
  625. struct schroder_stepper
  626. {
  627. template <class T>
  628. static T step(const T& x, const T& f0, const T& f1, const T& f2) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(T))
  629. {
  630. using std::fabs;
  631. T ratio = f0 / f1;
  632. T delta;
  633. if ((x != 0) && (fabs(ratio / x) < 0.1))
  634. {
  635. delta = ratio + (f2 / (2 * f1)) * ratio * ratio;
  636. // check second derivative doesn't over compensate:
  637. if (delta * ratio < 0)
  638. delta = ratio;
  639. }
  640. else
  641. delta = ratio; // fall back to Newton iteration.
  642. return delta;
  643. }
  644. };
  645. }
  646. template <class F, class T>
  647. T schroder_iterate(F f, T guess, T min, T max, int digits, boost::uintmax_t& max_iter) BOOST_NOEXCEPT_IF(policies::is_noexcept_error_policy<policies::policy<> >::value&& BOOST_MATH_IS_FLOAT(T) && noexcept(std::declval<F>()(std::declval<T>())))
  648. {
  649. return detail::second_order_root_finder<detail::schroder_stepper>(f, guess, min, max, digits, max_iter);
  650. }
  651. template <class F, class T>
  652. inline T schroder_iterate(F f, T guess, T min, T max, int digits) BOOST_NOEXCEPT_IF(policies::is_noexcept_error_policy<policies::policy<> >::value&& BOOST_MATH_IS_FLOAT(T) && noexcept(std::declval<F>()(std::declval<T>())))
  653. {
  654. boost::uintmax_t m = (std::numeric_limits<boost::uintmax_t>::max)();
  655. return schroder_iterate(f, guess, min, max, digits, m);
  656. }
  657. //
  658. // These two are the old spelling of this function, retained for backwards compatibility just in case:
  659. //
  660. template <class F, class T>
  661. T schroeder_iterate(F f, T guess, T min, T max, int digits, boost::uintmax_t& max_iter) BOOST_NOEXCEPT_IF(policies::is_noexcept_error_policy<policies::policy<> >::value&& BOOST_MATH_IS_FLOAT(T) && noexcept(std::declval<F>()(std::declval<T>())))
  662. {
  663. return detail::second_order_root_finder<detail::schroder_stepper>(f, guess, min, max, digits, max_iter);
  664. }
  665. template <class F, class T>
  666. inline T schroeder_iterate(F f, T guess, T min, T max, int digits) BOOST_NOEXCEPT_IF(policies::is_noexcept_error_policy<policies::policy<> >::value&& BOOST_MATH_IS_FLOAT(T) && noexcept(std::declval<F>()(std::declval<T>())))
  667. {
  668. boost::uintmax_t m = (std::numeric_limits<boost::uintmax_t>::max)();
  669. return schroder_iterate(f, guess, min, max, digits, m);
  670. }
  671. #ifndef BOOST_NO_CXX11_AUTO_DECLARATIONS
  672. /*
  673. * Why do we set the default maximum number of iterations to the number of digits in the type?
  674. * Because for double roots, the number of digits increases linearly with the number of iterations,
  675. * so this default should recover full precision even in this somewhat pathological case.
  676. * For isolated roots, the problem is so rapidly convergent that this doesn't matter at all.
  677. */
  678. template<class Complex, class F>
  679. Complex complex_newton(F g, Complex guess, int max_iterations = std::numeric_limits<typename Complex::value_type>::digits)
  680. {
  681. typedef typename Complex::value_type Real;
  682. using std::norm;
  683. using std::abs;
  684. using std::max;
  685. // z0, z1, and z2 cannot be the same, in case we immediately need to resort to Muller's Method:
  686. Complex z0 = guess + Complex(1, 0);
  687. Complex z1 = guess + Complex(0, 1);
  688. Complex z2 = guess;
  689. do {
  690. auto pair = g(z2);
  691. if (norm(pair.second) == 0)
  692. {
  693. // Muller's method. Notation follows Numerical Recipes, 9.5.2:
  694. Complex q = (z2 - z1) / (z1 - z0);
  695. auto P0 = g(z0);
  696. auto P1 = g(z1);
  697. Complex qp1 = static_cast<Complex>(1) + q;
  698. Complex A = q * (pair.first - qp1 * P1.first + q * P0.first);
  699. Complex B = (static_cast<Complex>(2) * q + static_cast<Complex>(1)) * pair.first - qp1 * qp1 * P1.first + q * q * P0.first;
  700. Complex C = qp1 * pair.first;
  701. Complex rad = sqrt(B * B - static_cast<Complex>(4) * A * C);
  702. Complex denom1 = B + rad;
  703. Complex denom2 = B - rad;
  704. Complex correction = (z1 - z2) * static_cast<Complex>(2) * C;
  705. if (norm(denom1) > norm(denom2))
  706. {
  707. correction /= denom1;
  708. }
  709. else
  710. {
  711. correction /= denom2;
  712. }
  713. z0 = z1;
  714. z1 = z2;
  715. z2 = z2 + correction;
  716. }
  717. else
  718. {
  719. z0 = z1;
  720. z1 = z2;
  721. z2 = z2 - (pair.first / pair.second);
  722. }
  723. // See: https://math.stackexchange.com/questions/3017766/constructing-newton-iteration-converging-to-non-root
  724. // If f' is continuous, then convergence of x_n -> x* implies f(x*) = 0.
  725. // This condition approximates this convergence condition by requiring three consecutive iterates to be clustered.
  726. Real tol = (max)(abs(z2) * std::numeric_limits<Real>::epsilon(), std::numeric_limits<Real>::epsilon());
  727. bool real_close = abs(z0.real() - z1.real()) < tol && abs(z0.real() - z2.real()) < tol && abs(z1.real() - z2.real()) < tol;
  728. bool imag_close = abs(z0.imag() - z1.imag()) < tol && abs(z0.imag() - z2.imag()) < tol && abs(z1.imag() - z2.imag()) < tol;
  729. if (real_close && imag_close)
  730. {
  731. return z2;
  732. }
  733. } while (max_iterations--);
  734. // The idea is that if we can get abs(f) < eps, we should, but if we go through all these iterations
  735. // and abs(f) < sqrt(eps), then roundoff error simply does not allow that we can evaluate f to < eps
  736. // This is somewhat awkward as it isn't scale invariant, but using the Daubechies coefficient example code,
  737. // I found this condition generates correct roots, whereas the scale invariant condition discussed here:
  738. // https://scicomp.stackexchange.com/questions/30597/defining-a-condition-number-and-termination-criteria-for-newtons-method
  739. // allows nonroots to be passed off as roots.
  740. auto pair = g(z2);
  741. if (abs(pair.first) < sqrt(std::numeric_limits<Real>::epsilon()))
  742. {
  743. return z2;
  744. }
  745. return { std::numeric_limits<Real>::quiet_NaN(),
  746. std::numeric_limits<Real>::quiet_NaN() };
  747. }
  748. #endif
  749. #if !defined(BOOST_NO_CXX17_IF_CONSTEXPR)
  750. // https://stackoverflow.com/questions/48979861/numerically-stable-method-for-solving-quadratic-equations/50065711
  751. namespace detail
  752. {
  753. #if defined(BOOST_GNU_STDLIB) && !defined(_GLIBCXX_USE_C99_MATH_TR1)
  754. inline float fma_workaround(float x, float y, float z) { return ::fmaf(x, y, z); }
  755. inline double fma_workaround(double x, double y, double z) { return ::fma(x, y, z); }
  756. #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
  757. inline long double fma_workaround(long double x, long double y, long double z) { return ::fmal(x, y, z); }
  758. #endif
  759. #endif
  760. template<class T>
  761. inline T discriminant(T const& a, T const& b, T const& c)
  762. {
  763. T w = 4 * a * c;
  764. #if defined(BOOST_GNU_STDLIB) && !defined(_GLIBCXX_USE_C99_MATH_TR1)
  765. T e = fma_workaround(-c, 4 * a, w);
  766. T f = fma_workaround(b, b, -w);
  767. #else
  768. T e = std::fma(-c, 4 * a, w);
  769. T f = std::fma(b, b, -w);
  770. #endif
  771. return f + e;
  772. }
  773. template<class T>
  774. std::pair<T, T> quadratic_roots_imp(T const& a, T const& b, T const& c)
  775. {
  776. #if defined(BOOST_GNU_STDLIB) && !defined(_GLIBCXX_USE_C99_MATH_TR1)
  777. using boost::math::copysign;
  778. #else
  779. using std::copysign;
  780. #endif
  781. using std::sqrt;
  782. if constexpr (std::is_floating_point<T>::value)
  783. {
  784. T nan = std::numeric_limits<T>::quiet_NaN();
  785. if (a == 0)
  786. {
  787. if (b == 0 && c != 0)
  788. {
  789. return std::pair<T, T>(nan, nan);
  790. }
  791. else if (b == 0 && c == 0)
  792. {
  793. return std::pair<T, T>(0, 0);
  794. }
  795. return std::pair<T, T>(-c / b, -c / b);
  796. }
  797. if (b == 0)
  798. {
  799. T x0_sq = -c / a;
  800. if (x0_sq < 0) {
  801. return std::pair<T, T>(nan, nan);
  802. }
  803. T x0 = sqrt(x0_sq);
  804. return std::pair<T, T>(-x0, x0);
  805. }
  806. T discriminant = detail::discriminant(a, b, c);
  807. // Is there a sane way to flush very small negative values to zero?
  808. // If there is I don't know of it.
  809. if (discriminant < 0)
  810. {
  811. return std::pair<T, T>(nan, nan);
  812. }
  813. T q = -(b + copysign(sqrt(discriminant), b)) / T(2);
  814. T x0 = q / a;
  815. T x1 = c / q;
  816. if (x0 < x1)
  817. {
  818. return std::pair<T, T>(x0, x1);
  819. }
  820. return std::pair<T, T>(x1, x0);
  821. }
  822. else if constexpr (boost::math::tools::is_complex_type<T>::value)
  823. {
  824. typename T::value_type nan = std::numeric_limits<typename T::value_type>::quiet_NaN();
  825. if (a.real() == 0 && a.imag() == 0)
  826. {
  827. using std::norm;
  828. if (b.real() == 0 && b.imag() && norm(c) != 0)
  829. {
  830. return std::pair<T, T>({ nan, nan }, { nan, nan });
  831. }
  832. else if (b.real() == 0 && b.imag() && c.real() == 0 && c.imag() == 0)
  833. {
  834. return std::pair<T, T>({ 0,0 }, { 0,0 });
  835. }
  836. return std::pair<T, T>(-c / b, -c / b);
  837. }
  838. if (b.real() == 0 && b.imag() == 0)
  839. {
  840. T x0_sq = -c / a;
  841. T x0 = sqrt(x0_sq);
  842. return std::pair<T, T>(-x0, x0);
  843. }
  844. // There's no fma for complex types:
  845. T discriminant = b * b - T(4) * a * c;
  846. T q = -(b + sqrt(discriminant)) / T(2);
  847. return std::pair<T, T>(q / a, c / q);
  848. }
  849. else // Most likely the type is a boost.multiprecision.
  850. { //There is no fma for multiprecision, and in addition it doesn't seem to be useful, so revert to the naive computation.
  851. T nan = std::numeric_limits<T>::quiet_NaN();
  852. if (a == 0)
  853. {
  854. if (b == 0 && c != 0)
  855. {
  856. return std::pair<T, T>(nan, nan);
  857. }
  858. else if (b == 0 && c == 0)
  859. {
  860. return std::pair<T, T>(0, 0);
  861. }
  862. return std::pair<T, T>(-c / b, -c / b);
  863. }
  864. if (b == 0)
  865. {
  866. T x0_sq = -c / a;
  867. if (x0_sq < 0) {
  868. return std::pair<T, T>(nan, nan);
  869. }
  870. T x0 = sqrt(x0_sq);
  871. return std::pair<T, T>(-x0, x0);
  872. }
  873. T discriminant = b * b - 4 * a * c;
  874. if (discriminant < 0)
  875. {
  876. return std::pair<T, T>(nan, nan);
  877. }
  878. T q = -(b + copysign(sqrt(discriminant), b)) / T(2);
  879. T x0 = q / a;
  880. T x1 = c / q;
  881. if (x0 < x1)
  882. {
  883. return std::pair<T, T>(x0, x1);
  884. }
  885. return std::pair<T, T>(x1, x0);
  886. }
  887. }
  888. } // namespace detail
  889. template<class T1, class T2 = T1, class T3 = T1>
  890. inline std::pair<typename tools::promote_args<T1, T2, T3>::type, typename tools::promote_args<T1, T2, T3>::type> quadratic_roots(T1 const& a, T2 const& b, T3 const& c)
  891. {
  892. typedef typename tools::promote_args<T1, T2, T3>::type value_type;
  893. return detail::quadratic_roots_imp(static_cast<value_type>(a), static_cast<value_type>(b), static_cast<value_type>(c));
  894. }
  895. #endif
  896. } // namespace tools
  897. } // namespace math
  898. } // namespace boost
  899. #endif // BOOST_MATH_TOOLS_NEWTON_SOLVER_HPP