Eigen  5.0.1
 
Loading...
Searching...
No Matches
HessenbergDecomposition.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
5// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
6//
7// This Source Code Form is subject to the terms of the Mozilla
8// Public License v. 2.0. If a copy of the MPL was not distributed
9// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10// SPDX-License-Identifier: MPL-2.0
11
12#ifndef EIGEN_HESSENBERGDECOMPOSITION_H
13#define EIGEN_HESSENBERGDECOMPOSITION_H
14
15// IWYU pragma: private
16#include "./InternalHeaderCheck.h"
17
18namespace Eigen {
19
20namespace internal {
21
22template <typename MatrixType>
24template <typename MatrixType>
25struct traits<HessenbergDecompositionMatrixHReturnType<MatrixType>> {
26 using ReturnType = typename MatrixType::PlainObject;
27};
28
29template <typename MatrixType, typename CoeffVectorType, typename WorkspaceType>
30void hessenberg_decomposition_inplace(MatrixType& matA, CoeffVectorType& hCoeffs, WorkspaceType& temp);
31
32} // namespace internal
33
64template <typename MatrixType_>
66 public:
68 using MatrixType = MatrixType_;
69
70 enum {
71 Size = MatrixType::RowsAtCompileTime,
72 SizeMinusOne = Size == Dynamic ? Dynamic : Size - 1,
73 Options = internal::plain_object_options<MatrixType>::value,
74 MaxSize = MatrixType::MaxRowsAtCompileTime,
75 MaxSizeMinusOne = MaxSize == Dynamic ? Dynamic : MaxSize - 1
76 };
77
79 using Scalar = typename MatrixType::Scalar;
80 using Index = Eigen::Index;
81
89
93
95
107 explicit HessenbergDecomposition(Index size = Size == Dynamic ? 2 : Size)
108 : m_matrix(size, size), m_temp(size), m_isInitialized(false) {
109 if (size > 1) m_hCoeffs.resize(size - 1);
110 }
111
121 template <typename InputType>
123 : m_matrix(matrix.derived()), m_temp(matrix.rows()), m_isInitialized(false) {
124 computeInPlace();
125 }
126
135 template <typename InputType>
137 : m_matrix(matrix.derived()), m_temp(matrix.rows()), m_isInitialized(false) {
138 computeInPlace();
139 }
140
158 template <typename InputType>
160 m_matrix = matrix.derived();
161 computeInPlace();
162 return *this;
163 }
164
179 eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized.");
180 return m_hCoeffs;
181 }
182
212 const MatrixType& packedMatrix() const {
213 eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized.");
214 return m_matrix;
215 }
216
232 eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized.");
233 return HouseholderSequenceType(m_matrix, m_hCoeffs.conjugate()).setLength(m_matrix.rows() - 1).setShift(1);
234 }
235
256 MatrixHReturnType matrixH() const {
257 eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized.");
258 return MatrixHReturnType(*this);
259 }
260
261 private:
262 using VectorType = Matrix<Scalar, 1, Size, int(Options) | int(RowMajor), 1, MaxSize>;
263 using RealScalar = typename NumTraits<Scalar>::Real;
264
265 void computeInPlace() {
266 if (m_matrix.rows() < 2) {
267 m_isInitialized = true;
268 return;
269 }
270 m_hCoeffs.resize(m_matrix.rows() - 1, 1);
271 internal::hessenberg_decomposition_inplace(m_matrix, m_hCoeffs, m_temp);
272 m_isInitialized = true;
273 }
274
275 protected:
276 MatrixType m_matrix;
277 CoeffVectorType m_hCoeffs;
278 VectorType m_temp;
279 bool m_isInitialized;
280};
281
282namespace internal {
283
299template <typename MatrixType, typename CoeffVectorType, typename WorkspaceType>
300void hessenberg_decomposition_inplace(MatrixType& matA, CoeffVectorType& hCoeffs, WorkspaceType& temp) {
301 using Scalar = typename MatrixType::Scalar;
302 using RealScalar = typename NumTraits<Scalar>::Real;
303 eigen_assert(matA.rows() == matA.cols());
304 Index n = matA.rows();
305 temp.resize(n);
306 for (Index i = 0; i < n - 1; ++i) {
307 // let's consider the vector v = i-th column starting at position i+1
308 Index remainingSize = n - i - 1;
309 RealScalar beta;
310 Scalar h;
311 auto householder = matA.col(i).tail(remainingSize);
312 const RealScalar tailSqNorm =
313 remainingSize == 1 ? RealScalar(0) : householder.tail(remainingSize - 1).unwind().squaredNorm();
314 const RealScalar tol = (std::numeric_limits<RealScalar>::min)();
315 // Preserve negligible subdiagonal entries instead of rotating them into much larger matrix coefficients. The
316 // latter can erase small eigenvalues through cancellation even though the reflector itself is accurate.
317 if (tailSqNorm <= tol && numext::abs2(numext::imag(householder.coeff(0))) <= tol) {
318 h = Scalar(0);
319 beta = numext::real(householder.coeff(0));
320 householder.tail(remainingSize - 1).setZero();
321 } else {
322 householder.makeHouseholderInPlace(h, beta);
323 }
324 matA.col(i).coeffRef(i + 1) = beta;
325 hCoeffs.coeffRef(i) = h;
326
327 // Apply similarity transformation to remaining columns,
328 // i.e., compute A = H A H'
329
330 // A = H A
331 matA.bottomRightCorner(remainingSize, remainingSize)
332 .applyHouseholderOnTheLeft(matA.col(i).tail(remainingSize - 1), h, &temp.coeffRef(0));
333
334 // A = A H'
335 matA.rightCols(remainingSize)
336 .applyHouseholderOnTheRight(matA.col(i).tail(remainingSize - 1), numext::conj(h), &temp.coeffRef(0));
337 }
338}
339
352template <typename MatrixType, typename CoeffVectorType, typename WorkspaceType, typename MatrixQType>
353void hessenberg_decomposition_inplace(MatrixType& matA, CoeffVectorType& hCoeffs, WorkspaceType& temp,
354 MatrixQType& matQ, bool computeQ) {
355 using HouseholderSequenceType =
356 HouseholderSequence<MatrixType, remove_all_t<typename CoeffVectorType::ConjugateReturnType>>;
357 const Index n = matA.rows();
358 hCoeffs.resize(n - 1);
359 hessenberg_decomposition_inplace(matA, hCoeffs, temp);
360 if (computeQ) {
361 Index firstReflector = 0;
362 while (firstReflector < n - 1 && numext::is_exactly_zero(hCoeffs.coeff(firstReflector))) ++firstReflector;
363 if (firstReflector == n - 1) {
364 // All tau_i = 0: Q = I, without allocating block Householder factors.
365 matQ.setIdentity(n, n);
366 } else {
367 HouseholderSequenceType(matA, hCoeffs.conjugate()).setLength(n - 1).setShift(1).evalTo(matQ, temp);
368 }
369 }
370 if (n > 2) matA.bottomLeftCorner(n - 2, n - 2).template triangularView<Lower>().setZero();
371}
372
388template <typename MatrixType>
390 : public ReturnByValue<HessenbergDecompositionMatrixHReturnType<MatrixType>> {
391 public:
397
403 template <typename ResultType>
404 inline void evalTo(ResultType& result) const {
405 result = m_hess.packedMatrix();
406 Index n = result.rows();
407 if (n > 2) result.bottomLeftCorner(n - 2, n - 2).template triangularView<Lower>().setZero();
408 }
409
410 Index rows() const { return m_hess.packedMatrix().rows(); }
411 Index cols() const { return m_hess.packedMatrix().cols(); }
412
413 protected:
414 const HessenbergDecomposition<MatrixType>& m_hess;
415};
416
417} // end namespace internal
418
419} // end namespace Eigen
420
421#endif // EIGEN_HESSENBERGDECOMPOSITION_H
Reduces a square matrix to Hessenberg form by an orthogonal similarity transformation.
Definition HessenbergDecomposition.h:65
HessenbergDecomposition(EigenBase< InputType > &matrix)
Constructor for inplace decomposition .
Definition HessenbergDecomposition.h:136
HessenbergDecomposition(Index size=Size==Dynamic ? 2 :Size)
Default constructor; the decomposition will be computed later.
Definition HessenbergDecomposition.h:107
HouseholderSequence< MatrixType, internal::remove_all_t< typename CoeffVectorType::ConjugateReturnType > > HouseholderSequenceType
Return type of matrixQ()
Definition HessenbergDecomposition.h:91
HessenbergDecomposition(const EigenBase< InputType > &matrix)
Constructor; computes Hessenberg decomposition of given matrix.
Definition HessenbergDecomposition.h:122
MatrixType_ MatrixType
Synonym for the template parameter MatrixType_.
Definition HessenbergDecomposition.h:68
const MatrixType & packedMatrix() const
Returns the internal representation of the decomposition.
Definition HessenbergDecomposition.h:212
MatrixHReturnType matrixH() const
Constructs the Hessenberg matrix H in the decomposition.
Definition HessenbergDecomposition.h:256
HouseholderSequenceType matrixQ() const
Reconstructs the orthogonal matrix Q in the decomposition.
Definition HessenbergDecomposition.h:231
typename MatrixType::Scalar Scalar
Scalar type for matrices of type MatrixType.
Definition HessenbergDecomposition.h:79
Eigen::Index Index
Definition HessenbergDecomposition.h:80
HessenbergDecomposition & compute(const EigenBase< InputType > &matrix)
Computes Hessenberg decomposition of given matrix.
Definition HessenbergDecomposition.h:159
Matrix< Scalar, SizeMinusOne, 1, Options &~RowMajor, MaxSizeMinusOne, 1 > CoeffVectorType
Type for vector of Householder coefficients.
Definition HessenbergDecomposition.h:88
const CoeffVectorType & householderCoefficients() const
Returns the Householder coefficients.
Definition HessenbergDecomposition.h:178
Sequence of Householder reflections acting on subspaces with decreasing size.
Definition HouseholderSequence.h:140
HouseholderSequence & setLength(Index length)
Sets the length of the Householder sequence.
Definition HouseholderSequence.h:526
HouseholderSequence & setShift(Index shift)
Sets the shift of the Householder sequence.
Definition HouseholderSequence.h:542
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:188
constexpr void resize(Index rows, Index cols)
Definition PlainObjectBase.h:282
@ RowMajor
Definition Constants.h:321
Definition EigenBase.h:34
constexpr Derived & derived()
Definition EigenBase.h:50
Expression type for return value of HessenbergDecomposition::matrixH()
Definition HessenbergDecomposition.h:390
void evalTo(ResultType &result) const
Hessenberg matrix in decomposition.
Definition HessenbergDecomposition.h:404
HessenbergDecompositionMatrixHReturnType(const HessenbergDecomposition< MatrixType > &hess)
Constructor.
Definition HessenbergDecomposition.h:396