Eigen  5.0.1
 
Loading...
Searching...
No Matches
ComplexEigenSolver.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2009 Claire Maurice
5// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
6// Copyright (C) 2010,2012 Jitse Niesen <jitse@maths.leeds.ac.uk>
7//
8// This Source Code Form is subject to the terms of the Mozilla
9// Public License v. 2.0. If a copy of the MPL was not distributed
10// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
11// SPDX-License-Identifier: MPL-2.0
12
13#ifndef EIGEN_COMPLEX_EIGEN_SOLVER_H
14#define EIGEN_COMPLEX_EIGEN_SOLVER_H
15
16#include "./ComplexSchur.h"
17
18// IWYU pragma: private
19#include "./InternalHeaderCheck.h"
20
21namespace Eigen {
22
49template <typename MatrixType_>
51 public:
53 using MatrixType = MatrixType_;
54
55 enum {
56 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
57 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
58 Options = internal::plain_object_options<MatrixType>::value,
59 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
60 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
61 };
62
64 using Scalar = typename MatrixType::Scalar;
65 using RealScalar = typename NumTraits<Scalar>::Real;
66 using Index = Eigen::Index;
67
74 using ComplexScalar = internal::make_complex_t<Scalar>;
75
81 using EigenvalueType = Matrix<ComplexScalar, ColsAtCompileTime, 1, Options & (~RowMajor), MaxColsAtCompileTime, 1>;
82
90
96 ComplexEigenSolver() : m_eivec(), m_eivalues(), m_schur(), m_isInitialized(false), m_eigenvectorsOk(false) {}
97
105 : m_eivec(size, size), m_eivalues(size), m_schur(size), m_isInitialized(false), m_eigenvectorsOk(false) {}
106
116 template <typename InputType>
117 explicit ComplexEigenSolver(const EigenBase<InputType>& matrix, bool computeEigenvectors = true)
118 : m_eivec(matrix.rows(), matrix.cols()),
119 m_eivalues(matrix.cols()),
120 m_schur(matrix.derived(), computeEigenvectors),
121 m_isInitialized(false),
122 m_eigenvectorsOk(false) {
123 computeFromSchur(computeEigenvectors);
124 }
125
137 template <typename InputType>
138 explicit ComplexEigenSolver(EigenBase<InputType>& matrix, bool computeEigenvectors = true)
139 : m_eivec(matrix.rows(), matrix.cols()),
140 m_eivalues(matrix.cols()),
141 m_schur(matrix.derived(), computeEigenvectors),
142 m_isInitialized(false),
143 m_eigenvectorsOk(false) {
144 computeFromSchur(computeEigenvectors);
145 }
146
168 eigen_assert(m_isInitialized && "ComplexEigenSolver is not initialized.");
169 eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
170 return m_eivec;
171 }
172
192 eigen_assert(m_isInitialized && "ComplexEigenSolver is not initialized.");
193 return m_eivalues;
194 }
195
220 template <typename InputType>
221 ComplexEigenSolver& compute(const EigenBase<InputType>& matrix, bool computeEigenvectors = true);
222
228 eigen_assert(m_isInitialized && "ComplexEigenSolver is not initialized.");
229 return m_schur.info();
230 }
231
234 m_schur.setMaxIterations(maxIters);
235 return *this;
236 }
237
239 Index getMaxIterations() const { return m_schur.getMaxIterations(); }
240
241 protected:
242 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
243
244 EigenvectorType m_eivec;
245 EigenvalueType m_eivalues;
246 // Holds the Schur form of the last matrix; computing the eigenvectors overwrites T with the eigenvectors of T.
248 bool m_isInitialized;
249 bool m_eigenvectorsOk;
250
251 private:
252 ComplexEigenSolver& computeFromSchur(bool computeEigenvectors);
253 void doComputeEigenvectors(RealScalar matrixnorm);
254 void sortEigenvalues(bool computeEigenvectors);
255};
256
257template <typename MatrixType>
258template <typename InputType>
259ComplexEigenSolver<MatrixType>& ComplexEigenSolver<MatrixType>::compute(const EigenBase<InputType>& matrix,
260 bool computeEigenvectors) {
261 // this code is inspired from Jampack
262 eigen_assert(matrix.cols() == matrix.rows());
263
264 // Do a complex Schur decomposition, A = U T U^*
265 // The eigenvalues are on the diagonal of T.
266 m_schur.compute(matrix.derived(), computeEigenvectors);
267 return computeFromSchur(computeEigenvectors);
268}
269
272template <typename MatrixType>
273ComplexEigenSolver<MatrixType>& ComplexEigenSolver<MatrixType>::computeFromSchur(bool computeEigenvectors) {
274 if (m_schur.info() == Success) {
275 m_eivalues = m_schur.matrixT().diagonal();
276 if (computeEigenvectors) doComputeEigenvectors(m_schur.matrixT().norm());
277 sortEigenvalues(computeEigenvectors);
278 }
279
280 m_isInitialized = true;
281 m_eigenvectorsOk = computeEigenvectors;
282 return *this;
283}
284
285template <typename MatrixType>
286void ComplexEigenSolver<MatrixType>::doComputeEigenvectors(RealScalar matrixnorm) {
287 const Index n = m_eivalues.size();
288
289 // Compute X such that T = X D X^(-1), where D is the diagonal of T.
290 // The matrix X is unit triangular. It overwrites T column by column from the last one: X(i,k) reads T(i,k) before
291 // replacing it, T(i,i+1..k-1) and T(i,i), T(k,k), which lie in columns not yet overwritten, and X(i+1..k-1,k),
292 // already computed.
293 typename ComplexSchur<MatrixType>::MatrixTType& matX = m_schur.m_matT;
294 matX.template triangularView<StrictlyLower>().setZero();
295 for (Index k = n - 1; k >= 0; k--) {
296 // Compute X(i,k) using the (i,k) entry of the equation X T = D X
297 for (Index i = k - 1; i >= 0; i--) {
298 matX.coeffRef(i, k) = -matX.coeff(i, k);
299 if (k - i - 1 > 0)
300 matX.coeffRef(i, k) -= (matX.row(i).segment(i + 1, k - i - 1) * matX.col(k).segment(i + 1, k - i - 1)).value();
301 ComplexScalar z = matX.coeff(i, i) - matX.coeff(k, k);
302 if (z == ComplexScalar(0)) {
303 // If the i-th and k-th eigenvalue are equal, then z equals 0.
304 // Use a small value instead, to prevent division by zero.
305 numext::real_ref(z) = numext::maxi(std::numeric_limits<RealScalar>::epsilon() * matrixnorm,
306 (std::numeric_limits<RealScalar>::min)());
307 }
308 matX.coeffRef(i, k) /= z;
309 }
310 matX.coeffRef(k, k) = ComplexScalar(1.0, 0.0);
311 }
312
313 // Compute V as V = U X; now A = U T U^* = U X D X^(-1) U^* = V D V^(-1)
314 m_eivec.noalias() = m_schur.matrixU() * matX;
315 // .. and normalize the eigenvectors
316 for (Index k = 0; k < n; k++) {
317 m_eivec.col(k).stableNormalize();
318 }
319}
320
321template <typename MatrixType>
322void ComplexEigenSolver<MatrixType>::sortEigenvalues(bool computeEigenvectors) {
323 const Index n = m_eivalues.size();
324 for (Index i = 0; i < n; i++) {
325 Index k;
326 m_eivalues.cwiseAbs().tail(n - i).minCoeff(&k);
327 if (k != 0) {
328 k += i;
329 std::swap(m_eivalues[k], m_eivalues[i]);
330 if (computeEigenvectors) m_eivec.col(i).swap(m_eivec.col(k));
331 }
332 }
333}
334
335} // end namespace Eigen
336
337#endif // EIGEN_COMPLEX_EIGEN_SOLVER_H
Computes eigenvalues and eigenvectors of general complex matrices.
Definition ComplexEigenSolver.h:50
MatrixType_ MatrixType
Synonym for the template parameter MatrixType_.
Definition ComplexEigenSolver.h:53
ComplexEigenSolver & compute(const EigenBase< InputType > &matrix, bool computeEigenvectors=true)
Computes eigendecomposition of given matrix.
ComplexEigenSolver(Index size)
Default Constructor with memory preallocation.
Definition ComplexEigenSolver.h:104
internal::make_complex_t< Scalar > ComplexScalar
Complex scalar type for MatrixType.
Definition ComplexEigenSolver.h:74
ComplexEigenSolver()
Default constructor.
Definition ComplexEigenSolver.h:96
ComplexEigenSolver & setMaxIterations(Index maxIters)
Sets the maximum number of iterations allowed.
Definition ComplexEigenSolver.h:233
typename MatrixType::Scalar Scalar
Scalar type for matrices of type MatrixType.
Definition ComplexEigenSolver.h:64
ComplexEigenSolver(const EigenBase< InputType > &matrix, bool computeEigenvectors=true)
Constructor; computes eigendecomposition of given matrix.
Definition ComplexEigenSolver.h:117
ComplexEigenSolver(EigenBase< InputType > &matrix, bool computeEigenvectors=true)
Constructor for inplace decomposition .
Definition ComplexEigenSolver.h:138
const EigenvectorType & eigenvectors() const
Returns the eigenvectors of given matrix.
Definition ComplexEigenSolver.h:167
Matrix< ComplexScalar, ColsAtCompileTime, 1, Options &(~RowMajor), MaxColsAtCompileTime, 1 > EigenvalueType
Type for vector of eigenvalues as returned by eigenvalues().
Definition ComplexEigenSolver.h:81
Matrix< ComplexScalar, RowsAtCompileTime, ColsAtCompileTime, Options, MaxRowsAtCompileTime, MaxColsAtCompileTime > EigenvectorType
Type for matrix of eigenvectors as returned by eigenvectors().
Definition ComplexEigenSolver.h:88
Index getMaxIterations() const
Returns the maximum number of iterations.
Definition ComplexEigenSolver.h:239
const EigenvalueType & eigenvalues() const
Returns the eigenvalues of given matrix.
Definition ComplexEigenSolver.h:191
ComputationInfo info() const
Reports whether previous computation was successful.
Definition ComplexEigenSolver.h:227
Eigen::Index Index
Definition ComplexEigenSolver.h:66
Performs a complex Schur decomposition of a real or complex square matrix.
Definition ComplexSchur.h:60
std::conditional_t< internal::is_ref< MatrixType >::value, MatrixType, ComplexMatrixType > MatrixTType
Type of the matrix returned by matrixT().
Definition ComplexSchur.h:96
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:188
ComputationInfo
Definition Constants.h:455
@ Success
Definition Constants.h:457
@ RowMajor
Definition Constants.h:321
Definition EigenBase.h:34