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-2009 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_HESSENBERGDECOMPOSITION_H 12*bf2c3715SXin Li #define EIGEN_HESSENBERGDECOMPOSITION_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 HessenbergDecompositionMatrixHReturnType; 19*bf2c3715SXin Li template<typename MatrixType> 20*bf2c3715SXin Li struct traits<HessenbergDecompositionMatrixHReturnType<MatrixType> > 21*bf2c3715SXin Li { 22*bf2c3715SXin Li typedef MatrixType ReturnType; 23*bf2c3715SXin Li }; 24*bf2c3715SXin Li 25*bf2c3715SXin Li } 26*bf2c3715SXin Li 27*bf2c3715SXin Li /** \eigenvalues_module \ingroup Eigenvalues_Module 28*bf2c3715SXin Li * 29*bf2c3715SXin Li * 30*bf2c3715SXin Li * \class HessenbergDecomposition 31*bf2c3715SXin Li * 32*bf2c3715SXin Li * \brief Reduces a square matrix to Hessenberg form by an orthogonal similarity transformation 33*bf2c3715SXin Li * 34*bf2c3715SXin Li * \tparam _MatrixType the type of the matrix of which we are computing the Hessenberg decomposition 35*bf2c3715SXin Li * 36*bf2c3715SXin Li * This class performs an Hessenberg decomposition of a matrix \f$ A \f$. In 37*bf2c3715SXin Li * the real case, the Hessenberg decomposition consists of an orthogonal 38*bf2c3715SXin Li * matrix \f$ Q \f$ and a Hessenberg matrix \f$ H \f$ such that \f$ A = Q H 39*bf2c3715SXin Li * Q^T \f$. An orthogonal matrix is a matrix whose inverse equals its 40*bf2c3715SXin Li * transpose (\f$ Q^{-1} = Q^T \f$). A Hessenberg matrix has zeros below the 41*bf2c3715SXin Li * subdiagonal, so it is almost upper triangular. The Hessenberg decomposition 42*bf2c3715SXin Li * of a complex matrix is \f$ A = Q H Q^* \f$ with \f$ Q \f$ unitary (that is, 43*bf2c3715SXin Li * \f$ Q^{-1} = Q^* \f$). 44*bf2c3715SXin Li * 45*bf2c3715SXin Li * Call the function compute() to compute the Hessenberg decomposition of a 46*bf2c3715SXin Li * given matrix. Alternatively, you can use the 47*bf2c3715SXin Li * HessenbergDecomposition(const MatrixType&) constructor which computes the 48*bf2c3715SXin Li * Hessenberg decomposition at construction time. Once the decomposition is 49*bf2c3715SXin Li * computed, you can use the matrixH() and matrixQ() functions to construct 50*bf2c3715SXin Li * the matrices H and Q in the decomposition. 51*bf2c3715SXin Li * 52*bf2c3715SXin Li * The documentation for matrixH() contains an example of the typical use of 53*bf2c3715SXin Li * this class. 54*bf2c3715SXin Li * 55*bf2c3715SXin Li * \sa class ComplexSchur, class Tridiagonalization, \ref QR_Module "QR Module" 56*bf2c3715SXin Li */ 57*bf2c3715SXin Li template<typename _MatrixType> class HessenbergDecomposition 58*bf2c3715SXin Li { 59*bf2c3715SXin Li public: 60*bf2c3715SXin Li 61*bf2c3715SXin Li /** \brief Synonym for the template parameter \p _MatrixType. */ 62*bf2c3715SXin Li typedef _MatrixType MatrixType; 63*bf2c3715SXin Li 64*bf2c3715SXin Li enum { 65*bf2c3715SXin Li Size = MatrixType::RowsAtCompileTime, 66*bf2c3715SXin Li SizeMinusOne = Size == Dynamic ? Dynamic : Size - 1, 67*bf2c3715SXin Li Options = MatrixType::Options, 68*bf2c3715SXin Li MaxSize = MatrixType::MaxRowsAtCompileTime, 69*bf2c3715SXin Li MaxSizeMinusOne = MaxSize == Dynamic ? Dynamic : MaxSize - 1 70*bf2c3715SXin Li }; 71*bf2c3715SXin Li 72*bf2c3715SXin Li /** \brief Scalar type for matrices of type #MatrixType. */ 73*bf2c3715SXin Li typedef typename MatrixType::Scalar Scalar; 74*bf2c3715SXin Li typedef Eigen::Index Index; ///< \deprecated since Eigen 3.3 75*bf2c3715SXin Li 76*bf2c3715SXin Li /** \brief Type for vector of Householder coefficients. 77*bf2c3715SXin Li * 78*bf2c3715SXin Li * This is column vector with entries of type #Scalar. The length of the 79*bf2c3715SXin Li * vector is one less than the size of #MatrixType, if it is a fixed-side 80*bf2c3715SXin Li * type. 81*bf2c3715SXin Li */ 82*bf2c3715SXin Li typedef Matrix<Scalar, SizeMinusOne, 1, Options & ~RowMajor, MaxSizeMinusOne, 1> CoeffVectorType; 83*bf2c3715SXin Li 84*bf2c3715SXin Li /** \brief Return type of matrixQ() */ 85*bf2c3715SXin Li typedef HouseholderSequence<MatrixType,typename internal::remove_all<typename CoeffVectorType::ConjugateReturnType>::type> HouseholderSequenceType; 86*bf2c3715SXin Li 87*bf2c3715SXin Li typedef internal::HessenbergDecompositionMatrixHReturnType<MatrixType> MatrixHReturnType; 88*bf2c3715SXin Li 89*bf2c3715SXin Li /** \brief Default constructor; the decomposition will be computed later. 90*bf2c3715SXin Li * 91*bf2c3715SXin Li * \param [in] size The size of the matrix whose Hessenberg decomposition will be computed. 92*bf2c3715SXin Li * 93*bf2c3715SXin Li * The default constructor is useful in cases in which the user intends to 94*bf2c3715SXin Li * perform decompositions via compute(). The \p size parameter is only 95*bf2c3715SXin Li * used as a hint. It is not an error to give a wrong \p size, but it may 96*bf2c3715SXin Li * impair performance. 97*bf2c3715SXin Li * 98*bf2c3715SXin Li * \sa compute() for an example. 99*bf2c3715SXin Li */ 100*bf2c3715SXin Li explicit HessenbergDecomposition(Index size = Size==Dynamic ? 2 : Size) 101*bf2c3715SXin Li : m_matrix(size,size), 102*bf2c3715SXin Li m_temp(size), 103*bf2c3715SXin Li m_isInitialized(false) 104*bf2c3715SXin Li { 105*bf2c3715SXin Li if(size>1) 106*bf2c3715SXin Li m_hCoeffs.resize(size-1); 107*bf2c3715SXin Li } 108*bf2c3715SXin Li 109*bf2c3715SXin Li /** \brief Constructor; computes Hessenberg decomposition of given matrix. 110*bf2c3715SXin Li * 111*bf2c3715SXin Li * \param[in] matrix Square matrix whose Hessenberg decomposition is to be computed. 112*bf2c3715SXin Li * 113*bf2c3715SXin Li * This constructor calls compute() to compute the Hessenberg 114*bf2c3715SXin Li * decomposition. 115*bf2c3715SXin Li * 116*bf2c3715SXin Li * \sa matrixH() for an example. 117*bf2c3715SXin Li */ 118*bf2c3715SXin Li template<typename InputType> 119*bf2c3715SXin Li explicit HessenbergDecomposition(const EigenBase<InputType>& matrix) 120*bf2c3715SXin Li : m_matrix(matrix.derived()), 121*bf2c3715SXin Li m_temp(matrix.rows()), 122*bf2c3715SXin Li m_isInitialized(false) 123*bf2c3715SXin Li { 124*bf2c3715SXin Li if(matrix.rows()<2) 125*bf2c3715SXin Li { 126*bf2c3715SXin Li m_isInitialized = true; 127*bf2c3715SXin Li return; 128*bf2c3715SXin Li } 129*bf2c3715SXin Li m_hCoeffs.resize(matrix.rows()-1,1); 130*bf2c3715SXin Li _compute(m_matrix, m_hCoeffs, m_temp); 131*bf2c3715SXin Li m_isInitialized = true; 132*bf2c3715SXin Li } 133*bf2c3715SXin Li 134*bf2c3715SXin Li /** \brief Computes Hessenberg decomposition of given matrix. 135*bf2c3715SXin Li * 136*bf2c3715SXin Li * \param[in] matrix Square matrix whose Hessenberg decomposition is to be computed. 137*bf2c3715SXin Li * \returns Reference to \c *this 138*bf2c3715SXin Li * 139*bf2c3715SXin Li * The Hessenberg decomposition is computed by bringing the columns of the 140*bf2c3715SXin Li * matrix successively in the required form using Householder reflections 141*bf2c3715SXin Li * (see, e.g., Algorithm 7.4.2 in Golub \& Van Loan, <i>%Matrix 142*bf2c3715SXin Li * Computations</i>). The cost is \f$ 10n^3/3 \f$ flops, where \f$ n \f$ 143*bf2c3715SXin Li * denotes the size of the given matrix. 144*bf2c3715SXin Li * 145*bf2c3715SXin Li * This method reuses of the allocated data in the HessenbergDecomposition 146*bf2c3715SXin Li * object. 147*bf2c3715SXin Li * 148*bf2c3715SXin Li * Example: \include HessenbergDecomposition_compute.cpp 149*bf2c3715SXin Li * Output: \verbinclude HessenbergDecomposition_compute.out 150*bf2c3715SXin Li */ 151*bf2c3715SXin Li template<typename InputType> 152*bf2c3715SXin Li HessenbergDecomposition& compute(const EigenBase<InputType>& matrix) 153*bf2c3715SXin Li { 154*bf2c3715SXin Li m_matrix = matrix.derived(); 155*bf2c3715SXin Li if(matrix.rows()<2) 156*bf2c3715SXin Li { 157*bf2c3715SXin Li m_isInitialized = true; 158*bf2c3715SXin Li return *this; 159*bf2c3715SXin Li } 160*bf2c3715SXin Li m_hCoeffs.resize(matrix.rows()-1,1); 161*bf2c3715SXin Li _compute(m_matrix, m_hCoeffs, m_temp); 162*bf2c3715SXin Li m_isInitialized = true; 163*bf2c3715SXin Li return *this; 164*bf2c3715SXin Li } 165*bf2c3715SXin Li 166*bf2c3715SXin Li /** \brief Returns the Householder coefficients. 167*bf2c3715SXin Li * 168*bf2c3715SXin Li * \returns a const reference to the vector of Householder coefficients 169*bf2c3715SXin Li * 170*bf2c3715SXin Li * \pre Either the constructor HessenbergDecomposition(const MatrixType&) 171*bf2c3715SXin Li * or the member function compute(const MatrixType&) has been called 172*bf2c3715SXin Li * before to compute the Hessenberg decomposition of a matrix. 173*bf2c3715SXin Li * 174*bf2c3715SXin Li * The Householder coefficients allow the reconstruction of the matrix 175*bf2c3715SXin Li * \f$ Q \f$ in the Hessenberg decomposition from the packed data. 176*bf2c3715SXin Li * 177*bf2c3715SXin Li * \sa packedMatrix(), \ref Householder_Module "Householder module" 178*bf2c3715SXin Li */ 179*bf2c3715SXin Li const CoeffVectorType& householderCoefficients() const 180*bf2c3715SXin Li { 181*bf2c3715SXin Li eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized."); 182*bf2c3715SXin Li return m_hCoeffs; 183*bf2c3715SXin Li } 184*bf2c3715SXin Li 185*bf2c3715SXin Li /** \brief Returns the internal representation of the decomposition 186*bf2c3715SXin Li * 187*bf2c3715SXin Li * \returns a const reference to a matrix with the internal representation 188*bf2c3715SXin Li * of the decomposition. 189*bf2c3715SXin Li * 190*bf2c3715SXin Li * \pre Either the constructor HessenbergDecomposition(const MatrixType&) 191*bf2c3715SXin Li * or the member function compute(const MatrixType&) has been called 192*bf2c3715SXin Li * before to compute the Hessenberg decomposition of a matrix. 193*bf2c3715SXin Li * 194*bf2c3715SXin Li * The returned matrix contains the following information: 195*bf2c3715SXin Li * - the upper part and lower sub-diagonal represent the Hessenberg matrix H 196*bf2c3715SXin Li * - the rest of the lower part contains the Householder vectors that, combined with 197*bf2c3715SXin Li * Householder coefficients returned by householderCoefficients(), 198*bf2c3715SXin Li * allows to reconstruct the matrix Q as 199*bf2c3715SXin Li * \f$ Q = H_{N-1} \ldots H_1 H_0 \f$. 200*bf2c3715SXin Li * Here, the matrices \f$ H_i \f$ are the Householder transformations 201*bf2c3715SXin Li * \f$ H_i = (I - h_i v_i v_i^T) \f$ 202*bf2c3715SXin Li * where \f$ h_i \f$ is the \f$ i \f$th Householder coefficient and 203*bf2c3715SXin Li * \f$ v_i \f$ is the Householder vector defined by 204*bf2c3715SXin Li * \f$ v_i = [ 0, \ldots, 0, 1, M(i+2,i), \ldots, M(N-1,i) ]^T \f$ 205*bf2c3715SXin Li * with M the matrix returned by this function. 206*bf2c3715SXin Li * 207*bf2c3715SXin Li * See LAPACK for further details on this packed storage. 208*bf2c3715SXin Li * 209*bf2c3715SXin Li * Example: \include HessenbergDecomposition_packedMatrix.cpp 210*bf2c3715SXin Li * Output: \verbinclude HessenbergDecomposition_packedMatrix.out 211*bf2c3715SXin Li * 212*bf2c3715SXin Li * \sa householderCoefficients() 213*bf2c3715SXin Li */ 214*bf2c3715SXin Li const MatrixType& packedMatrix() const 215*bf2c3715SXin Li { 216*bf2c3715SXin Li eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized."); 217*bf2c3715SXin Li return m_matrix; 218*bf2c3715SXin Li } 219*bf2c3715SXin Li 220*bf2c3715SXin Li /** \brief Reconstructs the orthogonal matrix Q in the decomposition 221*bf2c3715SXin Li * 222*bf2c3715SXin Li * \returns object representing the matrix Q 223*bf2c3715SXin Li * 224*bf2c3715SXin Li * \pre Either the constructor HessenbergDecomposition(const MatrixType&) 225*bf2c3715SXin Li * or the member function compute(const MatrixType&) has been called 226*bf2c3715SXin Li * before to compute the Hessenberg decomposition of a matrix. 227*bf2c3715SXin Li * 228*bf2c3715SXin Li * This function returns a light-weight object of template class 229*bf2c3715SXin Li * HouseholderSequence. You can either apply it directly to a matrix or 230*bf2c3715SXin Li * you can convert it to a matrix of type #MatrixType. 231*bf2c3715SXin Li * 232*bf2c3715SXin Li * \sa matrixH() for an example, class HouseholderSequence 233*bf2c3715SXin Li */ 234*bf2c3715SXin Li HouseholderSequenceType matrixQ() const 235*bf2c3715SXin Li { 236*bf2c3715SXin Li eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized."); 237*bf2c3715SXin Li return HouseholderSequenceType(m_matrix, m_hCoeffs.conjugate()) 238*bf2c3715SXin Li .setLength(m_matrix.rows() - 1) 239*bf2c3715SXin Li .setShift(1); 240*bf2c3715SXin Li } 241*bf2c3715SXin Li 242*bf2c3715SXin Li /** \brief Constructs the Hessenberg matrix H in the decomposition 243*bf2c3715SXin Li * 244*bf2c3715SXin Li * \returns expression object representing the matrix H 245*bf2c3715SXin Li * 246*bf2c3715SXin Li * \pre Either the constructor HessenbergDecomposition(const MatrixType&) 247*bf2c3715SXin Li * or the member function compute(const MatrixType&) has been called 248*bf2c3715SXin Li * before to compute the Hessenberg decomposition of a matrix. 249*bf2c3715SXin Li * 250*bf2c3715SXin Li * The object returned by this function constructs the Hessenberg matrix H 251*bf2c3715SXin Li * when it is assigned to a matrix or otherwise evaluated. The matrix H is 252*bf2c3715SXin Li * constructed from the packed matrix as returned by packedMatrix(): The 253*bf2c3715SXin Li * upper part (including the subdiagonal) of the packed matrix contains 254*bf2c3715SXin Li * the matrix H. It may sometimes be better to directly use the packed 255*bf2c3715SXin Li * matrix instead of constructing the matrix H. 256*bf2c3715SXin Li * 257*bf2c3715SXin Li * Example: \include HessenbergDecomposition_matrixH.cpp 258*bf2c3715SXin Li * Output: \verbinclude HessenbergDecomposition_matrixH.out 259*bf2c3715SXin Li * 260*bf2c3715SXin Li * \sa matrixQ(), packedMatrix() 261*bf2c3715SXin Li */ 262*bf2c3715SXin Li MatrixHReturnType matrixH() const 263*bf2c3715SXin Li { 264*bf2c3715SXin Li eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized."); 265*bf2c3715SXin Li return MatrixHReturnType(*this); 266*bf2c3715SXin Li } 267*bf2c3715SXin Li 268*bf2c3715SXin Li private: 269*bf2c3715SXin Li 270*bf2c3715SXin Li typedef Matrix<Scalar, 1, Size, int(Options) | int(RowMajor), 1, MaxSize> VectorType; 271*bf2c3715SXin Li typedef typename NumTraits<Scalar>::Real RealScalar; 272*bf2c3715SXin Li static void _compute(MatrixType& matA, CoeffVectorType& hCoeffs, VectorType& temp); 273*bf2c3715SXin Li 274*bf2c3715SXin Li protected: 275*bf2c3715SXin Li MatrixType m_matrix; 276*bf2c3715SXin Li CoeffVectorType m_hCoeffs; 277*bf2c3715SXin Li VectorType m_temp; 278*bf2c3715SXin Li bool m_isInitialized; 279*bf2c3715SXin Li }; 280*bf2c3715SXin Li 281*bf2c3715SXin Li /** \internal 282*bf2c3715SXin Li * Performs a tridiagonal decomposition of \a matA in place. 283*bf2c3715SXin Li * 284*bf2c3715SXin Li * \param matA the input selfadjoint matrix 285*bf2c3715SXin Li * \param hCoeffs returned Householder coefficients 286*bf2c3715SXin Li * 287*bf2c3715SXin Li * The result is written in the lower triangular part of \a matA. 288*bf2c3715SXin Li * 289*bf2c3715SXin Li * Implemented from Golub's "%Matrix Computations", algorithm 8.3.1. 290*bf2c3715SXin Li * 291*bf2c3715SXin Li * \sa packedMatrix() 292*bf2c3715SXin Li */ 293*bf2c3715SXin Li template<typename MatrixType> 294*bf2c3715SXin Li void HessenbergDecomposition<MatrixType>::_compute(MatrixType& matA, CoeffVectorType& hCoeffs, VectorType& temp) 295*bf2c3715SXin Li { 296*bf2c3715SXin Li eigen_assert(matA.rows()==matA.cols()); 297*bf2c3715SXin Li Index n = matA.rows(); 298*bf2c3715SXin Li temp.resize(n); 299*bf2c3715SXin Li for (Index i = 0; i<n-1; ++i) 300*bf2c3715SXin Li { 301*bf2c3715SXin Li // let's consider the vector v = i-th column starting at position i+1 302*bf2c3715SXin Li Index remainingSize = n-i-1; 303*bf2c3715SXin Li RealScalar beta; 304*bf2c3715SXin Li Scalar h; 305*bf2c3715SXin Li matA.col(i).tail(remainingSize).makeHouseholderInPlace(h, beta); 306*bf2c3715SXin Li matA.col(i).coeffRef(i+1) = beta; 307*bf2c3715SXin Li hCoeffs.coeffRef(i) = h; 308*bf2c3715SXin Li 309*bf2c3715SXin Li // Apply similarity transformation to remaining columns, 310*bf2c3715SXin Li // i.e., compute A = H A H' 311*bf2c3715SXin Li 312*bf2c3715SXin Li // A = H A 313*bf2c3715SXin Li matA.bottomRightCorner(remainingSize, remainingSize) 314*bf2c3715SXin Li .applyHouseholderOnTheLeft(matA.col(i).tail(remainingSize-1), h, &temp.coeffRef(0)); 315*bf2c3715SXin Li 316*bf2c3715SXin Li // A = A H' 317*bf2c3715SXin Li matA.rightCols(remainingSize) 318*bf2c3715SXin Li .applyHouseholderOnTheRight(matA.col(i).tail(remainingSize-1), numext::conj(h), &temp.coeffRef(0)); 319*bf2c3715SXin Li } 320*bf2c3715SXin Li } 321*bf2c3715SXin Li 322*bf2c3715SXin Li namespace internal { 323*bf2c3715SXin Li 324*bf2c3715SXin Li /** \eigenvalues_module \ingroup Eigenvalues_Module 325*bf2c3715SXin Li * 326*bf2c3715SXin Li * 327*bf2c3715SXin Li * \brief Expression type for return value of HessenbergDecomposition::matrixH() 328*bf2c3715SXin Li * 329*bf2c3715SXin Li * \tparam MatrixType type of matrix in the Hessenberg decomposition 330*bf2c3715SXin Li * 331*bf2c3715SXin Li * Objects of this type represent the Hessenberg matrix in the Hessenberg 332*bf2c3715SXin Li * decomposition of some matrix. The object holds a reference to the 333*bf2c3715SXin Li * HessenbergDecomposition class until the it is assigned or evaluated for 334*bf2c3715SXin Li * some other reason (the reference should remain valid during the life time 335*bf2c3715SXin Li * of this object). This class is the return type of 336*bf2c3715SXin Li * HessenbergDecomposition::matrixH(); there is probably no other use for this 337*bf2c3715SXin Li * class. 338*bf2c3715SXin Li */ 339*bf2c3715SXin Li template<typename MatrixType> struct HessenbergDecompositionMatrixHReturnType 340*bf2c3715SXin Li : public ReturnByValue<HessenbergDecompositionMatrixHReturnType<MatrixType> > 341*bf2c3715SXin Li { 342*bf2c3715SXin Li public: 343*bf2c3715SXin Li /** \brief Constructor. 344*bf2c3715SXin Li * 345*bf2c3715SXin Li * \param[in] hess Hessenberg decomposition 346*bf2c3715SXin Li */ 347*bf2c3715SXin Li HessenbergDecompositionMatrixHReturnType(const HessenbergDecomposition<MatrixType>& hess) : m_hess(hess) { } 348*bf2c3715SXin Li 349*bf2c3715SXin Li /** \brief Hessenberg matrix in decomposition. 350*bf2c3715SXin Li * 351*bf2c3715SXin Li * \param[out] result Hessenberg matrix in decomposition \p hess which 352*bf2c3715SXin Li * was passed to the constructor 353*bf2c3715SXin Li */ 354*bf2c3715SXin Li template <typename ResultType> 355*bf2c3715SXin Li inline void evalTo(ResultType& result) const 356*bf2c3715SXin Li { 357*bf2c3715SXin Li result = m_hess.packedMatrix(); 358*bf2c3715SXin Li Index n = result.rows(); 359*bf2c3715SXin Li if (n>2) 360*bf2c3715SXin Li result.bottomLeftCorner(n-2, n-2).template triangularView<Lower>().setZero(); 361*bf2c3715SXin Li } 362*bf2c3715SXin Li 363*bf2c3715SXin Li Index rows() const { return m_hess.packedMatrix().rows(); } 364*bf2c3715SXin Li Index cols() const { return m_hess.packedMatrix().cols(); } 365*bf2c3715SXin Li 366*bf2c3715SXin Li protected: 367*bf2c3715SXin Li const HessenbergDecomposition<MatrixType>& m_hess; 368*bf2c3715SXin Li }; 369*bf2c3715SXin Li 370*bf2c3715SXin Li } // end namespace internal 371*bf2c3715SXin Li 372*bf2c3715SXin Li } // end namespace Eigen 373*bf2c3715SXin Li 374*bf2c3715SXin Li #endif // EIGEN_HESSENBERGDECOMPOSITION_H 375