1*bf2c3715SXin Li // This file is part of Eigen, a lightweight C++ template library 2*bf2c3715SXin Li // for linear algebra. 3*bf2c3715SXin Li // 4*bf2c3715SXin Li // Copyright (C) 2008 Gael Guennebaud <[email protected]> 5*bf2c3715SXin Li // Copyright (C) 2010 Jitse Niesen <[email protected]> 6*bf2c3715SXin Li // 7*bf2c3715SXin Li // This Source Code Form is subject to the terms of the Mozilla 8*bf2c3715SXin Li // Public License v. 2.0. If a copy of the MPL was not distributed 9*bf2c3715SXin Li // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 10*bf2c3715SXin Li 11*bf2c3715SXin Li #ifndef EIGEN_TRIDIAGONALIZATION_H 12*bf2c3715SXin Li #define EIGEN_TRIDIAGONALIZATION_H 13*bf2c3715SXin Li 14*bf2c3715SXin Li namespace Eigen { 15*bf2c3715SXin Li 16*bf2c3715SXin Li namespace internal { 17*bf2c3715SXin Li 18*bf2c3715SXin Li template<typename MatrixType> struct TridiagonalizationMatrixTReturnType; 19*bf2c3715SXin Li template<typename MatrixType> 20*bf2c3715SXin Li struct traits<TridiagonalizationMatrixTReturnType<MatrixType> > 21*bf2c3715SXin Li : public traits<typename MatrixType::PlainObject> 22*bf2c3715SXin Li { 23*bf2c3715SXin Li typedef typename MatrixType::PlainObject ReturnType; // FIXME shall it be a BandMatrix? 24*bf2c3715SXin Li enum { Flags = 0 }; 25*bf2c3715SXin Li }; 26*bf2c3715SXin Li 27*bf2c3715SXin Li template<typename MatrixType, typename CoeffVectorType> 28*bf2c3715SXin Li EIGEN_DEVICE_FUNC 29*bf2c3715SXin Li void tridiagonalization_inplace(MatrixType& matA, CoeffVectorType& hCoeffs); 30*bf2c3715SXin Li } 31*bf2c3715SXin Li 32*bf2c3715SXin Li /** \eigenvalues_module \ingroup Eigenvalues_Module 33*bf2c3715SXin Li * 34*bf2c3715SXin Li * 35*bf2c3715SXin Li * \class Tridiagonalization 36*bf2c3715SXin Li * 37*bf2c3715SXin Li * \brief Tridiagonal decomposition of a selfadjoint matrix 38*bf2c3715SXin Li * 39*bf2c3715SXin Li * \tparam _MatrixType the type of the matrix of which we are computing the 40*bf2c3715SXin Li * tridiagonal decomposition; this is expected to be an instantiation of the 41*bf2c3715SXin Li * Matrix class template. 42*bf2c3715SXin Li * 43*bf2c3715SXin Li * This class performs a tridiagonal decomposition of a selfadjoint matrix \f$ A \f$ such that: 44*bf2c3715SXin Li * \f$ A = Q T Q^* \f$ where \f$ Q \f$ is unitary and \f$ T \f$ a real symmetric tridiagonal matrix. 45*bf2c3715SXin Li * 46*bf2c3715SXin Li * A tridiagonal matrix is a matrix which has nonzero elements only on the 47*bf2c3715SXin Li * main diagonal and the first diagonal below and above it. The Hessenberg 48*bf2c3715SXin Li * decomposition of a selfadjoint matrix is in fact a tridiagonal 49*bf2c3715SXin Li * decomposition. This class is used in SelfAdjointEigenSolver to compute the 50*bf2c3715SXin Li * eigenvalues and eigenvectors of a selfadjoint matrix. 51*bf2c3715SXin Li * 52*bf2c3715SXin Li * Call the function compute() to compute the tridiagonal decomposition of a 53*bf2c3715SXin Li * given matrix. Alternatively, you can use the Tridiagonalization(const MatrixType&) 54*bf2c3715SXin Li * constructor which computes the tridiagonal Schur decomposition at 55*bf2c3715SXin Li * construction time. Once the decomposition is computed, you can use the 56*bf2c3715SXin Li * matrixQ() and matrixT() functions to retrieve the matrices Q and T in the 57*bf2c3715SXin Li * decomposition. 58*bf2c3715SXin Li * 59*bf2c3715SXin Li * The documentation of Tridiagonalization(const MatrixType&) contains an 60*bf2c3715SXin Li * example of the typical use of this class. 61*bf2c3715SXin Li * 62*bf2c3715SXin Li * \sa class HessenbergDecomposition, class SelfAdjointEigenSolver 63*bf2c3715SXin Li */ 64*bf2c3715SXin Li template<typename _MatrixType> class Tridiagonalization 65*bf2c3715SXin Li { 66*bf2c3715SXin Li public: 67*bf2c3715SXin Li 68*bf2c3715SXin Li /** \brief Synonym for the template parameter \p _MatrixType. */ 69*bf2c3715SXin Li typedef _MatrixType MatrixType; 70*bf2c3715SXin Li 71*bf2c3715SXin Li typedef typename MatrixType::Scalar Scalar; 72*bf2c3715SXin Li typedef typename NumTraits<Scalar>::Real RealScalar; 73*bf2c3715SXin Li typedef Eigen::Index Index; ///< \deprecated since Eigen 3.3 74*bf2c3715SXin Li 75*bf2c3715SXin Li enum { 76*bf2c3715SXin Li Size = MatrixType::RowsAtCompileTime, 77*bf2c3715SXin Li SizeMinusOne = Size == Dynamic ? Dynamic : (Size > 1 ? Size - 1 : 1), 78*bf2c3715SXin Li Options = MatrixType::Options, 79*bf2c3715SXin Li MaxSize = MatrixType::MaxRowsAtCompileTime, 80*bf2c3715SXin Li MaxSizeMinusOne = MaxSize == Dynamic ? Dynamic : (MaxSize > 1 ? MaxSize - 1 : 1) 81*bf2c3715SXin Li }; 82*bf2c3715SXin Li 83*bf2c3715SXin Li typedef Matrix<Scalar, SizeMinusOne, 1, Options & ~RowMajor, MaxSizeMinusOne, 1> CoeffVectorType; 84*bf2c3715SXin Li typedef typename internal::plain_col_type<MatrixType, RealScalar>::type DiagonalType; 85*bf2c3715SXin Li typedef Matrix<RealScalar, SizeMinusOne, 1, Options & ~RowMajor, MaxSizeMinusOne, 1> SubDiagonalType; 86*bf2c3715SXin Li typedef typename internal::remove_all<typename MatrixType::RealReturnType>::type MatrixTypeRealView; 87*bf2c3715SXin Li typedef internal::TridiagonalizationMatrixTReturnType<MatrixTypeRealView> MatrixTReturnType; 88*bf2c3715SXin Li 89*bf2c3715SXin Li typedef typename internal::conditional<NumTraits<Scalar>::IsComplex, 90*bf2c3715SXin Li typename internal::add_const_on_value_type<typename Diagonal<const MatrixType>::RealReturnType>::type, 91*bf2c3715SXin Li const Diagonal<const MatrixType> 92*bf2c3715SXin Li >::type DiagonalReturnType; 93*bf2c3715SXin Li 94*bf2c3715SXin Li typedef typename internal::conditional<NumTraits<Scalar>::IsComplex, 95*bf2c3715SXin Li typename internal::add_const_on_value_type<typename Diagonal<const MatrixType, -1>::RealReturnType>::type, 96*bf2c3715SXin Li const Diagonal<const MatrixType, -1> 97*bf2c3715SXin Li >::type SubDiagonalReturnType; 98*bf2c3715SXin Li 99*bf2c3715SXin Li /** \brief Return type of matrixQ() */ 100*bf2c3715SXin Li typedef HouseholderSequence<MatrixType,typename internal::remove_all<typename CoeffVectorType::ConjugateReturnType>::type> HouseholderSequenceType; 101*bf2c3715SXin Li 102*bf2c3715SXin Li /** \brief Default constructor. 103*bf2c3715SXin Li * 104*bf2c3715SXin Li * \param [in] size Positive integer, size of the matrix whose tridiagonal 105*bf2c3715SXin Li * decomposition will be computed. 106*bf2c3715SXin Li * 107*bf2c3715SXin Li * The default constructor is useful in cases in which the user intends to 108*bf2c3715SXin Li * perform decompositions via compute(). The \p size parameter is only 109*bf2c3715SXin Li * used as a hint. It is not an error to give a wrong \p size, but it may 110*bf2c3715SXin Li * impair performance. 111*bf2c3715SXin Li * 112*bf2c3715SXin Li * \sa compute() for an example. 113*bf2c3715SXin Li */ 114*bf2c3715SXin Li explicit Tridiagonalization(Index size = Size==Dynamic ? 2 : Size) 115*bf2c3715SXin Li : m_matrix(size,size), 116*bf2c3715SXin Li m_hCoeffs(size > 1 ? size-1 : 1), 117*bf2c3715SXin Li m_isInitialized(false) 118*bf2c3715SXin Li {} 119*bf2c3715SXin Li 120*bf2c3715SXin Li /** \brief Constructor; computes tridiagonal decomposition of given matrix. 121*bf2c3715SXin Li * 122*bf2c3715SXin Li * \param[in] matrix Selfadjoint matrix whose tridiagonal decomposition 123*bf2c3715SXin Li * is to be computed. 124*bf2c3715SXin Li * 125*bf2c3715SXin Li * This constructor calls compute() to compute the tridiagonal decomposition. 126*bf2c3715SXin Li * 127*bf2c3715SXin Li * Example: \include Tridiagonalization_Tridiagonalization_MatrixType.cpp 128*bf2c3715SXin Li * Output: \verbinclude Tridiagonalization_Tridiagonalization_MatrixType.out 129*bf2c3715SXin Li */ 130*bf2c3715SXin Li template<typename InputType> 131*bf2c3715SXin Li explicit Tridiagonalization(const EigenBase<InputType>& matrix) 132*bf2c3715SXin Li : m_matrix(matrix.derived()), 133*bf2c3715SXin Li m_hCoeffs(matrix.cols() > 1 ? matrix.cols()-1 : 1), 134*bf2c3715SXin Li m_isInitialized(false) 135*bf2c3715SXin Li { 136*bf2c3715SXin Li internal::tridiagonalization_inplace(m_matrix, m_hCoeffs); 137*bf2c3715SXin Li m_isInitialized = true; 138*bf2c3715SXin Li } 139*bf2c3715SXin Li 140*bf2c3715SXin Li /** \brief Computes tridiagonal decomposition of given matrix. 141*bf2c3715SXin Li * 142*bf2c3715SXin Li * \param[in] matrix Selfadjoint matrix whose tridiagonal decomposition 143*bf2c3715SXin Li * is to be computed. 144*bf2c3715SXin Li * \returns Reference to \c *this 145*bf2c3715SXin Li * 146*bf2c3715SXin Li * The tridiagonal decomposition is computed by bringing the columns of 147*bf2c3715SXin Li * the matrix successively in the required form using Householder 148*bf2c3715SXin Li * reflections. The cost is \f$ 4n^3/3 \f$ flops, where \f$ n \f$ denotes 149*bf2c3715SXin Li * the size of the given matrix. 150*bf2c3715SXin Li * 151*bf2c3715SXin Li * This method reuses of the allocated data in the Tridiagonalization 152*bf2c3715SXin Li * object, if the size of the matrix does not change. 153*bf2c3715SXin Li * 154*bf2c3715SXin Li * Example: \include Tridiagonalization_compute.cpp 155*bf2c3715SXin Li * Output: \verbinclude Tridiagonalization_compute.out 156*bf2c3715SXin Li */ 157*bf2c3715SXin Li template<typename InputType> 158*bf2c3715SXin Li Tridiagonalization& compute(const EigenBase<InputType>& matrix) 159*bf2c3715SXin Li { 160*bf2c3715SXin Li m_matrix = matrix.derived(); 161*bf2c3715SXin Li m_hCoeffs.resize(matrix.rows()-1, 1); 162*bf2c3715SXin Li internal::tridiagonalization_inplace(m_matrix, m_hCoeffs); 163*bf2c3715SXin Li m_isInitialized = true; 164*bf2c3715SXin Li return *this; 165*bf2c3715SXin Li } 166*bf2c3715SXin Li 167*bf2c3715SXin Li /** \brief Returns the Householder coefficients. 168*bf2c3715SXin Li * 169*bf2c3715SXin Li * \returns a const reference to the vector of Householder coefficients 170*bf2c3715SXin Li * 171*bf2c3715SXin Li * \pre Either the constructor Tridiagonalization(const MatrixType&) or 172*bf2c3715SXin Li * the member function compute(const MatrixType&) has been called before 173*bf2c3715SXin Li * to compute the tridiagonal decomposition of a matrix. 174*bf2c3715SXin Li * 175*bf2c3715SXin Li * The Householder coefficients allow the reconstruction of the matrix 176*bf2c3715SXin Li * \f$ Q \f$ in the tridiagonal decomposition from the packed data. 177*bf2c3715SXin Li * 178*bf2c3715SXin Li * Example: \include Tridiagonalization_householderCoefficients.cpp 179*bf2c3715SXin Li * Output: \verbinclude Tridiagonalization_householderCoefficients.out 180*bf2c3715SXin Li * 181*bf2c3715SXin Li * \sa packedMatrix(), \ref Householder_Module "Householder module" 182*bf2c3715SXin Li */ 183*bf2c3715SXin Li inline CoeffVectorType householderCoefficients() const 184*bf2c3715SXin Li { 185*bf2c3715SXin Li eigen_assert(m_isInitialized && "Tridiagonalization is not initialized."); 186*bf2c3715SXin Li return m_hCoeffs; 187*bf2c3715SXin Li } 188*bf2c3715SXin Li 189*bf2c3715SXin Li /** \brief Returns the internal representation of the decomposition 190*bf2c3715SXin Li * 191*bf2c3715SXin Li * \returns a const reference to a matrix with the internal representation 192*bf2c3715SXin Li * of the decomposition. 193*bf2c3715SXin Li * 194*bf2c3715SXin Li * \pre Either the constructor Tridiagonalization(const MatrixType&) or 195*bf2c3715SXin Li * the member function compute(const MatrixType&) has been called before 196*bf2c3715SXin Li * to compute the tridiagonal decomposition of a matrix. 197*bf2c3715SXin Li * 198*bf2c3715SXin Li * The returned matrix contains the following information: 199*bf2c3715SXin Li * - the strict upper triangular part is equal to the input matrix A. 200*bf2c3715SXin Li * - the diagonal and lower sub-diagonal represent the real tridiagonal 201*bf2c3715SXin Li * symmetric matrix T. 202*bf2c3715SXin Li * - the rest of the lower part contains the Householder vectors that, 203*bf2c3715SXin Li * combined with Householder coefficients returned by 204*bf2c3715SXin Li * householderCoefficients(), allows to reconstruct the matrix Q as 205*bf2c3715SXin Li * \f$ Q = H_{N-1} \ldots H_1 H_0 \f$. 206*bf2c3715SXin Li * Here, the matrices \f$ H_i \f$ are the Householder transformations 207*bf2c3715SXin Li * \f$ H_i = (I - h_i v_i v_i^T) \f$ 208*bf2c3715SXin Li * where \f$ h_i \f$ is the \f$ i \f$th Householder coefficient and 209*bf2c3715SXin Li * \f$ v_i \f$ is the Householder vector defined by 210*bf2c3715SXin Li * \f$ v_i = [ 0, \ldots, 0, 1, M(i+2,i), \ldots, M(N-1,i) ]^T \f$ 211*bf2c3715SXin Li * with M the matrix returned by this function. 212*bf2c3715SXin Li * 213*bf2c3715SXin Li * See LAPACK for further details on this packed storage. 214*bf2c3715SXin Li * 215*bf2c3715SXin Li * Example: \include Tridiagonalization_packedMatrix.cpp 216*bf2c3715SXin Li * Output: \verbinclude Tridiagonalization_packedMatrix.out 217*bf2c3715SXin Li * 218*bf2c3715SXin Li * \sa householderCoefficients() 219*bf2c3715SXin Li */ 220*bf2c3715SXin Li inline const MatrixType& packedMatrix() const 221*bf2c3715SXin Li { 222*bf2c3715SXin Li eigen_assert(m_isInitialized && "Tridiagonalization is not initialized."); 223*bf2c3715SXin Li return m_matrix; 224*bf2c3715SXin Li } 225*bf2c3715SXin Li 226*bf2c3715SXin Li /** \brief Returns the unitary matrix Q in the decomposition 227*bf2c3715SXin Li * 228*bf2c3715SXin Li * \returns object representing the matrix Q 229*bf2c3715SXin Li * 230*bf2c3715SXin Li * \pre Either the constructor Tridiagonalization(const MatrixType&) or 231*bf2c3715SXin Li * the member function compute(const MatrixType&) has been called before 232*bf2c3715SXin Li * to compute the tridiagonal decomposition of a matrix. 233*bf2c3715SXin Li * 234*bf2c3715SXin Li * This function returns a light-weight object of template class 235*bf2c3715SXin Li * HouseholderSequence. You can either apply it directly to a matrix or 236*bf2c3715SXin Li * you can convert it to a matrix of type #MatrixType. 237*bf2c3715SXin Li * 238*bf2c3715SXin Li * \sa Tridiagonalization(const MatrixType&) for an example, 239*bf2c3715SXin Li * matrixT(), class HouseholderSequence 240*bf2c3715SXin Li */ 241*bf2c3715SXin Li HouseholderSequenceType matrixQ() const 242*bf2c3715SXin Li { 243*bf2c3715SXin Li eigen_assert(m_isInitialized && "Tridiagonalization is not initialized."); 244*bf2c3715SXin Li return HouseholderSequenceType(m_matrix, m_hCoeffs.conjugate()) 245*bf2c3715SXin Li .setLength(m_matrix.rows() - 1) 246*bf2c3715SXin Li .setShift(1); 247*bf2c3715SXin Li } 248*bf2c3715SXin Li 249*bf2c3715SXin Li /** \brief Returns an expression of the tridiagonal matrix T in the decomposition 250*bf2c3715SXin Li * 251*bf2c3715SXin Li * \returns expression object representing the matrix T 252*bf2c3715SXin Li * 253*bf2c3715SXin Li * \pre Either the constructor Tridiagonalization(const MatrixType&) or 254*bf2c3715SXin Li * the member function compute(const MatrixType&) has been called before 255*bf2c3715SXin Li * to compute the tridiagonal decomposition of a matrix. 256*bf2c3715SXin Li * 257*bf2c3715SXin Li * Currently, this function can be used to extract the matrix T from internal 258*bf2c3715SXin Li * data and copy it to a dense matrix object. In most cases, it may be 259*bf2c3715SXin Li * sufficient to directly use the packed matrix or the vector expressions 260*bf2c3715SXin Li * returned by diagonal() and subDiagonal() instead of creating a new 261*bf2c3715SXin Li * dense copy matrix with this function. 262*bf2c3715SXin Li * 263*bf2c3715SXin Li * \sa Tridiagonalization(const MatrixType&) for an example, 264*bf2c3715SXin Li * matrixQ(), packedMatrix(), diagonal(), subDiagonal() 265*bf2c3715SXin Li */ 266*bf2c3715SXin Li MatrixTReturnType matrixT() const 267*bf2c3715SXin Li { 268*bf2c3715SXin Li eigen_assert(m_isInitialized && "Tridiagonalization is not initialized."); 269*bf2c3715SXin Li return MatrixTReturnType(m_matrix.real()); 270*bf2c3715SXin Li } 271*bf2c3715SXin Li 272*bf2c3715SXin Li /** \brief Returns the diagonal of the tridiagonal matrix T in the decomposition. 273*bf2c3715SXin Li * 274*bf2c3715SXin Li * \returns expression representing the diagonal of T 275*bf2c3715SXin Li * 276*bf2c3715SXin Li * \pre Either the constructor Tridiagonalization(const MatrixType&) or 277*bf2c3715SXin Li * the member function compute(const MatrixType&) has been called before 278*bf2c3715SXin Li * to compute the tridiagonal decomposition of a matrix. 279*bf2c3715SXin Li * 280*bf2c3715SXin Li * Example: \include Tridiagonalization_diagonal.cpp 281*bf2c3715SXin Li * Output: \verbinclude Tridiagonalization_diagonal.out 282*bf2c3715SXin Li * 283*bf2c3715SXin Li * \sa matrixT(), subDiagonal() 284*bf2c3715SXin Li */ 285*bf2c3715SXin Li DiagonalReturnType diagonal() const; 286*bf2c3715SXin Li 287*bf2c3715SXin Li /** \brief Returns the subdiagonal of the tridiagonal matrix T in the decomposition. 288*bf2c3715SXin Li * 289*bf2c3715SXin Li * \returns expression representing the subdiagonal of T 290*bf2c3715SXin Li * 291*bf2c3715SXin Li * \pre Either the constructor Tridiagonalization(const MatrixType&) or 292*bf2c3715SXin Li * the member function compute(const MatrixType&) has been called before 293*bf2c3715SXin Li * to compute the tridiagonal decomposition of a matrix. 294*bf2c3715SXin Li * 295*bf2c3715SXin Li * \sa diagonal() for an example, matrixT() 296*bf2c3715SXin Li */ 297*bf2c3715SXin Li SubDiagonalReturnType subDiagonal() const; 298*bf2c3715SXin Li 299*bf2c3715SXin Li protected: 300*bf2c3715SXin Li 301*bf2c3715SXin Li MatrixType m_matrix; 302*bf2c3715SXin Li CoeffVectorType m_hCoeffs; 303*bf2c3715SXin Li bool m_isInitialized; 304*bf2c3715SXin Li }; 305*bf2c3715SXin Li 306*bf2c3715SXin Li template<typename MatrixType> 307*bf2c3715SXin Li typename Tridiagonalization<MatrixType>::DiagonalReturnType 308*bf2c3715SXin Li Tridiagonalization<MatrixType>::diagonal() const 309*bf2c3715SXin Li { 310*bf2c3715SXin Li eigen_assert(m_isInitialized && "Tridiagonalization is not initialized."); 311*bf2c3715SXin Li return m_matrix.diagonal().real(); 312*bf2c3715SXin Li } 313*bf2c3715SXin Li 314*bf2c3715SXin Li template<typename MatrixType> 315*bf2c3715SXin Li typename Tridiagonalization<MatrixType>::SubDiagonalReturnType 316*bf2c3715SXin Li Tridiagonalization<MatrixType>::subDiagonal() const 317*bf2c3715SXin Li { 318*bf2c3715SXin Li eigen_assert(m_isInitialized && "Tridiagonalization is not initialized."); 319*bf2c3715SXin Li return m_matrix.template diagonal<-1>().real(); 320*bf2c3715SXin Li } 321*bf2c3715SXin Li 322*bf2c3715SXin Li namespace internal { 323*bf2c3715SXin Li 324*bf2c3715SXin Li /** \internal 325*bf2c3715SXin Li * Performs a tridiagonal decomposition of the selfadjoint matrix \a matA in-place. 326*bf2c3715SXin Li * 327*bf2c3715SXin Li * \param[in,out] matA On input the selfadjoint matrix. Only the \b lower triangular part is referenced. 328*bf2c3715SXin Li * On output, the strict upper part is left unchanged, and the lower triangular part 329*bf2c3715SXin Li * represents the T and Q matrices in packed format has detailed below. 330*bf2c3715SXin Li * \param[out] hCoeffs returned Householder coefficients (see below) 331*bf2c3715SXin Li * 332*bf2c3715SXin Li * On output, the tridiagonal selfadjoint matrix T is stored in the diagonal 333*bf2c3715SXin Li * and lower sub-diagonal of the matrix \a matA. 334*bf2c3715SXin Li * The unitary matrix Q is represented in a compact way as a product of 335*bf2c3715SXin Li * Householder reflectors \f$ H_i \f$ such that: 336*bf2c3715SXin Li * \f$ Q = H_{N-1} \ldots H_1 H_0 \f$. 337*bf2c3715SXin Li * The Householder reflectors are defined as 338*bf2c3715SXin Li * \f$ H_i = (I - h_i v_i v_i^T) \f$ 339*bf2c3715SXin Li * where \f$ h_i = hCoeffs[i]\f$ is the \f$ i \f$th Householder coefficient and 340*bf2c3715SXin Li * \f$ v_i \f$ is the Householder vector defined by 341*bf2c3715SXin Li * \f$ v_i = [ 0, \ldots, 0, 1, matA(i+2,i), \ldots, matA(N-1,i) ]^T \f$. 342*bf2c3715SXin Li * 343*bf2c3715SXin Li * Implemented from Golub's "Matrix Computations", algorithm 8.3.1. 344*bf2c3715SXin Li * 345*bf2c3715SXin Li * \sa Tridiagonalization::packedMatrix() 346*bf2c3715SXin Li */ 347*bf2c3715SXin Li template<typename MatrixType, typename CoeffVectorType> 348*bf2c3715SXin Li EIGEN_DEVICE_FUNC 349*bf2c3715SXin Li void tridiagonalization_inplace(MatrixType& matA, CoeffVectorType& hCoeffs) 350*bf2c3715SXin Li { 351*bf2c3715SXin Li using numext::conj; 352*bf2c3715SXin Li typedef typename MatrixType::Scalar Scalar; 353*bf2c3715SXin Li typedef typename MatrixType::RealScalar RealScalar; 354*bf2c3715SXin Li Index n = matA.rows(); 355*bf2c3715SXin Li eigen_assert(n==matA.cols()); 356*bf2c3715SXin Li eigen_assert(n==hCoeffs.size()+1 || n==1); 357*bf2c3715SXin Li 358*bf2c3715SXin Li for (Index i = 0; i<n-1; ++i) 359*bf2c3715SXin Li { 360*bf2c3715SXin Li Index remainingSize = n-i-1; 361*bf2c3715SXin Li RealScalar beta; 362*bf2c3715SXin Li Scalar h; 363*bf2c3715SXin Li matA.col(i).tail(remainingSize).makeHouseholderInPlace(h, beta); 364*bf2c3715SXin Li 365*bf2c3715SXin Li // Apply similarity transformation to remaining columns, 366*bf2c3715SXin Li // i.e., A = H A H' where H = I - h v v' and v = matA.col(i).tail(n-i-1) 367*bf2c3715SXin Li matA.col(i).coeffRef(i+1) = 1; 368*bf2c3715SXin Li 369*bf2c3715SXin Li hCoeffs.tail(n-i-1).noalias() = (matA.bottomRightCorner(remainingSize,remainingSize).template selfadjointView<Lower>() 370*bf2c3715SXin Li * (conj(h) * matA.col(i).tail(remainingSize))); 371*bf2c3715SXin Li 372*bf2c3715SXin Li 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); 373*bf2c3715SXin Li 374*bf2c3715SXin Li matA.bottomRightCorner(remainingSize, remainingSize).template selfadjointView<Lower>() 375*bf2c3715SXin Li .rankUpdate(matA.col(i).tail(remainingSize), hCoeffs.tail(remainingSize), Scalar(-1)); 376*bf2c3715SXin Li 377*bf2c3715SXin Li matA.col(i).coeffRef(i+1) = beta; 378*bf2c3715SXin Li hCoeffs.coeffRef(i) = h; 379*bf2c3715SXin Li } 380*bf2c3715SXin Li } 381*bf2c3715SXin Li 382*bf2c3715SXin Li // forward declaration, implementation at the end of this file 383*bf2c3715SXin Li template<typename MatrixType, 384*bf2c3715SXin Li int Size=MatrixType::ColsAtCompileTime, 385*bf2c3715SXin Li bool IsComplex=NumTraits<typename MatrixType::Scalar>::IsComplex> 386*bf2c3715SXin Li struct tridiagonalization_inplace_selector; 387*bf2c3715SXin Li 388*bf2c3715SXin Li /** \brief Performs a full tridiagonalization in place 389*bf2c3715SXin Li * 390*bf2c3715SXin Li * \param[in,out] mat On input, the selfadjoint matrix whose tridiagonal 391*bf2c3715SXin Li * decomposition is to be computed. Only the lower triangular part referenced. 392*bf2c3715SXin Li * The rest is left unchanged. On output, the orthogonal matrix Q 393*bf2c3715SXin Li * in the decomposition if \p extractQ is true. 394*bf2c3715SXin Li * \param[out] diag The diagonal of the tridiagonal matrix T in the 395*bf2c3715SXin Li * decomposition. 396*bf2c3715SXin Li * \param[out] subdiag The subdiagonal of the tridiagonal matrix T in 397*bf2c3715SXin Li * the decomposition. 398*bf2c3715SXin Li * \param[in] extractQ If true, the orthogonal matrix Q in the 399*bf2c3715SXin Li * decomposition is computed and stored in \p mat. 400*bf2c3715SXin Li * 401*bf2c3715SXin Li * Computes the tridiagonal decomposition of the selfadjoint matrix \p mat in place 402*bf2c3715SXin Li * such that \f$ mat = Q T Q^* \f$ where \f$ Q \f$ is unitary and \f$ T \f$ a real 403*bf2c3715SXin Li * symmetric tridiagonal matrix. 404*bf2c3715SXin Li * 405*bf2c3715SXin Li * The tridiagonal matrix T is passed to the output parameters \p diag and \p subdiag. If 406*bf2c3715SXin Li * \p extractQ is true, then the orthogonal matrix Q is passed to \p mat. Otherwise the lower 407*bf2c3715SXin Li * part of the matrix \p mat is destroyed. 408*bf2c3715SXin Li * 409*bf2c3715SXin Li * The vectors \p diag and \p subdiag are not resized. The function 410*bf2c3715SXin Li * assumes that they are already of the correct size. The length of the 411*bf2c3715SXin Li * vector \p diag should equal the number of rows in \p mat, and the 412*bf2c3715SXin Li * length of the vector \p subdiag should be one left. 413*bf2c3715SXin Li * 414*bf2c3715SXin Li * This implementation contains an optimized path for 3-by-3 matrices 415*bf2c3715SXin Li * which is especially useful for plane fitting. 416*bf2c3715SXin Li * 417*bf2c3715SXin Li * \note Currently, it requires two temporary vectors to hold the intermediate 418*bf2c3715SXin Li * Householder coefficients, and to reconstruct the matrix Q from the Householder 419*bf2c3715SXin Li * reflectors. 420*bf2c3715SXin Li * 421*bf2c3715SXin Li * Example (this uses the same matrix as the example in 422*bf2c3715SXin Li * Tridiagonalization::Tridiagonalization(const MatrixType&)): 423*bf2c3715SXin Li * \include Tridiagonalization_decomposeInPlace.cpp 424*bf2c3715SXin Li * Output: \verbinclude Tridiagonalization_decomposeInPlace.out 425*bf2c3715SXin Li * 426*bf2c3715SXin Li * \sa class Tridiagonalization 427*bf2c3715SXin Li */ 428*bf2c3715SXin Li template<typename MatrixType, typename DiagonalType, typename SubDiagonalType, typename CoeffVectorType> 429*bf2c3715SXin Li EIGEN_DEVICE_FUNC 430*bf2c3715SXin Li void tridiagonalization_inplace(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag, 431*bf2c3715SXin Li CoeffVectorType& hcoeffs, bool extractQ) 432*bf2c3715SXin Li { 433*bf2c3715SXin Li eigen_assert(mat.cols()==mat.rows() && diag.size()==mat.rows() && subdiag.size()==mat.rows()-1); 434*bf2c3715SXin Li tridiagonalization_inplace_selector<MatrixType>::run(mat, diag, subdiag, hcoeffs, extractQ); 435*bf2c3715SXin Li } 436*bf2c3715SXin Li 437*bf2c3715SXin Li /** \internal 438*bf2c3715SXin Li * General full tridiagonalization 439*bf2c3715SXin Li */ 440*bf2c3715SXin Li template<typename MatrixType, int Size, bool IsComplex> 441*bf2c3715SXin Li struct tridiagonalization_inplace_selector 442*bf2c3715SXin Li { 443*bf2c3715SXin Li typedef typename Tridiagonalization<MatrixType>::CoeffVectorType CoeffVectorType; 444*bf2c3715SXin Li typedef typename Tridiagonalization<MatrixType>::HouseholderSequenceType HouseholderSequenceType; 445*bf2c3715SXin Li template<typename DiagonalType, typename SubDiagonalType> 446*bf2c3715SXin Li static EIGEN_DEVICE_FUNC 447*bf2c3715SXin Li void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag, CoeffVectorType& hCoeffs, bool extractQ) 448*bf2c3715SXin Li { 449*bf2c3715SXin Li tridiagonalization_inplace(mat, hCoeffs); 450*bf2c3715SXin Li diag = mat.diagonal().real(); 451*bf2c3715SXin Li subdiag = mat.template diagonal<-1>().real(); 452*bf2c3715SXin Li if(extractQ) 453*bf2c3715SXin Li mat = HouseholderSequenceType(mat, hCoeffs.conjugate()) 454*bf2c3715SXin Li .setLength(mat.rows() - 1) 455*bf2c3715SXin Li .setShift(1); 456*bf2c3715SXin Li } 457*bf2c3715SXin Li }; 458*bf2c3715SXin Li 459*bf2c3715SXin Li /** \internal 460*bf2c3715SXin Li * Specialization for 3x3 real matrices. 461*bf2c3715SXin Li * Especially useful for plane fitting. 462*bf2c3715SXin Li */ 463*bf2c3715SXin Li template<typename MatrixType> 464*bf2c3715SXin Li struct tridiagonalization_inplace_selector<MatrixType,3,false> 465*bf2c3715SXin Li { 466*bf2c3715SXin Li typedef typename MatrixType::Scalar Scalar; 467*bf2c3715SXin Li typedef typename MatrixType::RealScalar RealScalar; 468*bf2c3715SXin Li 469*bf2c3715SXin Li template<typename DiagonalType, typename SubDiagonalType, typename CoeffVectorType> 470*bf2c3715SXin Li static void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag, CoeffVectorType&, bool extractQ) 471*bf2c3715SXin Li { 472*bf2c3715SXin Li using std::sqrt; 473*bf2c3715SXin Li const RealScalar tol = (std::numeric_limits<RealScalar>::min)(); 474*bf2c3715SXin Li diag[0] = mat(0,0); 475*bf2c3715SXin Li RealScalar v1norm2 = numext::abs2(mat(2,0)); 476*bf2c3715SXin Li if(v1norm2 <= tol) 477*bf2c3715SXin Li { 478*bf2c3715SXin Li diag[1] = mat(1,1); 479*bf2c3715SXin Li diag[2] = mat(2,2); 480*bf2c3715SXin Li subdiag[0] = mat(1,0); 481*bf2c3715SXin Li subdiag[1] = mat(2,1); 482*bf2c3715SXin Li if (extractQ) 483*bf2c3715SXin Li mat.setIdentity(); 484*bf2c3715SXin Li } 485*bf2c3715SXin Li else 486*bf2c3715SXin Li { 487*bf2c3715SXin Li RealScalar beta = sqrt(numext::abs2(mat(1,0)) + v1norm2); 488*bf2c3715SXin Li RealScalar invBeta = RealScalar(1)/beta; 489*bf2c3715SXin Li Scalar m01 = mat(1,0) * invBeta; 490*bf2c3715SXin Li Scalar m02 = mat(2,0) * invBeta; 491*bf2c3715SXin Li Scalar q = RealScalar(2)*m01*mat(2,1) + m02*(mat(2,2) - mat(1,1)); 492*bf2c3715SXin Li diag[1] = mat(1,1) + m02*q; 493*bf2c3715SXin Li diag[2] = mat(2,2) - m02*q; 494*bf2c3715SXin Li subdiag[0] = beta; 495*bf2c3715SXin Li subdiag[1] = mat(2,1) - m01 * q; 496*bf2c3715SXin Li if (extractQ) 497*bf2c3715SXin Li { 498*bf2c3715SXin Li mat << 1, 0, 0, 499*bf2c3715SXin Li 0, m01, m02, 500*bf2c3715SXin Li 0, m02, -m01; 501*bf2c3715SXin Li } 502*bf2c3715SXin Li } 503*bf2c3715SXin Li } 504*bf2c3715SXin Li }; 505*bf2c3715SXin Li 506*bf2c3715SXin Li /** \internal 507*bf2c3715SXin Li * Trivial specialization for 1x1 matrices 508*bf2c3715SXin Li */ 509*bf2c3715SXin Li template<typename MatrixType, bool IsComplex> 510*bf2c3715SXin Li struct tridiagonalization_inplace_selector<MatrixType,1,IsComplex> 511*bf2c3715SXin Li { 512*bf2c3715SXin Li typedef typename MatrixType::Scalar Scalar; 513*bf2c3715SXin Li 514*bf2c3715SXin Li template<typename DiagonalType, typename SubDiagonalType, typename CoeffVectorType> 515*bf2c3715SXin Li static EIGEN_DEVICE_FUNC 516*bf2c3715SXin Li void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType&, CoeffVectorType&, bool extractQ) 517*bf2c3715SXin Li { 518*bf2c3715SXin Li diag(0,0) = numext::real(mat(0,0)); 519*bf2c3715SXin Li if(extractQ) 520*bf2c3715SXin Li mat(0,0) = Scalar(1); 521*bf2c3715SXin Li } 522*bf2c3715SXin Li }; 523*bf2c3715SXin Li 524*bf2c3715SXin Li /** \internal 525*bf2c3715SXin Li * \eigenvalues_module \ingroup Eigenvalues_Module 526*bf2c3715SXin Li * 527*bf2c3715SXin Li * \brief Expression type for return value of Tridiagonalization::matrixT() 528*bf2c3715SXin Li * 529*bf2c3715SXin Li * \tparam MatrixType type of underlying dense matrix 530*bf2c3715SXin Li */ 531*bf2c3715SXin Li template<typename MatrixType> struct TridiagonalizationMatrixTReturnType 532*bf2c3715SXin Li : public ReturnByValue<TridiagonalizationMatrixTReturnType<MatrixType> > 533*bf2c3715SXin Li { 534*bf2c3715SXin Li public: 535*bf2c3715SXin Li /** \brief Constructor. 536*bf2c3715SXin Li * 537*bf2c3715SXin Li * \param[in] mat The underlying dense matrix 538*bf2c3715SXin Li */ 539*bf2c3715SXin Li TridiagonalizationMatrixTReturnType(const MatrixType& mat) : m_matrix(mat) { } 540*bf2c3715SXin Li 541*bf2c3715SXin Li template <typename ResultType> 542*bf2c3715SXin Li inline void evalTo(ResultType& result) const 543*bf2c3715SXin Li { 544*bf2c3715SXin Li result.setZero(); 545*bf2c3715SXin Li result.template diagonal<1>() = m_matrix.template diagonal<-1>().conjugate(); 546*bf2c3715SXin Li result.diagonal() = m_matrix.diagonal(); 547*bf2c3715SXin Li result.template diagonal<-1>() = m_matrix.template diagonal<-1>(); 548*bf2c3715SXin Li } 549*bf2c3715SXin Li 550*bf2c3715SXin Li EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_matrix.rows(); } 551*bf2c3715SXin Li EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_matrix.cols(); } 552*bf2c3715SXin Li 553*bf2c3715SXin Li protected: 554*bf2c3715SXin Li typename MatrixType::Nested m_matrix; 555*bf2c3715SXin Li }; 556*bf2c3715SXin Li 557*bf2c3715SXin Li } // end namespace internal 558*bf2c3715SXin Li 559*bf2c3715SXin Li } // end namespace Eigen 560*bf2c3715SXin Li 561*bf2c3715SXin Li #endif // EIGEN_TRIDIAGONALIZATION_H 562