roots.hpp 26 KB

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