PolynomialSolver.h
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2010 Manuel Yguel <manuel.yguel@gmail.com>
5 //
6 // This Source Code Form is subject to the terms of the Mozilla
7 // Public License v. 2.0. If a copy of the MPL was not distributed
8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 
10 #ifndef EIGEN_POLYNOMIAL_SOLVER_H
11 #define EIGEN_POLYNOMIAL_SOLVER_H
12 
13 // IWYU pragma: private
14 #include "./InternalHeaderCheck.h"
15 
16 namespace Eigen {
17 
31 template <typename Scalar_, int Deg_>
33  public:
35 
36  typedef Scalar_ Scalar;
37  typedef typename NumTraits<Scalar>::Real RealScalar;
38  typedef std::complex<RealScalar> RootType;
39  typedef Matrix<RootType, Deg_, 1> RootsType;
40 
41  typedef DenseIndex Index;
42 
43  protected:
44  template <typename OtherPolynomial>
45  inline void setPolynomial(const OtherPolynomial& poly) {
46  m_roots.resize(poly.size() - 1);
47  }
48 
49  public:
50  template <typename OtherPolynomial>
51  inline PolynomialSolverBase(const OtherPolynomial& poly) {
52  setPolynomial(poly());
53  }
54 
56 
57  public:
59  inline const RootsType& roots() const { return m_roots; }
60 
61  public:
72  template <typename Stl_back_insertion_sequence>
73  inline void realRoots(Stl_back_insertion_sequence& bi_seq,
74  const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision()) const {
75  using std::abs;
76  bi_seq.clear();
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());
80  }
81  }
82  }
83 
84  protected:
85  template <typename squaredNormBinaryPredicate>
86  inline const RootType& selectComplexRoot_withRespectToNorm(squaredNormBinaryPredicate& pred) const {
87  Index res = 0;
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)) {
92  res = i;
93  norm2 = currNorm2;
94  }
95  }
96  return m_roots[res];
97  }
98 
99  public:
103  inline const RootType& greatestRoot() const {
104  std::greater<RealScalar> greater;
105  return selectComplexRoot_withRespectToNorm(greater);
106  }
107 
111  inline const RootType& smallestRoot() const {
112  std::less<RealScalar> less;
114  }
115 
116  protected:
117  template <typename squaredRealPartBinaryPredicate>
119  squaredRealPartBinaryPredicate& pred, bool& hasArealRoot,
120  const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision()) const {
121  using std::abs;
122  hasArealRoot = false;
123  Index res = 0;
124  RealScalar abs2(0);
125 
126  for (Index i = 0; i < m_roots.size(); ++i) {
127  if (abs(m_roots[i].imag()) <= absImaginaryThreshold) {
128  if (!hasArealRoot) {
129  hasArealRoot = true;
130  res = i;
131  abs2 = m_roots[i].real() * m_roots[i].real();
132  } else {
133  const RealScalar currAbs2 = m_roots[i].real() * m_roots[i].real();
134  if (pred(currAbs2, abs2)) {
135  abs2 = currAbs2;
136  res = i;
137  }
138  }
139  } else if (!hasArealRoot) {
140  if (abs(m_roots[i].imag()) < abs(m_roots[res].imag())) {
141  res = i;
142  }
143  }
144  }
145  return numext::real_ref(m_roots[res]);
146  }
147 
148  template <typename RealPartBinaryPredicate>
150  RealPartBinaryPredicate& pred, bool& hasArealRoot,
151  const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision()) const {
152  using std::abs;
153  hasArealRoot = false;
154  Index res = 0;
155  RealScalar val(0);
156 
157  for (Index i = 0; i < m_roots.size(); ++i) {
158  if (abs(m_roots[i].imag()) <= absImaginaryThreshold) {
159  if (!hasArealRoot) {
160  hasArealRoot = true;
161  res = i;
162  val = m_roots[i].real();
163  } else {
164  const RealScalar curr = m_roots[i].real();
165  if (pred(curr, val)) {
166  val = curr;
167  res = i;
168  }
169  }
170  } else {
171  if (abs(m_roots[i].imag()) < abs(m_roots[res].imag())) {
172  res = i;
173  }
174  }
175  }
176  return numext::real_ref(m_roots[res]);
177  }
178 
179  public:
195  bool& hasArealRoot, const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision()) const {
196  std::greater<RealScalar> greater;
197  return selectRealRoot_withRespectToAbsRealPart(greater, hasArealRoot, absImaginaryThreshold);
198  }
199 
215  bool& hasArealRoot, const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision()) const {
216  std::less<RealScalar> less;
217  return selectRealRoot_withRespectToAbsRealPart(less, hasArealRoot, absImaginaryThreshold);
218  }
219 
235  bool& hasArealRoot, const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision()) const {
236  std::greater<RealScalar> greater;
237  return selectRealRoot_withRespectToRealPart(greater, hasArealRoot, absImaginaryThreshold);
238  }
239 
255  bool& hasArealRoot, const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision()) const {
256  std::less<RealScalar> less;
257  return selectRealRoot_withRespectToRealPart(less, hasArealRoot, absImaginaryThreshold);
258  }
259 
260  protected:
262 };
263 
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;
269 
299 template <typename Scalar_, int Deg_>
300 class PolynomialSolver : public PolynomialSolverBase<Scalar_, Deg_> {
301  public:
303 
304  typedef PolynomialSolverBase<Scalar_, Deg_> PS_Base;
306 
307  typedef Matrix<Scalar, Deg_, Deg_> CompanionMatrixType;
308  typedef std::conditional_t<NumTraits<Scalar>::IsComplex, ComplexEigenSolver<CompanionMatrixType>,
311  typedef std::conditional_t<NumTraits<Scalar>::IsComplex, Scalar, std::complex<Scalar> > ComplexScalar;
312 
313  public:
315  template <typename OtherPolynomial>
316  void compute(const OtherPolynomial& poly) {
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);
321  companion.balance();
322  m_eigenSolver.compute(companion.denseMatrix());
324  m_roots = m_eigenSolver.eigenvalues();
325  // cleanup noise in imaginary part of real roots:
326  // if the imaginary part is rather small compared to the real part
327  // and that cancelling the imaginary part yield a smaller evaluation,
328  // then it's safe to keep the real part only.
329  RealScalar coarse_prec = RealScalar(std::pow(4, poly.size() + 1)) * NumTraits<RealScalar>::epsilon();
330  for (Index i = 0; i < m_roots.size(); ++i) {
332  coarse_prec)) {
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;
336  }
337  }
338  }
339  } else if (poly.size() == 2) {
340  m_roots.resize(1);
341  m_roots[0] = -poly[0] / poly[1];
342  }
343  }
344 
345  public:
346  template <typename OtherPolynomial>
347  inline PolynomialSolver(const OtherPolynomial& poly) {
348  compute(poly);
349  }
350 
351  inline PolynomialSolver() {}
352 
353  protected:
354  using PS_Base::m_roots;
356 };
357 
358 template <typename Scalar_>
359 class PolynomialSolver<Scalar_, 1> : public PolynomialSolverBase<Scalar_, 1> {
360  public:
363 
364  public:
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];
371  }
372 
373  public:
374  template <typename OtherPolynomial>
375  inline PolynomialSolver(const OtherPolynomial& poly) {
376  compute(poly);
377  }
378 
379  inline PolynomialSolver() {}
380 
381  protected:
382  using PS_Base::m_roots;
383 };
384 
385 } // end namespace Eigen
386 
387 #endif // EIGEN_POLYNOMIAL_SOLVER_H
AnnoyingScalar abs(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:135
AnnoyingScalar imag(const AnnoyingScalar &)
Definition: AnnoyingScalar.h:132
int i
Definition: BiCGSTAB_step_by_step.cpp:9
#define eigen_assert(x)
Definition: Macros.h:910
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(Scalar, Size)
Definition: Memory.h:880
cout<< "Here is the matrix m:"<< endl<< m<< endl;Matrix< ptrdiff_t, 3, 1 > res
Definition: PartialRedux_count.cpp:3
#define EIGEN_POLYNOMIAL_SOLVER_BASE_INHERITED_TYPES(BASE)
Definition: PolynomialSolver.h:264
boost::multiprecision::number< boost::multiprecision::cpp_dec_float< 100 >, boost::multiprecision::et_on > Real
Definition: boostmultiprec.cpp:77
Computes eigenvalues and eigenvectors of general complex matrices.
Definition: ComplexEigenSolver.h:49
Computes eigenvalues and eigenvectors of general matrices.
Definition: EigenSolver.h:68
The matrix class, also used for vectors and row-vectors.
Definition: Eigen/Eigen/src/Core/Matrix.h:186
EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void resize(Index rows, Index cols)
Definition: PlainObjectBase.h:294
Defined to be inherited by polynomial solvers: it provides convenient methods such as.
Definition: PolynomialSolver.h:32
void setPolynomial(const OtherPolynomial &poly)
Definition: PolynomialSolver.h:45
const RealScalar & selectRealRoot_withRespectToRealPart(RealPartBinaryPredicate &pred, bool &hasArealRoot, const RealScalar &absImaginaryThreshold=NumTraits< Scalar >::dummy_precision()) const
Definition: PolynomialSolver.h:149
PolynomialSolverBase(const OtherPolynomial &poly)
Definition: PolynomialSolver.h:51
const RootType & greatestRoot() const
Definition: PolynomialSolver.h:103
std::complex< RealScalar > RootType
Definition: PolynomialSolver.h:38
const RootType & smallestRoot() const
Definition: PolynomialSolver.h:111
const RootType & selectComplexRoot_withRespectToNorm(squaredNormBinaryPredicate &pred) const
Definition: PolynomialSolver.h:86
const RealScalar & greatestRealRoot(bool &hasArealRoot, const RealScalar &absImaginaryThreshold=NumTraits< Scalar >::dummy_precision()) const
Definition: PolynomialSolver.h:234
const RealScalar & selectRealRoot_withRespectToAbsRealPart(squaredRealPartBinaryPredicate &pred, bool &hasArealRoot, const RealScalar &absImaginaryThreshold=NumTraits< Scalar >::dummy_precision()) const
Definition: PolynomialSolver.h:118
void realRoots(Stl_back_insertion_sequence &bi_seq, const RealScalar &absImaginaryThreshold=NumTraits< Scalar >::dummy_precision()) const
Definition: PolynomialSolver.h:73
PolynomialSolverBase()
Definition: PolynomialSolver.h:55
const RealScalar & smallestRealRoot(bool &hasArealRoot, const RealScalar &absImaginaryThreshold=NumTraits< Scalar >::dummy_precision()) const
Definition: PolynomialSolver.h:254
NumTraits< Scalar >::Real RealScalar
Definition: PolynomialSolver.h:37
Scalar_ Scalar
Definition: PolynomialSolver.h:36
const RealScalar & absSmallestRealRoot(bool &hasArealRoot, const RealScalar &absImaginaryThreshold=NumTraits< Scalar >::dummy_precision()) const
Definition: PolynomialSolver.h:214
RootsType m_roots
Definition: PolynomialSolver.h:261
const RealScalar & absGreatestRealRoot(bool &hasArealRoot, const RealScalar &absImaginaryThreshold=NumTraits< Scalar >::dummy_precision()) const
Definition: PolynomialSolver.h:194
const RootsType & roots() const
Definition: PolynomialSolver.h:59
DenseIndex Index
Definition: PolynomialSolver.h:41
void compute(const OtherPolynomial &poly)
Definition: PolynomialSolver.h:367
PolynomialSolver()
Definition: PolynomialSolver.h:379
PolynomialSolver(const OtherPolynomial &poly)
Definition: PolynomialSolver.h:375
PolynomialSolverBase< Scalar_, 1 > PS_Base
Definition: PolynomialSolver.h:361
A polynomial solver.
Definition: PolynomialSolver.h:300
EigenSolverType m_eigenSolver
Definition: PolynomialSolver.h:355
void compute(const OtherPolynomial &poly)
Definition: PolynomialSolver.h:316
PolynomialSolver(const OtherPolynomial &poly)
Definition: PolynomialSolver.h:347
PolynomialSolver()
Definition: PolynomialSolver.h:351
RootsType m_roots
Definition: PolynomialSolver.h:261
std::conditional_t< NumTraits< Scalar >::IsComplex, ComplexEigenSolver< CompanionMatrixType >, EigenSolver< CompanionMatrixType > > EigenSolverType
Definition: PolynomialSolver.h:310
std::conditional_t< NumTraits< Scalar >::IsComplex, Scalar, std::complex< Scalar > > ComplexScalar
Definition: PolynomialSolver.h:311
Definition: Companion.h:34
DenseCompanionMatrixType denseMatrix() const
Definition: Companion.h:80
void balance()
Definition: Companion.h:193
@ IsComplex
Definition: common.h:73
float real
Definition: datatypes.h:10
@ Success
Definition: Constants.h:440
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 pow(const bfloat16 &a, const bfloat16 &b)
Definition: BFloat16.h:625
EIGEN_DEVICE_FUNC bool isMuchSmallerThan(const Scalar &x, const OtherScalar &y, const typename NumTraits< Scalar >::Real &precision=NumTraits< Scalar >::dummy_precision())
Definition: MathFunctions.h:1916
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE std::enable_if_t< NumTraits< T >::IsSigned||NumTraits< T >::IsComplex, typename NumTraits< T >::Real > abs(const T &x)
Definition: MathFunctions.h:1355
EIGEN_DEVICE_FUNC internal::add_const_on_value_type_t< EIGEN_MATHFUNC_RETVAL(real_ref, Scalar)> real_ref(const Scalar &x)
Definition: MathFunctions.h:1051
EIGEN_DEVICE_FUNC bool abs2(bool x)
Definition: MathFunctions.h:1102
Namespace containing all symbols from the Eigen library.
Definition: bench_norm.cpp:70
const AutoDiffScalar< DerType > & real(const AutoDiffScalar< DerType > &x)
Definition: AutoDiffScalar.h:486
DerType::Scalar imag(const AutoDiffScalar< DerType > &)
Definition: AutoDiffScalar.h:490
EIGEN_DEFAULT_DENSE_INDEX_TYPE DenseIndex
Definition: Meta.h:75
const int Dynamic
Definition: Constants.h:25
T poly_eval(const Polynomials &poly, const T &x)
Definition: PolynomialUtils.h:47
val
Definition: calibrate.py:119
double epsilon
Definition: osc_ring_sarah_asymptotics.h:43
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition: NumTraits.h:217
Definition: datatypes.h:12