// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2016 Rasmus Munk Larsen <rmlarsen@google.com>
//
// 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_COMPLETEORTHOGONALDECOMPOSITION_H
#define EIGEN_COMPLETEORTHOGONALDECOMPOSITION_H

#include "./InternalHeaderCheck.h"

namespace Eigen {

namespace internal {
template <typename MatrixType_>
struct traits<CompleteOrthogonalDecomposition<MatrixType_> >
    : traits<MatrixType_> {
  typedef MatrixXpr XprKind;
  typedef SolverStorage StorageKind;
  typedef int StorageIndex;
  enum { Flags = 0 };
};

}  // end namespace internal

/** \ingroup QR_Module
  *
  * \class CompleteOrthogonalDecomposition
  *
  * \brief Complete orthogonal decomposition (COD) of a matrix.
  *
  * \tparam MatrixType_ the type of the matrix of which we are computing the COD.
  *
  * This class performs a rank-revealing complete orthogonal decomposition of a
  * matrix  \b A into matrices \b P, \b Q, \b T, and \b Z such that
  * \f[
  *  \mathbf{A} \, \mathbf{P} = \mathbf{Q} \,
  *                     \begin{bmatrix} \mathbf{T} &  \mathbf{0} \\
  *                                     \mathbf{0} & \mathbf{0} \end{bmatrix} \, \mathbf{Z}
  * \f]
  * by using Householder transformations. Here, \b P is a permutation matrix,
  * \b Q and \b Z are unitary matrices and \b T an upper triangular matrix of
  * size rank-by-rank. \b A may be rank deficient.
  *
  * This class supports the \link InplaceDecomposition inplace decomposition \endlink mechanism.
  * 
  * \sa MatrixBase::completeOrthogonalDecomposition()
  */
template <typename MatrixType_> class CompleteOrthogonalDecomposition
          : public SolverBase<CompleteOrthogonalDecomposition<MatrixType_> >
{
 public:
  typedef MatrixType_ MatrixType;
  typedef SolverBase<CompleteOrthogonalDecomposition> Base;

  template<typename Derived>
  friend struct internal::solve_assertion;

  EIGEN_GENERIC_PUBLIC_INTERFACE(CompleteOrthogonalDecomposition)
  enum {
    MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
    MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
  };
  typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType;
  typedef PermutationMatrix<ColsAtCompileTime, MaxColsAtCompileTime>
      PermutationType;
  typedef typename internal::plain_row_type<MatrixType, Index>::type
      IntRowVectorType;
  typedef typename internal::plain_row_type<MatrixType>::type RowVectorType;
  typedef typename internal::plain_row_type<MatrixType, RealScalar>::type
      RealRowVectorType;
  typedef HouseholderSequence<
      MatrixType, internal::remove_all_t<
                      typename HCoeffsType::ConjugateReturnType>>
      HouseholderSequenceType;
  typedef typename MatrixType::PlainObject PlainObject;

 private:
  typedef typename PermutationType::Index PermIndexType;

 public:
  /**
   * \brief Default Constructor.
   *
   * The default constructor is useful in cases in which the user intends to
   * perform decompositions via
   * \c CompleteOrthogonalDecomposition::compute(const* MatrixType&).
   */
  CompleteOrthogonalDecomposition() : m_cpqr(), m_zCoeffs(), m_temp() {}

  /** \brief Default Constructor with memory preallocation
   *
   * Like the default constructor but with preallocation of the internal data
   * according to the specified problem \a size.
   * \sa CompleteOrthogonalDecomposition()
   */
  CompleteOrthogonalDecomposition(Index rows, Index cols)
      : m_cpqr(rows, cols), m_zCoeffs((std::min)(rows, cols)), m_temp(cols) {}

  /** \brief Constructs a complete orthogonal decomposition from a given
   * matrix.
   *
   * This constructor computes the complete orthogonal decomposition of the
   * matrix \a matrix by calling the method compute(). The default
   * threshold for rank determination will be used. It is a short cut for:
   *
   * \code
   * CompleteOrthogonalDecomposition<MatrixType> cod(matrix.rows(),
   *                                                 matrix.cols());
   * cod.setThreshold(Default);
   * cod.compute(matrix);
   * \endcode
   *
   * \sa compute()
   */
  template <typename InputType>
  explicit CompleteOrthogonalDecomposition(const EigenBase<InputType>& matrix)
      : m_cpqr(matrix.rows(), matrix.cols()),
        m_zCoeffs((std::min)(matrix.rows(), matrix.cols())),
        m_temp(matrix.cols())
  {
    compute(matrix.derived());
  }

  /** \brief Constructs a complete orthogonal decomposition from a given matrix
    *
    * This overloaded constructor is provided for \link InplaceDecomposition inplace decomposition \endlink when \c MatrixType is a Eigen::Ref.
    *
    * \sa CompleteOrthogonalDecomposition(const EigenBase&)
    */
  template<typename InputType>
  explicit CompleteOrthogonalDecomposition(EigenBase<InputType>& matrix)
    : m_cpqr(matrix.derived()),
      m_zCoeffs((std::min)(matrix.rows(), matrix.cols())),
      m_temp(matrix.cols())
  {
    computeInPlace();
  } 

  #ifdef EIGEN_PARSED_BY_DOXYGEN
  /** This method computes the minimum-norm solution X to a least squares
   * problem \f[\mathrm{minimize} \|A X - B\|, \f] where \b A is the matrix of
   * which \c *this is the complete orthogonal decomposition.
   *
   * \param b the right-hand sides of the problem to solve.
   *
   * \returns a solution.
   *
   */
  template <typename Rhs>
  inline const Solve<CompleteOrthogonalDecomposition, Rhs> solve(
      const MatrixBase<Rhs>& b) const;
  #endif

  HouseholderSequenceType householderQ(void) const;
  HouseholderSequenceType matrixQ(void) const { return m_cpqr.householderQ(); }

  /** \returns the matrix \b Z.
   */
  MatrixType matrixZ() const {
    MatrixType Z = MatrixType::Identity(m_cpqr.cols(), m_cpqr.cols());
    applyZOnTheLeftInPlace<false>(Z);
    return Z;
  }

  /** \returns a reference to the matrix where the complete orthogonal
   * decomposition is stored
   */
  const MatrixType& matrixQTZ() const { return m_cpqr.matrixQR(); }

  /** \returns a reference to the matrix where the complete orthogonal
   * decomposition is stored.
   * \warning The strict lower part and \code cols() - rank() \endcode right
   * columns of this matrix contains internal values.
   * Only the upper triangular part should be referenced. To get it, use
   * \code matrixT().template triangularView<Upper>() \endcode
   * For rank-deficient matrices, use
   * \code
   * matrixT().topLeftCorner(rank(), rank()).template triangularView<Upper>()
   * \endcode
   */
  const MatrixType& matrixT() const { return m_cpqr.matrixQR(); }

  template <typename InputType>
  CompleteOrthogonalDecomposition& compute(const EigenBase<InputType>& matrix) {
    // Compute the column pivoted QR factorization A P = Q R.
    m_cpqr.compute(matrix);
    computeInPlace();
    return *this;
  }

  /** \returns a const reference to the column permutation matrix */
  const PermutationType& colsPermutation() const {
    return m_cpqr.colsPermutation();
  }

    /** \returns the determinant of the matrix of which
   * *this is the complete orthogonal decomposition. It has only linear
   * complexity (that is, O(n) where n is the dimension of the square matrix)
   * as the complete orthogonal decomposition has already been computed.
   *
   * \note This is only for square matrices.
   *
   * \warning a determinant can be very big or small, so for matrices
   * of large enough dimension, there is a risk of overflow/underflow.
   * One way to work around that is to use logAbsDeterminant() instead.
   *
   * \sa absDeterminant(), logAbsDeterminant(), MatrixBase::determinant()
   */
  typename MatrixType::Scalar determinant() const;

  /** \returns the absolute value of the determinant of the matrix of which
   * *this is the complete orthogonal decomposition. It has only linear
   * complexity (that is, O(n) where n is the dimension of the square matrix)
   * as the complete orthogonal decomposition has already been computed.
   *
   * \note This is only for square matrices.
   *
   * \warning a determinant can be very big or small, so for matrices
   * of large enough dimension, there is a risk of overflow/underflow.
   * One way to work around that is to use logAbsDeterminant() instead.
   *
   * \sa determinant(), logAbsDeterminant(), MatrixBase::determinant()
   */
  typename MatrixType::RealScalar absDeterminant() const;

  /** \returns the natural log of the absolute value of the determinant of the
   * matrix of which *this is the complete orthogonal decomposition. It has
   * only linear complexity (that is, O(n) where n is the dimension of the
   * square matrix) as the complete orthogonal decomposition has already been
   * computed.
   *
   * \note This is only for square matrices.
   *
   * \note This method is useful to work around the risk of overflow/underflow
   * that's inherent to determinant computation.
   *
   * \sa determinant(), absDeterminant(), MatrixBase::determinant()
   */
  typename MatrixType::RealScalar logAbsDeterminant() const;

  /** \returns the rank of the matrix of which *this is the complete orthogonal
   * decomposition.
   *
   * \note This method has to determine which pivots should be considered
   * nonzero. For that, it uses the threshold value that you can control by
   * calling setThreshold(const RealScalar&).
   */
  inline Index rank() const { return m_cpqr.rank(); }

  /** \returns the dimension of the kernel of the matrix of which *this is the
   * complete orthogonal decomposition.
   *
   * \note This method has to determine which pivots should be considered
   * nonzero. For that, it uses the threshold value that you can control by
   * calling setThreshold(const RealScalar&).
   */
  inline Index dimensionOfKernel() const { return m_cpqr.dimensionOfKernel(); }

  /** \returns true if the matrix of which *this is the decomposition represents
   * an injective linear map, i.e. has trivial kernel; false otherwise.
   *
   * \note This method has to determine which pivots should be considered
   * nonzero. For that, it uses the threshold value that you can control by
   * calling setThreshold(const RealScalar&).
   */
  inline bool isInjective() const { return m_cpqr.isInjective(); }

  /** \returns true if the matrix of which *this is the decomposition represents
   * a surjective linear map; false otherwise.
   *
   * \note This method has to determine which pivots should be considered
   * nonzero. For that, it uses the threshold value that you can control by
   * calling setThreshold(const RealScalar&).
   */
  inline bool isSurjective() const { return m_cpqr.isSurjective(); }

  /** \returns true if the matrix of which *this is the complete orthogonal
   * decomposition is invertible.
   *
   * \note This method has to determine which pivots should be considered
   * nonzero. For that, it uses the threshold value that you can control by
   * calling setThreshold(const RealScalar&).
   */
  inline bool isInvertible() const { return m_cpqr.isInvertible(); }

  /** \returns the pseudo-inverse of the matrix of which *this is the complete
   * orthogonal decomposition.
   * \warning: Do not compute \c this->pseudoInverse()*rhs to solve a linear systems.
   * It is more efficient and numerically stable to call \c this->solve(rhs).
   */
  inline const Inverse<CompleteOrthogonalDecomposition> pseudoInverse() const
  {
    eigen_assert(m_cpqr.m_isInitialized && "CompleteOrthogonalDecomposition is not initialized.");
    return Inverse<CompleteOrthogonalDecomposition>(*this);
  }

  inline Index rows() const { return m_cpqr.rows(); }
  inline Index cols() const { return m_cpqr.cols(); }

  /** \returns a const reference to the vector of Householder coefficients used
   * to represent the factor \c Q.
   *
   * For advanced uses only.
   */
  inline const HCoeffsType& hCoeffs() const { return m_cpqr.hCoeffs(); }

  /** \returns a const reference to the vector of Householder coefficients
   * used to represent the factor \c Z.
   *
   * For advanced uses only.
   */
  const HCoeffsType& zCoeffs() const { return m_zCoeffs; }

  /** Allows to prescribe a threshold to be used by certain methods, such as
   * rank(), who need to determine when pivots are to be considered nonzero.
   * Most be called before calling compute().
   *
   * When it needs to get the threshold value, Eigen calls threshold(). By
   * default, this uses a formula to automatically determine a reasonable
   * threshold. Once you have called the present method
   * setThreshold(const RealScalar&), your value is used instead.
   *
   * \param threshold The new value to use as the threshold.
   *
   * A pivot will be considered nonzero if its absolute value is strictly
   * greater than
   *  \f$ \vert pivot \vert \leqslant threshold \times \vert maxpivot \vert \f$
   * where maxpivot is the biggest pivot.
   *
   * If you want to come back to the default behavior, call
   * setThreshold(Default_t)
   */
  CompleteOrthogonalDecomposition& setThreshold(const RealScalar& threshold) {
    m_cpqr.setThreshold(threshold);
    return *this;
  }

  /** Allows to come back to the default behavior, letting Eigen use its default
   * formula for determining the threshold.
   *
   * You should pass the special object Eigen::Default as parameter here.
   * \code qr.setThreshold(Eigen::Default); \endcode
   *
   * See the documentation of setThreshold(const RealScalar&).
   */
  CompleteOrthogonalDecomposition& setThreshold(Default_t) {
    m_cpqr.setThreshold(Default);
    return *this;
  }

  /** Returns the threshold that will be used by certain methods such as rank().
   *
   * See the documentation of setThreshold(const RealScalar&).
   */
  RealScalar threshold() const { return m_cpqr.threshold(); }

  /** \returns the number of nonzero pivots in the complete orthogonal
   * decomposition. Here nonzero is meant in the exact sense, not in a
   * fuzzy sense. So that notion isn't really intrinsically interesting,
   * but it is still useful when implementing algorithms.
   *
   * \sa rank()
   */
  inline Index nonzeroPivots() const { return m_cpqr.nonzeroPivots(); }

  /** \returns the absolute value of the biggest pivot, i.e. the biggest
   *          diagonal coefficient of R.
   */
  inline RealScalar maxPivot() const { return m_cpqr.maxPivot(); }

  /** \brief Reports whether the complete orthogonal decomposition was
   * successful.
   *
   * \note This function always returns \c Success. It is provided for
   * compatibility
   * with other factorization routines.
   * \returns \c Success
   */
  ComputationInfo info() const {
    eigen_assert(m_cpqr.m_isInitialized && "Decomposition is not initialized.");
    return Success;
  }

#ifndef EIGEN_PARSED_BY_DOXYGEN
  template <typename RhsType, typename DstType>
  void _solve_impl(const RhsType& rhs, DstType& dst) const;

  template<bool Conjugate, typename RhsType, typename DstType>
  void _solve_impl_transposed(const RhsType &rhs, DstType &dst) const;
#endif

 protected:
  EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)

  template<bool Transpose_, typename Rhs>
  void _check_solve_assertion(const Rhs& b) const {
      EIGEN_ONLY_USED_FOR_DEBUG(b);
      eigen_assert(m_cpqr.m_isInitialized && "CompleteOrthogonalDecomposition is not initialized.");
      eigen_assert((Transpose_?derived().cols():derived().rows())==b.rows() && "CompleteOrthogonalDecomposition::solve(): invalid number of rows of the right hand side matrix b");
  }

  void computeInPlace();

  /** Overwrites \b rhs with \f$ \mathbf{Z} * \mathbf{rhs} \f$ or
   *  \f$ \mathbf{\overline Z} * \mathbf{rhs} \f$ if \c Conjugate 
   *  is set to \c true.
   */
  template <bool Conjugate, typename Rhs>
  void applyZOnTheLeftInPlace(Rhs& rhs) const;

  /** Overwrites \b rhs with \f$ \mathbf{Z}^* * \mathbf{rhs} \f$.
   */
  template <typename Rhs>
  void applyZAdjointOnTheLeftInPlace(Rhs& rhs) const;

  ColPivHouseholderQR<MatrixType> m_cpqr;
  HCoeffsType m_zCoeffs;
  RowVectorType m_temp;
};

template <typename MatrixType>
typename MatrixType::Scalar
CompleteOrthogonalDecomposition<MatrixType>::determinant() const {
  return m_cpqr.determinant();
}

template <typename MatrixType>
typename MatrixType::RealScalar
CompleteOrthogonalDecomposition<MatrixType>::absDeterminant() const {
  return m_cpqr.absDeterminant();
}

template <typename MatrixType>
typename MatrixType::RealScalar
CompleteOrthogonalDecomposition<MatrixType>::logAbsDeterminant() const {
  return m_cpqr.logAbsDeterminant();
}

/** Performs the complete orthogonal decomposition of the given matrix \a
 * matrix. The result of the factorization is stored into \c *this, and a
 * reference to \c *this is returned.
 *
 * \sa class CompleteOrthogonalDecomposition,
 * CompleteOrthogonalDecomposition(const MatrixType&)
 */
template <typename MatrixType>
void CompleteOrthogonalDecomposition<MatrixType>::computeInPlace()
{
  // the column permutation is stored as int indices, so just to be sure:
  eigen_assert(m_cpqr.cols() <= NumTraits<int>::highest());

  const Index rank = m_cpqr.rank();
  const Index cols = m_cpqr.cols();
  const Index rows = m_cpqr.rows();
  m_zCoeffs.resize((std::min)(rows, cols));
  m_temp.resize(cols);

  if (rank < cols) {
    // We have reduced the (permuted) matrix to the form
    //   [R11 R12]
    //   [ 0  R22]
    // where R11 is r-by-r (r = rank) upper triangular, R12 is
    // r-by-(n-r), and R22 is empty or the norm of R22 is negligible.
    // We now compute the complete orthogonal decomposition by applying
    // Householder transformations from the right to the upper trapezoidal
    // matrix X = [R11 R12] to zero out R12 and obtain the factorization
    // [R11 R12] = [T11 0] * Z, where T11 is r-by-r upper triangular and
    // Z = Z(0) * Z(1) ... Z(r-1) is an n-by-n orthogonal matrix.
    // We store the data representing Z in R12 and m_zCoeffs.
    for (Index k = rank - 1; k >= 0; --k) {
      if (k != rank - 1) {
        // Given the API for Householder reflectors, it is more convenient if
        // we swap the leading parts of columns k and r-1 (zero-based) to form
        // the matrix X_k = [X(0:k, k), X(0:k, r:n)]
        m_cpqr.m_qr.col(k).head(k + 1).swap(
            m_cpqr.m_qr.col(rank - 1).head(k + 1));
      }
      // Construct Householder reflector Z(k) to zero out the last row of X_k,
      // i.e. choose Z(k) such that
      // [X(k, k), X(k, r:n)] * Z(k) = [beta, 0, .., 0].
      RealScalar beta;
      m_cpqr.m_qr.row(k)
          .tail(cols - rank + 1)
          .makeHouseholderInPlace(m_zCoeffs(k), beta);
      m_cpqr.m_qr(k, rank - 1) = beta;
      if (k > 0) {
        // Apply Z(k) to the first k rows of X_k
        m_cpqr.m_qr.topRightCorner(k, cols - rank + 1)
            .applyHouseholderOnTheRight(
                m_cpqr.m_qr.row(k).tail(cols - rank).adjoint(), m_zCoeffs(k),
                &m_temp(0));
      }
      if (k != rank - 1) {
        // Swap X(0:k,k) back to its proper location.
        m_cpqr.m_qr.col(k).head(k + 1).swap(
            m_cpqr.m_qr.col(rank - 1).head(k + 1));
      }
    }
  }
}

template <typename MatrixType>
template <bool Conjugate, typename Rhs>
void CompleteOrthogonalDecomposition<MatrixType>::applyZOnTheLeftInPlace(
    Rhs& rhs) const {
  const Index cols = this->cols();
  const Index nrhs = rhs.cols();
  const Index rank = this->rank();
  Matrix<typename Rhs::Scalar, Dynamic, 1> temp((std::max)(cols, nrhs));
  for (Index k = rank-1; k >= 0; --k) {
    if (k != rank - 1) {
      rhs.row(k).swap(rhs.row(rank - 1));
    }
    rhs.middleRows(rank - 1, cols - rank + 1)
        .applyHouseholderOnTheLeft(
            matrixQTZ().row(k).tail(cols - rank).transpose().template conjugateIf<!Conjugate>(), zCoeffs().template conjugateIf<Conjugate>()(k),
            &temp(0));
    if (k != rank - 1) {
      rhs.row(k).swap(rhs.row(rank - 1));
    }
  }
}

template <typename MatrixType>
template <typename Rhs>
void CompleteOrthogonalDecomposition<MatrixType>::applyZAdjointOnTheLeftInPlace(
    Rhs& rhs) const {
  const Index cols = this->cols();
  const Index nrhs = rhs.cols();
  const Index rank = this->rank();
  Matrix<typename Rhs::Scalar, Dynamic, 1> temp((std::max)(cols, nrhs));
  for (Index k = 0; k < rank; ++k) {
    if (k != rank - 1) {
      rhs.row(k).swap(rhs.row(rank - 1));
    }
    rhs.middleRows(rank - 1, cols - rank + 1)
        .applyHouseholderOnTheLeft(
            matrixQTZ().row(k).tail(cols - rank).adjoint(), zCoeffs()(k),
            &temp(0));
    if (k != rank - 1) {
      rhs.row(k).swap(rhs.row(rank - 1));
    }
  }
}

#ifndef EIGEN_PARSED_BY_DOXYGEN
template <typename MatrixType_>
template <typename RhsType, typename DstType>
void CompleteOrthogonalDecomposition<MatrixType_>::_solve_impl(
    const RhsType& rhs, DstType& dst) const {
  const Index rank = this->rank();
  if (rank == 0) {
    dst.setZero();
    return;
  }

  // Compute c = Q^* * rhs
  typename RhsType::PlainObject c(rhs);
  c.applyOnTheLeft(matrixQ().setLength(rank).adjoint());

  // Solve T z = c(1:rank, :)
  dst.topRows(rank) = matrixT()
                          .topLeftCorner(rank, rank)
                          .template triangularView<Upper>()
                          .solve(c.topRows(rank));

  const Index cols = this->cols();
  if (rank < cols) {
    // Compute y = Z^* * [ z ]
    //                   [ 0 ]
    dst.bottomRows(cols - rank).setZero();
    applyZAdjointOnTheLeftInPlace(dst);
  }

  // Undo permutation to get x = P^{-1} * y.
  dst = colsPermutation() * dst;
}

template<typename MatrixType_>
template<bool Conjugate, typename RhsType, typename DstType>
void CompleteOrthogonalDecomposition<MatrixType_>::_solve_impl_transposed(const RhsType &rhs, DstType &dst) const
{
  const Index rank = this->rank();

  if (rank == 0) {
    dst.setZero();
    return;
  }

  typename RhsType::PlainObject c(colsPermutation().transpose()*rhs);

  if (rank < cols()) {
    applyZOnTheLeftInPlace<!Conjugate>(c);
  }

  matrixT().topLeftCorner(rank, rank)
           .template triangularView<Upper>()
           .transpose().template conjugateIf<Conjugate>()
           .solveInPlace(c.topRows(rank));

  dst.topRows(rank) = c.topRows(rank);
  dst.bottomRows(rows()-rank).setZero();

  dst.applyOnTheLeft(householderQ().setLength(rank).template conjugateIf<!Conjugate>() );
}
#endif

namespace internal {

template<typename MatrixType>
struct traits<Inverse<CompleteOrthogonalDecomposition<MatrixType> > >
  : traits<typename Transpose<typename MatrixType::PlainObject>::PlainObject>
{
  enum { Flags = 0 };
};

template<typename DstXprType, typename MatrixType>
struct Assignment<DstXprType, Inverse<CompleteOrthogonalDecomposition<MatrixType> >, internal::assign_op<typename DstXprType::Scalar,typename CompleteOrthogonalDecomposition<MatrixType>::Scalar>, Dense2Dense>
{
  typedef CompleteOrthogonalDecomposition<MatrixType> CodType;
  typedef Inverse<CodType> SrcXprType;
  static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<typename DstXprType::Scalar,typename CodType::Scalar> &)
  {
    typedef Matrix<typename CodType::Scalar, CodType::RowsAtCompileTime, CodType::RowsAtCompileTime, 0, CodType::MaxRowsAtCompileTime, CodType::MaxRowsAtCompileTime> IdentityMatrixType;
    dst = src.nestedExpression().solve(IdentityMatrixType::Identity(src.cols(), src.cols()));
  }
};

} // end namespace internal

/** \returns the matrix Q as a sequence of householder transformations */
template <typename MatrixType>
typename CompleteOrthogonalDecomposition<MatrixType>::HouseholderSequenceType
CompleteOrthogonalDecomposition<MatrixType>::householderQ() const {
  return m_cpqr.householderQ();
}

/** \return the complete orthogonal decomposition of \c *this.
  *
  * \sa class CompleteOrthogonalDecomposition
  */
template <typename Derived>
const CompleteOrthogonalDecomposition<typename MatrixBase<Derived>::PlainObject>
MatrixBase<Derived>::completeOrthogonalDecomposition() const {
  return CompleteOrthogonalDecomposition<PlainObject>(eval());
}

}  // end namespace Eigen

#endif  // EIGEN_COMPLETEORTHOGONALDECOMPOSITION_H
