|
| 1 | +[section:polynomial_roots Complex Roots of a Polynomial] |
| 2 | + |
| 3 | +`` |
| 4 | +#include <boost/math/tools/polynomial_roots.hpp> |
| 5 | +#include <boost/math/tools/amvw_roots.hpp> |
| 6 | +`` |
| 7 | + |
| 8 | + template <class Real> |
| 9 | + std::vector<std::complex<Real> > |
| 10 | + polynomial_roots(std::vector<Real> coefficients, |
| 11 | + unsigned precision = std::numeric_limits<Real>::digits); |
| 12 | + |
| 13 | + template <class Real> |
| 14 | + std::vector<std::complex<Real> > |
| 15 | + amvw_roots(std::vector<Real> coefficients); |
| 16 | + |
| 17 | +`polynomial_roots` computes all finite complex roots of a polynomial with real, |
| 18 | +floating-point coefficients. Coefficients are supplied in ascending order, so |
| 19 | +`{a0, a1, ..., an}` represents |
| 20 | +[@https://en.wikipedia.org/wiki/Polynomial a0 + a1 z + ... + an z^n]. |
| 21 | +The returned order is unspecified. |
| 22 | + |
| 23 | +The implementation follows the piecewise approximation strategy of Imbach and |
| 24 | +Moroz: a Newton-polygon sweep divides the complex plane into radial rings, the |
| 25 | +rings are divided into angular sectors, and low-degree Taylor polynomials are |
| 26 | +factored locally. Candidate roots are polished and checked against the input |
| 27 | +polynomial. A global Aberth iteration is used as a safety net for unresolved or |
| 28 | +ill-conditioned clusters. |
| 29 | + |
| 30 | +Exact leading zero coefficients are ignored. Exact trailing zero coefficients |
| 31 | +produce the corresponding number of roots at zero. The zero polynomial, a zero |
| 32 | +precision request, and non-finite coefficients cause `std::domain_error` to be |
| 33 | +thrown. |
| 34 | + |
| 35 | +The optional `precision` argument is measured in bits and controls the local |
| 36 | +approximation order. Its default is appropriate for the coefficient type. |
| 37 | + |
| 38 | +[heading The companion QR algorithm] |
| 39 | + |
| 40 | +`amvw_roots` computes the same roots as the eigenvalues of the companion matrix, |
| 41 | +by the core-chasing QR algorithm of Aurentz, Mach, Vandebril and Watkins. It |
| 42 | +stores the companion matrix as O(n) 2x2 unitary rotations, so it takes O(n[super 2]) |
| 43 | +time and O(n) memory, against O(n[super 3]) and O(n[super 2]) for a dense |
| 44 | +eigensolver. Before the iteration the variable is scaled so that the constant |
| 45 | +and leading coefficients have equal magnitude. |
| 46 | + |
| 47 | +The two functions make different guarantees. `amvw_roots` is proven normwise |
| 48 | +backward stable: all of its roots are the exact roots of a single polynomial |
| 49 | +whose coefficient vector is within a modest multiple of n[epsilon] of the input, |
| 50 | +relative to the norm of the coefficients. `polynomial_roots` checks a stronger, |
| 51 | +coefficientwise, bound on each root: each one is an exact root of a polynomial |
| 52 | +whose coefficients each differ from the input in only the last few bits. |
| 53 | +It has no a priori proof of convergence, but it returns only roots that |
| 54 | +pass this check. The coefficientwise bound matters when the roots span many |
| 55 | +orders of magnitude, as in [prod](z - 10[super -k]): the small roots are |
| 56 | +determined by the small coefficients, which a normwise perturbation may change |
| 57 | +completely, so `amvw_roots` gets the small roots wrong while `polynomial_roots` |
| 58 | +gets them to nearly full precision. For roots of comparable magnitude the |
| 59 | +two agree. |
| 60 | + |
| 61 | +Exact zero coefficients are handled as for `polynomial_roots`. The zero |
| 62 | +polynomial and non-finite coefficients cause `std::domain_error` to be |
| 63 | +thrown, and `std::runtime_error` is thrown in the unlikely event that the QR |
| 64 | +iteration fails to converge. |
| 65 | + |
| 66 | +[heading Example] |
| 67 | + |
| 68 | + std::vector<double> p{1, 0, 1}; // 1 + z^2 |
| 69 | + auto roots = boost::math::tools::polynomial_roots(p); |
| 70 | + |
| 71 | +The result contains approximations to `i` and `-i`. |
| 72 | + |
| 73 | +[heading References] |
| 74 | + |
| 75 | +J. Imbach and G. Moroz, "Fast evaluation and root finding for polynomials with |
| 76 | +floating-point coefficients", 2023. |
| 77 | + |
| 78 | +J. L. Aurentz, T. Mach, R. Vandebril and D. S. Watkins, "Fast and backward |
| 79 | +stable computation of roots of polynomials", SIAM J. Matrix Anal. Appl. 36 |
| 80 | +(2015), 942-973. |
| 81 | + |
| 82 | +J. L. Aurentz, T. Mach, L. Robol, R. Vandebril and D. S. Watkins, "Fast and |
| 83 | +backward stable computation of roots of polynomials, Part II: backward error |
| 84 | +analysis; companion matrix and companion pencil", SIAM J. Matrix Anal. Appl. |
| 85 | +39 (2018), 1245-1269. |
| 86 | + |
| 87 | +[endsect] |
0 commit comments