roots.hpp 34 KB

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