roots.hpp 35 KB

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