Eigen::EigenSolver< MatrixType_ > Class Template Reference

Computes eigenvalues and eigenvectors of general matrices. More...

Public Types

enum  {
  RowsAtCompileTime ,
  ColsAtCompileTime ,
  Options ,
  MaxRowsAtCompileTime ,
  MaxColsAtCompileTime
}
 
typedef std::complex< RealScalarComplexScalar
 Complex scalar type for MatrixType. More...
 
typedef Matrix< ComplexScalar, ColsAtCompileTime, 1, Options &~RowMajor, MaxColsAtCompileTime, 1 > EigenvalueType
 Type for vector of eigenvalues as returned by eigenvalues(). More...
 
typedef Matrix< ComplexScalar, RowsAtCompileTime, ColsAtCompileTime, Options, MaxRowsAtCompileTime, MaxColsAtCompileTimeEigenvectorsType
 Type for matrix of eigenvectors as returned by eigenvectors(). More...
 
typedef Eigen::Index Index
 
typedef MatrixType_ MatrixType
 Synonym for the template parameter MatrixType_. More...
 
typedef NumTraits< Scalar >::Real RealScalar
 
typedef MatrixType::Scalar Scalar
 Scalar type for matrices of type MatrixType. More...
 

Public Member Functions

template<typename InputType >
EigenSolver< MatrixType > & compute (const EigenBase< InputType > &matrix, bool computeEigenvectors)
 
template<typename InputType >
EigenSolvercompute (const EigenBase< InputType > &matrix, bool computeEigenvectors=true)
 Computes eigendecomposition of given matrix. More...
 
 EigenSolver ()
 Default constructor. More...
 
template<typename InputType >
 EigenSolver (const EigenBase< InputType > &matrix, bool computeEigenvectors=true)
 Constructor; computes eigendecomposition of given matrix. More...
 
 EigenSolver (Index size)
 Default constructor with memory preallocation. More...
 
const EigenvalueTypeeigenvalues () const
 Returns the eigenvalues of given matrix. More...
 
EigenvectorsType eigenvectors () const
 Returns the eigenvectors of given matrix. More...
 
Index getMaxIterations ()
 Returns the maximum number of iterations. More...
 
ComputationInfo info () const
 
MatrixType pseudoEigenvalueMatrix () const
 Returns the block-diagonal matrix in the pseudo-eigendecomposition. More...
 
const MatrixTypepseudoEigenvectors () const
 Returns the pseudo-eigenvectors of given matrix. More...
 
EigenSolversetMaxIterations (Index maxIters)
 Sets the maximum number of iterations allowed. More...
 

Protected Types

typedef Matrix< Scalar, ColsAtCompileTime, 1, Options &~RowMajor, MaxColsAtCompileTime, 1 > ColumnVectorType
 

Static Protected Member Functions

static void check_template_parameters ()
 

Protected Attributes

bool m_eigenvectorsOk
 
EigenvalueType m_eivalues
 
MatrixType m_eivec
 
ComputationInfo m_info
 
bool m_isInitialized
 
MatrixType m_matT
 
RealSchur< MatrixTypem_realSchur
 
ColumnVectorType m_tmp
 

Private Member Functions

void doComputeEigenvectors ()
 

Detailed Description

template<typename MatrixType_>
class Eigen::EigenSolver< MatrixType_ >

Computes eigenvalues and eigenvectors of general matrices.

This is defined in the Eigenvalues module.

Template Parameters
MatrixType_the type of the matrix of which we are computing the eigendecomposition; this is expected to be an instantiation of the Matrix class template. Currently, only real matrices are supported.

The eigenvalues and eigenvectors of a matrix \( A \) are scalars \( \lambda \) and vectors \( v \) such that \( Av = \lambda v \). If \( D \) is a diagonal matrix with the eigenvalues on the diagonal, and \( V \) is a matrix with the eigenvectors as its columns, then \( A V = V D \). The matrix \( V \) is almost always invertible, in which case we have \( A = V D V^{-1} \). This is called the eigendecomposition.

The eigenvalues and eigenvectors of a matrix may be complex, even when the matrix is real. However, we can choose real matrices \( V \) and \( D \) satisfying \( A V = V D \), just like the eigendecomposition, if the matrix \( D \) is not required to be diagonal, but if it is allowed to have blocks of the form

\[ \begin{bmatrix} u & v \\ -v & u \end{bmatrix} \]

(where \( u \) and \( v \) are real numbers) on the diagonal. These blocks correspond to complex eigenvalue pairs \( u \pm iv \). We call this variant of the eigendecomposition the pseudo-eigendecomposition.

Call the function compute() to compute the eigenvalues and eigenvectors of a given matrix. Alternatively, you can use the EigenSolver(const MatrixType&, bool) constructor which computes the eigenvalues and eigenvectors at construction time. Once the eigenvalue and eigenvectors are computed, they can be retrieved with the eigenvalues() and eigenvectors() functions. The pseudoEigenvalueMatrix() and pseudoEigenvectors() methods allow the construction of the pseudo-eigendecomposition.

The documentation for EigenSolver(const MatrixType&, bool) contains an example of the typical use of this class.

Note
The implementation is adapted from JAMA (public domain). Their code is based on EISPACK.
See also
MatrixBase::eigenvalues(), class ComplexEigenSolver, class SelfAdjointEigenSolver

Definition at line 66 of file EigenSolver.h.

Member Typedef Documentation

◆ ColumnVectorType

template<typename MatrixType_ >
typedef Matrix<Scalar, ColsAtCompileTime, 1, Options & ~RowMajor, MaxColsAtCompileTime, 1> Eigen::EigenSolver< MatrixType_ >::ColumnVectorType
protected

Definition at line 321 of file EigenSolver.h.

◆ ComplexScalar

template<typename MatrixType_ >
typedef std::complex<RealScalar> Eigen::EigenSolver< MatrixType_ >::ComplexScalar

Complex scalar type for MatrixType.

This is std::complex<Scalar> if Scalar is real (e.g., float or double) and just Scalar if Scalar is complex.

Definition at line 92 of file EigenSolver.h.

◆ EigenvalueType

template<typename MatrixType_ >
typedef Matrix<ComplexScalar, ColsAtCompileTime, 1, Options & ~RowMajor, MaxColsAtCompileTime, 1> Eigen::EigenSolver< MatrixType_ >::EigenvalueType

Type for vector of eigenvalues as returned by eigenvalues().

This is a column vector with entries of type ComplexScalar. The length of the vector is the size of MatrixType.

Definition at line 99 of file EigenSolver.h.

◆ EigenvectorsType

Type for matrix of eigenvectors as returned by eigenvectors().

This is a square matrix with entries of type ComplexScalar. The size is the same as the size of MatrixType.

Definition at line 106 of file EigenSolver.h.

◆ Index

template<typename MatrixType_ >
typedef Eigen::Index Eigen::EigenSolver< MatrixType_ >::Index
Deprecated:
since Eigen 3.3

Definition at line 84 of file EigenSolver.h.

◆ MatrixType

template<typename MatrixType_ >
typedef MatrixType_ Eigen::EigenSolver< MatrixType_ >::MatrixType

Synonym for the template parameter MatrixType_.

Definition at line 71 of file EigenSolver.h.

◆ RealScalar

template<typename MatrixType_ >
typedef NumTraits<Scalar>::Real Eigen::EigenSolver< MatrixType_ >::RealScalar

Definition at line 83 of file EigenSolver.h.

◆ Scalar

template<typename MatrixType_ >
typedef MatrixType::Scalar Eigen::EigenSolver< MatrixType_ >::Scalar

Scalar type for matrices of type MatrixType.

Definition at line 82 of file EigenSolver.h.

Member Enumeration Documentation

◆ anonymous enum

template<typename MatrixType_ >
anonymous enum
Enumerator
RowsAtCompileTime 
ColsAtCompileTime 
Options 
MaxRowsAtCompileTime 
MaxColsAtCompileTime 

Definition at line 73 of file EigenSolver.h.

73  {
74  RowsAtCompileTime = MatrixType::RowsAtCompileTime,
75  ColsAtCompileTime = MatrixType::ColsAtCompileTime,
76  Options = MatrixType::Options,
77  MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
78  MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
79  };

Constructor & Destructor Documentation

◆ EigenSolver() [1/3]

template<typename MatrixType_ >
Eigen::EigenSolver< MatrixType_ >::EigenSolver ( )
inline

Default constructor.

The default constructor is useful in cases in which the user intends to perform decompositions via EigenSolver::compute(const MatrixType&, bool).

See also
compute() for an example.

Definition at line 115 of file EigenSolver.h.

115 : m_eivec(), m_eivalues(), m_isInitialized(false), m_eigenvectorsOk(false), m_realSchur(), m_matT(), m_tmp() {}
MatrixType m_eivec
Definition: EigenSolver.h:313
RealSchur< MatrixType > m_realSchur
Definition: EigenSolver.h:318
MatrixType m_matT
Definition: EigenSolver.h:319
EigenvalueType m_eivalues
Definition: EigenSolver.h:314
ColumnVectorType m_tmp
Definition: EigenSolver.h:322

◆ EigenSolver() [2/3]

template<typename MatrixType_ >
Eigen::EigenSolver< MatrixType_ >::EigenSolver ( Index  size)
inlineexplicit

Default constructor with memory preallocation.

Like the default constructor but with preallocation of the internal data according to the specified problem size.

See also
EigenSolver()

Definition at line 123 of file EigenSolver.h.

124  : m_eivec(size, size),
125  m_eivalues(size),
126  m_isInitialized(false),
127  m_eigenvectorsOk(false),
128  m_realSchur(size),
129  m_matT(size, size),
130  m_tmp(size)
131  {}

◆ EigenSolver() [3/3]

template<typename MatrixType_ >
template<typename InputType >
Eigen::EigenSolver< MatrixType_ >::EigenSolver ( const EigenBase< InputType > &  matrix,
bool  computeEigenvectors = true 
)
inlineexplicit

Constructor; computes eigendecomposition of given matrix.

Parameters
[in]matrixSquare matrix whose eigendecomposition is to be computed.
[in]computeEigenvectorsIf true, both the eigenvectors and the eigenvalues are computed; if false, only the eigenvalues are computed.

This constructor calls compute() to compute the eigenvalues and eigenvectors.

Example:

cout << "Here is a random 6x6 matrix, A:" << endl << A << endl << endl;
EigenSolver<MatrixXd> es(A);
cout << "The eigenvalues of A are:" << endl << es.eigenvalues() << endl;
cout << "The matrix of eigenvectors, V, is:" << endl << es.eigenvectors() << endl << endl;
complex<double> lambda = es.eigenvalues()[0];
cout << "Consider the first eigenvalue, lambda = " << lambda << endl;
VectorXcd v = es.eigenvectors().col(0);
cout << "If v is the corresponding eigenvector, then lambda * v = " << endl << lambda * v << endl;
cout << "... and A * v = " << endl << A.cast<complex<double> >() * v << endl << endl;
MatrixXcd D = es.eigenvalues().asDiagonal();
MatrixXcd V = es.eigenvectors();
cout << "Finally, V * D * V^(-1) = " << endl << V * D * V.inverse() << endl;
Array< int, Dynamic, 1 > v
MatrixXcf A
cout<< "The eigenvalues of A are:"<< endl<< ces.eigenvalues()<< endl;cout<< "The matrix of eigenvectors, V, is:"<< endl<< ces.eigenvectors()<< endl<< endl;complex< float > lambda
EigenSolver< MatrixXf > es
static const RandomReturnType Random()
Definition: Random.h:114
Matrix< std::complex< double >, Dynamic, 1 > VectorXcd
Dynamic×1 vector of type std::complex<double>.
Definition: Matrix.h:504
Matrix< double, Dynamic, Dynamic > MatrixXd
Dynamic×Dynamic matrix of type double.
Definition: Matrix.h:502
Matrix< std::complex< double >, Dynamic, Dynamic > MatrixXcd
Dynamic×Dynamic matrix of type std::complex<double>.
Definition: Matrix.h:504

Output:

Here is a random 6x6 matrix, A:
   0.68   -0.33   -0.27  -0.717  -0.687  0.0259
 -0.211   0.536  0.0268   0.214  -0.198   0.678
  0.566  -0.444   0.904  -0.967   -0.74   0.225
  0.597   0.108   0.832  -0.514  -0.782  -0.408
  0.823 -0.0452   0.271  -0.726   0.998   0.275
 -0.605   0.258   0.435   0.608  -0.563  0.0486

The eigenvalues of A are:
  (0.049,1.06)
 (0.049,-1.06)
     (0.967,0)
     (0.353,0)
 (0.618,0.129)
(0.618,-0.129)
The matrix of eigenvectors, V, is:
 (-0.292,-0.454)   (-0.292,0.454)      (-0.0607,0)       (-0.733,0)    (0.59,-0.121)     (0.59,0.121)
  (0.134,-0.104)    (0.134,0.104)       (-0.799,0)        (0.136,0)    (0.334,0.368)   (0.334,-0.368)
  (-0.422,-0.18)    (-0.422,0.18)        (0.192,0)       (0.0563,0)  (-0.335,-0.143)   (-0.335,0.143)
 (-0.589,0.0274) (-0.589,-0.0274)      (-0.0788,0)       (-0.627,0)   (0.322,-0.155)    (0.322,0.155)
  (-0.248,0.132)  (-0.248,-0.132)        (0.401,0)        (0.218,0) (-0.335,-0.0761)  (-0.335,0.0761)
    (0.105,0.18)    (0.105,-0.18)       (-0.392,0)     (-0.00564,0)  (-0.0324,0.103) (-0.0324,-0.103)

Consider the first eigenvalue, lambda = (0.049,1.06)
If v is the corresponding eigenvector, then lambda * v = 
  (0.466,-0.331)
   (0.117,0.137)
   (0.17,-0.456)
(-0.0578,-0.622)
 (-0.152,-0.256)
   (-0.186,0.12)
... and A * v = 
  (0.466,-0.331)
   (0.117,0.137)
   (0.17,-0.456)
(-0.0578,-0.622)
 (-0.152,-0.256)
   (-0.186,0.12)

Finally, V * D * V^(-1) = 
          (0.68,0)  (-0.33,-5.55e-17)   (-0.27,6.66e-16)         (-0.717,0) (-0.687,-8.88e-16) (0.0259,-4.44e-16)
 (-0.211,2.22e-16)   (0.536,3.21e-17)         (0.0268,0)          (0.214,0)         (-0.198,0)  (0.678,-4.44e-16)
  (0.566,4.44e-16)  (-0.444,5.55e-17)   (0.904,1.11e-16) (-0.967,-3.33e-16)   (-0.74,4.44e-16)      (0.225,2e-15)
 (0.597,-4.44e-16)  (0.108,-2.78e-17)   (0.832,3.33e-16) (-0.514,-1.11e-16) (-0.782,-1.33e-15)  (-0.408,1.33e-15)
  (0.823,8.88e-16) (-0.0452,4.16e-17)  (0.271,-3.89e-16) (-0.726,-6.66e-16)   (0.998,1.33e-15)   (0.275,2.22e-15)
(-0.605,-9.71e-17)   (0.258,4.16e-17)  (0.435,-8.33e-17)   (0.608,1.18e-16) (-0.563,-2.78e-16) (0.0486,-2.95e-16)
See also
compute()

Definition at line 149 of file EigenSolver.h.

150  : m_eivec(matrix.rows(), matrix.cols()),
151  m_eivalues(matrix.cols()),
152  m_isInitialized(false),
153  m_eigenvectorsOk(false),
154  m_realSchur(matrix.cols()),
155  m_matT(matrix.rows(), matrix.cols()),
156  m_tmp(matrix.cols())
157  {
158  compute(matrix.derived(), computeEigenvectors);
159  }
EigenSolver & compute(const EigenBase< InputType > &matrix, bool computeEigenvectors=true)
Computes eigendecomposition of given matrix.

Member Function Documentation

◆ check_template_parameters()

template<typename MatrixType_ >
static void Eigen::EigenSolver< MatrixType_ >::check_template_parameters ( )
inlinestaticprotected

Definition at line 307 of file EigenSolver.h.

308  {
310  EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsComplex, NUMERIC_TYPE_MUST_BE_REAL);
311  }
#define EIGEN_STATIC_ASSERT(X, MSG)
Definition: StaticAssert.h:26
#define EIGEN_STATIC_ASSERT_NON_INTEGER(TYPE)
Definition: StaticAssert.h:81
MatrixType::Scalar Scalar
Scalar type for matrices of type MatrixType.
Definition: EigenSolver.h:82

◆ compute() [1/2]

template<typename MatrixType_ >
template<typename InputType >
EigenSolver<MatrixType>& Eigen::EigenSolver< MatrixType_ >::compute ( const EigenBase< InputType > &  matrix,
bool  computeEigenvectors 
)

Definition at line 381 of file EigenSolver.h.

382 {
384 
385  using std::sqrt;
386  using std::abs;
387  using numext::isfinite;
388  eigen_assert(matrix.cols() == matrix.rows());
389 
390  // Reduce to real Schur form.
391  m_realSchur.compute(matrix.derived(), computeEigenvectors);
392 
393  m_info = m_realSchur.info();
394 
395  if (m_info == Success)
396  {
398  if (computeEigenvectors)
400 
401  // Compute eigenvalues from matT
402  m_eivalues.resize(matrix.cols());
403  Index i = 0;
404  while (i < matrix.cols())
405  {
406  if (i == matrix.cols() - 1 || m_matT.coeff(i+1, i) == Scalar(0))
407  {
408  m_eivalues.coeffRef(i) = m_matT.coeff(i, i);
409  if(!(isfinite)(m_eivalues.coeffRef(i)))
410  {
411  m_isInitialized = true;
412  m_eigenvectorsOk = false;
414  return *this;
415  }
416  ++i;
417  }
418  else
419  {
420  Scalar p = Scalar(0.5) * (m_matT.coeff(i, i) - m_matT.coeff(i+1, i+1));
421  Scalar z;
422  // Compute z = sqrt(abs(p * p + m_matT.coeff(i+1, i) * m_matT.coeff(i, i+1)));
423  // without overflow
424  {
425  Scalar t0 = m_matT.coeff(i+1, i);
426  Scalar t1 = m_matT.coeff(i, i+1);
427  Scalar maxval = numext::maxi<Scalar>(abs(p),numext::maxi<Scalar>(abs(t0),abs(t1)));
428  t0 /= maxval;
429  t1 /= maxval;
430  Scalar p0 = p/maxval;
431  z = maxval * sqrt(abs(p0 * p0 + t0 * t1));
432  }
433 
434  m_eivalues.coeffRef(i) = ComplexScalar(m_matT.coeff(i+1, i+1) + p, z);
435  m_eivalues.coeffRef(i+1) = ComplexScalar(m_matT.coeff(i+1, i+1) + p, -z);
437  {
438  m_isInitialized = true;
439  m_eigenvectorsOk = false;
441  return *this;
442  }
443  i += 2;
444  }
445  }
446 
447  // Compute eigenvectors.
448  if (computeEigenvectors)
450  }
451 
452  m_isInitialized = true;
453  m_eigenvectorsOk = computeEigenvectors;
454 
455  return *this;
456 }
const AbsReturnType abs() const
const SqrtReturnType sqrt() const
#define eigen_assert(x)
Definition: Macros.h:902
Vector3f p0
float * p
void doComputeEigenvectors()
Definition: EigenSolver.h:460
std::complex< RealScalar > ComplexScalar
Complex scalar type for MatrixType.
Definition: EigenSolver.h:92
static void check_template_parameters()
Definition: EigenSolver.h:307
Eigen::Index Index
Definition: EigenSolver.h:84
ComputationInfo m_info
Definition: EigenSolver.h:317
constexpr void resize(Index rows, Index cols)
constexpr Scalar & coeffRef(Index rowId, Index colId)
const MatrixType & matrixU() const
Returns the orthogonal matrix in the Schur decomposition.
Definition: RealSchur.h:129
ComputationInfo info() const
Reports whether previous computation was successful.
Definition: RealSchur.h:197
const MatrixType & matrixT() const
Returns the quasi-triangular matrix in the Schur decomposition.
Definition: RealSchur.h:146
RealSchur & compute(const EigenBase< InputType > &matrix, bool computeU=true)
Computes Schur decomposition of given matrix.
@ NumericalIssue
Definition: Constants.h:448
@ Success
Definition: Constants.h:446
EIGEN_ALWAYS_INLINE bool() isfinite(const Eigen::bfloat16 &h)
Definition: BFloat16.h:790
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_isfinite_op< typename Derived::Scalar >, const Derived > isfinite(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_abs_op< typename Derived::Scalar >, const Derived > abs(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_sqrt_op< typename Derived::Scalar >, const Derived > sqrt(const Eigen::ArrayBase< Derived > &x)

◆ compute() [2/2]

template<typename MatrixType_ >
template<typename InputType >
EigenSolver& Eigen::EigenSolver< MatrixType_ >::compute ( const EigenBase< InputType > &  matrix,
bool  computeEigenvectors = true 
)

Computes eigendecomposition of given matrix.

Parameters
[in]matrixSquare matrix whose eigendecomposition is to be computed.
[in]computeEigenvectorsIf true, both the eigenvectors and the eigenvalues are computed; if false, only the eigenvalues are computed.
Returns
Reference to *this

This function computes the eigenvalues of the real matrix matrix. The eigenvalues() function can be used to retrieve them. If computeEigenvectors is true, then the eigenvectors are also computed and can be retrieved by calling eigenvectors().

The matrix is first reduced to real Schur form using the RealSchur class. The Schur decomposition is then used to compute the eigenvalues and eigenvectors.

The cost of the computation is dominated by the cost of the Schur decomposition, which is very approximately \( 25n^3 \) (where \( n \) is the size of the matrix) if computeEigenvectors is true, and \( 10n^3 \) if computeEigenvectors is false.

This method reuses of the allocated data in the EigenSolver object.

Example:

EigenSolver<MatrixXf> es;
es.compute(A, /* computeEigenvectors = */ false);
cout << "The eigenvalues of A are: " << es.eigenvalues().transpose() << endl;
es.compute(A + MatrixXf::Identity(4,4), false); // re-use es to compute eigenvalues of A+I
cout << "The eigenvalues of A+I are: " << es.eigenvalues().transpose() << endl;
static const IdentityReturnType Identity()
Matrix< float, Dynamic, Dynamic > MatrixXf
Dynamic×Dynamic matrix of type float.
Definition: Matrix.h:501

Output:

The eigenvalues of A are:    (0.755,0.528)   (0.755,-0.528)  (-0.323,0.0965) (-0.323,-0.0965)
The eigenvalues of A+I are:    (1.75,0.528)   (1.75,-0.528)  (0.677,0.0965) (0.677,-0.0965)

◆ doComputeEigenvectors()

template<typename MatrixType >
void Eigen::EigenSolver< MatrixType >::doComputeEigenvectors
private

Definition at line 460 of file EigenSolver.h.

461 {
462  using std::abs;
463  const Index size = m_eivec.cols();
464  const Scalar eps = NumTraits<Scalar>::epsilon();
465 
466  // inefficient! this is already computed in RealSchur
467  Scalar norm(0);
468  for (Index j = 0; j < size; ++j)
469  {
470  norm += m_matT.row(j).segment((std::max)(j-1,Index(0)), size-(std::max)(j-1,Index(0))).cwiseAbs().sum();
471  }
472 
473  // Backsubstitute to find vectors of upper triangular form
474  if (norm == Scalar(0))
475  {
476  return;
477  }
478 
479  for (Index n = size-1; n >= 0; n--)
480  {
481  Scalar p = m_eivalues.coeff(n).real();
482  Scalar q = m_eivalues.coeff(n).imag();
483 
484  // Scalar vector
485  if (q == Scalar(0))
486  {
487  Scalar lastr(0), lastw(0);
488  Index l = n;
489 
490  m_matT.coeffRef(n,n) = Scalar(1);
491  for (Index i = n-1; i >= 0; i--)
492  {
493  Scalar w = m_matT.coeff(i,i) - p;
494  Scalar r = m_matT.row(i).segment(l,n-l+1).dot(m_matT.col(n).segment(l, n-l+1));
495 
496  if (m_eivalues.coeff(i).imag() < Scalar(0))
497  {
498  lastw = w;
499  lastr = r;
500  }
501  else
502  {
503  l = i;
504  if (m_eivalues.coeff(i).imag() == Scalar(0))
505  {
506  if (w != Scalar(0))
507  m_matT.coeffRef(i,n) = -r / w;
508  else
509  m_matT.coeffRef(i,n) = -r / (eps * norm);
510  }
511  else // Solve real equations
512  {
513  Scalar x = m_matT.coeff(i,i+1);
514  Scalar y = m_matT.coeff(i+1,i);
515  Scalar denom = (m_eivalues.coeff(i).real() - p) * (m_eivalues.coeff(i).real() - p) + m_eivalues.coeff(i).imag() * m_eivalues.coeff(i).imag();
516  Scalar t = (x * lastr - lastw * r) / denom;
517  m_matT.coeffRef(i,n) = t;
518  if (abs(x) > abs(lastw))
519  m_matT.coeffRef(i+1,n) = (-r - w * t) / x;
520  else
521  m_matT.coeffRef(i+1,n) = (-lastr - y * t) / lastw;
522  }
523 
524  // Overflow control
525  Scalar t = abs(m_matT.coeff(i,n));
526  if ((eps * t) * t > Scalar(1))
527  m_matT.col(n).tail(size-i) /= t;
528  }
529  }
530  }
531  else if (q < Scalar(0) && n > 0) // Complex vector
532  {
533  Scalar lastra(0), lastsa(0), lastw(0);
534  Index l = n-1;
535 
536  // Last vector component imaginary so matrix is triangular
537  if (abs(m_matT.coeff(n,n-1)) > abs(m_matT.coeff(n-1,n)))
538  {
539  m_matT.coeffRef(n-1,n-1) = q / m_matT.coeff(n,n-1);
540  m_matT.coeffRef(n-1,n) = -(m_matT.coeff(n,n) - p) / m_matT.coeff(n,n-1);
541  }
542  else
543  {
544  ComplexScalar cc = ComplexScalar(Scalar(0),-m_matT.coeff(n-1,n)) / ComplexScalar(m_matT.coeff(n-1,n-1)-p,q);
545  m_matT.coeffRef(n-1,n-1) = numext::real(cc);
546  m_matT.coeffRef(n-1,n) = numext::imag(cc);
547  }
548  m_matT.coeffRef(n,n-1) = Scalar(0);
549  m_matT.coeffRef(n,n) = Scalar(1);
550  for (Index i = n-2; i >= 0; i--)
551  {
552  Scalar ra = m_matT.row(i).segment(l, n-l+1).dot(m_matT.col(n-1).segment(l, n-l+1));
553  Scalar sa = m_matT.row(i).segment(l, n-l+1).dot(m_matT.col(n).segment(l, n-l+1));
554  Scalar w = m_matT.coeff(i,i) - p;
555 
556  if (m_eivalues.coeff(i).imag() < Scalar(0))
557  {
558  lastw = w;
559  lastra = ra;
560  lastsa = sa;
561  }
562  else
563  {
564  l = i;
565  if (m_eivalues.coeff(i).imag() == RealScalar(0))
566  {
567  ComplexScalar cc = ComplexScalar(-ra,-sa) / ComplexScalar(w,q);
568  m_matT.coeffRef(i,n-1) = numext::real(cc);
569  m_matT.coeffRef(i,n) = numext::imag(cc);
570  }
571  else
572  {
573  // Solve complex equations
574  Scalar x = m_matT.coeff(i,i+1);
575  Scalar y = m_matT.coeff(i+1,i);
576  Scalar vr = (m_eivalues.coeff(i).real() - p) * (m_eivalues.coeff(i).real() - p) + m_eivalues.coeff(i).imag() * m_eivalues.coeff(i).imag() - q * q;
577  Scalar vi = (m_eivalues.coeff(i).real() - p) * Scalar(2) * q;
578  if ((vr == Scalar(0)) && (vi == Scalar(0)))
579  vr = eps * norm * (abs(w) + abs(q) + abs(x) + abs(y) + abs(lastw));
580 
581  ComplexScalar cc = ComplexScalar(x*lastra-lastw*ra+q*sa,x*lastsa-lastw*sa-q*ra) / ComplexScalar(vr,vi);
582  m_matT.coeffRef(i,n-1) = numext::real(cc);
583  m_matT.coeffRef(i,n) = numext::imag(cc);
584  if (abs(x) > (abs(lastw) + abs(q)))
585  {
586  m_matT.coeffRef(i+1,n-1) = (-ra - w * m_matT.coeff(i,n-1) + q * m_matT.coeff(i,n)) / x;
587  m_matT.coeffRef(i+1,n) = (-sa - w * m_matT.coeff(i,n) - q * m_matT.coeff(i,n-1)) / x;
588  }
589  else
590  {
591  cc = ComplexScalar(-lastra-y*m_matT.coeff(i,n-1),-lastsa-y*m_matT.coeff(i,n)) / ComplexScalar(lastw,q);
592  m_matT.coeffRef(i+1,n-1) = numext::real(cc);
593  m_matT.coeffRef(i+1,n) = numext::imag(cc);
594  }
595  }
596 
597  // Overflow control
598  Scalar t = numext::maxi<Scalar>(abs(m_matT.coeff(i,n-1)),abs(m_matT.coeff(i,n)));
599  if ((eps * t) * t > Scalar(1))
600  m_matT.block(i, n-1, size-i, 2) /= t;
601 
602  }
603  }
604 
605  // We handled a pair of complex conjugate eigenvalues, so need to skip them both
606  n--;
607  }
608  else
609  {
610  eigen_assert(0 && "Internal bug in EigenSolver (INF or NaN has not been detected)"); // this should not happen
611  }
612  }
613 
614  // Back transformation to get eigenvectors of original matrix
615  for (Index j = size-1; j >= 0; j--)
616  {
617  m_tmp.noalias() = m_eivec.leftCols(j+1) * m_matT.col(j).segment(0, j+1);
618  m_eivec.col(j) = m_tmp;
619  }
620 }
int n
const ImagReturnType imag() const
RealReturnType real() const
RowVector3d w
NumTraits< Scalar >::Real RealScalar
Definition: EigenSolver.h:83
constexpr const Scalar & coeff(Index rowId, Index colId) const
bfloat16() max(const bfloat16 &a, const bfloat16 &b)
Definition: BFloat16.h:690
const Scalar & y
std::ptrdiff_t j

◆ eigenvalues()

template<typename MatrixType_ >
const EigenvalueType& Eigen::EigenSolver< MatrixType_ >::eigenvalues ( ) const
inline

Returns the eigenvalues of given matrix.

Returns
A const reference to the column vector containing the eigenvalues.
Precondition
Either the constructor EigenSolver(const MatrixType&,bool) or the member function compute(const MatrixType&, bool) has been called before.

The eigenvalues are repeated according to their algebraic multiplicity, so there are as many eigenvalues as rows in the matrix. The eigenvalues are not sorted in any particular order.

Example:

EigenSolver<MatrixXd> es(ones, false);
cout << "The eigenvalues of the 3x3 matrix of ones are:"
<< endl << es.eigenvalues() << endl;
static const ConstantReturnType Ones()

Output:

The eigenvalues of the 3x3 matrix of ones are:
(-5.31e-17,0)
        (3,0)
        (0,0)
See also
eigenvectors(), pseudoEigenvalueMatrix(), MatrixBase::eigenvalues()

Definition at line 246 of file EigenSolver.h.

247  {
248  eigen_assert(m_isInitialized && "EigenSolver is not initialized.");
249  return m_eivalues;
250  }

◆ eigenvectors()

template<typename MatrixType >
EigenSolver< MatrixType >::EigenvectorsType Eigen::EigenSolver< MatrixType >::eigenvectors

Returns the eigenvectors of given matrix.

Returns
Matrix whose columns are the (possibly complex) eigenvectors.
Precondition
Either the constructor EigenSolver(const MatrixType&,bool) or the member function compute(const MatrixType&, bool) has been called before, and computeEigenvectors was set to true (the default).

Column \( k \) of the returned matrix is an eigenvector corresponding to eigenvalue number \( k \) as returned by eigenvalues(). The eigenvectors are normalized to have (Euclidean) norm equal to one. The matrix returned by this function is the matrix \( V \) in the eigendecomposition \( A = V D V^{-1} \), if it exists.

Example:

EigenSolver<MatrixXd> es(ones);
cout << "The first eigenvector of the 3x3 matrix of ones is:"
<< endl << es.eigenvectors().col(0) << endl;

Output:

The first eigenvector of the 3x3 matrix of ones is:
(-0.816,0)
 (0.408,0)
 (0.408,0)
See also
eigenvalues(), pseudoEigenvectors()

Definition at line 347 of file EigenSolver.h.

348 {
349  eigen_assert(m_isInitialized && "EigenSolver is not initialized.");
350  eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
351  const RealScalar precision = RealScalar(2)*NumTraits<RealScalar>::epsilon();
352  Index n = m_eivec.cols();
353  EigenvectorsType matV(n,n);
354  for (Index j=0; j<n; ++j)
355  {
357  {
358  // we have a real eigen value
359  matV.col(j) = m_eivec.col(j).template cast<ComplexScalar>();
360  matV.col(j).normalize();
361  }
362  else
363  {
364  // we have a pair of complex eigen values
365  for (Index i=0; i<n; ++i)
366  {
367  matV.coeffRef(i,j) = ComplexScalar(m_eivec.coeff(i,j), m_eivec.coeff(i,j+1));
368  matV.coeffRef(i,j+1) = ComplexScalar(m_eivec.coeff(i,j), -m_eivec.coeff(i,j+1));
369  }
370  matV.col(j).normalize();
371  matV.col(j+1).normalize();
372  ++j;
373  }
374  }
375  return matV;
376 }
Matrix< ComplexScalar, RowsAtCompileTime, ColsAtCompileTime, Options, MaxRowsAtCompileTime, MaxColsAtCompileTime > EigenvectorsType
Type for matrix of eigenvectors as returned by eigenvectors().
Definition: EigenSolver.h:106
bool isMuchSmallerThan(const Scalar &x, const OtherScalar &y, const typename NumTraits< Scalar >::Real &precision=NumTraits< Scalar >::dummy_precision())

◆ getMaxIterations()

template<typename MatrixType_ >
Index Eigen::EigenSolver< MatrixType_ >::getMaxIterations ( )
inline

Returns the maximum number of iterations.

Definition at line 297 of file EigenSolver.h.

298  {
299  return m_realSchur.getMaxIterations();
300  }
Index getMaxIterations()
Returns the maximum number of iterations.
Definition: RealSchur.h:215

◆ info()

template<typename MatrixType_ >
ComputationInfo Eigen::EigenSolver< MatrixType_ >::info ( ) const
inline
Returns
NumericalIssue if the input contains INF or NaN values or overflow occurred. Returns Success otherwise.

Definition at line 283 of file EigenSolver.h.

284  {
285  eigen_assert(m_isInitialized && "EigenSolver is not initialized.");
286  return m_info;
287  }

◆ pseudoEigenvalueMatrix()

template<typename MatrixType >
MatrixType Eigen::EigenSolver< MatrixType >::pseudoEigenvalueMatrix

Returns the block-diagonal matrix in the pseudo-eigendecomposition.

Returns
A block-diagonal matrix.
Precondition
Either the constructor EigenSolver(const MatrixType&,bool) or the member function compute(const MatrixType&, bool) has been called before.

The matrix \( D \) returned by this function is real and block-diagonal. The blocks on the diagonal are either 1-by-1 or 2-by-2 blocks of the form \( \begin{bmatrix} u & v \\ -v & u \end{bmatrix} \). These blocks are not sorted in any particular order. The matrix \( D \) and the matrix \( V \) returned by pseudoEigenvectors() satisfy \( AV = VD \).

See also
pseudoEigenvectors() for an example, eigenvalues()

Definition at line 326 of file EigenSolver.h.

327 {
328  eigen_assert(m_isInitialized && "EigenSolver is not initialized.");
329  const RealScalar precision = RealScalar(2)*NumTraits<RealScalar>::epsilon();
330  Index n = m_eivalues.rows();
331  MatrixType matD = MatrixType::Zero(n,n);
332  for (Index i=0; i<n; ++i)
333  {
335  matD.coeffRef(i,i) = numext::real(m_eivalues.coeff(i));
336  else
337  {
338  matD.template block<2,2>(i,i) << numext::real(m_eivalues.coeff(i)), numext::imag(m_eivalues.coeff(i)),
340  ++i;
341  }
342  }
343  return matD;
344 }
Matrix< float, 1, Dynamic > MatrixType
EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT

◆ pseudoEigenvectors()

template<typename MatrixType_ >
const MatrixType& Eigen::EigenSolver< MatrixType_ >::pseudoEigenvectors ( ) const
inline

Returns the pseudo-eigenvectors of given matrix.

Returns
Const reference to matrix whose columns are the pseudo-eigenvectors.
Precondition
Either the constructor EigenSolver(const MatrixType&,bool) or the member function compute(const MatrixType&, bool) has been called before, and computeEigenvectors was set to true (the default).

The real matrix \( V \) returned by this function and the block-diagonal matrix \( D \) returned by pseudoEigenvalueMatrix() satisfy \( AV = VD \).

Example:

cout << "Here is a random 6x6 matrix, A:" << endl << A << endl << endl;
EigenSolver<MatrixXd> es(A);
MatrixXd D = es.pseudoEigenvalueMatrix();
MatrixXd V = es.pseudoEigenvectors();
cout << "The pseudo-eigenvalue matrix D is:" << endl << D << endl;
cout << "The pseudo-eigenvector matrix V is:" << endl << V << endl;
cout << "Finally, V * D * V^(-1) = " << endl << V * D * V.inverse() << endl;

Output:

Here is a random 6x6 matrix, A:
   0.68   -0.33   -0.27  -0.717  -0.687  0.0259
 -0.211   0.536  0.0268   0.214  -0.198   0.678
  0.566  -0.444   0.904  -0.967   -0.74   0.225
  0.597   0.108   0.832  -0.514  -0.782  -0.408
  0.823 -0.0452   0.271  -0.726   0.998   0.275
 -0.605   0.258   0.435   0.608  -0.563  0.0486

The pseudo-eigenvalue matrix D is:
 0.049   1.06      0      0      0      0
 -1.06  0.049      0      0      0      0
     0      0  0.967      0      0      0
     0      0      0  0.353      0      0
     0      0      0      0  0.618  0.129
     0      0      0      0 -0.129  0.618
The pseudo-eigenvector matrix V is:
  -0.571   -0.888   -0.066    -1.13     17.2    -3.53
   0.263   -0.204   -0.869     0.21     9.73     10.7
  -0.827   -0.352    0.209   0.0871    -9.74    -4.17
   -1.15   0.0535  -0.0857   -0.971     9.36    -4.52
  -0.485    0.258    0.436    0.337    -9.74    -2.21
   0.206    0.353   -0.426 -0.00873   -0.944     2.98
Finally, V * D * V^(-1) = 
   0.68   -0.33   -0.27  -0.717  -0.687  0.0259
 -0.211   0.536  0.0268   0.214  -0.198   0.678
  0.566  -0.444   0.904  -0.967   -0.74   0.225
  0.597   0.108   0.832  -0.514  -0.782  -0.408
  0.823 -0.0452   0.271  -0.726   0.998   0.275
 -0.605   0.258   0.435   0.608  -0.563  0.0486
See also
pseudoEigenvalueMatrix(), eigenvectors()

Definition at line 201 of file EigenSolver.h.

202  {
203  eigen_assert(m_isInitialized && "EigenSolver is not initialized.");
204  eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
205  return m_eivec;
206  }

◆ setMaxIterations()

template<typename MatrixType_ >
EigenSolver& Eigen::EigenSolver< MatrixType_ >::setMaxIterations ( Index  maxIters)
inline

Sets the maximum number of iterations allowed.

Definition at line 290 of file EigenSolver.h.

291  {
292  m_realSchur.setMaxIterations(maxIters);
293  return *this;
294  }
RealSchur & setMaxIterations(Index maxIters)
Sets the maximum number of iterations allowed.
Definition: RealSchur.h:208

Member Data Documentation

◆ m_eigenvectorsOk

template<typename MatrixType_ >
bool Eigen::EigenSolver< MatrixType_ >::m_eigenvectorsOk
protected

Definition at line 316 of file EigenSolver.h.

◆ m_eivalues

template<typename MatrixType_ >
EigenvalueType Eigen::EigenSolver< MatrixType_ >::m_eivalues
protected

Definition at line 314 of file EigenSolver.h.

◆ m_eivec

template<typename MatrixType_ >
MatrixType Eigen::EigenSolver< MatrixType_ >::m_eivec
protected

Definition at line 313 of file EigenSolver.h.

◆ m_info

template<typename MatrixType_ >
ComputationInfo Eigen::EigenSolver< MatrixType_ >::m_info
protected

Definition at line 317 of file EigenSolver.h.

◆ m_isInitialized

template<typename MatrixType_ >
bool Eigen::EigenSolver< MatrixType_ >::m_isInitialized
protected

Definition at line 315 of file EigenSolver.h.

◆ m_matT

template<typename MatrixType_ >
MatrixType Eigen::EigenSolver< MatrixType_ >::m_matT
protected

Definition at line 319 of file EigenSolver.h.

◆ m_realSchur

template<typename MatrixType_ >
RealSchur<MatrixType> Eigen::EigenSolver< MatrixType_ >::m_realSchur
protected

Definition at line 318 of file EigenSolver.h.

◆ m_tmp

template<typename MatrixType_ >
ColumnVectorType Eigen::EigenSolver< MatrixType_ >::m_tmp
protected

Definition at line 322 of file EigenSolver.h.


The documentation for this class was generated from the following file: