34 #include <Eigen/Eigenvalues>
42 Eigen::VectorXd RemoveLeadingZeros(
const Eigen::VectorXd&
coeffs) {
44 for (; num_zeros <
coeffs.size(); ++num_zeros) {
45 if (
coeffs(num_zeros) != 0) {
53 Eigen::VectorXd RemoveTrailingZeros(
const Eigen::VectorXd&
coeffs) {
55 for (; num_zeros <
coeffs.size(); ++num_zeros) {
66 Eigen::VectorXd* real, Eigen::VectorXd* imag) {
67 CHECK_EQ(
coeffs.size(), 2);
73 if (real !=
nullptr) {
78 if (imag !=
nullptr) {
87 Eigen::VectorXd* real,
88 Eigen::VectorXd* imag) {
89 CHECK_EQ(
coeffs.size(), 3);
96 const double b =
coeffs(1);
97 const double c =
coeffs(2);
98 if (b == 0 && c == 0) {
99 if (real !=
nullptr) {
103 if (imag !=
nullptr) {
110 const double d = b * b - 4 *
a * c;
113 const double sqrt_d = std::sqrt(d);
114 if (real !=
nullptr) {
117 (*real)(0) = (-b - sqrt_d) / (2 *
a);
118 (*real)(1) = (2 * c) / (-b - sqrt_d);
120 (*real)(0) = (2 * c) / (-b + sqrt_d);
121 (*real)(1) = (-b + sqrt_d) / (2 *
a);
124 if (imag !=
nullptr) {
129 if (real !=
nullptr) {
131 real->setConstant(-b / (2 *
a));
133 if (imag !=
nullptr) {
135 (*imag)(0) = std::sqrt(-d) / (2 *
a);
136 (*imag)(1) = -(*imag)(0);
144 Eigen::VectorXd* real,
145 Eigen::VectorXd* imag) {
146 CHECK_GE(coeffs_all.size(), 2);
148 const Eigen::VectorXd
coeffs = RemoveLeadingZeros(coeffs_all);
150 const int degree =
coeffs.size() - 1;
154 }
else if (degree == 1) {
156 }
else if (degree == 2) {
161 Eigen::VectorXcd roots(degree);
162 roots(degree - 1) = std::complex<double>(1, 0);
163 for (
int i = degree - 2; i >= 0; --i) {
164 roots(i) = roots(i + 1) * std::complex<double>(1, 1);
168 const int kMaxNumIterations = 100;
169 const double kMaxRootChange = 1
e-10;
170 for (
int iter = 0; iter < kMaxNumIterations; ++iter) {
171 double max_root_change = 0.0;
172 for (
int i = 0; i < degree; ++i) {
173 const std::complex<double> root_i = roots(i);
174 std::complex<double> numerator =
coeffs[0];
175 std::complex<double> denominator =
coeffs[0];
176 for (
int j = 0; j < degree; ++j) {
177 numerator = numerator * root_i +
coeffs[j + 1];
179 denominator = denominator * (root_i - roots(j));
182 const std::complex<double> root_i_change = numerator / denominator;
183 roots(i) = root_i - root_i_change;
185 std::max(max_root_change, std::abs(root_i_change.real()));
187 std::max(max_root_change, std::abs(root_i_change.imag()));
191 if (max_root_change < kMaxRootChange) {
196 if (real !=
nullptr) {
197 real->resize(degree);
198 *real = roots.real();
200 if (imag !=
nullptr) {
201 imag->resize(degree);
202 *imag = roots.imag();
209 Eigen::VectorXd* real,
210 Eigen::VectorXd* imag) {
211 CHECK_GE(coeffs_all.size(), 2);
213 Eigen::VectorXd
coeffs = RemoveLeadingZeros(coeffs_all);
215 const int degree =
coeffs.size() - 1;
219 }
else if (degree == 1) {
221 }
else if (degree == 2) {
230 if (real !=
nullptr) {
234 if (imag !=
nullptr) {
242 Eigen::MatrixXd C(
coeffs.size() - 1,
coeffs.size() - 1);
250 Eigen::EigenSolver<Eigen::MatrixXd> solver(C,
false);
251 if (solver.info() != Eigen::Success) {
256 const int effective_degree =
259 if (real !=
nullptr) {
260 real->resize(effective_degree);
261 real->head(
coeffs.size() - 1) = solver.eigenvalues().real();
262 if (effective_degree >
coeffs.size() - 1) {
263 (*real)(real->size() - 1) = 0;
266 if (imag !=
nullptr) {
267 imag->resize(effective_degree);
268 imag->head(
coeffs.size() - 1) = solver.eigenvalues().imag();
269 if (effective_degree >
coeffs.size() - 1) {
270 (*imag)(imag->size() - 1) = 0;
bool FindPolynomialRootsCompanionMatrix(const Eigen::VectorXd &coeffs_all, Eigen::VectorXd *real, Eigen::VectorXd *imag)
bool FindLinearPolynomialRoots(const Eigen::VectorXd &coeffs, Eigen::VectorXd *real, Eigen::VectorXd *imag)
bool FindQuadraticPolynomialRoots(const Eigen::VectorXd &coeffs, Eigen::VectorXd *real, Eigen::VectorXd *imag)
bool FindPolynomialRootsDurandKerner(const Eigen::VectorXd &coeffs_all, Eigen::VectorXd *real, Eigen::VectorXd *imag)
Eigen::MatrixXd::Index Index