11#ifndef EIGEN_TRIDIAGONAL_EIGENSOLVER_H
12#define EIGEN_TRIDIAGONAL_EIGENSOLVER_H
14#include "./TridiagonalBisection.h"
15#include "./TridiagonalInverseIteration.h"
18#include "./InternalHeaderCheck.h"
75template <
typename Scalar_>
81 static_assert(NumTraits<Scalar>::IsComplex == 0 && NumTraits<Scalar>::IsInteger == 0,
82 "TridiagonalEigenSolver requires a real floating-point scalar type; for the eigenvalues of a complex "
83 "Hermitian tridiagonal matrix, pass subdiag.cwiseAbs() as the real sub-diagonal (see the class "
96 : m_eivalues(size), m_eivec(size, size), m_diag(size), m_subdiag(size > 1 ? size - 1 : 0) {}
102 template <
typename DiagType,
typename SubdiagType>
106 compute(diag, subdiag, options, range);
123 template <
typename DiagType,
typename SubdiagType>
127 eigen_assert((options & ~EigVecMask) == 0 && (options & EigVecMask) != EigVecMask &&
"invalid option parameter");
147 template <
typename DiagType,
typename SubdiagType>
164 eigen_assert(m_isInitialized &&
"TridiagonalEigenSolver is not initialized.");
165 eigen_assert(m_info ==
Success &&
"computeEigenvectors() requires a preceding successful eigenvalue computation");
166 computeEigenvectorsImpl();
212 template <
typename DiagType,
typename SubdiagType,
typename EivalsType>
225 eigen_assert(m_isInitialized &&
"TridiagonalEigenSolver is not initialized.");
238 eigen_assert(m_isInitialized &&
"TridiagonalEigenSolver is not initialized.");
239 eigen_assert(m_eigenvectorsOk &&
"The eigenvectors have not been computed.");
248 eigen_assert(m_isInitialized &&
"TridiagonalEigenSolver is not initialized.");
258 using ComputeScalar = std::conditional_t<(NumTraits<Scalar>::digits() < NumTraits<float>::digits()),
float, Scalar>;
260 void computeEigenvectorsImpl();
274 bool m_isInitialized =
false;
275 bool m_eigenvectorsOk =
false;
278template <
typename Scalar_>
279template <
typename DiagType,
typename SubdiagType>
281 const MatrixBase<DiagType>& diag,
const MatrixBase<SubdiagType>& subdiag,
const EigenvalueRange& range) {
282 static_assert(internal::is_same<typename DiagType::Scalar, Scalar>::value &&
283 internal::is_same<typename SubdiagType::Scalar, Scalar>::value,
284 "diag and subdiag must have the solver's scalar type");
285 const Index n = diag.size();
286 EIGEN_UNUSED_VARIABLE(n);
287 eigen_assert(subdiag.size() == (n > 0 ? n - 1 : 0) &&
"sub-diagonal must have one fewer entry than the diagonal");
291 m_eigenvectorsOk =
false;
297 if (!(m_diag.allFinite() && m_subdiag.allFinite())) {
298 m_eivalues.resize(0);
299 m_eivaluesc.resize(0);
301 m_isInitialized =
true;
305 if (internal::is_same<Scalar, ComputeScalar>::value) {
306 internal::tridiagonal_bisection(m_diag, m_subdiag, range, RealScalar(0), m_eivalues);
307 m_eivaluesc.resize(0);
313 internal::tridiagonal_bisection(cdiag, csubdiag, range, ComputeScalar(0), m_eivaluesc);
314 m_eivalues = m_eivaluesc.template cast<Scalar>();
317 m_isInitialized =
true;
321template <
typename Scalar_>
322template <
typename DiagType,
typename SubdiagType,
typename EivalsType>
326 static_assert(internal::is_same<typename DiagType::Scalar, Scalar>::value &&
327 internal::is_same<typename SubdiagType::Scalar, Scalar>::value &&
328 internal::is_same<typename EivalsType::Scalar, Scalar>::value,
329 "diag, subdiag and eigenvalues must have the solver's scalar type");
330 const Index n = diag.size();
331 EIGEN_UNUSED_VARIABLE(n);
332 eigen_assert(subdiag.size() == (n > 0 ? n - 1 : 0) &&
"sub-diagonal must have one fewer entry than the diagonal");
333 eigen_assert(eigenvalues.size() <= n &&
"cannot request more eigenvectors than the size of the matrix");
337 m_eivalues = eigenvalues;
338 m_eivaluesc.resize(0);
342 if (!(m_diag.allFinite() && m_subdiag.allFinite() && m_eivalues.allFinite())) {
343 m_eivalues.resize(0);
344 m_eivec.resize(m_diag.size(), 0);
346 m_isInitialized =
true;
347 m_eigenvectorsOk =
false;
351 computeEigenvectorsImpl();
355template <
typename Scalar_>
356void TridiagonalEigenSolver<Scalar_>::computeEigenvectorsImpl() {
357 const Index n = m_diag.size();
358 const Index m = m_eivalues.size();
359 m_eivec.resize(n, m);
361 if (internal::is_same<Scalar, ComputeScalar>::value) {
362 nonconv = internal::tridiagonal_inverse_iteration(m_diag, m_subdiag, m_eivalues, m_eivec);
365 internal::tridiagonal_rayleigh_ritz_refine(m_diag, m_subdiag, m_eivalues, m_eivec);
373 (m_eivaluesc.size() == m) ? m_eivaluesc : m_eivalues.template cast<ComputeScalar>();
375 nonconv = internal::tridiagonal_inverse_iteration(cdiag, csubdiag, cw, cvec);
376 internal::tridiagonal_rayleigh_ritz_refine(cdiag, csubdiag, cw, cvec);
377 m_eivec = cvec.template cast<Scalar>();
383 m_isInitialized =
true;
384 m_eigenvectorsOk =
true;
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:53
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:188
Computes eigenvalues and eigenvectors of a real symmetric tridiagonal matrix.
Definition TridiagonalEigenSolver.h:76
Matrix< Scalar, Dynamic, 1 > VectorType
Type for the eigenvalues and the input diagonals: a dynamic-size column vector.
Definition TridiagonalEigenSolver.h:87
TridiagonalEigenSolver & computeEigenvectors(const MatrixBase< DiagType > &diag, const MatrixBase< SubdiagType > &subdiag, const MatrixBase< EivalsType > &eigenvalues)
Computes eigenvectors of a tridiagonal matrix by inverse iteration from known eigenvalues.
TridiagonalEigenSolver & computeEigenvectors()
Computes eigenvectors for the eigenvalues of the preceding compute step, by inverse iteration.
Definition TridiagonalEigenSolver.h:163
ComputationInfo info() const
Reports whether the computation was successful.
Definition TridiagonalEigenSolver.h:247
TridiagonalEigenSolver & compute(const MatrixBase< DiagType > &diag, const MatrixBase< SubdiagType > &subdiag, int options=ComputeEigenvectors, const EigenvalueRange &range=EigenvalueRange::all())
Computes the selected eigenvalues, and optionally eigenvectors, of a real symmetric tridiagonal matri...
Definition TridiagonalEigenSolver.h:124
const MatrixType & eigenvectors() const
Returns the computed eigenvectors, one column per eigenvalue.
Definition TridiagonalEigenSolver.h:237
TridiagonalEigenSolver(Index size)
Constructor pre-allocating room for the full spectrum of a matrix of dimension size.
Definition TridiagonalEigenSolver.h:95
TridiagonalEigenSolver()=default
Default constructor. Call compute() before querying any result.
Matrix< Scalar, Dynamic, Dynamic > MatrixType
Type for the eigenvector matrix: dynamic-size, one column per selected eigenvalue.
Definition TridiagonalEigenSolver.h:89
TridiagonalEigenSolver & computeEigenvalues(const MatrixBase< DiagType > &diag, const MatrixBase< SubdiagType > &subdiag, const EigenvalueRange &range=EigenvalueRange::all())
Computes the selected eigenvalues (only) of a real symmetric tridiagonal matrix.
TridiagonalEigenSolver(const MatrixBase< DiagType > &diag, const MatrixBase< SubdiagType > &subdiag, int options=ComputeEigenvectors, const EigenvalueRange &range=EigenvalueRange::all())
Constructor; computes the eigendecomposition of the given tridiagonal matrix.
Definition TridiagonalEigenSolver.h:103
Scalar_ Scalar
Scalar type of the matrix; must be real.
Definition TridiagonalEigenSolver.h:79
const VectorType & eigenvalues() const
Returns the computed eigenvalues, in non-decreasing order.
Definition TridiagonalEigenSolver.h:224
ComputationInfo
Definition Constants.h:455
@ InvalidInput
Definition Constants.h:464
@ Success
Definition Constants.h:457
@ NoConvergence
Definition Constants.h:461
@ ComputeEigenvectors
Definition Constants.h:406
Selects which eigenvalues to compute in a spectral-bisection solve.
Definition TridiagonalBisection.h:38
static EigenvalueRange all()
Definition TridiagonalBisection.h:50