// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef EIGEN_HESSENBERGDECOMPOSITION_H
#define EIGEN_HESSENBERGDECOMPOSITION_H

namespace Eigen { 

namespace internal {
  
template<typename MatrixType> struct HessenbergDecompositionMatrixHReturnType;
template<typename MatrixType>
struct traits<HessenbergDecompositionMatrixHReturnType<MatrixType> >
{
  typedef MatrixType ReturnType;
};

}

/** \eigenvalues_module \ingroup Eigenvalues_Module
  *
  *
  * \class HessenbergDecomposition
  *
  * \brief Reduces a square matrix to Hessenberg form by an orthogonal similarity transformation
  *
  * \tparam _MatrixType the type of the matrix of which we are computing the Hessenberg decomposition
  *
  * This class performs an Hessenberg decomposition of a matrix \f$ A \f$. In
  * the real case, the Hessenberg decomposition consists of an orthogonal
  * matrix \f$ Q \f$ and a Hessenberg matrix \f$ H \f$ such that \f$ A = Q H
  * Q^T \f$. An orthogonal matrix is a matrix whose inverse equals its
  * transpose (\f$ Q^{-1} = Q^T \f$). A Hessenberg matrix has zeros below the
  * subdiagonal, so it is almost upper triangular. The Hessenberg decomposition
  * of a complex matrix is \f$ A = Q H Q^* \f$ with \f$ Q \f$ unitary (that is,
  * \f$ Q^{-1} = Q^* \f$).
  *
  * Call the function compute() to compute the Hessenberg decomposition of a
  * given matrix. Alternatively, you can use the
  * HessenbergDecomposition(const MatrixType&) constructor which computes the
  * Hessenberg decomposition at construction time. Once the decomposition is
  * computed, you can use the matrixH() and matrixQ() functions to construct
  * the matrices H and Q in the decomposition.
  *
  * The documentation for matrixH() contains an example of the typical use of
  * this class.
  *
  * \sa class ComplexSchur, class Tridiagonalization, \ref QR_Module "QR Module"
  */
template<typename _MatrixType> class HessenbergDecomposition
{
  public:

    /** \brief Synonym for the template parameter \p _MatrixType. */
    typedef _MatrixType MatrixType;

    enum {
      Size = MatrixType::RowsAtCompileTime,
      SizeMinusOne = Size == Dynamic ? Dynamic : Size - 1,
      Options = MatrixType::Options,
      MaxSize = MatrixType::MaxRowsAtCompileTime,
      MaxSizeMinusOne = MaxSize == Dynamic ? Dynamic : MaxSize - 1
    };

    /** \brief Scalar type for matrices of type #MatrixType. */
    typedef typename MatrixType::Scalar Scalar;
    typedef Eigen::Index Index; ///< \deprecated since Eigen 3.3

    /** \brief Type for vector of Householder coefficients.
      *
      * This is column vector with entries of type #Scalar. The length of the
      * vector is one less than the size of #MatrixType, if it is a fixed-side
      * type.
      */
    typedef Matrix<Scalar, SizeMinusOne, 1, Options & ~RowMajor, MaxSizeMinusOne, 1> CoeffVectorType;

    /** \brief Return type of matrixQ() */
    typedef HouseholderSequence<MatrixType,typename internal::remove_all<typename CoeffVectorType::ConjugateReturnType>::type> HouseholderSequenceType;
    
    typedef internal::HessenbergDecompositionMatrixHReturnType<MatrixType> MatrixHReturnType;

    /** \brief Default constructor; the decomposition will be computed later.
      *
      * \param [in] size  The size of the matrix whose Hessenberg decomposition will be computed.
      *
      * The default constructor is useful in cases in which the user intends to
      * perform decompositions via compute().  The \p size parameter is only
      * used as a hint. It is not an error to give a wrong \p size, but it may
      * impair performance.
      *
      * \sa compute() for an example.
      */
    explicit HessenbergDecomposition(Index size = Size==Dynamic ? 2 : Size)
      : m_matrix(size,size),
        m_temp(size),
        m_isInitialized(false)
    {
      if(size>1)
        m_hCoeffs.resize(size-1);
    }

    /** \brief Constructor; computes Hessenberg decomposition of given matrix.
      *
      * \param[in]  matrix  Square matrix whose Hessenberg decomposition is to be computed.
      *
      * This constructor calls compute() to compute the Hessenberg
      * decomposition.
      *
      * \sa matrixH() for an example.
      */
    template<typename InputType>
    explicit HessenbergDecomposition(const EigenBase<InputType>& matrix)
      : m_matrix(matrix.derived()),
        m_temp(matrix.rows()),
        m_isInitialized(false)
    {
      if(matrix.rows()<2)
      {
        m_isInitialized = true;
        return;
      }
      m_hCoeffs.resize(matrix.rows()-1,1);
      _compute(m_matrix, m_hCoeffs, m_temp);
      m_isInitialized = true;
    }

    /** \brief Computes Hessenberg decomposition of given matrix.
      *
      * \param[in]  matrix  Square matrix whose Hessenberg decomposition is to be computed.
      * \returns    Reference to \c *this
      *
      * The Hessenberg decomposition is computed by bringing the columns of the
      * matrix successively in the required form using Householder reflections
      * (see, e.g., Algorithm 7.4.2 in Golub \& Van Loan, <i>%Matrix
      * Computations</i>). The cost is \f$ 10n^3/3 \f$ flops, where \f$ n \f$
      * denotes the size of the given matrix.
      *
      * This method reuses of the allocated data in the HessenbergDecomposition
      * object.
      *
      * Example: \include HessenbergDecomposition_compute.cpp
      * Output: \verbinclude HessenbergDecomposition_compute.out
      */
    template<typename InputType>
    HessenbergDecomposition& compute(const EigenBase<InputType>& matrix)
    {
      m_matrix = matrix.derived();
      if(matrix.rows()<2)
      {
        m_isInitialized = true;
        return *this;
      }
      m_hCoeffs.resize(matrix.rows()-1,1);
      _compute(m_matrix, m_hCoeffs, m_temp);
      m_isInitialized = true;
      return *this;
    }

    /** \brief Returns the Householder coefficients.
      *
      * \returns a const reference to the vector of Householder coefficients
      *
      * \pre Either the constructor HessenbergDecomposition(const MatrixType&)
      * or the member function compute(const MatrixType&) has been called
      * before to compute the Hessenberg decomposition of a matrix.
      *
      * The Householder coefficients allow the reconstruction of the matrix
      * \f$ Q \f$ in the Hessenberg decomposition from the packed data.
      *
      * \sa packedMatrix(), \ref Householder_Module "Householder module"
      */
    const CoeffVectorType& householderCoefficients() const
    {
      eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized.");
      return m_hCoeffs;
    }

    /** \brief Returns the internal representation of the decomposition
      *
      *	\returns a const reference to a matrix with the internal representation
      *	         of the decomposition.
      *
      * \pre Either the constructor HessenbergDecomposition(const MatrixType&)
      * or the member function compute(const MatrixType&) has been called
      * before to compute the Hessenberg decomposition of a matrix.
      *
      * The returned matrix contains the following information:
      *  - the upper part and lower sub-diagonal represent the Hessenberg matrix H
      *  - the rest of the lower part contains the Householder vectors that, combined with
      *    Householder coefficients returned by householderCoefficients(),
      *    allows to reconstruct the matrix Q as
      *       \f$ Q = H_{N-1} \ldots H_1 H_0 \f$.
      *    Here, the matrices \f$ H_i \f$ are the Householder transformations
      *       \f$ H_i = (I - h_i v_i v_i^T) \f$
      *    where \f$ h_i \f$ is the \f$ i \f$th Householder coefficient and
      *    \f$ v_i \f$ is the Householder vector defined by
      *       \f$ v_i = [ 0, \ldots, 0, 1, M(i+2,i), \ldots, M(N-1,i) ]^T \f$
      *    with M the matrix returned by this function.
      *
      * See LAPACK for further details on this packed storage.
      *
      * Example: \include HessenbergDecomposition_packedMatrix.cpp
      * Output: \verbinclude HessenbergDecomposition_packedMatrix.out
      *
      * \sa householderCoefficients()
      */
    const MatrixType& packedMatrix() const
    {
      eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized.");
      return m_matrix;
    }

    /** \brief Reconstructs the orthogonal matrix Q in the decomposition
      *
      * \returns object representing the matrix Q
      *
      * \pre Either the constructor HessenbergDecomposition(const MatrixType&)
      * or the member function compute(const MatrixType&) has been called
      * before to compute the Hessenberg decomposition of a matrix.
      *
      * This function returns a light-weight object of template class
      * HouseholderSequence. You can either apply it directly to a matrix or
      * you can convert it to a matrix of type #MatrixType.
      *
      * \sa matrixH() for an example, class HouseholderSequence
      */
    HouseholderSequenceType matrixQ() const
    {
      eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized.");
      return HouseholderSequenceType(m_matrix, m_hCoeffs.conjugate())
             .setLength(m_matrix.rows() - 1)
             .setShift(1);
    }

    /** \brief Constructs the Hessenberg matrix H in the decomposition
      *
      * \returns expression object representing the matrix H
      *
      * \pre Either the constructor HessenbergDecomposition(const MatrixType&)
      * or the member function compute(const MatrixType&) has been called
      * before to compute the Hessenberg decomposition of a matrix.
      *
      * The object returned by this function constructs the Hessenberg matrix H
      * when it is assigned to a matrix or otherwise evaluated. The matrix H is
      * constructed from the packed matrix as returned by packedMatrix(): The
      * upper part (including the subdiagonal) of the packed matrix contains
      * the matrix H. It may sometimes be better to directly use the packed
      * matrix instead of constructing the matrix H.
      *
      * Example: \include HessenbergDecomposition_matrixH.cpp
      * Output: \verbinclude HessenbergDecomposition_matrixH.out
      *
      * \sa matrixQ(), packedMatrix()
      */
    MatrixHReturnType matrixH() const
    {
      eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized.");
      return MatrixHReturnType(*this);
    }

  private:

    typedef Matrix<Scalar, 1, Size, int(Options) | int(RowMajor), 1, MaxSize> VectorType;
    typedef typename NumTraits<Scalar>::Real RealScalar;
    static void _compute(MatrixType& matA, CoeffVectorType& hCoeffs, VectorType& temp);

  protected:
    MatrixType m_matrix;
    CoeffVectorType m_hCoeffs;
    VectorType m_temp;
    bool m_isInitialized;
};

/** \internal
  * Performs a tridiagonal decomposition of \a matA in place.
  *
  * \param matA the input selfadjoint matrix
  * \param hCoeffs returned Householder coefficients
  *
  * The result is written in the lower triangular part of \a matA.
  *
  * Implemented from Golub's "%Matrix Computations", algorithm 8.3.1.
  *
  * \sa packedMatrix()
  */
template<typename MatrixType>
void HessenbergDecomposition<MatrixType>::_compute(MatrixType& matA, CoeffVectorType& hCoeffs, VectorType& temp)
{
  eigen_assert(matA.rows()==matA.cols());
  Index n = matA.rows();
  temp.resize(n);
  for (Index i = 0; i<n-1; ++i)
  {
    // let's consider the vector v = i-th column starting at position i+1
    Index remainingSize = n-i-1;
    RealScalar beta;
    Scalar h;
    matA.col(i).tail(remainingSize).makeHouseholderInPlace(h, beta);
    matA.col(i).coeffRef(i+1) = beta;
    hCoeffs.coeffRef(i) = h;

    // Apply similarity transformation to remaining columns,
    // i.e., compute A = H A H'

    // A = H A
    matA.bottomRightCorner(remainingSize, remainingSize)
        .applyHouseholderOnTheLeft(matA.col(i).tail(remainingSize-1), h, &temp.coeffRef(0));

    // A = A H'
    matA.rightCols(remainingSize)
        .applyHouseholderOnTheRight(matA.col(i).tail(remainingSize-1), numext::conj(h), &temp.coeffRef(0));
  }
}

namespace internal {

/** \eigenvalues_module \ingroup Eigenvalues_Module
  *
  *
  * \brief Expression type for return value of HessenbergDecomposition::matrixH()
  *
  * \tparam MatrixType type of matrix in the Hessenberg decomposition
  *
  * Objects of this type represent the Hessenberg matrix in the Hessenberg
  * decomposition of some matrix. The object holds a reference to the
  * HessenbergDecomposition class until the it is assigned or evaluated for
  * some other reason (the reference should remain valid during the life time
  * of this object). This class is the return type of
  * HessenbergDecomposition::matrixH(); there is probably no other use for this
  * class.
  */
template<typename MatrixType> struct HessenbergDecompositionMatrixHReturnType
: public ReturnByValue<HessenbergDecompositionMatrixHReturnType<MatrixType> >
{
  public:
    /** \brief Constructor.
      *
      * \param[in] hess  Hessenberg decomposition
      */
    HessenbergDecompositionMatrixHReturnType(const HessenbergDecomposition<MatrixType>& hess) : m_hess(hess) { }

    /** \brief Hessenberg matrix in decomposition.
      *
      * \param[out] result  Hessenberg matrix in decomposition \p hess which
      *                     was passed to the constructor
      */
    template <typename ResultType>
    inline void evalTo(ResultType& result) const
    {
      result = m_hess.packedMatrix();
      Index n = result.rows();
      if (n>2)
        result.bottomLeftCorner(n-2, n-2).template triangularView<Lower>().setZero();
    }

    Index rows() const { return m_hess.packedMatrix().rows(); }
    Index cols() const { return m_hess.packedMatrix().cols(); }

  protected:
    const HessenbergDecomposition<MatrixType>& m_hess;
};

} // end namespace internal

} // end namespace Eigen

#endif // EIGEN_HESSENBERGDECOMPOSITION_H
