bug #707: add inplace decomposition through Ref<> for Cholesky, LU and QR decompositions.

This commit is contained in:
Gael Guennebaud
2016-07-04 15:13:35 +02:00
parent 75e80792cc
commit 32a41ee659
10 changed files with 337 additions and 64 deletions

View File

@@ -51,7 +51,6 @@ template<typename _MatrixType> class ColPivHouseholderQR
enum {
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
ColsAtCompileTime = MatrixType::ColsAtCompileTime,
Options = MatrixType::Options,
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
};
@@ -59,7 +58,6 @@ template<typename _MatrixType> class ColPivHouseholderQR
typedef typename MatrixType::RealScalar RealScalar;
// FIXME should be int
typedef typename MatrixType::StorageIndex StorageIndex;
typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime, Options, MaxRowsAtCompileTime, MaxRowsAtCompileTime> MatrixQType;
typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType;
typedef PermutationMatrix<ColsAtCompileTime, MaxColsAtCompileTime> PermutationType;
typedef typename internal::plain_row_type<MatrixType, Index>::type IntRowVectorType;
@@ -135,6 +133,27 @@ template<typename _MatrixType> class ColPivHouseholderQR
compute(matrix.derived());
}
/** \brief Constructs a QR factorization from a given matrix
*
* This overloaded constructor is provided for inplace solving when \c MatrixType is a Eigen::Ref.
*
* \sa ColPivHouseholderQR(const EigenBase&)
*/
template<typename InputType>
explicit ColPivHouseholderQR(EigenBase<InputType>& matrix)
: m_qr(matrix.derived()),
m_hCoeffs((std::min)(matrix.rows(),matrix.cols())),
m_colsPermutation(PermIndexType(matrix.cols())),
m_colsTranspositions(matrix.cols()),
m_temp(matrix.cols()),
m_colNormsUpdated(matrix.cols()),
m_colNormsDirect(matrix.cols()),
m_isInitialized(false),
m_usePrescribedThreshold(false)
{
computeInPlace();
}
/** This method finds a solution x to the equation Ax=b, where A is the matrix of which
* *this is the QR decomposition, if any exists.
*
@@ -453,21 +472,19 @@ template<typename MatrixType>
template<typename InputType>
ColPivHouseholderQR<MatrixType>& ColPivHouseholderQR<MatrixType>::compute(const EigenBase<InputType>& matrix)
{
check_template_parameters();
// the column permutation is stored as int indices, so just to be sure:
eigen_assert(matrix.cols()<=NumTraits<int>::highest());
m_qr = matrix;
m_qr = matrix.derived();
computeInPlace();
return *this;
}
template<typename MatrixType>
void ColPivHouseholderQR<MatrixType>::computeInPlace()
{
check_template_parameters();
// the column permutation is stored as int indices, so just to be sure:
eigen_assert(m_qr.cols()<=NumTraits<int>::highest());
using std::abs;
Index rows = m_qr.rows();

View File

@@ -48,16 +48,12 @@ class CompleteOrthogonalDecomposition {
enum {
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
ColsAtCompileTime = MatrixType::ColsAtCompileTime,
Options = MatrixType::Options,
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
};
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
typedef typename MatrixType::StorageIndex StorageIndex;
typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime, Options,
MaxRowsAtCompileTime, MaxRowsAtCompileTime>
MatrixQType;
typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType;
typedef PermutationMatrix<ColsAtCompileTime, MaxColsAtCompileTime>
PermutationType;
@@ -114,10 +110,27 @@ class CompleteOrthogonalDecomposition {
explicit CompleteOrthogonalDecomposition(const EigenBase<InputType>& matrix)
: m_cpqr(matrix.rows(), matrix.cols()),
m_zCoeffs((std::min)(matrix.rows(), matrix.cols())),
m_temp(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 inplace solving 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();
}
/** 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.
@@ -165,7 +178,12 @@ class CompleteOrthogonalDecomposition {
const MatrixType& matrixT() const { return m_cpqr.matrixQR(); }
template <typename InputType>
CompleteOrthogonalDecomposition& compute(const EigenBase<InputType>& matrix);
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 {
@@ -354,6 +372,8 @@ class CompleteOrthogonalDecomposition {
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
}
void computeInPlace();
/** Overwrites \b rhs with \f$ \mathbf{Z}^* * \mathbf{rhs} \f$.
*/
template <typename Rhs>
@@ -384,20 +404,16 @@ CompleteOrthogonalDecomposition<MatrixType>::logAbsDeterminant() const {
* CompleteOrthogonalDecomposition(const MatrixType&)
*/
template <typename MatrixType>
template <typename InputType>
CompleteOrthogonalDecomposition<MatrixType>& CompleteOrthogonalDecomposition<
MatrixType>::compute(const EigenBase<InputType>& matrix) {
void CompleteOrthogonalDecomposition<MatrixType>::computeInPlace()
{
check_template_parameters();
// the column permutation is stored as int indices, so just to be sure:
eigen_assert(matrix.cols() <= NumTraits<int>::highest());
// Compute the column pivoted QR factorization A P = Q R.
m_cpqr.compute(matrix);
eigen_assert(m_cpqr.cols() <= NumTraits<int>::highest());
const Index rank = m_cpqr.rank();
const Index cols = matrix.cols();
const Index rows = matrix.rows();
const Index cols = m_cpqr.cols();
const Index rows = m_cpqr.rows();
m_zCoeffs.resize((std::min)(rows, cols));
m_temp.resize(cols);
@@ -443,7 +459,6 @@ CompleteOrthogonalDecomposition<MatrixType>& CompleteOrthogonalDecomposition<
}
}
}
return *this;
}
template <typename MatrixType>

View File

@@ -60,7 +60,6 @@ template<typename _MatrixType> class FullPivHouseholderQR
enum {
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
ColsAtCompileTime = MatrixType::ColsAtCompileTime,
Options = MatrixType::Options,
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
};
@@ -135,6 +134,26 @@ template<typename _MatrixType> class FullPivHouseholderQR
compute(matrix.derived());
}
/** \brief Constructs a QR factorization from a given matrix
*
* This overloaded constructor is provided for inplace solving when \c MatrixType is a Eigen::Ref.
*
* \sa FullPivHouseholderQR(const EigenBase&)
*/
template<typename InputType>
explicit FullPivHouseholderQR(EigenBase<InputType>& matrix)
: m_qr(matrix.derived()),
m_hCoeffs((std::min)(matrix.rows(), matrix.cols())),
m_rows_transpositions((std::min)(matrix.rows(), matrix.cols())),
m_cols_transpositions((std::min)(matrix.rows(), matrix.cols())),
m_cols_permutation(matrix.cols()),
m_temp(matrix.cols()),
m_isInitialized(false),
m_usePrescribedThreshold(false)
{
computeInPlace();
}
/** This method finds a solution x to the equation Ax=b, where A is the matrix of which
* \c *this is the QR decomposition.
*
@@ -430,18 +449,16 @@ template<typename MatrixType>
template<typename InputType>
FullPivHouseholderQR<MatrixType>& FullPivHouseholderQR<MatrixType>::compute(const EigenBase<InputType>& matrix)
{
check_template_parameters();
m_qr = matrix.derived();
computeInPlace();
return *this;
}
template<typename MatrixType>
void FullPivHouseholderQR<MatrixType>::computeInPlace()
{
check_template_parameters();
using std::abs;
Index rows = m_qr.rows();
Index cols = m_qr.cols();

View File

@@ -47,7 +47,6 @@ template<typename _MatrixType> class HouseholderQR
enum {
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
ColsAtCompileTime = MatrixType::ColsAtCompileTime,
Options = MatrixType::Options,
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
};
@@ -102,6 +101,24 @@ template<typename _MatrixType> class HouseholderQR
compute(matrix.derived());
}
/** \brief Constructs a QR factorization from a given matrix
*
* This overloaded constructor is provided for inplace solving when
* \c MatrixType is a Eigen::Ref.
*
* \sa HouseholderQR(const EigenBase&)
*/
template<typename InputType>
explicit HouseholderQR(EigenBase<InputType>& matrix)
: m_qr(matrix.derived()),
m_hCoeffs((std::min)(matrix.rows(),matrix.cols())),
m_temp(matrix.cols()),
m_isInitialized(false)
{
computeInPlace();
}
/** This method finds a solution x to the equation Ax=b, where A is the matrix of which
* *this is the QR decomposition, if any exists.
*
@@ -151,7 +168,11 @@ template<typename _MatrixType> class HouseholderQR
}
template<typename InputType>
HouseholderQR& compute(const EigenBase<InputType>& matrix);
HouseholderQR& compute(const EigenBase<InputType>& matrix) {
m_qr = matrix.derived();
computeInPlace();
return *this;
}
/** \returns the absolute value of the determinant of the matrix of which
* *this is the QR decomposition. It has only linear complexity
@@ -203,6 +224,8 @@ template<typename _MatrixType> class HouseholderQR
{
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
}
void computeInPlace();
MatrixType m_qr;
HCoeffsType m_hCoeffs;
@@ -354,16 +377,14 @@ void HouseholderQR<_MatrixType>::_solve_impl(const RhsType &rhs, DstType &dst) c
* \sa class HouseholderQR, HouseholderQR(const MatrixType&)
*/
template<typename MatrixType>
template<typename InputType>
HouseholderQR<MatrixType>& HouseholderQR<MatrixType>::compute(const EigenBase<InputType>& matrix)
void HouseholderQR<MatrixType>::computeInPlace()
{
check_template_parameters();
Index rows = matrix.rows();
Index cols = matrix.cols();
Index rows = m_qr.rows();
Index cols = m_qr.cols();
Index size = (std::min)(rows,cols);
m_qr = matrix.derived();
m_hCoeffs.resize(size);
m_temp.resize(cols);
@@ -371,7 +392,6 @@ HouseholderQR<MatrixType>& HouseholderQR<MatrixType>::compute(const EigenBase<In
internal::householder_qr_inplace_blocked<MatrixType, HCoeffsType>::run(m_qr, m_hCoeffs, 48, m_temp.data());
m_isInitialized = true;
return *this;
}
#ifndef __CUDACC__