Eigen  3.4.90 (git rev 5a9f66fb35d03a4da9ef8976e67a61b30aa16dcf)
 
Loading...
Searching...
No Matches
Tridiagonalization.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2008 Gael Guennebaud <[email protected]>
5// Copyright (C) 2010 Jitse Niesen <[email protected]>
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
11#ifndef EIGEN_TRIDIAGONALIZATION_H
12#define EIGEN_TRIDIAGONALIZATION_H
13
14// IWYU pragma: private
15#include "./InternalHeaderCheck.h"
16
17namespace Eigen {
18
19namespace internal {
20
21template <typename MatrixType>
22struct TridiagonalizationMatrixTReturnType;
23template <typename MatrixType>
24struct traits<TridiagonalizationMatrixTReturnType<MatrixType>> : public traits<typename MatrixType::PlainObject> {
25 typedef typename MatrixType::PlainObject ReturnType; // FIXME shall it be a BandMatrix?
26 enum { Flags = 0 };
27};
28
29template <typename MatrixType, typename CoeffVectorType>
30EIGEN_DEVICE_FUNC void tridiagonalization_inplace(MatrixType& matA, CoeffVectorType& hCoeffs);
31} // namespace internal
32
65template <typename MatrixType_>
67 public:
69 typedef MatrixType_ MatrixType;
70
71 typedef typename MatrixType::Scalar Scalar;
72 typedef typename NumTraits<Scalar>::Real RealScalar;
74
75 enum {
76 Size = MatrixType::RowsAtCompileTime,
77 SizeMinusOne = Size == Dynamic ? Dynamic : (Size > 1 ? Size - 1 : 1),
78 Options = internal::traits<MatrixType>::Options,
79 MaxSize = MatrixType::MaxRowsAtCompileTime,
80 MaxSizeMinusOne = MaxSize == Dynamic ? Dynamic : (MaxSize > 1 ? MaxSize - 1 : 1)
81 };
82
84 typedef typename internal::plain_col_type<MatrixType, RealScalar>::type DiagonalType;
86 typedef internal::remove_all_t<typename MatrixType::RealReturnType> MatrixTypeRealView;
87 typedef internal::TridiagonalizationMatrixTReturnType<MatrixTypeRealView> MatrixTReturnType;
88
89 typedef std::conditional_t<NumTraits<Scalar>::IsComplex,
90 internal::add_const_on_value_type_t<typename Diagonal<const MatrixType>::RealReturnType>,
92 DiagonalReturnType;
93
94 typedef std::conditional_t<
96 internal::add_const_on_value_type_t<typename Diagonal<const MatrixType, -1>::RealReturnType>,
97 const Diagonal<const MatrixType, -1>>
98 SubDiagonalReturnType;
99
103
116 explicit Tridiagonalization(Index size = Size == Dynamic ? 2 : Size)
117 : m_matrix(size, size), m_hCoeffs(size > 1 ? size - 1 : 1), m_isInitialized(false) {}
118
129 template <typename InputType>
131 : m_matrix(matrix.derived()), m_hCoeffs(matrix.cols() > 1 ? matrix.cols() - 1 : 1), m_isInitialized(false) {
132 internal::tridiagonalization_inplace(m_matrix, m_hCoeffs);
133 m_isInitialized = true;
134 }
135
153 template <typename InputType>
155 m_matrix = matrix.derived();
156 m_hCoeffs.resize(matrix.rows() - 1, 1);
157 internal::tridiagonalization_inplace(m_matrix, m_hCoeffs);
158 m_isInitialized = true;
159 return *this;
160 }
161
179 eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
180 return m_hCoeffs;
181 }
182
214 inline const MatrixType& packedMatrix() const {
215 eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
216 return m_matrix;
217 }
218
235 eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
236 return HouseholderSequenceType(m_matrix, m_hCoeffs.conjugate()).setLength(m_matrix.rows() - 1).setShift(1);
237 }
238
256 MatrixTReturnType matrixT() const {
257 eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
258 return MatrixTReturnType(m_matrix.real());
259 }
260
274 DiagonalReturnType diagonal() const;
275
286 SubDiagonalReturnType subDiagonal() const;
287
288 protected:
289 MatrixType m_matrix;
290 CoeffVectorType m_hCoeffs;
291 bool m_isInitialized;
292};
293
294template <typename MatrixType>
295typename Tridiagonalization<MatrixType>::DiagonalReturnType Tridiagonalization<MatrixType>::diagonal() const {
296 eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
297 return m_matrix.diagonal().real();
298}
299
300template <typename MatrixType>
301typename Tridiagonalization<MatrixType>::SubDiagonalReturnType Tridiagonalization<MatrixType>::subDiagonal() const {
302 eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
303 return m_matrix.template diagonal<-1>().real();
304}
305
306namespace internal {
307
331template <typename MatrixType, typename CoeffVectorType>
332EIGEN_DEVICE_FUNC void tridiagonalization_inplace(MatrixType& matA, CoeffVectorType& hCoeffs) {
333 using numext::conj;
334 typedef typename MatrixType::Scalar Scalar;
335 typedef typename MatrixType::RealScalar RealScalar;
336 Index n = matA.rows();
337 eigen_assert(n == matA.cols());
338 eigen_assert(n == hCoeffs.size() + 1 || n == 1);
339
340 for (Index i = 0; i < n - 1; ++i) {
341 Index remainingSize = n - i - 1;
342 RealScalar beta;
343 Scalar h;
344 matA.col(i).tail(remainingSize).makeHouseholderInPlace(h, beta);
345
346 // Apply similarity transformation to remaining columns,
347 // i.e., A = H A H' where H = I - h v v' and v = matA.col(i).tail(n-i-1)
348 matA.col(i).coeffRef(i + 1) = 1;
349
350 hCoeffs.tail(n - i - 1).noalias() =
351 (matA.bottomRightCorner(remainingSize, remainingSize).template selfadjointView<Lower>() *
352 (conj(h) * matA.col(i).tail(remainingSize)));
353
354 hCoeffs.tail(n - i - 1) +=
355 (conj(h) * RealScalar(-0.5) * (hCoeffs.tail(remainingSize).dot(matA.col(i).tail(remainingSize)))) *
356 matA.col(i).tail(n - i - 1);
357
358 matA.bottomRightCorner(remainingSize, remainingSize)
359 .template selfadjointView<Lower>()
360 .rankUpdate(matA.col(i).tail(remainingSize), hCoeffs.tail(remainingSize), Scalar(-1));
361
362 matA.col(i).coeffRef(i + 1) = beta;
363 hCoeffs.coeffRef(i) = h;
364 }
365}
366
367// forward declaration, implementation at the end of this file
368template <typename MatrixType, int Size = MatrixType::ColsAtCompileTime,
369 bool IsComplex = NumTraits<typename MatrixType::Scalar>::IsComplex>
370struct tridiagonalization_inplace_selector;
371
412template <typename MatrixType, typename DiagonalType, typename SubDiagonalType, typename CoeffVectorType,
413 typename WorkSpaceType>
414EIGEN_DEVICE_FUNC void tridiagonalization_inplace(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag,
415 CoeffVectorType& hcoeffs, WorkSpaceType& workspace, bool extractQ) {
416 eigen_assert(mat.cols() == mat.rows() && diag.size() == mat.rows() && subdiag.size() == mat.rows() - 1);
417 tridiagonalization_inplace_selector<MatrixType>::run(mat, diag, subdiag, hcoeffs, workspace, extractQ);
418}
419
423template <typename MatrixType, int Size, bool IsComplex>
424struct tridiagonalization_inplace_selector {
425 typedef typename Tridiagonalization<MatrixType>::HouseholderSequenceType HouseholderSequenceType;
426 template <typename DiagonalType, typename SubDiagonalType, typename CoeffVectorType, typename WorkSpaceType>
427 static EIGEN_DEVICE_FUNC void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag,
428 CoeffVectorType& hCoeffs, WorkSpaceType& workspace, bool extractQ) {
429 tridiagonalization_inplace(mat, hCoeffs);
430 diag = mat.diagonal().real();
431 subdiag = mat.template diagonal<-1>().real();
432 if (extractQ) {
433 HouseholderSequenceType(mat, hCoeffs.conjugate()).setLength(mat.rows() - 1).setShift(1).evalTo(mat, workspace);
434 }
435 }
436};
437
442template <typename MatrixType>
443struct tridiagonalization_inplace_selector<MatrixType, 3, false> {
444 typedef typename MatrixType::Scalar Scalar;
445 typedef typename MatrixType::RealScalar RealScalar;
446
447 template <typename DiagonalType, typename SubDiagonalType, typename CoeffVectorType, typename WorkSpaceType>
448 static EIGEN_DEVICE_FUNC void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag, CoeffVectorType&,
449 WorkSpaceType&, bool extractQ) {
450 using std::sqrt;
451 const RealScalar tol = (std::numeric_limits<RealScalar>::min)();
452 diag[0] = mat(0, 0);
453 RealScalar v1norm2 = numext::abs2(mat(2, 0));
454 if (v1norm2 <= tol) {
455 diag[1] = mat(1, 1);
456 diag[2] = mat(2, 2);
457 subdiag[0] = mat(1, 0);
458 subdiag[1] = mat(2, 1);
459 if (extractQ) mat.setIdentity();
460 } else {
461 RealScalar beta = sqrt(numext::abs2(mat(1, 0)) + v1norm2);
462 RealScalar invBeta = RealScalar(1) / beta;
463 Scalar m01 = mat(1, 0) * invBeta;
464 Scalar m02 = mat(2, 0) * invBeta;
465 Scalar q = RealScalar(2) * m01 * mat(2, 1) + m02 * (mat(2, 2) - mat(1, 1));
466 diag[1] = mat(1, 1) + m02 * q;
467 diag[2] = mat(2, 2) - m02 * q;
468 subdiag[0] = beta;
469 subdiag[1] = mat(2, 1) - m01 * q;
470 if (extractQ) {
471 mat << 1, 0, 0, 0, m01, m02, 0, m02, -m01;
472 }
473 }
474 }
475};
476
480template <typename MatrixType, bool IsComplex>
481struct tridiagonalization_inplace_selector<MatrixType, 1, IsComplex> {
482 typedef typename MatrixType::Scalar Scalar;
483
484 template <typename DiagonalType, typename SubDiagonalType, typename CoeffVectorType, typename WorkSpaceType>
485 static EIGEN_DEVICE_FUNC void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType&, CoeffVectorType&,
486 WorkSpaceType&, bool extractQ) {
487 diag(0, 0) = numext::real(mat(0, 0));
488 if (extractQ) mat(0, 0) = Scalar(1);
489 }
490};
491
499template <typename MatrixType>
500struct TridiagonalizationMatrixTReturnType : public ReturnByValue<TridiagonalizationMatrixTReturnType<MatrixType>> {
501 public:
506 TridiagonalizationMatrixTReturnType(const MatrixType& mat) : m_matrix(mat) {}
507
508 template <typename ResultType>
509 inline void evalTo(ResultType& result) const {
510 result.setZero();
511 result.template diagonal<1>() = m_matrix.template diagonal<-1>().conjugate();
512 result.diagonal() = m_matrix.diagonal();
513 result.template diagonal<-1>() = m_matrix.template diagonal<-1>();
514 }
515
516 EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_matrix.rows(); }
517 EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_matrix.cols(); }
518
519 protected:
520 typename MatrixType::Nested m_matrix;
521};
522
523} // end namespace internal
524
525} // end namespace Eigen
526
527#endif // EIGEN_TRIDIAGONALIZATION_H
Expression of a diagonal/subdiagonal/superdiagonal in a matrix.
Definition Diagonal.h:68
Sequence of Householder reflections acting on subspaces with decreasing size.
Definition HouseholderSequence.h:117
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:186
constexpr void resize(Index rows, Index cols)
Definition PlainObjectBase.h:294
Tridiagonal decomposition of a selfadjoint matrix.
Definition Tridiagonalization.h:66
Tridiagonalization(Index size=Size==Dynamic ? 2 :Size)
Default constructor.
Definition Tridiagonalization.h:116
DiagonalReturnType diagonal() const
Returns the diagonal of the tridiagonal matrix T in the decomposition.
Definition Tridiagonalization.h:295
MatrixType_ MatrixType
Synonym for the template parameter MatrixType_.
Definition Tridiagonalization.h:69
const MatrixType & packedMatrix() const
Returns the internal representation of the decomposition.
Definition Tridiagonalization.h:214
CoeffVectorType householderCoefficients() const
Returns the Householder coefficients.
Definition Tridiagonalization.h:178
HouseholderSequence< MatrixType, internal::remove_all_t< typename CoeffVectorType::ConjugateReturnType > > HouseholderSequenceType
Return type of matrixQ()
Definition Tridiagonalization.h:102
SubDiagonalReturnType subDiagonal() const
Returns the subdiagonal of the tridiagonal matrix T in the decomposition.
Definition Tridiagonalization.h:301
HouseholderSequenceType matrixQ() const
Returns the unitary matrix Q in the decomposition.
Definition Tridiagonalization.h:234
MatrixTReturnType matrixT() const
Returns an expression of the tridiagonal matrix T in the decomposition.
Definition Tridiagonalization.h:256
Tridiagonalization(const EigenBase< InputType > &matrix)
Constructor; computes tridiagonal decomposition of given matrix.
Definition Tridiagonalization.h:130
Tridiagonalization & compute(const EigenBase< InputType > &matrix)
Computes tridiagonal decomposition of given matrix.
Definition Tridiagonalization.h:154
Eigen::Index Index
Definition Tridiagonalization.h:73
Namespace containing all symbols from the Eigen library.
Definition Core:137
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_sqrt_op< typename Derived::Scalar >, const Derived > sqrt(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_real_op< typename Derived::Scalar >, const Derived > real(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_conjugate_op< typename Derived::Scalar >, const Derived > conj(const Eigen::ArrayBase< Derived > &x)
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition Meta.h:83
const int Dynamic
Definition Constants.h:25
Definition EigenBase.h:33
Derived & derived()
Definition EigenBase.h:49
EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT
Definition EigenBase.h:59
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition Meta.h:523