13#ifndef EIGEN_COMPLEX_SCHUR_H
14#define EIGEN_COMPLEX_SCHUR_H
16#include "./HessenbergDecomposition.h"
19#include "./InternalHeaderCheck.h"
24template <
typename MatrixType,
bool IsComplex>
25struct complex_schur_reduce_to_hessenberg;
28template <
typename MatrixType_>
59template <
typename MatrixType_>
62 using MatrixType = MatrixType_;
64 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
65 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
66 Options = internal::plain_object_options<MatrixType>::value,
67 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
68 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
72 using Scalar =
typename MatrixType::Scalar;
73 using RealScalar =
typename NumTraits<Scalar>::Real;
110 : m_matT(size, size),
113 m_isInitialized(false),
114 m_matUisUptodate(false),
126 template <
typename InputType>
128 : m_matT(matrix.rows(), matrix.cols()),
129 m_matU(matrix.rows(), matrix.cols()),
130 m_hess(matrix.rows()),
131 m_isInitialized(false),
132 m_matUisUptodate(false),
146 template <typename InputType, bool IsRef = internal::is_ref<MatrixType>::value, std::enable_if_t<IsRef, int> = 0>
148 : m_matT(matrix.derived()),
149 m_matU(matrix.rows(), matrix.cols()),
150 m_hess(matrix.rows()),
151 m_isInitialized(false),
152 m_matUisUptodate(false),
154 computeInPlace(computeU);
172 eigen_assert(m_isInitialized &&
"ComplexSchur is not initialized.");
173 eigen_assert(m_matUisUptodate &&
"The matrix U has not been computed during the ComplexSchur decomposition.");
195 eigen_assert(m_isInitialized &&
"ComplexSchur is not initialized.");
220 template <
typename InputType>
240 template <
typename HessMatrixType,
typename OrthMatrixType>
242 bool computeU =
true);
249 eigen_assert(m_isInitialized &&
"ComplexSchur is not initialized.");
259 m_maxIters = maxIters;
274 EIGEN_STATIC_ASSERT(NumTraits<Scalar>::IsComplex || !internal::is_ref<MatrixType>::value,
275 INPLACE_COMPLEXSCHUR_REQUIRES_A_COMPLEX_MATRIX_TYPE)
279 internal::complex_schur_reduce_to_hessenberg<MatrixType, NumTraits<Scalar>::IsComplex> m_hess;
281 bool m_isInitialized;
282 bool m_matUisUptodate;
290 bool subdiagonalEntryIsNeglegible(
Index i);
292 void reduceToTriangularForm(
bool computeU);
293 friend struct internal::complex_schur_reduce_to_hessenberg<MatrixType,
NumTraits<
Scalar>::IsComplex>;
299template <typename MatrixType>
300inline bool
ComplexSchur<MatrixType>::subdiagonalEntryIsNeglegible(Index i) {
301 RealScalar d = numext::norm1(m_matT.coeff(i, i)) + numext::norm1(m_matT.coeff(i + 1, i + 1));
302 RealScalar sd = numext::norm1(m_matT.coeff(i + 1, i));
303 if (internal::isMuchSmallerThan(sd, d, NumTraits<RealScalar>::epsilon())) {
311template <
typename MatrixType>
314 if ((iter == 10 || iter == 20) && iu > 1) {
317 abs(numext::real(m_matT.coeff(iu - 1, iu - 2))));
322 Matrix<ComplexScalar, 2, 2> t = m_matT.template block<2, 2>(iu - 1, iu - 1);
323 const RealScalar normt = t.cwiseAbs().sum();
324 const auto factors = internal::safe_scaling<RealScalar>::scale_to(t, t, normt);
333 RealScalar eival1_norm = numext::norm1(eival1);
334 RealScalar eival2_norm = numext::norm1(eival2);
337 if (eival1_norm > eival2_norm)
338 eival2 = det / eival1;
339 else if (!numext::is_exactly_zero(eival2_norm))
340 eival1 = det / eival2;
343 ComplexScalar shift = numext::norm1(eival1 - t.coeff(1, 1)) < numext::norm1(eival2 - t.coeff(1, 1)) ? eival1 : eival2;
344 internal::safe_scaling<RealScalar>::unscale_in_place(shift, factors);
348template <
typename MatrixType>
349template <
typename InputType>
351 m_matUisUptodate =
false;
352 eigen_assert(matrix.cols() == matrix.rows());
354 if (matrix.cols() <= 1) {
355 m_matT = matrix.derived().template cast<ComplexScalar>();
356 if (computeU) m_matU = ComplexMatrixType::Identity(matrix.rows(), matrix.cols());
358 m_isInitialized =
true;
359 m_matUisUptodate = computeU;
370 const RealScalar maxCoeff = internal::safe_scaling<RealScalar>::recover_flushed_max_coeff(
371 matrix.derived(), matrix.derived().cwiseAbs().template maxCoeff<PropagateNaN>());
372 const internal::safe_scaling_factors<RealScalar> factors = internal::safe_scaling<RealScalar>::with_scaled(
373 matrix.derived(), maxCoeff, [&](
const auto& scaled) { m_hess.run(*this, scaled, computeU); });
376 internal::safe_scaling<RealScalar>::unscale_in_place(m_matT, maxCoeff, factors);
381template <
typename MatrixType>
383 m_matUisUptodate =
false;
384 eigen_assert(m_matT.cols() == m_matT.rows());
386 if (m_matT.cols() <= 1) {
387 if (computeU) m_matU = ComplexMatrixType::Identity(m_matT.rows(), m_matT.cols());
389 m_isInitialized =
true;
390 m_matUisUptodate = computeU;
394 const RealScalar maxCoeff = internal::safe_scaling<RealScalar>::recover_flushed_max_coeff(
395 m_matT, m_matT.cwiseAbs().template maxCoeff<PropagateNaN>());
396 const internal::safe_scaling_factors<RealScalar> factors =
397 internal::safe_scaling<RealScalar>::scale_in_place(m_matT, maxCoeff);
398 m_hess.runInPlace(*
this, computeU);
400 internal::safe_scaling<RealScalar>::unscale_in_place(m_matT, maxCoeff, factors);
404template <
typename MatrixType>
405template <
typename HessMatrixType,
typename OrthMatrixType>
407 const OrthMatrixType& matrixQ,
409 if (!internal::is_same_dense(m_matT, matrixH)) m_matT = matrixH;
410 if (computeU && !internal::is_same_dense(m_matU, matrixQ)) m_matU = matrixQ;
411 reduceToTriangularForm(computeU);
417template <
typename MatrixType,
bool IsComplex>
418struct complex_schur_reduce_to_hessenberg {
420 using Schur = ComplexSchur<MatrixType>;
421 using Scalar =
typename Schur::ComplexScalar;
422 using CoeffVectorType = Matrix<Scalar, Schur::RowsAtCompileTime == Dynamic ? Dynamic : Schur::RowsAtCompileTime - 1,
423 1, Schur::Options & ~RowMajor,
424 Schur::MaxRowsAtCompileTime == Dynamic ? Dynamic : Schur::MaxRowsAtCompileTime - 1, 1>;
425 using WorkspaceType =
426 Matrix<Scalar, Schur::ColsAtCompileTime, 1, Schur::Options & ~RowMajor, Schur::MaxColsAtCompileTime, 1>;
428 explicit complex_schur_reduce_to_hessenberg(Index size) : m_workspace(size) {
429 if (size > 1) m_hCoeffs.resize(size - 1);
432 template <
typename InputType>
433 void run(Schur& _this,
const InputType& matrix,
bool computeU) {
434 _this.m_matT = matrix;
435 runInPlace(_this, computeU);
438 void runInPlace(Schur& _this,
bool computeU) {
439 hessenberg_decomposition_inplace(_this.m_matT, m_hCoeffs, m_workspace, _this.m_matU, computeU);
442 CoeffVectorType m_hCoeffs;
443 WorkspaceType m_workspace;
446template <
typename MatrixType>
447struct complex_schur_reduce_to_hessenberg<MatrixType, false> {
448 using Schur = ComplexSchur<MatrixType>;
450 explicit complex_schur_reduce_to_hessenberg(Index size) : m_hess(size) {}
452 template <
typename InputType>
453 void run(Schur& _this,
const InputType& matrix,
bool computeU) {
454 using ComplexScalar =
typename Schur::ComplexScalar;
457 m_hess.compute(matrix);
458 _this.m_matT = m_hess.matrixH().template cast<ComplexScalar>();
461 MatrixType Q = m_hess.matrixQ();
462 _this.m_matU = Q.template cast<ComplexScalar>();
466 HessenbergDecomposition<MatrixType> m_hess;
472template <
typename MatrixType>
474 Index maxIters = m_maxIters;
481 Index iu = m_matT.cols() - 1;
489 if (!subdiagonalEntryIsNeglegible(iu - 1))
break;
500 if (totalIter > maxIters)
break;
504 while (il > 0 && !subdiagonalEntryIsNeglegible(il - 1)) {
513 JacobiRotation<ComplexScalar> rot;
514 rot.makeGivens(m_matT.coeff(il, il) - shift, m_matT.coeff(il + 1, il));
515 m_matT.rightCols(m_matT.cols() - il).applyOnTheLeft(il, il + 1, rot.adjoint());
516 m_matT.topRows((std::min)(il + 2, iu) + 1).applyOnTheRight(il, il + 1, rot);
517 if (computeU) m_matU.applyOnTheRight(il, il + 1, rot);
519 for (
Index i = il + 1; i < iu; i++) {
520 rot.makeGivens(m_matT.coeffRef(i, i - 1), m_matT.coeffRef(i + 1, i - 1), &m_matT.coeffRef(i, i - 1));
522 m_matT.rightCols(m_matT.cols() - i).applyOnTheLeft(i, i + 1, rot.adjoint());
523 m_matT.topRows((std::min)(i + 2, iu) + 1).applyOnTheRight(i, i + 1, rot);
524 if (computeU) m_matU.applyOnTheRight(i, i + 1, rot);
528 if (totalIter <= maxIters)
533 m_isInitialized =
true;
534 m_matUisUptodate = computeU;
Computes eigenvalues and eigenvectors of general complex matrices.
Definition ComplexEigenSolver.h:50
ComputationInfo info() const
Reports whether previous computation was successful.
Definition ComplexSchur.h:248
Eigen::Index Index
Definition ComplexSchur.h:74
std::conditional_t< internal::is_ref< MatrixType >::value, MatrixType, ComplexMatrixType > MatrixTType
Type of the matrix returned by matrixT().
Definition ComplexSchur.h:96
ComplexSchur(Index size=RowsAtCompileTime==Dynamic ? 1 :RowsAtCompileTime)
Default constructor.
Definition ComplexSchur.h:109
const MatrixTType & matrixT() const
Returns the triangular matrix in the Schur decomposition.
Definition ComplexSchur.h:194
Matrix< ComplexScalar, RowsAtCompileTime, ColsAtCompileTime, Options, MaxRowsAtCompileTime, MaxColsAtCompileTime > ComplexMatrixType
Type for the matrices in the Schur decomposition.
Definition ComplexSchur.h:89
typename MatrixType::Scalar Scalar
Scalar type for matrices of type MatrixType_.
Definition ComplexSchur.h:72
ComplexSchur & computeFromHessenberg(const HessMatrixType &matrixH, const OrthMatrixType &matrixQ, bool computeU=true)
Compute Schur decomposition from a given Hessenberg matrix.
Index getMaxIterations() const
Returns the maximum number of iterations.
Definition ComplexSchur.h:264
static const int m_maxIterationsPerRow
Definition ComplexSchur.h:271
internal::make_complex_t< Scalar > ComplexScalar
Complex scalar type for MatrixType_.
Definition ComplexSchur.h:82
ComplexSchur(const EigenBase< InputType > &matrix, bool computeU=true)
Constructor; computes Schur decomposition of given matrix.
Definition ComplexSchur.h:127
ComplexSchur(EigenBase< InputType > &matrix, bool computeU=true)
Constructor for inplace decomposition .
Definition ComplexSchur.h:147
ComplexSchur & compute(const EigenBase< InputType > &matrix, bool computeU=true)
Computes Schur decomposition of given matrix.
ComplexSchur & setMaxIterations(Index maxIters)
Sets the maximum number of iterations allowed.
Definition ComplexSchur.h:258
const ComplexMatrixType & matrixU() const
Returns the unitary matrix in the Schur decomposition.
Definition ComplexSchur.h:171
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:188
ComputationInfo
Definition Constants.h:455
@ Success
Definition Constants.h:457
@ NoConvergence
Definition Constants.h:461
Definition EigenBase.h:34
constexpr Derived & derived()
Definition EigenBase.h:50
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition NumTraits.h:233