10#ifndef EIGEN_POLYNOMIAL_SOLVER_H
11#define EIGEN_POLYNOMIAL_SOLVER_H
14#include "./InternalHeaderCheck.h"
31template <
typename Scalar_,
int Deg_>
32class PolynomialSolverBase {
34 EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(Scalar_, Deg_ ==
Dynamic ?
Dynamic : Deg_)
36 typedef Scalar_ Scalar;
38 typedef internal::make_complex_t<Scalar> RootType;
41 typedef DenseIndex Index;
44 template <
typename OtherPolynomial>
45 inline void setPolynomial(
const OtherPolynomial& poly) {
46 m_roots.
resize(poly.size() - 1);
50 template <
typename OtherPolynomial>
51 inline PolynomialSolverBase(
const OtherPolynomial& poly) {
52 setPolynomial(poly());
55 inline PolynomialSolverBase() {}
59 inline const RootsType&
roots()
const {
return m_roots; }
72 template <
typename Stl_back_insertion_sequence>
73 inline void realRoots(Stl_back_insertion_sequence& bi_seq,
77 for (Index i = 0; i < m_roots.size(); ++i) {
78 if (
abs(m_roots[i].
imag()) < absImaginaryThreshold) {
79 bi_seq.push_back(m_roots[i].
real());
85 template <
typename squaredNormBinaryPredicate>
86 inline const RootType& selectComplexRoot_withRespectToNorm(squaredNormBinaryPredicate& pred)
const {
88 RealScalar norm2 = numext::abs2(m_roots[0]);
89 for (
Index i = 1; i < m_roots.size(); ++i) {
90 const RealScalar currNorm2 = numext::abs2(m_roots[i]);
91 if (pred(currNorm2, norm2)) {
104 std::greater<RealScalar> greater;
105 return selectComplexRoot_withRespectToNorm(greater);
112 std::less<RealScalar> less;
113 return selectComplexRoot_withRespectToNorm(less);
117 template <
typename squaredRealPartBinaryPredicate>
118 inline const RealScalar& selectRealRoot_withRespectToAbsRealPart(
119 squaredRealPartBinaryPredicate& pred,
bool& hasArealRoot,
122 hasArealRoot =
false;
126 for (
Index i = 0; i < m_roots.size(); ++i) {
127 if (
abs(m_roots[i].
imag()) <= absImaginaryThreshold) {
131 abs2 = m_roots[i].real() * m_roots[i].real();
133 const RealScalar currAbs2 = m_roots[i].real() * m_roots[i].real();
134 if (pred(currAbs2,
abs2)) {
139 }
else if (!hasArealRoot) {
145 return numext::real_ref(m_roots[res]);
148 template <
typename RealPartBinaryPredicate>
149 inline const RealScalar& selectRealRoot_withRespectToRealPart(
150 RealPartBinaryPredicate& pred,
bool& hasArealRoot,
151 const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision())
const {
153 hasArealRoot =
false;
157 for (Index i = 0; i < m_roots.size(); ++i) {
158 if (
abs(m_roots[i].
imag()) <= absImaginaryThreshold) {
162 val = m_roots[i].real();
164 const RealScalar curr = m_roots[i].real();
165 if (pred(curr, val)) {
176 return numext::real_ref(m_roots[res]);
196 std::greater<RealScalar> greater;
197 return selectRealRoot_withRespectToAbsRealPart(greater, hasArealRoot, absImaginaryThreshold);
216 std::less<RealScalar> less;
217 return selectRealRoot_withRespectToAbsRealPart(less, hasArealRoot, absImaginaryThreshold);
236 std::greater<RealScalar> greater;
237 return selectRealRoot_withRespectToRealPart(greater, hasArealRoot, absImaginaryThreshold);
256 std::less<RealScalar> less;
257 return selectRealRoot_withRespectToRealPart(less, hasArealRoot, absImaginaryThreshold);
264#define EIGEN_POLYNOMIAL_SOLVER_BASE_INHERITED_TYPES(BASE) \
265 typedef typename BASE::Scalar Scalar; \
266 typedef typename BASE::RealScalar RealScalar; \
267 typedef typename BASE::RootType RootType; \
268 typedef typename BASE::RootsType RootsType;
299template <
typename Scalar_,
int Deg_>
300class PolynomialSolver :
public PolynomialSolverBase<Scalar_, Deg_> {
302 EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(Scalar_, Deg_ ==
Dynamic ?
Dynamic : Deg_)
304 typedef PolynomialSolverBase<Scalar_, Deg_> PS_Base;
305 EIGEN_POLYNOMIAL_SOLVER_BASE_INHERITED_TYPES(PS_Base)
311 typedef internal::make_complex_t<Scalar_> ComplexScalar;
315 template <
typename OtherPolynomial>
317 eigen_assert(Scalar(0) != poly[poly.size() - 1]);
318 eigen_assert(poly.size() > 1);
319 if (poly.size() > 2) {
320 internal::companion<Scalar, Deg_> companion(poly);
322 m_eigenSolver.compute(companion.denseMatrix());
324 m_roots = m_eigenSolver.eigenvalues();
330 for (Index i = 0; i < m_roots.size(); ++i) {
331 if (internal::isMuchSmallerThan(numext::abs(numext::imag(m_roots[i])), numext::abs(numext::real(m_roots[i])),
333 ComplexScalar as_real_root = ComplexScalar(numext::real(m_roots[i]));
334 if (numext::abs(
poly_eval(poly, as_real_root)) <= numext::abs(
poly_eval(poly, m_roots[i]))) {
335 m_roots[i] = as_real_root;
339 }
else if (poly.size() == 2) {
341 m_roots[0] = -poly[0] / poly[1];
346 template <
typename OtherPolynomial>
351 inline PolynomialSolver() {}
354 using PS_Base::m_roots;
355 EigenSolverType m_eigenSolver;
358template <
typename Scalar_>
361 typedef PolynomialSolverBase<Scalar_, 1> PS_Base;
362 EIGEN_POLYNOMIAL_SOLVER_BASE_INHERITED_TYPES(PS_Base)
366 template <
typename OtherPolynomial>
367 void compute(
const OtherPolynomial& poly) {
368 eigen_assert(poly.size() == 2);
369 eigen_assert(Scalar(0) != poly[1]);
370 m_roots[0] = -poly[0] / poly[1];
374 template <
typename OtherPolynomial>
375 inline PolynomialSolver(
const OtherPolynomial& poly) {
379 inline PolynomialSolver() {}
382 using PS_Base::m_roots;
constexpr void resize(Index rows, Index cols)
Defined to be inherited by polynomial solvers: it provides convenient methods such as.
Definition PolynomialSolver.h:32
const RealScalar & smallestRealRoot(bool &hasArealRoot, const RealScalar &absImaginaryThreshold=NumTraits< Scalar >::dummy_precision()) const
Definition PolynomialSolver.h:254
const RealScalar & absGreatestRealRoot(bool &hasArealRoot, const RealScalar &absImaginaryThreshold=NumTraits< Scalar >::dummy_precision()) const
Definition PolynomialSolver.h:194
const RealScalar & absSmallestRealRoot(bool &hasArealRoot, const RealScalar &absImaginaryThreshold=NumTraits< Scalar >::dummy_precision()) const
Definition PolynomialSolver.h:214
void realRoots(Stl_back_insertion_sequence &bi_seq, const RealScalar &absImaginaryThreshold=NumTraits< Scalar >::dummy_precision()) const
Definition PolynomialSolver.h:73
const RootType & greatestRoot() const
Definition PolynomialSolver.h:103
const RealScalar & greatestRealRoot(bool &hasArealRoot, const RealScalar &absImaginaryThreshold=NumTraits< Scalar >::dummy_precision()) const
Definition PolynomialSolver.h:234
const RootType & smallestRoot() const
Definition PolynomialSolver.h:111
const RootsType & roots() const
Definition PolynomialSolver.h:59
A polynomial solver.
Definition PolynomialSolver.h:300
void compute(const OtherPolynomial &poly)
Definition PolynomialSolver.h:316
T poly_eval(const Polynomials &poly, const T &x)
Definition PolynomialUtils.h:47
Namespace containing all symbols from the Eigen library.
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_real_op< typename Derived::Scalar >, const Derived > real(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_abs_op< typename Derived::Scalar >, const Derived > abs(const Eigen::ArrayBase< Derived > &x)
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_abs2_op< typename Derived::Scalar >, const Derived > abs2(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_imag_op< typename Derived::Scalar >, const Derived > imag(const Eigen::ArrayBase< Derived > &x)