12#ifndef EIGEN_TRIDIAGONALIZATION_H
13#define EIGEN_TRIDIAGONALIZATION_H
16#include "./InternalHeaderCheck.h"
22template <
typename MatrixType>
23struct TridiagonalizationMatrixTReturnType;
24template <
typename MatrixType>
25struct traits<TridiagonalizationMatrixTReturnType<MatrixType>> :
public traits<typename MatrixType::PlainObject> {
30 using ReturnType =
typename MatrixType::PlainObject;
34template <
typename MatrixType,
typename CoeffVectorType>
35EIGEN_DEVICE_FUNC
void tridiagonalization_inplace(MatrixType& matA, CoeffVectorType& hCoeffs);
70template <
typename MatrixType_>
76 using Scalar =
typename MatrixType::Scalar;
77 using RealScalar =
typename NumTraits<Scalar>::Real;
81 Size = MatrixType::RowsAtCompileTime,
82 SizeMinusOne = Size == Dynamic ? Dynamic : (Size > 1 ? Size - 1 : 1),
83 Options = internal::plain_object_options<MatrixType>::value,
84 MaxSize = MatrixType::MaxRowsAtCompileTime,
85 MaxSizeMinusOne = MaxSize == Dynamic ? Dynamic : (MaxSize > 1 ? MaxSize - 1 : 1)
89 using DiagonalType =
typename internal::plain_col_type<MatrixType, RealScalar>::type;
91 using MatrixTypeRealView = internal::remove_all_t<typename MatrixType::RealReturnType>;
92 using MatrixTReturnType = internal::TridiagonalizationMatrixTReturnType<MatrixTypeRealView>;
94 using DiagonalReturnType =
95 std::conditional_t<NumTraits<Scalar>::IsComplex,
96 internal::add_const_on_value_type_t<typename Diagonal<const MatrixType>::RealReturnType>,
99 using SubDiagonalReturnType =
100 std::conditional_t<NumTraits<Scalar>::IsComplex,
101 internal::add_const_on_value_type_t<
typename Diagonal<
const MatrixType, -1>::RealReturnType>,
121 : m_matrix(size, size), m_hCoeffs(size > 1 ? size - 1 : 1), m_isInitialized(false) {}
133 template <
typename InputType>
135 : m_matrix(matrix.derived()), m_hCoeffs(matrix.cols() > 1 ? matrix.cols() - 1 : 1), m_isInitialized(false) {
136 internal::tridiagonalization_inplace(m_matrix, m_hCoeffs);
137 m_isInitialized =
true;
148 template <
typename InputType>
150 : m_matrix(matrix.derived()), m_hCoeffs(matrix.cols() > 1 ? matrix.cols() - 1 : 1), m_isInitialized(false) {
151 internal::tridiagonalization_inplace(m_matrix, m_hCoeffs);
152 m_isInitialized =
true;
172 template <
typename InputType>
175 m_hCoeffs.resize(matrix.
rows() - 1, 1);
176 internal::tridiagonalization_inplace(m_matrix, m_hCoeffs);
177 m_isInitialized =
true;
198 eigen_assert(m_isInitialized &&
"Tridiagonalization is not initialized.");
234 eigen_assert(m_isInitialized &&
"Tridiagonalization is not initialized.");
254 eigen_assert(m_isInitialized &&
"Tridiagonalization is not initialized.");
276 eigen_assert(m_isInitialized &&
"Tridiagonalization is not initialized.");
277 return MatrixTReturnType(m_matrix.real());
309 CoeffVectorType m_hCoeffs;
310 bool m_isInitialized;
313template <
typename MatrixType>
315 eigen_assert(m_isInitialized &&
"Tridiagonalization is not initialized.");
316 return m_matrix.diagonal().real();
319template <
typename MatrixType>
321 eigen_assert(m_isInitialized &&
"Tridiagonalization is not initialized.");
322 return m_matrix.template
diagonal<-1>().real();
351template <
typename MatrixType,
typename CoeffVectorType>
352EIGEN_DEVICE_FUNC
void tridiagonalization_inplace_unblocked(MatrixType& matA, CoeffVectorType& hCoeffs) {
354 using Scalar =
typename MatrixType::Scalar;
355 using RealScalar =
typename MatrixType::RealScalar;
356 Index n = matA.rows();
357 eigen_assert(n == matA.cols());
358 eigen_assert(n == hCoeffs.size() + 1 || n == 1);
360 for (Index i = 0; i < n - 1; ++i) {
361 Index remainingSize = n - i - 1;
364 matA.col(i).tail(remainingSize).makeHouseholderInPlace(h, beta);
368 matA.col(i).coeffRef(i + 1) = Scalar(1);
370 hCoeffs.tail(n - i - 1).noalias() =
371 (matA.bottomRightCorner(remainingSize, remainingSize).
template selfadjointView<Lower>() *
372 (conj(h) * matA.col(i).tail(remainingSize)));
374 hCoeffs.tail(n - i - 1) +=
375 (conj(h) * RealScalar(-0.5) * (hCoeffs.tail(remainingSize).dot(matA.col(i).tail(remainingSize)))) *
376 matA.col(i).tail(n - i - 1);
378 matA.bottomRightCorner(remainingSize, remainingSize)
379 .template selfadjointView<Lower>()
380 .rankUpdate(matA.col(i).tail(remainingSize), hCoeffs.tail(remainingSize), Scalar(-1));
382 matA.col(i).coeffRef(i + 1) = beta;
383 hCoeffs.coeffRef(i) = h;
387#if !defined(EIGEN_GPU_COMPILE_PHASE)
394template <
typename MatrixType,
typename CoeffVectorType>
395void tridiagonalization_inplace_blocked(MatrixType& matA, CoeffVectorType& hCoeffs, Index nb = 16) {
397 using Scalar =
typename MatrixType::Scalar;
398 using RealScalar =
typename MatrixType::RealScalar;
399 const Index n = matA.rows();
400 eigen_assert(n == matA.cols());
401 eigen_assert(n == hCoeffs.size() + 1);
402 eigen_assert(nb >= 2 && nb < n);
410 using WorkMatrixType = Matrix<Scalar, Dynamic, Dynamic, StorageOrder>;
411 WorkMatrixType W(n, nb);
412 Matrix<Scalar, Dynamic, 1> temp(nb);
413 Matrix<RealScalar, Dynamic, 1> betas(nb);
417 using BlockingType = gemm_blocking_space<StorageOrder, Scalar, Scalar, Dynamic, Dynamic, Dynamic>;
418 const Index maxTrailingSize = n - nb;
419 BlockingType blocking(maxTrailingSize, maxTrailingSize, nb, 1,
false);
420 blocking.allocateAll();
423 for (; j0 + nb < n - 1; j0 += nb) {
424 const Index j_end = j0 + nb;
430 for (Index j = j0; j < j_end; ++j) {
431 const Index local_j = j - j0;
432 const Index remainingSize = n - j - 1;
439 auto col_j = matA.col(j).segment(j, n - j);
440 col_j.noalias() -= matA.block(j, j0, n - j, local_j) * W.row(j).head(local_j).adjoint();
441 col_j.noalias() -= W.block(j, 0, n - j, local_j) * matA.row(j).segment(j0, local_j).adjoint();
443 matA.coeffRef(j, j) = numext::real(matA.coeff(j, j));
449 matA.col(j).tail(remainingSize).makeHouseholderInPlace(h, beta);
450 betas(local_j) = beta;
451 matA.col(j).coeffRef(j + 1) = Scalar(1);
453 auto v = matA.col(j).tail(remainingSize);
454 auto w = W.col(local_j).tail(remainingSize);
459 matA.bottomRightCorner(remainingSize, remainingSize).template selfadjointView<Lower>() * (conj(h) * v);
463 auto V_prev = matA.block(j + 1, j0, remainingSize, local_j);
464 auto W_prev = W.block(j + 1, 0, remainingSize, local_j);
467 temp.head(local_j).noalias() = W_prev.adjoint() * v;
468 w.noalias() -= conj(h) * (V_prev * temp.head(local_j));
471 temp.head(local_j).noalias() = V_prev.adjoint() * v;
472 w.noalias() -= conj(h) * (W_prev * temp.head(local_j));
476 w += (conj(h) * RealScalar(-0.5) * w.dot(v)) * v;
478 hCoeffs.coeffRef(j) = h;
484 const Index trailingSize = n - j_end;
485 if (trailingSize > 0) {
486 const Scalar* V_data = &matA.coeffRef(j_end, j0);
487 const Scalar* W_data = &W.coeffRef(j_end, 0);
488 Scalar* C_data = &matA.coeffRef(j_end, j_end);
489 const Index V_stride = matA.outerStride();
490 const Index W_stride = W.outerStride();
491 const Index C_stride = matA.outerStride();
494 general_matrix_matrix_triangular_product<Index, Scalar, StorageOrder,
false, Scalar, RhsStorageOrder,
495 NumTraits<Scalar>::IsComplex, StorageOrder, 1,
496 Lower>::run(trailingSize, nb, V_data, V_stride, W_data, W_stride, C_data,
497 1, C_stride, Scalar(-1), blocking);
500 general_matrix_matrix_triangular_product<Index, Scalar, StorageOrder,
false, Scalar, RhsStorageOrder,
501 NumTraits<Scalar>::IsComplex, StorageOrder, 1,
502 Lower>::run(trailingSize, nb, W_data, W_stride, V_data, V_stride, C_data,
503 1, C_stride, Scalar(-1), blocking);
507 for (Index j = j0; j < j_end; ++j) {
508 matA.coeffRef(j + 1, j) = betas(j - j0);
514 const Index remaining = n - j0;
515 auto trailing = matA.bottomRightCorner(remaining, remaining);
516 auto hCoeffs_tail = hCoeffs.segment(j0, remaining - 1);
517 tridiagonalization_inplace_unblocked(trailing, hCoeffs_tail);
526template <
typename MatrixType,
typename CoeffVectorType>
527EIGEN_DEVICE_FUNC
void tridiagonalization_inplace(MatrixType& matA, CoeffVectorType& hCoeffs) {
528 eigen_assert(matA.rows() == matA.cols());
529 eigen_assert(matA.rows() == hCoeffs.size() + 1 || matA.rows() == 1);
531#if !defined(EIGEN_GPU_COMPILE_PHASE)
532 EIGEN_IF_CONSTEXPR (MatrixType::RowsAtCompileTime == Dynamic || MatrixType::ColsAtCompileTime == Dynamic) {
533 if (matA.rows() >= 96) {
534 tridiagonalization_inplace_blocked(matA, hCoeffs);
539 tridiagonalization_inplace_unblocked(matA, hCoeffs);
543template <
typename MatrixType,
int Size = MatrixType::ColsAtCompileTime,
544 bool IsComplex = NumTraits<typename MatrixType::Scalar>::IsComplex>
545struct tridiagonalization_inplace_selector;
589template <
typename MatrixType,
typename DiagonalType,
typename SubDiagonalType,
typename CoeffVectorType,
590 typename WorkSpaceType>
591EIGEN_DEVICE_FUNC
void tridiagonalization_inplace(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag,
592 CoeffVectorType& hcoeffs, WorkSpaceType& workspace,
bool extractQ) {
593 eigen_assert(mat.cols() == mat.rows() && diag.size() == mat.rows() && subdiag.size() == mat.rows() - 1);
594 tridiagonalization_inplace_selector<MatrixType>::run(mat, diag, subdiag, hcoeffs, workspace, extractQ);
600template <
typename MatrixType,
int Size,
bool IsComplex>
601struct tridiagonalization_inplace_selector {
603 template <
typename DiagonalType,
typename SubDiagonalType,
typename CoeffVectorType,
typename WorkSpaceType>
604 static EIGEN_DEVICE_FUNC
void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag,
605 CoeffVectorType& hCoeffs, WorkSpaceType& workspace,
bool extractQ) {
606 tridiagonalization_inplace(mat, hCoeffs);
607 diag = mat.diagonal().real();
608 subdiag = mat.template diagonal<-1>().real();
610 HouseholderSequenceType(mat, hCoeffs.conjugate()).setLength(mat.rows() - 1).setShift(1).evalTo(mat, workspace);
619template <
typename MatrixType>
620struct tridiagonalization_inplace_selector<MatrixType, 3, false> {
621 using Scalar =
typename MatrixType::Scalar;
622 using RealScalar =
typename MatrixType::RealScalar;
624 template <
typename DiagonalType,
typename SubDiagonalType,
typename CoeffVectorType,
typename WorkSpaceType>
625 static EIGEN_DEVICE_FUNC
void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag, CoeffVectorType&,
626 WorkSpaceType&,
bool extractQ) {
628 const RealScalar tol = (std::numeric_limits<RealScalar>::min)();
630 RealScalar v1norm2 = numext::abs2(mat(2, 0));
631 if (v1norm2 <= tol) {
634 subdiag[0] = mat(1, 0);
635 subdiag[1] = mat(2, 1);
636 if (extractQ) mat.setIdentity();
638 RealScalar beta = sqrt(numext::abs2(mat(1, 0)) + v1norm2);
639 RealScalar invBeta = RealScalar(1) / beta;
640 Scalar m01 = mat(1, 0) * invBeta;
641 Scalar m02 = mat(2, 0) * invBeta;
642 Scalar q = RealScalar(2) * m01 * mat(2, 1) + m02 * (mat(2, 2) - mat(1, 1));
643 diag[1] = mat(1, 1) + m02 * q;
644 diag[2] = mat(2, 2) - m02 * q;
646 subdiag[1] = mat(2, 1) - m01 * q;
648 mat << Scalar(1), Scalar(0), Scalar(0), Scalar(0), m01, m02, Scalar(0), m02, -m01;
657template <
typename MatrixType,
bool IsComplex>
658struct tridiagonalization_inplace_selector<MatrixType, 1, IsComplex> {
659 using Scalar =
typename MatrixType::Scalar;
661 template <
typename DiagonalType,
typename SubDiagonalType,
typename CoeffVectorType,
typename WorkSpaceType>
662 static EIGEN_DEVICE_FUNC
void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType&, CoeffVectorType&,
663 WorkSpaceType&,
bool extractQ) {
664 diag(0, 0) = numext::real(mat(0, 0));
665 if (extractQ) mat(0, 0) = Scalar(1);
676template <
typename MatrixType>
677struct TridiagonalizationMatrixTReturnType :
public ReturnByValue<TridiagonalizationMatrixTReturnType<MatrixType>> {
683 TridiagonalizationMatrixTReturnType(
const MatrixType& mat) : m_matrix(mat) {}
685 template <
typename ResultType>
686 inline void evalTo(ResultType& result)
const {
688 result.template diagonal<1>() = m_matrix.template diagonal<-1>().conjugate();
689 result.diagonal() = m_matrix.diagonal();
690 result.template diagonal<-1>() = m_matrix.template diagonal<-1>();
693 constexpr Index rows() const noexcept {
return m_matrix.rows(); }
694 constexpr Index cols() const noexcept {
return m_matrix.cols(); }
697 typename MatrixType::Nested m_matrix;
Expression of a diagonal/subdiagonal/superdiagonal in a matrix.
Definition Diagonal.h:78
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
Tridiagonalization(Index size=Size==Dynamic ? 2 :Size)
Default constructor.
Definition Tridiagonalization.h:120
DiagonalReturnType diagonal() const
Returns the diagonal of the tridiagonal matrix T in the decomposition.
Definition Tridiagonalization.h:314
Tridiagonalization(EigenBase< InputType > &matrix)
Constructor for inplace decomposition .
Definition Tridiagonalization.h:149
Eigen::Index Index
Definition Tridiagonalization.h:78
const MatrixType & packedMatrix() const
Returns the internal representation of the decomposition.
Definition Tridiagonalization.h:233
CoeffVectorType householderCoefficients() const
Returns the Householder coefficients.
Definition Tridiagonalization.h:197
HouseholderSequence< MatrixType, internal::remove_all_t< typename CoeffVectorType::ConjugateReturnType > > HouseholderSequenceType
Definition Tridiagonalization.h:105
SubDiagonalReturnType subDiagonal() const
Returns the subdiagonal of the tridiagonal matrix T in the decomposition.
Definition Tridiagonalization.h:320
HouseholderSequenceType matrixQ() const
Returns the unitary matrix Q in the decomposition.
Definition Tridiagonalization.h:253
MatrixType MatrixType
Definition Tridiagonalization.h:74
MatrixTReturnType matrixT() const
Returns an expression of the tridiagonal matrix T in the decomposition.
Definition Tridiagonalization.h:275
Tridiagonalization(const EigenBase< InputType > &matrix)
Constructor; computes tridiagonal decomposition of given matrix.
Definition Tridiagonalization.h:134
Tridiagonalization & compute(const EigenBase< InputType > &matrix)
Computes tridiagonal decomposition of given matrix.
Definition Tridiagonalization.h:173
@ Lower
Definition Constants.h:212
@ ColMajor
Definition Constants.h:319
@ RowMajor
Definition Constants.h:321
constexpr unsigned int RowMajorBit
Definition Constants.h:71
Definition EigenBase.h:34
constexpr Derived & derived()
Definition EigenBase.h:50
constexpr Index rows() const noexcept
Definition EigenBase.h:60