mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
*port the Cholesky module to the new solve() API
*improve documentation
This commit is contained in:
@@ -27,6 +27,8 @@
|
||||
#ifndef EIGEN_LDLT_H
|
||||
#define EIGEN_LDLT_H
|
||||
|
||||
template<typename MatrixType, typename Rhs> struct ei_ldlt_solve_impl;
|
||||
|
||||
/** \ingroup cholesky_Module
|
||||
*
|
||||
* \class LDLT
|
||||
@@ -43,8 +45,8 @@
|
||||
* zeros in the bottom right rank(A) - n submatrix. Avoiding the square root
|
||||
* on D also stabilizes the computation.
|
||||
*
|
||||
* Remember that Cholesky decompositions are not rank-revealing. Also, do not use a Cholesky decomposition to determine
|
||||
* whether a system of equations has a solution.
|
||||
* Remember that Cholesky decompositions are not rank-revealing. Also, do not use a Cholesky
|
||||
* decomposition to determine whether a system of equations has a solution.
|
||||
*
|
||||
* \sa MatrixBase::ldlt(), class LLT
|
||||
*/
|
||||
@@ -117,14 +119,37 @@ template<typename MatrixType> class LDLT
|
||||
return m_sign == -1;
|
||||
}
|
||||
|
||||
template<typename RhsDerived, typename ResultType>
|
||||
bool solve(const MatrixBase<RhsDerived> &b, ResultType *result) const;
|
||||
|
||||
/** \returns a solution x of \f$ A x = b \f$ using the current decomposition of A.
|
||||
*
|
||||
* \note_about_checking_solutions
|
||||
*
|
||||
* \sa solveInPlace(), MatrixBase::ldlt()
|
||||
*/
|
||||
template<typename Rhs>
|
||||
inline const ei_ldlt_solve_impl<MatrixType, Rhs>
|
||||
solve(const MatrixBase<Rhs>& b) const
|
||||
{
|
||||
ei_assert(m_isInitialized && "LDLT is not initialized.");
|
||||
ei_assert(m_matrix.rows()==b.rows()
|
||||
&& "LDLT::solve(): invalid number of rows of the right hand side matrix b");
|
||||
return ei_ldlt_solve_impl<MatrixType, Rhs>(*this, b.derived());
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
bool solveInPlace(MatrixBase<Derived> &bAndX) const;
|
||||
|
||||
LDLT& compute(const MatrixType& matrix);
|
||||
|
||||
/** \returns the LDLT decomposition matrix
|
||||
*
|
||||
* TODO: document the storage layout
|
||||
*/
|
||||
inline const MatrixType& matrixLDLT() const
|
||||
{
|
||||
ei_assert(m_isInitialized && "LDLT is not initialized.");
|
||||
return m_matrix;
|
||||
}
|
||||
|
||||
protected:
|
||||
/** \internal
|
||||
* Used to compute and store the Cholesky decomposition A = L D L^* = U^* D U.
|
||||
@@ -134,7 +159,7 @@ template<typename MatrixType> class LDLT
|
||||
*/
|
||||
MatrixType m_matrix;
|
||||
IntColVectorType m_p;
|
||||
IntColVectorType m_transpositions;
|
||||
IntColVectorType m_transpositions; // FIXME do we really need to store permanently the transpositions?
|
||||
int m_sign;
|
||||
bool m_isInitialized;
|
||||
};
|
||||
@@ -238,27 +263,38 @@ LDLT<MatrixType>& LDLT<MatrixType>::compute(const MatrixType& a)
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Computes the solution x of \f$ A x = b \f$ using the current decomposition of A.
|
||||
* The result is stored in \a result
|
||||
*
|
||||
* \returns true always! If you need to check for existence of solutions, use another decomposition like LU, QR, or SVD.
|
||||
*
|
||||
* In other words, it computes \f$ b = A^{-1} b \f$ with
|
||||
* \f$ P^T{L^{*}}^{-1} D^{-1} L^{-1} P b \f$ from right to left.
|
||||
*
|
||||
* \sa LDLT::solveInPlace(), MatrixBase::ldlt()
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
template<typename RhsDerived, typename ResultType>
|
||||
bool LDLT<MatrixType>
|
||||
::solve(const MatrixBase<RhsDerived> &b, ResultType *result) const
|
||||
template<typename MatrixType,typename Rhs>
|
||||
struct ei_traits<ei_ldlt_solve_impl<MatrixType,Rhs> >
|
||||
{
|
||||
ei_assert(m_isInitialized && "LDLT is not initialized.");
|
||||
const int size = m_matrix.rows();
|
||||
ei_assert(size==b.rows() && "LDLT::solve(): invalid number of rows of the right hand side matrix b");
|
||||
*result = b;
|
||||
return solveInPlace(*result);
|
||||
}
|
||||
typedef Matrix<typename Rhs::Scalar,
|
||||
MatrixType::ColsAtCompileTime,
|
||||
Rhs::ColsAtCompileTime,
|
||||
Rhs::PlainMatrixType::Options,
|
||||
MatrixType::MaxColsAtCompileTime,
|
||||
Rhs::MaxColsAtCompileTime> ReturnMatrixType;
|
||||
};
|
||||
|
||||
template<typename MatrixType, typename Rhs>
|
||||
struct ei_ldlt_solve_impl : public ReturnByValue<ei_ldlt_solve_impl<MatrixType, Rhs> >
|
||||
{
|
||||
typedef typename ei_cleantype<typename Rhs::Nested>::type RhsNested;
|
||||
typedef LDLT<MatrixType> LDLTType;
|
||||
const LDLTType& m_ldlt;
|
||||
const typename Rhs::Nested m_rhs;
|
||||
|
||||
ei_ldlt_solve_impl(const LDLTType& ldlt, const Rhs& rhs)
|
||||
: m_ldlt(ldlt), m_rhs(rhs)
|
||||
{}
|
||||
|
||||
inline int rows() const { return m_ldlt.matrixLDLT().cols(); }
|
||||
inline int cols() const { return m_rhs.cols(); }
|
||||
|
||||
template<typename Dest> void evalTo(Dest& dst) const
|
||||
{
|
||||
dst = m_rhs;
|
||||
m_ldlt.solveInPlace(dst);
|
||||
}
|
||||
};
|
||||
|
||||
/** This is the \em in-place version of solve().
|
||||
*
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#define EIGEN_LLT_H
|
||||
|
||||
template<typename MatrixType, int UpLo> struct LLT_Traits;
|
||||
template<typename MatrixType, int UpLo, typename Rhs> struct ei_llt_solve_impl;
|
||||
|
||||
/** \ingroup cholesky_Module
|
||||
*
|
||||
@@ -99,14 +100,41 @@ template<typename MatrixType, int _UpLo> class LLT
|
||||
return Traits::getL(m_matrix);
|
||||
}
|
||||
|
||||
template<typename RhsDerived, typename ResultType>
|
||||
bool solve(const MatrixBase<RhsDerived> &b, ResultType *result) const;
|
||||
|
||||
/** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A.
|
||||
*
|
||||
* Since this LLT class assumes anyway that the matrix A is invertible, the solution
|
||||
* theoretically exists and is unique regardless of b.
|
||||
*
|
||||
* Example: \include LLT_solve.cpp
|
||||
* Output: \verbinclude LLT_solve.out
|
||||
*
|
||||
* \sa solveInPlace(), MatrixBase::llt()
|
||||
*/
|
||||
template<typename Rhs>
|
||||
inline const ei_llt_solve_impl<MatrixType, UpLo, Rhs>
|
||||
solve(const MatrixBase<Rhs>& b) const
|
||||
{
|
||||
ei_assert(m_isInitialized && "LLT is not initialized.");
|
||||
ei_assert(m_matrix.rows()==b.rows()
|
||||
&& "LLT::solve(): invalid number of rows of the right hand side matrix b");
|
||||
return ei_llt_solve_impl<MatrixType, UpLo, Rhs>(*this, b.derived());
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
bool solveInPlace(MatrixBase<Derived> &bAndX) const;
|
||||
|
||||
LLT& compute(const MatrixType& matrix);
|
||||
|
||||
/** \returns the LLT decomposition matrix
|
||||
*
|
||||
* TODO: document the storage layout
|
||||
*/
|
||||
inline const MatrixType& matrixLLT() const
|
||||
{
|
||||
ei_assert(m_isInitialized && "LLT is not initialized.");
|
||||
return m_matrix;
|
||||
}
|
||||
|
||||
protected:
|
||||
/** \internal
|
||||
* Used to compute and store L
|
||||
@@ -229,28 +257,38 @@ LLT<MatrixType,_UpLo>& LLT<MatrixType,_UpLo>::compute(const MatrixType& a)
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Computes the solution x of \f$ A x = b \f$ using the current decomposition of A.
|
||||
* The result is stored in \a result
|
||||
*
|
||||
* \returns true always! If you need to check for existence of solutions, use another decomposition like LU, QR, or SVD.
|
||||
*
|
||||
* In other words, it computes \f$ b = A^{-1} b \f$ with
|
||||
* \f$ {L^{*}}^{-1} L^{-1} b \f$ from right to left.
|
||||
*
|
||||
* Example: \include LLT_solve.cpp
|
||||
* Output: \verbinclude LLT_solve.out
|
||||
*
|
||||
* \sa LLT::solveInPlace(), MatrixBase::llt()
|
||||
*/
|
||||
template<typename MatrixType, int _UpLo>
|
||||
template<typename RhsDerived, typename ResultType>
|
||||
bool LLT<MatrixType,_UpLo>::solve(const MatrixBase<RhsDerived> &b, ResultType *result) const
|
||||
template<typename MatrixType, int UpLo, typename Rhs>
|
||||
struct ei_traits<ei_llt_solve_impl<MatrixType,UpLo,Rhs> >
|
||||
{
|
||||
ei_assert(m_isInitialized && "LLT is not initialized.");
|
||||
const int size = m_matrix.rows();
|
||||
ei_assert(size==b.rows() && "LLT::solve(): invalid number of rows of the right hand side matrix b");
|
||||
return solveInPlace((*result) = b);
|
||||
}
|
||||
typedef Matrix<typename Rhs::Scalar,
|
||||
MatrixType::ColsAtCompileTime,
|
||||
Rhs::ColsAtCompileTime,
|
||||
Rhs::PlainMatrixType::Options,
|
||||
MatrixType::MaxColsAtCompileTime,
|
||||
Rhs::MaxColsAtCompileTime> ReturnMatrixType;
|
||||
};
|
||||
|
||||
template<typename MatrixType, int UpLo, typename Rhs>
|
||||
struct ei_llt_solve_impl : public ReturnByValue<ei_llt_solve_impl<MatrixType,UpLo,Rhs> >
|
||||
{
|
||||
typedef typename ei_cleantype<typename Rhs::Nested>::type RhsNested;
|
||||
typedef LLT<MatrixType,UpLo> LLTType;
|
||||
const LLTType& m_llt;
|
||||
const typename Rhs::Nested m_rhs;
|
||||
|
||||
ei_llt_solve_impl(const LLTType& llt, const Rhs& rhs)
|
||||
: m_llt(llt), m_rhs(rhs)
|
||||
{}
|
||||
|
||||
inline int rows() const { return m_llt.matrixLLT().cols(); }
|
||||
inline int cols() const { return m_rhs.cols(); }
|
||||
|
||||
template<typename Dest> void evalTo(Dest& dst) const
|
||||
{
|
||||
dst = m_rhs;
|
||||
m_llt.solveInPlace(dst);
|
||||
}
|
||||
};
|
||||
|
||||
/** This is the \em in-place version of solve().
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user