Eigen  3.4.90 (git rev 67eeba6e720c5745abc77ae6c92ce0a44aa7b7ae)
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 <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>
30 EIGEN_DEVICE_FUNC
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;
74  typedef typename NumTraits<Scalar>::Real RealScalar;
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;
88  typedef internal::remove_all_t<typename MatrixType::RealReturnType> MatrixTypeRealView;
89  typedef internal::TridiagonalizationMatrixTReturnType<MatrixTypeRealView> MatrixTReturnType;
90 
91  typedef std::conditional_t<NumTraits<Scalar>::IsComplex,
92  internal::add_const_on_value_type_t<typename Diagonal<const MatrixType>::RealReturnType>,
94  > DiagonalReturnType;
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>
99  > SubDiagonalReturnType;
100 
103 
116  explicit Tridiagonalization(Index size = Size==Dynamic ? 2 : Size)
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  {
138  internal::tridiagonalization_inplace(m_matrix, m_hCoeffs);
139  m_isInitialized = true;
140  }
141 
159  template<typename InputType>
161  {
162  m_matrix = matrix.derived();
163  m_hCoeffs.resize(matrix.rows()-1, 1);
164  internal::tridiagonalization_inplace(m_matrix, m_hCoeffs);
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 
268  MatrixTReturnType matrixT() const
269  {
270  eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
271  return MatrixTReturnType(m_matrix.real());
272  }
273 
287  DiagonalReturnType diagonal() const;
288 
299  SubDiagonalReturnType subDiagonal() const;
300 
301  protected:
302 
303  MatrixType m_matrix;
304  CoeffVectorType m_hCoeffs;
305  bool m_isInitialized;
306 };
307 
308 template<typename MatrixType>
309 typename Tridiagonalization<MatrixType>::DiagonalReturnType
311 {
312  eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
313  return m_matrix.diagonal().real();
314 }
315 
316 template<typename MatrixType>
317 typename Tridiagonalization<MatrixType>::SubDiagonalReturnType
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>
350 EIGEN_DEVICE_FUNC
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,
387  bool IsComplex=NumTraits<typename MatrixType::Scalar>::IsComplex>
388 struct tridiagonalization_inplace_selector;
389 
430 template<typename MatrixType, typename DiagonalType, typename SubDiagonalType, typename CoeffVectorType>
431 EIGEN_DEVICE_FUNC
432 void tridiagonalization_inplace(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag,
433  CoeffVectorType& hcoeffs, 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, 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>
447  static EIGEN_DEVICE_FUNC
448  void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag, CoeffVectorType& hCoeffs, bool extractQ)
449  {
450  tridiagonalization_inplace(mat, hCoeffs);
451  diag = mat.diagonal().real();
452  subdiag = mat.template diagonal<-1>().real();
453  if(extractQ)
454  mat = HouseholderSequenceType(mat, hCoeffs.conjugate())
455  .setLength(mat.rows() - 1)
456  .setShift(1);
457  }
458 };
459 
464 template<typename MatrixType>
465 struct tridiagonalization_inplace_selector<MatrixType,3,false>
466 {
467  typedef typename MatrixType::Scalar Scalar;
468  typedef typename MatrixType::RealScalar RealScalar;
469 
470  template<typename DiagonalType, typename SubDiagonalType, typename CoeffVectorType>
471  static void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag, CoeffVectorType&, bool extractQ)
472  {
473  using std::sqrt;
474  const RealScalar tol = (std::numeric_limits<RealScalar>::min)();
475  diag[0] = mat(0,0);
476  RealScalar v1norm2 = numext::abs2(mat(2,0));
477  if(v1norm2 <= tol)
478  {
479  diag[1] = mat(1,1);
480  diag[2] = mat(2,2);
481  subdiag[0] = mat(1,0);
482  subdiag[1] = mat(2,1);
483  if (extractQ)
484  mat.setIdentity();
485  }
486  else
487  {
488  RealScalar beta = sqrt(numext::abs2(mat(1,0)) + v1norm2);
489  RealScalar invBeta = RealScalar(1)/beta;
490  Scalar m01 = mat(1,0) * invBeta;
491  Scalar m02 = mat(2,0) * invBeta;
492  Scalar q = RealScalar(2)*m01*mat(2,1) + m02*(mat(2,2) - mat(1,1));
493  diag[1] = mat(1,1) + m02*q;
494  diag[2] = mat(2,2) - m02*q;
495  subdiag[0] = beta;
496  subdiag[1] = mat(2,1) - m01 * q;
497  if (extractQ)
498  {
499  mat << 1, 0, 0,
500  0, m01, m02,
501  0, m02, -m01;
502  }
503  }
504  }
505 };
506 
510 template<typename MatrixType, bool IsComplex>
511 struct tridiagonalization_inplace_selector<MatrixType,1,IsComplex>
512 {
513  typedef typename MatrixType::Scalar Scalar;
514 
515  template<typename DiagonalType, typename SubDiagonalType, typename CoeffVectorType>
516  static EIGEN_DEVICE_FUNC
517  void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType&, CoeffVectorType&, bool extractQ)
518  {
519  diag(0,0) = numext::real(mat(0,0));
520  if(extractQ)
521  mat(0,0) = Scalar(1);
522  }
523 };
524 
532 template<typename MatrixType> struct TridiagonalizationMatrixTReturnType
533 : public ReturnByValue<TridiagonalizationMatrixTReturnType<MatrixType> >
534 {
535  public:
540  TridiagonalizationMatrixTReturnType(const MatrixType& mat) : m_matrix(mat) { }
541 
542  template <typename ResultType>
543  inline void evalTo(ResultType& result) const
544  {
545  result.setZero();
546  result.template diagonal<1>() = m_matrix.template diagonal<-1>().conjugate();
547  result.diagonal() = m_matrix.diagonal();
548  result.template diagonal<-1>() = m_matrix.template diagonal<-1>();
549  }
550 
551  EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_matrix.rows(); }
552  EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_matrix.cols(); }
553 
554  protected:
555  typename MatrixType::Nested m_matrix;
556 };
557 
558 } // end namespace internal
559 
560 } // end namespace Eigen
561 
562 #endif // EIGEN_TRIDIAGONALIZATION_H
Expression of a diagonal/subdiagonal/superdiagonal in a matrix.
Definition: Diagonal.h:67
Sequence of Householder reflections acting on subspaces with decreasing size.
Definition: HouseholderSequence.h:123
void resize(Index rows, Index cols)
Definition: PlainObjectBase.h:283
Tridiagonal decomposition of a selfadjoint matrix.
Definition: Tridiagonalization.h:67
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:310
MatrixType_ MatrixType
Synonym for the template parameter MatrixType_.
Definition: Tridiagonalization.h:71
Tridiagonalization & compute(const EigenBase< InputType > &matrix)
Computes tridiagonal decomposition of given matrix.
Definition: Tridiagonalization.h:160
CoeffVectorType householderCoefficients() const
Returns the Householder coefficients.
Definition: Tridiagonalization.h:185
SubDiagonalReturnType subDiagonal() const
Returns the subdiagonal of the tridiagonal matrix T in the decomposition.
Definition: Tridiagonalization.h:318
HouseholderSequence< MatrixType, internal::remove_all_t< typename CoeffVectorType::ConjugateReturnType > > HouseholderSequenceType
Return type of matrixQ()
Definition: Tridiagonalization.h:102
HouseholderSequenceType matrixQ() const
Returns the unitary matrix Q in the decomposition.
Definition: Tridiagonalization.h:243
const MatrixType & packedMatrix() const
Returns the internal representation of the decomposition.
Definition: Tridiagonalization.h:222
MatrixTReturnType matrixT() const
Returns an expression of the tridiagonal matrix T in the decomposition.
Definition: Tridiagonalization.h:268
Tridiagonalization(const EigenBase< InputType > &matrix)
Constructor; computes tridiagonal decomposition of given matrix.
Definition: Tridiagonalization.h:133
Eigen::Index Index
Definition: Tridiagonalization.h:75
Namespace containing all symbols from the Eigen library.
Definition: Core:139
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:59
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)
Definition: EigenBase.h:32
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