Tridiagonalization.h
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2008 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 
11 #ifndef EIGEN_TRIDIAGONALIZATION_H
12 #define EIGEN_TRIDIAGONALIZATION_H
13 
14 #include "./InternalHeaderCheck.h"
15 
16 namespace Eigen {
17 
18 namespace internal {
19 
20 template<typename MatrixType> struct TridiagonalizationMatrixTReturnType;
21 template<typename MatrixType>
22 struct traits<TridiagonalizationMatrixTReturnType<MatrixType> >
23  : public traits<typename MatrixType::PlainObject>
24 {
25  typedef typename MatrixType::PlainObject ReturnType; // FIXME shall it be a BandMatrix?
26  enum { Flags = 0 };
27 };
28 
29 template<typename MatrixType, typename CoeffVectorType>
31 void tridiagonalization_inplace(MatrixType& matA, CoeffVectorType& hCoeffs);
32 }
33 
66 template<typename MatrixType_> class Tridiagonalization
67 {
68  public:
69 
71  typedef MatrixType_ MatrixType;
72 
73  typedef typename MatrixType::Scalar Scalar;
75  typedef Eigen::Index Index;
76 
77  enum {
78  Size = MatrixType::RowsAtCompileTime,
79  SizeMinusOne = Size == Dynamic ? Dynamic : (Size > 1 ? Size - 1 : 1),
80  Options = MatrixType::Options,
81  MaxSize = MatrixType::MaxRowsAtCompileTime,
82  MaxSizeMinusOne = MaxSize == Dynamic ? Dynamic : (MaxSize > 1 ? MaxSize - 1 : 1)
83  };
84 
86  typedef typename internal::plain_col_type<MatrixType, RealScalar>::type DiagonalType;
89  typedef internal::TridiagonalizationMatrixTReturnType<MatrixTypeRealView> MatrixTReturnType;
90 
91  typedef std::conditional_t<NumTraits<Scalar>::IsComplex,
95 
96  typedef std::conditional_t<NumTraits<Scalar>::IsComplex,
97  internal::add_const_on_value_type_t<typename Diagonal<const MatrixType, -1>::RealReturnType>,
98  const Diagonal<const MatrixType, -1>
100 
103 
117  : m_matrix(size,size),
118  m_hCoeffs(size > 1 ? size-1 : 1),
119  m_isInitialized(false)
120  {}
121 
132  template<typename InputType>
133  explicit Tridiagonalization(const EigenBase<InputType>& matrix)
134  : m_matrix(matrix.derived()),
135  m_hCoeffs(matrix.cols() > 1 ? matrix.cols()-1 : 1),
136  m_isInitialized(false)
137  {
139  m_isInitialized = true;
140  }
141 
159  template<typename InputType>
161  {
162  m_matrix = matrix.derived();
163  m_hCoeffs.resize(matrix.rows()-1, 1);
165  m_isInitialized = true;
166  return *this;
167  }
168 
186  {
187  eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
188  return m_hCoeffs;
189  }
190 
222  inline const MatrixType& packedMatrix() const
223  {
224  eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
225  return m_matrix;
226  }
227 
244  {
245  eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
246  return HouseholderSequenceType(m_matrix, m_hCoeffs.conjugate())
247  .setLength(m_matrix.rows() - 1)
248  .setShift(1);
249  }
250 
269  {
270  eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
271  return MatrixTReturnType(m_matrix.real());
272  }
273 
288 
300 
301  protected:
302 
306 };
307 
308 template<typename MatrixType>
311 {
312  eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
313  return m_matrix.diagonal().real();
314 }
315 
316 template<typename MatrixType>
319 {
320  eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
321  return m_matrix.template diagonal<-1>().real();
322 }
323 
324 namespace internal {
325 
349 template<typename MatrixType, typename CoeffVectorType>
351 void tridiagonalization_inplace(MatrixType& matA, CoeffVectorType& hCoeffs)
352 {
353  using numext::conj;
354  typedef typename MatrixType::Scalar Scalar;
355  typedef typename MatrixType::RealScalar RealScalar;
356  Index n = matA.rows();
357  eigen_assert(n==matA.cols());
358  eigen_assert(n==hCoeffs.size()+1 || n==1);
359 
360  for (Index i = 0; i<n-1; ++i)
361  {
362  Index remainingSize = n-i-1;
363  RealScalar beta;
364  Scalar h;
365  matA.col(i).tail(remainingSize).makeHouseholderInPlace(h, beta);
366 
367  // Apply similarity transformation to remaining columns,
368  // i.e., A = H A H' where H = I - h v v' and v = matA.col(i).tail(n-i-1)
369  matA.col(i).coeffRef(i+1) = 1;
370 
371  hCoeffs.tail(n-i-1).noalias() = (matA.bottomRightCorner(remainingSize,remainingSize).template selfadjointView<Lower>()
372  * (conj(h) * matA.col(i).tail(remainingSize)));
373 
374  hCoeffs.tail(n-i-1) += (conj(h)*RealScalar(-0.5)*(hCoeffs.tail(remainingSize).dot(matA.col(i).tail(remainingSize)))) * matA.col(i).tail(n-i-1);
375 
376  matA.bottomRightCorner(remainingSize, remainingSize).template selfadjointView<Lower>()
377  .rankUpdate(matA.col(i).tail(remainingSize), hCoeffs.tail(remainingSize), Scalar(-1));
378 
379  matA.col(i).coeffRef(i+1) = beta;
380  hCoeffs.coeffRef(i) = h;
381  }
382 }
383 
384 // forward declaration, implementation at the end of this file
385 template<typename MatrixType,
386  int Size=MatrixType::ColsAtCompileTime,
388 struct tridiagonalization_inplace_selector;
389 
430 template<typename MatrixType, typename DiagonalType, typename SubDiagonalType, typename CoeffVectorType, typename WorkSpaceType>
432 void tridiagonalization_inplace(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag,
433  CoeffVectorType& hcoeffs, WorkSpaceType& workspace, bool extractQ)
434 {
435  eigen_assert(mat.cols()==mat.rows() && diag.size()==mat.rows() && subdiag.size()==mat.rows()-1);
436  tridiagonalization_inplace_selector<MatrixType>::run(mat, diag, subdiag, hcoeffs, workspace, extractQ);
437 }
438 
442 template<typename MatrixType, int Size, bool IsComplex>
443 struct tridiagonalization_inplace_selector
444 {
445  typedef typename Tridiagonalization<MatrixType>::HouseholderSequenceType HouseholderSequenceType;
446  template<typename DiagonalType, typename SubDiagonalType, typename CoeffVectorType, typename WorkSpaceType>
447  static EIGEN_DEVICE_FUNC
448  void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag, CoeffVectorType& hCoeffs, WorkSpaceType& workspace, bool extractQ)
449  {
451  diag = mat.diagonal().real();
452  subdiag = mat.template diagonal<-1>().real();
453  if (extractQ) {
454  HouseholderSequenceType(mat, hCoeffs.conjugate())
455  .setLength(mat.rows() - 1)
456  .setShift(1)
457  .evalTo(mat, workspace);
458  }
459  }
460 };
461 
466 template<typename MatrixType>
467 struct tridiagonalization_inplace_selector<MatrixType,3,false>
468 {
469  typedef typename MatrixType::Scalar Scalar;
470  typedef typename MatrixType::RealScalar RealScalar;
471 
472  template<typename DiagonalType, typename SubDiagonalType, typename CoeffVectorType, typename WorkSpaceType>
473  static void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag, CoeffVectorType&, WorkSpaceType&, bool extractQ)
474  {
475  using std::sqrt;
476  const RealScalar tol = (std::numeric_limits<RealScalar>::min)();
477  diag[0] = mat(0,0);
478  RealScalar v1norm2 = numext::abs2(mat(2,0));
479  if(v1norm2 <= tol)
480  {
481  diag[1] = mat(1,1);
482  diag[2] = mat(2,2);
483  subdiag[0] = mat(1,0);
484  subdiag[1] = mat(2,1);
485  if (extractQ)
486  mat.setIdentity();
487  }
488  else
489  {
490  RealScalar beta = sqrt(numext::abs2(mat(1,0)) + v1norm2);
491  RealScalar invBeta = RealScalar(1)/beta;
492  Scalar m01 = mat(1,0) * invBeta;
493  Scalar m02 = mat(2,0) * invBeta;
494  Scalar q = RealScalar(2)*m01*mat(2,1) + m02*(mat(2,2) - mat(1,1));
495  diag[1] = mat(1,1) + m02*q;
496  diag[2] = mat(2,2) - m02*q;
497  subdiag[0] = beta;
498  subdiag[1] = mat(2,1) - m01 * q;
499  if (extractQ)
500  {
501  mat << 1, 0, 0,
502  0, m01, m02,
503  0, m02, -m01;
504  }
505  }
506  }
507 };
508 
512 template<typename MatrixType, bool IsComplex>
513 struct tridiagonalization_inplace_selector<MatrixType,1,IsComplex>
514 {
515  typedef typename MatrixType::Scalar Scalar;
516 
517  template<typename DiagonalType, typename SubDiagonalType, typename CoeffVectorType, typename WorkSpaceType>
518  static EIGEN_DEVICE_FUNC
519  void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType&, CoeffVectorType&, WorkSpaceType&, bool extractQ)
520  {
521  diag(0,0) = numext::real(mat(0,0));
522  if(extractQ)
523  mat(0,0) = Scalar(1);
524  }
525 };
526 
534 template<typename MatrixType> struct TridiagonalizationMatrixTReturnType
535 : public ReturnByValue<TridiagonalizationMatrixTReturnType<MatrixType> >
536 {
537  public:
542  TridiagonalizationMatrixTReturnType(const MatrixType& mat) : m_matrix(mat) { }
543 
544  template <typename ResultType>
545  inline void evalTo(ResultType& result) const
546  {
547  result.setZero();
548  result.template diagonal<1>() = m_matrix.template diagonal<-1>().conjugate();
549  result.diagonal() = m_matrix.diagonal();
550  result.template diagonal<-1>() = m_matrix.template diagonal<-1>();
551  }
552 
553  EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_matrix.rows(); }
554  EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_matrix.cols(); }
555 
556  protected:
557  typename MatrixType::Nested m_matrix;
558 };
559 
560 } // end namespace internal
561 
562 } // end namespace Eigen
563 
564 #endif // EIGEN_TRIDIAGONALIZATION_H
const SqrtReturnType sqrt() const
int n
RealReturnType real() const
ConjugateReturnType conjugate() const
#define EIGEN_NOEXCEPT
Definition: Macros.h:1260
#define EIGEN_CONSTEXPR
Definition: Macros.h:747
#define EIGEN_DEVICE_FUNC
Definition: Macros.h:883
#define eigen_assert(x)
Definition: Macros.h:902
MatrixXf matA(2, 2)
Matrix< float, 1, Dynamic > MatrixType
NumTraits< Scalar >::Real RealScalar
Definition: DenseBase.h:68
internal::traits< Derived >::Scalar Scalar
Definition: DenseBase.h:61
Expression of a diagonal/subdiagonal/superdiagonal in a matrix.
Definition: Diagonal.h:67
Sequence of Householder reflections acting on subspaces with decreasing size.
Base::PlainObject PlainObject
Definition: Matrix.h:194
constexpr void resize(Index rows, Index cols)
Tridiagonal decomposition of a selfadjoint matrix.
Tridiagonalization(Index size=Size==Dynamic ? 2 :Size)
Default constructor.
DiagonalReturnType diagonal() const
Returns the diagonal of the tridiagonal matrix T in the decomposition.
std::conditional_t< NumTraits< Scalar >::IsComplex, internal::add_const_on_value_type_t< typename Diagonal< const MatrixType, -1 >::RealReturnType >, const Diagonal< const MatrixType, -1 > > SubDiagonalReturnType
internal::plain_col_type< MatrixType, RealScalar >::type DiagonalType
std::conditional_t< NumTraits< Scalar >::IsComplex, internal::add_const_on_value_type_t< typename Diagonal< const MatrixType >::RealReturnType >, const Diagonal< const MatrixType > > DiagonalReturnType
MatrixType_ MatrixType
Synonym for the template parameter MatrixType_.
Tridiagonalization & compute(const EigenBase< InputType > &matrix)
Computes tridiagonal decomposition of given matrix.
CoeffVectorType householderCoefficients() const
Returns the Householder coefficients.
internal::remove_all_t< typename MatrixType::RealReturnType > MatrixTypeRealView
internal::TridiagonalizationMatrixTReturnType< MatrixTypeRealView > MatrixTReturnType
Matrix< Scalar, SizeMinusOne, 1, Options &~RowMajor, MaxSizeMinusOne, 1 > CoeffVectorType
SubDiagonalReturnType subDiagonal() const
Returns the subdiagonal of the tridiagonal matrix T in the decomposition.
HouseholderSequence< MatrixType, internal::remove_all_t< typename CoeffVectorType::ConjugateReturnType > > HouseholderSequenceType
Return type of matrixQ()
HouseholderSequenceType matrixQ() const
Returns the unitary matrix Q in the decomposition.
const MatrixType & packedMatrix() const
Returns the internal representation of the decomposition.
MatrixTReturnType matrixT() const
Returns an expression of the tridiagonal matrix T in the decomposition.
Tridiagonalization(const EigenBase< InputType > &matrix)
Constructor; computes tridiagonal decomposition of given matrix.
Matrix< RealScalar, SizeMinusOne, 1, Options &~RowMajor, MaxSizeMinusOne, 1 > SubDiagonalType
NumTraits< Scalar >::Real RealScalar
bfloat16() min(const bfloat16 &a, const bfloat16 &b)
Definition: BFloat16.h:684
void tridiagonalization_inplace(MatrixType &matA, CoeffVectorType &hCoeffs)
typename remove_all< T >::type remove_all_t
Definition: Meta.h:119
typename add_const_on_value_type< T >::type add_const_on_value_type_t
Definition: Meta.h:176
bool abs2(bool x)
: InteropHeaders
Definition: Core:139
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:82
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_conjugate_op< typename Derived::Scalar >, const Derived > conj(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 int Dynamic
Definition: Constants.h:24
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_sqrt_op< typename Derived::Scalar >, const Derived > sqrt(const Eigen::ArrayBase< Derived > &x)
Derived & derived()
Definition: EigenBase.h:48
EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT
Definition: EigenBase.h:62
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition: NumTraits.h:231