Back to home page

EIC code displayed by LXR

 
 

    


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