mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-08-05 11:40:40 +08:00
Port QR module to Solve/Inverse
This commit is contained in:
parent
ae40583965
commit
9be72cda2a
@ -13,6 +13,15 @@
|
|||||||
|
|
||||||
namespace Eigen {
|
namespace Eigen {
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
template<typename _MatrixType> struct traits<ColPivHouseholderQR<_MatrixType> >
|
||||||
|
: traits<_MatrixType>
|
||||||
|
{
|
||||||
|
enum { Flags = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace internal
|
||||||
|
|
||||||
/** \ingroup QR_Module
|
/** \ingroup QR_Module
|
||||||
*
|
*
|
||||||
* \class ColPivHouseholderQR
|
* \class ColPivHouseholderQR
|
||||||
@ -56,6 +65,7 @@ template<typename _MatrixType> class ColPivHouseholderQR
|
|||||||
typedef typename internal::plain_row_type<MatrixType>::type RowVectorType;
|
typedef typename internal::plain_row_type<MatrixType>::type RowVectorType;
|
||||||
typedef typename internal::plain_row_type<MatrixType, RealScalar>::type RealRowVectorType;
|
typedef typename internal::plain_row_type<MatrixType, RealScalar>::type RealRowVectorType;
|
||||||
typedef HouseholderSequence<MatrixType,typename internal::remove_all<typename HCoeffsType::ConjugateReturnType>::type> HouseholderSequenceType;
|
typedef HouseholderSequence<MatrixType,typename internal::remove_all<typename HCoeffsType::ConjugateReturnType>::type> HouseholderSequenceType;
|
||||||
|
typedef typename MatrixType::PlainObject PlainObject;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -137,6 +147,15 @@ template<typename _MatrixType> class ColPivHouseholderQR
|
|||||||
* Example: \include ColPivHouseholderQR_solve.cpp
|
* Example: \include ColPivHouseholderQR_solve.cpp
|
||||||
* Output: \verbinclude ColPivHouseholderQR_solve.out
|
* Output: \verbinclude ColPivHouseholderQR_solve.out
|
||||||
*/
|
*/
|
||||||
|
#ifdef EIGEN_TEST_EVALUATORS
|
||||||
|
template<typename Rhs>
|
||||||
|
inline const Solve<ColPivHouseholderQR, Rhs>
|
||||||
|
solve(const MatrixBase<Rhs>& b) const
|
||||||
|
{
|
||||||
|
eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
|
||||||
|
return Solve<ColPivHouseholderQR, Rhs>(*this, b.derived());
|
||||||
|
}
|
||||||
|
#else
|
||||||
template<typename Rhs>
|
template<typename Rhs>
|
||||||
inline const internal::solve_retval<ColPivHouseholderQR, Rhs>
|
inline const internal::solve_retval<ColPivHouseholderQR, Rhs>
|
||||||
solve(const MatrixBase<Rhs>& b) const
|
solve(const MatrixBase<Rhs>& b) const
|
||||||
@ -144,9 +163,10 @@ template<typename _MatrixType> class ColPivHouseholderQR
|
|||||||
eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
|
eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
|
||||||
return internal::solve_retval<ColPivHouseholderQR, Rhs>(*this, b.derived());
|
return internal::solve_retval<ColPivHouseholderQR, Rhs>(*this, b.derived());
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
HouseholderSequenceType householderQ(void) const;
|
HouseholderSequenceType householderQ() const;
|
||||||
HouseholderSequenceType matrixQ(void) const
|
HouseholderSequenceType matrixQ() const
|
||||||
{
|
{
|
||||||
return householderQ();
|
return householderQ();
|
||||||
}
|
}
|
||||||
@ -284,6 +304,13 @@ template<typename _MatrixType> class ColPivHouseholderQR
|
|||||||
* \note If this matrix is not invertible, the returned matrix has undefined coefficients.
|
* \note If this matrix is not invertible, the returned matrix has undefined coefficients.
|
||||||
* Use isInvertible() to first determine whether this matrix is invertible.
|
* Use isInvertible() to first determine whether this matrix is invertible.
|
||||||
*/
|
*/
|
||||||
|
#ifdef EIGEN_TEST_EVALUATORS
|
||||||
|
inline const Inverse<ColPivHouseholderQR> inverse() const
|
||||||
|
{
|
||||||
|
eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
|
||||||
|
return Inverse<ColPivHouseholderQR>(*this);
|
||||||
|
}
|
||||||
|
#else
|
||||||
inline const
|
inline const
|
||||||
internal::solve_retval<ColPivHouseholderQR, typename MatrixType::IdentityReturnType>
|
internal::solve_retval<ColPivHouseholderQR, typename MatrixType::IdentityReturnType>
|
||||||
inverse() const
|
inverse() const
|
||||||
@ -292,6 +319,7 @@ template<typename _MatrixType> class ColPivHouseholderQR
|
|||||||
return internal::solve_retval<ColPivHouseholderQR,typename MatrixType::IdentityReturnType>
|
return internal::solve_retval<ColPivHouseholderQR,typename MatrixType::IdentityReturnType>
|
||||||
(*this, MatrixType::Identity(m_qr.rows(), m_qr.cols()));
|
(*this, MatrixType::Identity(m_qr.rows(), m_qr.cols()));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
inline Index rows() const { return m_qr.rows(); }
|
inline Index rows() const { return m_qr.rows(); }
|
||||||
inline Index cols() const { return m_qr.cols(); }
|
inline Index cols() const { return m_qr.cols(); }
|
||||||
@ -383,6 +411,12 @@ template<typename _MatrixType> class ColPivHouseholderQR
|
|||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||||
|
template<typename RhsType, typename DstType>
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
|
void _solve_impl(const RhsType &rhs, DstType &dst) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MatrixType m_qr;
|
MatrixType m_qr;
|
||||||
HCoeffsType m_hCoeffs;
|
HCoeffsType m_hCoeffs;
|
||||||
@ -514,8 +548,41 @@ ColPivHouseholderQR<MatrixType>& ColPivHouseholderQR<MatrixType>::compute(const
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||||
|
template<typename _MatrixType>
|
||||||
|
template<typename RhsType, typename DstType>
|
||||||
|
void ColPivHouseholderQR<_MatrixType>::_solve_impl(const RhsType &rhs, DstType &dst) const
|
||||||
|
{
|
||||||
|
eigen_assert(rhs.rows() == rows());
|
||||||
|
|
||||||
|
const Index nonzero_pivots = nonzeroPivots();
|
||||||
|
|
||||||
|
if(nonzero_pivots == 0)
|
||||||
|
{
|
||||||
|
dst.setZero();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
typename RhsType::PlainObject c(rhs);
|
||||||
|
|
||||||
|
// Note that the matrix Q = H_0^* H_1^*... so its inverse is Q^* = (H_0 H_1 ...)^T
|
||||||
|
c.applyOnTheLeft(householderSequence(m_qr, m_hCoeffs)
|
||||||
|
.setLength(nonzero_pivots)
|
||||||
|
.transpose()
|
||||||
|
);
|
||||||
|
|
||||||
|
m_qr.topLeftCorner(nonzero_pivots, nonzero_pivots)
|
||||||
|
.template triangularView<Upper>()
|
||||||
|
.solveInPlace(c.topRows(nonzero_pivots));
|
||||||
|
|
||||||
|
for(Index i = 0; i < nonzero_pivots; ++i) dst.row(m_colsPermutation.indices().coeff(i)) = c.row(i);
|
||||||
|
for(Index i = nonzero_pivots; i < cols(); ++i) dst.row(m_colsPermutation.indices().coeff(i)).setZero();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
#ifndef EIGEN_TEST_EVALUATORS
|
||||||
template<typename _MatrixType, typename Rhs>
|
template<typename _MatrixType, typename Rhs>
|
||||||
struct solve_retval<ColPivHouseholderQR<_MatrixType>, Rhs>
|
struct solve_retval<ColPivHouseholderQR<_MatrixType>, Rhs>
|
||||||
: solve_retval_base<ColPivHouseholderQR<_MatrixType>, Rhs>
|
: solve_retval_base<ColPivHouseholderQR<_MatrixType>, Rhs>
|
||||||
@ -524,34 +591,23 @@ struct solve_retval<ColPivHouseholderQR<_MatrixType>, Rhs>
|
|||||||
|
|
||||||
template<typename Dest> void evalTo(Dest& dst) const
|
template<typename Dest> void evalTo(Dest& dst) const
|
||||||
{
|
{
|
||||||
eigen_assert(rhs().rows() == dec().rows());
|
dec()._solve_impl(rhs(), dst);
|
||||||
|
|
||||||
const Index cols = dec().cols(),
|
|
||||||
nonzero_pivots = dec().nonzeroPivots();
|
|
||||||
|
|
||||||
if(nonzero_pivots == 0)
|
|
||||||
{
|
|
||||||
dst.setZero();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
typename Rhs::PlainObject c(rhs());
|
|
||||||
|
|
||||||
// Note that the matrix Q = H_0^* H_1^*... so its inverse is Q^* = (H_0 H_1 ...)^T
|
|
||||||
c.applyOnTheLeft(householderSequence(dec().matrixQR(), dec().hCoeffs())
|
|
||||||
.setLength(dec().nonzeroPivots())
|
|
||||||
.transpose()
|
|
||||||
);
|
|
||||||
|
|
||||||
dec().matrixR()
|
|
||||||
.topLeftCorner(nonzero_pivots, nonzero_pivots)
|
|
||||||
.template triangularView<Upper>()
|
|
||||||
.solveInPlace(c.topRows(nonzero_pivots));
|
|
||||||
|
|
||||||
for(Index i = 0; i < nonzero_pivots; ++i) dst.row(dec().colsPermutation().indices().coeff(i)) = c.row(i);
|
|
||||||
for(Index i = nonzero_pivots; i < cols; ++i) dst.row(dec().colsPermutation().indices().coeff(i)).setZero();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef EIGEN_TEST_EVALUATORS
|
||||||
|
template<typename DstXprType, typename MatrixType, typename Scalar>
|
||||||
|
struct Assignment<DstXprType, Inverse<ColPivHouseholderQR<MatrixType> >, internal::assign_op<Scalar>, Dense2Dense, Scalar>
|
||||||
|
{
|
||||||
|
typedef ColPivHouseholderQR<MatrixType> QrType;
|
||||||
|
typedef Inverse<QrType> SrcXprType;
|
||||||
|
static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<Scalar> &)
|
||||||
|
{
|
||||||
|
dst = src.nestedExpression().solve(MatrixType::Identity(src.rows(), src.cols()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
} // end namespace internal
|
} // end namespace internal
|
||||||
|
|
||||||
|
@ -15,6 +15,12 @@ namespace Eigen {
|
|||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
template<typename _MatrixType> struct traits<FullPivHouseholderQR<_MatrixType> >
|
||||||
|
: traits<_MatrixType>
|
||||||
|
{
|
||||||
|
enum { Flags = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
template<typename MatrixType> struct FullPivHouseholderQRMatrixQReturnType;
|
template<typename MatrixType> struct FullPivHouseholderQRMatrixQReturnType;
|
||||||
|
|
||||||
template<typename MatrixType>
|
template<typename MatrixType>
|
||||||
@ -23,7 +29,7 @@ struct traits<FullPivHouseholderQRMatrixQReturnType<MatrixType> >
|
|||||||
typedef typename MatrixType::PlainObject ReturnType;
|
typedef typename MatrixType::PlainObject ReturnType;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // end namespace internal
|
||||||
|
|
||||||
/** \ingroup QR_Module
|
/** \ingroup QR_Module
|
||||||
*
|
*
|
||||||
@ -69,6 +75,7 @@ template<typename _MatrixType> class FullPivHouseholderQR
|
|||||||
typedef PermutationMatrix<ColsAtCompileTime, MaxColsAtCompileTime> PermutationType;
|
typedef PermutationMatrix<ColsAtCompileTime, MaxColsAtCompileTime> PermutationType;
|
||||||
typedef typename internal::plain_row_type<MatrixType>::type RowVectorType;
|
typedef typename internal::plain_row_type<MatrixType>::type RowVectorType;
|
||||||
typedef typename internal::plain_col_type<MatrixType>::type ColVectorType;
|
typedef typename internal::plain_col_type<MatrixType>::type ColVectorType;
|
||||||
|
typedef typename MatrixType::PlainObject PlainObject;
|
||||||
|
|
||||||
/** \brief Default Constructor.
|
/** \brief Default Constructor.
|
||||||
*
|
*
|
||||||
@ -144,6 +151,15 @@ template<typename _MatrixType> class FullPivHouseholderQR
|
|||||||
* Example: \include FullPivHouseholderQR_solve.cpp
|
* Example: \include FullPivHouseholderQR_solve.cpp
|
||||||
* Output: \verbinclude FullPivHouseholderQR_solve.out
|
* Output: \verbinclude FullPivHouseholderQR_solve.out
|
||||||
*/
|
*/
|
||||||
|
#ifdef EIGEN_TEST_EVALUATORS
|
||||||
|
template<typename Rhs>
|
||||||
|
inline const Solve<FullPivHouseholderQR, Rhs>
|
||||||
|
solve(const MatrixBase<Rhs>& b) const
|
||||||
|
{
|
||||||
|
eigen_assert(m_isInitialized && "FullPivHouseholderQR is not initialized.");
|
||||||
|
return Solve<FullPivHouseholderQR, Rhs>(*this, b.derived());
|
||||||
|
}
|
||||||
|
#else
|
||||||
template<typename Rhs>
|
template<typename Rhs>
|
||||||
inline const internal::solve_retval<FullPivHouseholderQR, Rhs>
|
inline const internal::solve_retval<FullPivHouseholderQR, Rhs>
|
||||||
solve(const MatrixBase<Rhs>& b) const
|
solve(const MatrixBase<Rhs>& b) const
|
||||||
@ -151,6 +167,7 @@ template<typename _MatrixType> class FullPivHouseholderQR
|
|||||||
eigen_assert(m_isInitialized && "FullPivHouseholderQR is not initialized.");
|
eigen_assert(m_isInitialized && "FullPivHouseholderQR is not initialized.");
|
||||||
return internal::solve_retval<FullPivHouseholderQR, Rhs>(*this, b.derived());
|
return internal::solve_retval<FullPivHouseholderQR, Rhs>(*this, b.derived());
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/** \returns Expression object representing the matrix Q
|
/** \returns Expression object representing the matrix Q
|
||||||
*/
|
*/
|
||||||
@ -280,7 +297,15 @@ template<typename _MatrixType> class FullPivHouseholderQR
|
|||||||
*
|
*
|
||||||
* \note If this matrix is not invertible, the returned matrix has undefined coefficients.
|
* \note If this matrix is not invertible, the returned matrix has undefined coefficients.
|
||||||
* Use isInvertible() to first determine whether this matrix is invertible.
|
* Use isInvertible() to first determine whether this matrix is invertible.
|
||||||
*/ inline const
|
*/
|
||||||
|
#ifdef EIGEN_TEST_EVALUATORS
|
||||||
|
inline const Inverse<FullPivHouseholderQR> inverse() const
|
||||||
|
{
|
||||||
|
eigen_assert(m_isInitialized && "FullPivHouseholderQR is not initialized.");
|
||||||
|
return Inverse<FullPivHouseholderQR>(*this);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
inline const
|
||||||
internal::solve_retval<FullPivHouseholderQR, typename MatrixType::IdentityReturnType>
|
internal::solve_retval<FullPivHouseholderQR, typename MatrixType::IdentityReturnType>
|
||||||
inverse() const
|
inverse() const
|
||||||
{
|
{
|
||||||
@ -288,6 +313,7 @@ template<typename _MatrixType> class FullPivHouseholderQR
|
|||||||
return internal::solve_retval<FullPivHouseholderQR,typename MatrixType::IdentityReturnType>
|
return internal::solve_retval<FullPivHouseholderQR,typename MatrixType::IdentityReturnType>
|
||||||
(*this, MatrixType::Identity(m_qr.rows(), m_qr.cols()));
|
(*this, MatrixType::Identity(m_qr.rows(), m_qr.cols()));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
inline Index rows() const { return m_qr.rows(); }
|
inline Index rows() const { return m_qr.rows(); }
|
||||||
inline Index cols() const { return m_qr.cols(); }
|
inline Index cols() const { return m_qr.cols(); }
|
||||||
@ -367,6 +393,12 @@ template<typename _MatrixType> class FullPivHouseholderQR
|
|||||||
*/
|
*/
|
||||||
RealScalar maxPivot() const { return m_maxpivot; }
|
RealScalar maxPivot() const { return m_maxpivot; }
|
||||||
|
|
||||||
|
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||||
|
template<typename RhsType, typename DstType>
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
|
void _solve_impl(const RhsType &rhs, DstType &dst) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MatrixType m_qr;
|
MatrixType m_qr;
|
||||||
HCoeffsType m_hCoeffs;
|
HCoeffsType m_hCoeffs;
|
||||||
@ -485,8 +517,46 @@ FullPivHouseholderQR<MatrixType>& FullPivHouseholderQR<MatrixType>::compute(cons
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||||
|
template<typename _MatrixType>
|
||||||
|
template<typename RhsType, typename DstType>
|
||||||
|
void FullPivHouseholderQR<_MatrixType>::_solve_impl(const RhsType &rhs, DstType &dst) const
|
||||||
|
{
|
||||||
|
eigen_assert(rhs.rows() == rows());
|
||||||
|
const Index l_rank = rank();
|
||||||
|
|
||||||
|
// FIXME introduce nonzeroPivots() and use it here. and more generally,
|
||||||
|
// make the same improvements in this dec as in FullPivLU.
|
||||||
|
if(l_rank==0)
|
||||||
|
{
|
||||||
|
dst.setZero();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
typename RhsType::PlainObject c(rhs);
|
||||||
|
|
||||||
|
Matrix<Scalar,1,RhsType::ColsAtCompileTime> temp(rhs.cols());
|
||||||
|
for (Index k = 0; k < l_rank; ++k)
|
||||||
|
{
|
||||||
|
Index remainingSize = rows()-k;
|
||||||
|
c.row(k).swap(c.row(m_rows_transpositions.coeff(k)));
|
||||||
|
c.bottomRightCorner(remainingSize, rhs.cols())
|
||||||
|
.applyHouseholderOnTheLeft(m_qr.col(k).tail(remainingSize-1),
|
||||||
|
m_hCoeffs.coeff(k), &temp.coeffRef(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_qr.topLeftCorner(l_rank, l_rank)
|
||||||
|
.template triangularView<Upper>()
|
||||||
|
.solveInPlace(c.topRows(l_rank));
|
||||||
|
|
||||||
|
for(Index i = 0; i < l_rank; ++i) dst.row(m_cols_permutation.indices().coeff(i)) = c.row(i);
|
||||||
|
for(Index i = l_rank; i < cols(); ++i) dst.row(m_cols_permutation.indices().coeff(i)).setZero();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
#ifndef EIGEN_TEST_EVALUATORS
|
||||||
template<typename _MatrixType, typename Rhs>
|
template<typename _MatrixType, typename Rhs>
|
||||||
struct solve_retval<FullPivHouseholderQR<_MatrixType>, Rhs>
|
struct solve_retval<FullPivHouseholderQR<_MatrixType>, Rhs>
|
||||||
: solve_retval_base<FullPivHouseholderQR<_MatrixType>, Rhs>
|
: solve_retval_base<FullPivHouseholderQR<_MatrixType>, Rhs>
|
||||||
@ -495,38 +565,23 @@ struct solve_retval<FullPivHouseholderQR<_MatrixType>, Rhs>
|
|||||||
|
|
||||||
template<typename Dest> void evalTo(Dest& dst) const
|
template<typename Dest> void evalTo(Dest& dst) const
|
||||||
{
|
{
|
||||||
const Index rows = dec().rows(), cols = dec().cols();
|
dec()._solve_impl(rhs(), dst);
|
||||||
eigen_assert(rhs().rows() == rows);
|
|
||||||
|
|
||||||
// FIXME introduce nonzeroPivots() and use it here. and more generally,
|
|
||||||
// make the same improvements in this dec as in FullPivLU.
|
|
||||||
if(dec().rank()==0)
|
|
||||||
{
|
|
||||||
dst.setZero();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
typename Rhs::PlainObject c(rhs());
|
|
||||||
|
|
||||||
Matrix<Scalar,1,Rhs::ColsAtCompileTime> temp(rhs().cols());
|
|
||||||
for (Index k = 0; k < dec().rank(); ++k)
|
|
||||||
{
|
|
||||||
Index remainingSize = rows-k;
|
|
||||||
c.row(k).swap(c.row(dec().rowsTranspositions().coeff(k)));
|
|
||||||
c.bottomRightCorner(remainingSize, rhs().cols())
|
|
||||||
.applyHouseholderOnTheLeft(dec().matrixQR().col(k).tail(remainingSize-1),
|
|
||||||
dec().hCoeffs().coeff(k), &temp.coeffRef(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
dec().matrixQR()
|
|
||||||
.topLeftCorner(dec().rank(), dec().rank())
|
|
||||||
.template triangularView<Upper>()
|
|
||||||
.solveInPlace(c.topRows(dec().rank()));
|
|
||||||
|
|
||||||
for(Index i = 0; i < dec().rank(); ++i) dst.row(dec().colsPermutation().indices().coeff(i)) = c.row(i);
|
|
||||||
for(Index i = dec().rank(); i < cols; ++i) dst.row(dec().colsPermutation().indices().coeff(i)).setZero();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
#endif // EIGEN_TEST_EVALUATORS
|
||||||
|
|
||||||
|
#ifdef EIGEN_TEST_EVALUATORS
|
||||||
|
template<typename DstXprType, typename MatrixType, typename Scalar>
|
||||||
|
struct Assignment<DstXprType, Inverse<FullPivHouseholderQR<MatrixType> >, internal::assign_op<Scalar>, Dense2Dense, Scalar>
|
||||||
|
{
|
||||||
|
typedef FullPivHouseholderQR<MatrixType> QrType;
|
||||||
|
typedef Inverse<QrType> SrcXprType;
|
||||||
|
static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<Scalar> &)
|
||||||
|
{
|
||||||
|
dst = src.nestedExpression().solve(MatrixType::Identity(src.rows(), src.cols()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/** \ingroup QR_Module
|
/** \ingroup QR_Module
|
||||||
*
|
*
|
||||||
@ -534,6 +589,7 @@ struct solve_retval<FullPivHouseholderQR<_MatrixType>, Rhs>
|
|||||||
*
|
*
|
||||||
* \tparam MatrixType type of underlying dense matrix
|
* \tparam MatrixType type of underlying dense matrix
|
||||||
*/
|
*/
|
||||||
|
// #ifndef EIGEN_TEST_EVALUATORS
|
||||||
template<typename MatrixType> struct FullPivHouseholderQRMatrixQReturnType
|
template<typename MatrixType> struct FullPivHouseholderQRMatrixQReturnType
|
||||||
: public ReturnByValue<FullPivHouseholderQRMatrixQReturnType<MatrixType> >
|
: public ReturnByValue<FullPivHouseholderQRMatrixQReturnType<MatrixType> >
|
||||||
{
|
{
|
||||||
@ -589,6 +645,13 @@ protected:
|
|||||||
typename IntDiagSizeVectorType::Nested m_rowsTranspositions;
|
typename IntDiagSizeVectorType::Nested m_rowsTranspositions;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// #ifdef EIGEN_TEST_EVALUATORS
|
||||||
|
// template<typename MatrixType>
|
||||||
|
// struct evaluator<FullPivHouseholderQRMatrixQReturnType<MatrixType> >
|
||||||
|
// : public evaluator<ReturnByValue<FullPivHouseholderQRMatrixQReturnType<MatrixType> > >
|
||||||
|
// {};
|
||||||
|
// #endif
|
||||||
|
|
||||||
} // end namespace internal
|
} // end namespace internal
|
||||||
|
|
||||||
template<typename MatrixType>
|
template<typename MatrixType>
|
||||||
|
@ -117,6 +117,15 @@ template<typename _MatrixType> class HouseholderQR
|
|||||||
* Example: \include HouseholderQR_solve.cpp
|
* Example: \include HouseholderQR_solve.cpp
|
||||||
* Output: \verbinclude HouseholderQR_solve.out
|
* Output: \verbinclude HouseholderQR_solve.out
|
||||||
*/
|
*/
|
||||||
|
#ifdef EIGEN_TEST_EVALUATORS
|
||||||
|
template<typename Rhs>
|
||||||
|
inline const Solve<HouseholderQR, Rhs>
|
||||||
|
solve(const MatrixBase<Rhs>& b) const
|
||||||
|
{
|
||||||
|
eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
|
||||||
|
return Solve<HouseholderQR, Rhs>(*this, b.derived());
|
||||||
|
}
|
||||||
|
#else
|
||||||
template<typename Rhs>
|
template<typename Rhs>
|
||||||
inline const internal::solve_retval<HouseholderQR, Rhs>
|
inline const internal::solve_retval<HouseholderQR, Rhs>
|
||||||
solve(const MatrixBase<Rhs>& b) const
|
solve(const MatrixBase<Rhs>& b) const
|
||||||
@ -124,6 +133,7 @@ template<typename _MatrixType> class HouseholderQR
|
|||||||
eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
|
eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
|
||||||
return internal::solve_retval<HouseholderQR, Rhs>(*this, b.derived());
|
return internal::solve_retval<HouseholderQR, Rhs>(*this, b.derived());
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/** This method returns an expression of the unitary matrix Q as a sequence of Householder transformations.
|
/** This method returns an expression of the unitary matrix Q as a sequence of Householder transformations.
|
||||||
*
|
*
|
||||||
@ -188,6 +198,12 @@ template<typename _MatrixType> class HouseholderQR
|
|||||||
*/
|
*/
|
||||||
const HCoeffsType& hCoeffs() const { return m_hCoeffs; }
|
const HCoeffsType& hCoeffs() const { return m_hCoeffs; }
|
||||||
|
|
||||||
|
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||||
|
template<typename RhsType, typename DstType>
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
|
void _solve_impl(const RhsType &rhs, DstType &dst) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MatrixType m_qr;
|
MatrixType m_qr;
|
||||||
HCoeffsType m_hCoeffs;
|
HCoeffsType m_hCoeffs;
|
||||||
@ -308,6 +324,35 @@ struct householder_qr_inplace_blocked
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end namespace internal
|
||||||
|
|
||||||
|
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||||
|
template<typename _MatrixType>
|
||||||
|
template<typename RhsType, typename DstType>
|
||||||
|
void HouseholderQR<_MatrixType>::_solve_impl(const RhsType &rhs, DstType &dst) const
|
||||||
|
{
|
||||||
|
const Index rank = (std::min)(rows(), cols());
|
||||||
|
eigen_assert(rhs.rows() == rows());
|
||||||
|
|
||||||
|
typename RhsType::PlainObject c(rhs);
|
||||||
|
|
||||||
|
// Note that the matrix Q = H_0^* H_1^*... so its inverse is Q^* = (H_0 H_1 ...)^T
|
||||||
|
c.applyOnTheLeft(householderSequence(
|
||||||
|
m_qr.leftCols(rank),
|
||||||
|
m_hCoeffs.head(rank)).transpose()
|
||||||
|
);
|
||||||
|
|
||||||
|
m_qr.topLeftCorner(rank, rank)
|
||||||
|
.template triangularView<Upper>()
|
||||||
|
.solveInPlace(c.topRows(rank));
|
||||||
|
|
||||||
|
dst.topRows(rank) = c.topRows(rank);
|
||||||
|
dst.bottomRows(cols()-rank).setZero();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
template<typename _MatrixType, typename Rhs>
|
template<typename _MatrixType, typename Rhs>
|
||||||
struct solve_retval<HouseholderQR<_MatrixType>, Rhs>
|
struct solve_retval<HouseholderQR<_MatrixType>, Rhs>
|
||||||
: solve_retval_base<HouseholderQR<_MatrixType>, Rhs>
|
: solve_retval_base<HouseholderQR<_MatrixType>, Rhs>
|
||||||
@ -316,25 +361,7 @@ struct solve_retval<HouseholderQR<_MatrixType>, Rhs>
|
|||||||
|
|
||||||
template<typename Dest> void evalTo(Dest& dst) const
|
template<typename Dest> void evalTo(Dest& dst) const
|
||||||
{
|
{
|
||||||
const Index rows = dec().rows(), cols = dec().cols();
|
dec()._solve_impl(rhs(), dst);
|
||||||
const Index rank = (std::min)(rows, cols);
|
|
||||||
eigen_assert(rhs().rows() == rows);
|
|
||||||
|
|
||||||
typename Rhs::PlainObject c(rhs());
|
|
||||||
|
|
||||||
// Note that the matrix Q = H_0^* H_1^*... so its inverse is Q^* = (H_0 H_1 ...)^T
|
|
||||||
c.applyOnTheLeft(householderSequence(
|
|
||||||
dec().matrixQR().leftCols(rank),
|
|
||||||
dec().hCoeffs().head(rank)).transpose()
|
|
||||||
);
|
|
||||||
|
|
||||||
dec().matrixQR()
|
|
||||||
.topLeftCorner(rank, rank)
|
|
||||||
.template triangularView<Upper>()
|
|
||||||
.solveInPlace(c.topRows(rank));
|
|
||||||
|
|
||||||
dst.topRows(rank) = c.topRows(rank);
|
|
||||||
dst.bottomRows(cols-rank).setZero();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user