|
|
|||
File indexing completed on 2025-12-13 10:25:41
0001 // This file is part of Eigen, a lightweight C++ template library 0002 // for linear algebra. 0003 // 0004 // Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr> 0005 // Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk> 0006 // 0007 // This Source Code Form is subject to the terms of the Mozilla 0008 // Public License v. 2.0. If a copy of the MPL was not distributed 0009 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 0010 0011 #ifndef EIGEN_HESSENBERGDECOMPOSITION_H 0012 #define EIGEN_HESSENBERGDECOMPOSITION_H 0013 0014 namespace RivetEigen { 0015 0016 namespace internal { 0017 0018 template<typename MatrixType> struct HessenbergDecompositionMatrixHReturnType; 0019 template<typename MatrixType> 0020 struct traits<HessenbergDecompositionMatrixHReturnType<MatrixType> > 0021 { 0022 typedef MatrixType ReturnType; 0023 }; 0024 0025 } 0026 0027 /** \eigenvalues_module \ingroup Eigenvalues_Module 0028 * 0029 * 0030 * \class HessenbergDecomposition 0031 * 0032 * \brief Reduces a square matrix to Hessenberg form by an orthogonal similarity transformation 0033 * 0034 * \tparam _MatrixType the type of the matrix of which we are computing the Hessenberg decomposition 0035 * 0036 * This class performs an Hessenberg decomposition of a matrix \f$ A \f$. In 0037 * the real case, the Hessenberg decomposition consists of an orthogonal 0038 * matrix \f$ Q \f$ and a Hessenberg matrix \f$ H \f$ such that \f$ A = Q H 0039 * Q^T \f$. An orthogonal matrix is a matrix whose inverse equals its 0040 * transpose (\f$ Q^{-1} = Q^T \f$). A Hessenberg matrix has zeros below the 0041 * subdiagonal, so it is almost upper triangular. The Hessenberg decomposition 0042 * of a complex matrix is \f$ A = Q H Q^* \f$ with \f$ Q \f$ unitary (that is, 0043 * \f$ Q^{-1} = Q^* \f$). 0044 * 0045 * Call the function compute() to compute the Hessenberg decomposition of a 0046 * given matrix. Alternatively, you can use the 0047 * HessenbergDecomposition(const MatrixType&) constructor which computes the 0048 * Hessenberg decomposition at construction time. Once the decomposition is 0049 * computed, you can use the matrixH() and matrixQ() functions to construct 0050 * the matrices H and Q in the decomposition. 0051 * 0052 * The documentation for matrixH() contains an example of the typical use of 0053 * this class. 0054 * 0055 * \sa class ComplexSchur, class Tridiagonalization, \ref QR_Module "QR Module" 0056 */ 0057 template<typename _MatrixType> class HessenbergDecomposition 0058 { 0059 public: 0060 0061 /** \brief Synonym for the template parameter \p _MatrixType. */ 0062 typedef _MatrixType MatrixType; 0063 0064 enum { 0065 Size = MatrixType::RowsAtCompileTime, 0066 SizeMinusOne = Size == Dynamic ? Dynamic : Size - 1, 0067 Options = MatrixType::Options, 0068 MaxSize = MatrixType::MaxRowsAtCompileTime, 0069 MaxSizeMinusOne = MaxSize == Dynamic ? Dynamic : MaxSize - 1 0070 }; 0071 0072 /** \brief Scalar type for matrices of type #MatrixType. */ 0073 typedef typename MatrixType::Scalar Scalar; 0074 typedef RivetEigen::Index Index; ///< \deprecated since Eigen 3.3 0075 0076 /** \brief Type for vector of Householder coefficients. 0077 * 0078 * This is column vector with entries of type #Scalar. The length of the 0079 * vector is one less than the size of #MatrixType, if it is a fixed-side 0080 * type. 0081 */ 0082 typedef Matrix<Scalar, SizeMinusOne, 1, Options & ~RowMajor, MaxSizeMinusOne, 1> CoeffVectorType; 0083 0084 /** \brief Return type of matrixQ() */ 0085 typedef HouseholderSequence<MatrixType,typename internal::remove_all<typename CoeffVectorType::ConjugateReturnType>::type> HouseholderSequenceType; 0086 0087 typedef internal::HessenbergDecompositionMatrixHReturnType<MatrixType> MatrixHReturnType; 0088 0089 /** \brief Default constructor; the decomposition will be computed later. 0090 * 0091 * \param [in] size The size of the matrix whose Hessenberg decomposition will be computed. 0092 * 0093 * The default constructor is useful in cases in which the user intends to 0094 * perform decompositions via compute(). The \p size parameter is only 0095 * used as a hint. It is not an error to give a wrong \p size, but it may 0096 * impair performance. 0097 * 0098 * \sa compute() for an example. 0099 */ 0100 explicit HessenbergDecomposition(Index size = Size==Dynamic ? 2 : Size) 0101 : m_matrix(size,size), 0102 m_temp(size), 0103 m_isInitialized(false) 0104 { 0105 if(size>1) 0106 m_hCoeffs.resize(size-1); 0107 } 0108 0109 /** \brief Constructor; computes Hessenberg decomposition of given matrix. 0110 * 0111 * \param[in] matrix Square matrix whose Hessenberg decomposition is to be computed. 0112 * 0113 * This constructor calls compute() to compute the Hessenberg 0114 * decomposition. 0115 * 0116 * \sa matrixH() for an example. 0117 */ 0118 template<typename InputType> 0119 explicit HessenbergDecomposition(const EigenBase<InputType>& matrix) 0120 : m_matrix(matrix.derived()), 0121 m_temp(matrix.rows()), 0122 m_isInitialized(false) 0123 { 0124 if(matrix.rows()<2) 0125 { 0126 m_isInitialized = true; 0127 return; 0128 } 0129 m_hCoeffs.resize(matrix.rows()-1,1); 0130 _compute(m_matrix, m_hCoeffs, m_temp); 0131 m_isInitialized = true; 0132 } 0133 0134 /** \brief Computes Hessenberg decomposition of given matrix. 0135 * 0136 * \param[in] matrix Square matrix whose Hessenberg decomposition is to be computed. 0137 * \returns Reference to \c *this 0138 * 0139 * The Hessenberg decomposition is computed by bringing the columns of the 0140 * matrix successively in the required form using Householder reflections 0141 * (see, e.g., Algorithm 7.4.2 in Golub \& Van Loan, <i>%Matrix 0142 * Computations</i>). The cost is \f$ 10n^3/3 \f$ flops, where \f$ n \f$ 0143 * denotes the size of the given matrix. 0144 * 0145 * This method reuses of the allocated data in the HessenbergDecomposition 0146 * object. 0147 * 0148 * Example: \include HessenbergDecomposition_compute.cpp 0149 * Output: \verbinclude HessenbergDecomposition_compute.out 0150 */ 0151 template<typename InputType> 0152 HessenbergDecomposition& compute(const EigenBase<InputType>& matrix) 0153 { 0154 m_matrix = matrix.derived(); 0155 if(matrix.rows()<2) 0156 { 0157 m_isInitialized = true; 0158 return *this; 0159 } 0160 m_hCoeffs.resize(matrix.rows()-1,1); 0161 _compute(m_matrix, m_hCoeffs, m_temp); 0162 m_isInitialized = true; 0163 return *this; 0164 } 0165 0166 /** \brief Returns the Householder coefficients. 0167 * 0168 * \returns a const reference to the vector of Householder coefficients 0169 * 0170 * \pre Either the constructor HessenbergDecomposition(const MatrixType&) 0171 * or the member function compute(const MatrixType&) has been called 0172 * before to compute the Hessenberg decomposition of a matrix. 0173 * 0174 * The Householder coefficients allow the reconstruction of the matrix 0175 * \f$ Q \f$ in the Hessenberg decomposition from the packed data. 0176 * 0177 * \sa packedMatrix(), \ref Householder_Module "Householder module" 0178 */ 0179 const CoeffVectorType& householderCoefficients() const 0180 { 0181 eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized."); 0182 return m_hCoeffs; 0183 } 0184 0185 /** \brief Returns the internal representation of the decomposition 0186 * 0187 * \returns a const reference to a matrix with the internal representation 0188 * of the decomposition. 0189 * 0190 * \pre Either the constructor HessenbergDecomposition(const MatrixType&) 0191 * or the member function compute(const MatrixType&) has been called 0192 * before to compute the Hessenberg decomposition of a matrix. 0193 * 0194 * The returned matrix contains the following information: 0195 * - the upper part and lower sub-diagonal represent the Hessenberg matrix H 0196 * - the rest of the lower part contains the Householder vectors that, combined with 0197 * Householder coefficients returned by householderCoefficients(), 0198 * allows to reconstruct the matrix Q as 0199 * \f$ Q = H_{N-1} \ldots H_1 H_0 \f$. 0200 * Here, the matrices \f$ H_i \f$ are the Householder transformations 0201 * \f$ H_i = (I - h_i v_i v_i^T) \f$ 0202 * where \f$ h_i \f$ is the \f$ i \f$th Householder coefficient and 0203 * \f$ v_i \f$ is the Householder vector defined by 0204 * \f$ v_i = [ 0, \ldots, 0, 1, M(i+2,i), \ldots, M(N-1,i) ]^T \f$ 0205 * with M the matrix returned by this function. 0206 * 0207 * See LAPACK for further details on this packed storage. 0208 * 0209 * Example: \include HessenbergDecomposition_packedMatrix.cpp 0210 * Output: \verbinclude HessenbergDecomposition_packedMatrix.out 0211 * 0212 * \sa householderCoefficients() 0213 */ 0214 const MatrixType& packedMatrix() const 0215 { 0216 eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized."); 0217 return m_matrix; 0218 } 0219 0220 /** \brief Reconstructs the orthogonal matrix Q in the decomposition 0221 * 0222 * \returns object representing the matrix Q 0223 * 0224 * \pre Either the constructor HessenbergDecomposition(const MatrixType&) 0225 * or the member function compute(const MatrixType&) has been called 0226 * before to compute the Hessenberg decomposition of a matrix. 0227 * 0228 * This function returns a light-weight object of template class 0229 * HouseholderSequence. You can either apply it directly to a matrix or 0230 * you can convert it to a matrix of type #MatrixType. 0231 * 0232 * \sa matrixH() for an example, class HouseholderSequence 0233 */ 0234 HouseholderSequenceType matrixQ() const 0235 { 0236 eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized."); 0237 return HouseholderSequenceType(m_matrix, m_hCoeffs.conjugate()) 0238 .setLength(m_matrix.rows() - 1) 0239 .setShift(1); 0240 } 0241 0242 /** \brief Constructs the Hessenberg matrix H in the decomposition 0243 * 0244 * \returns expression object representing the matrix H 0245 * 0246 * \pre Either the constructor HessenbergDecomposition(const MatrixType&) 0247 * or the member function compute(const MatrixType&) has been called 0248 * before to compute the Hessenberg decomposition of a matrix. 0249 * 0250 * The object returned by this function constructs the Hessenberg matrix H 0251 * when it is assigned to a matrix or otherwise evaluated. The matrix H is 0252 * constructed from the packed matrix as returned by packedMatrix(): The 0253 * upper part (including the subdiagonal) of the packed matrix contains 0254 * the matrix H. It may sometimes be better to directly use the packed 0255 * matrix instead of constructing the matrix H. 0256 * 0257 * Example: \include HessenbergDecomposition_matrixH.cpp 0258 * Output: \verbinclude HessenbergDecomposition_matrixH.out 0259 * 0260 * \sa matrixQ(), packedMatrix() 0261 */ 0262 MatrixHReturnType matrixH() const 0263 { 0264 eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized."); 0265 return MatrixHReturnType(*this); 0266 } 0267 0268 private: 0269 0270 typedef Matrix<Scalar, 1, Size, int(Options) | int(RowMajor), 1, MaxSize> VectorType; 0271 typedef typename NumTraits<Scalar>::Real RealScalar; 0272 static void _compute(MatrixType& matA, CoeffVectorType& hCoeffs, VectorType& temp); 0273 0274 protected: 0275 MatrixType m_matrix; 0276 CoeffVectorType m_hCoeffs; 0277 VectorType m_temp; 0278 bool m_isInitialized; 0279 }; 0280 0281 /** \internal 0282 * Performs a tridiagonal decomposition of \a matA in place. 0283 * 0284 * \param matA the input selfadjoint matrix 0285 * \param hCoeffs returned Householder coefficients 0286 * 0287 * The result is written in the lower triangular part of \a matA. 0288 * 0289 * Implemented from Golub's "%Matrix Computations", algorithm 8.3.1. 0290 * 0291 * \sa packedMatrix() 0292 */ 0293 template<typename MatrixType> 0294 void HessenbergDecomposition<MatrixType>::_compute(MatrixType& matA, CoeffVectorType& hCoeffs, VectorType& temp) 0295 { 0296 eigen_assert(matA.rows()==matA.cols()); 0297 Index n = matA.rows(); 0298 temp.resize(n); 0299 for (Index i = 0; i<n-1; ++i) 0300 { 0301 // let's consider the vector v = i-th column starting at position i+1 0302 Index remainingSize = n-i-1; 0303 RealScalar beta; 0304 Scalar h; 0305 matA.col(i).tail(remainingSize).makeHouseholderInPlace(h, beta); 0306 matA.col(i).coeffRef(i+1) = beta; 0307 hCoeffs.coeffRef(i) = h; 0308 0309 // Apply similarity transformation to remaining columns, 0310 // i.e., compute A = H A H' 0311 0312 // A = H A 0313 matA.bottomRightCorner(remainingSize, remainingSize) 0314 .applyHouseholderOnTheLeft(matA.col(i).tail(remainingSize-1), h, &temp.coeffRef(0)); 0315 0316 // A = A H' 0317 matA.rightCols(remainingSize) 0318 .applyHouseholderOnTheRight(matA.col(i).tail(remainingSize-1), numext::conj(h), &temp.coeffRef(0)); 0319 } 0320 } 0321 0322 namespace internal { 0323 0324 /** \eigenvalues_module \ingroup Eigenvalues_Module 0325 * 0326 * 0327 * \brief Expression type for return value of HessenbergDecomposition::matrixH() 0328 * 0329 * \tparam MatrixType type of matrix in the Hessenberg decomposition 0330 * 0331 * Objects of this type represent the Hessenberg matrix in the Hessenberg 0332 * decomposition of some matrix. The object holds a reference to the 0333 * HessenbergDecomposition class until the it is assigned or evaluated for 0334 * some other reason (the reference should remain valid during the life time 0335 * of this object). This class is the return type of 0336 * HessenbergDecomposition::matrixH(); there is probably no other use for this 0337 * class. 0338 */ 0339 template<typename MatrixType> struct HessenbergDecompositionMatrixHReturnType 0340 : public ReturnByValue<HessenbergDecompositionMatrixHReturnType<MatrixType> > 0341 { 0342 public: 0343 /** \brief Constructor. 0344 * 0345 * \param[in] hess Hessenberg decomposition 0346 */ 0347 HessenbergDecompositionMatrixHReturnType(const HessenbergDecomposition<MatrixType>& hess) : m_hess(hess) { } 0348 0349 /** \brief Hessenberg matrix in decomposition. 0350 * 0351 * \param[out] result Hessenberg matrix in decomposition \p hess which 0352 * was passed to the constructor 0353 */ 0354 template <typename ResultType> 0355 inline void evalTo(ResultType& result) const 0356 { 0357 result = m_hess.packedMatrix(); 0358 Index n = result.rows(); 0359 if (n>2) 0360 result.bottomLeftCorner(n-2, n-2).template triangularView<Lower>().setZero(); 0361 } 0362 0363 Index rows() const { return m_hess.packedMatrix().rows(); } 0364 Index cols() const { return m_hess.packedMatrix().cols(); } 0365 0366 protected: 0367 const HessenbergDecomposition<MatrixType>& m_hess; 0368 }; 0369 0370 } // end namespace internal 0371 0372 } // end namespace RivetEigen 0373 0374 #endif // EIGEN_HESSENBERGDECOMPOSITION_H
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|