aboutsummaryrefslogtreecommitdiffhomepage
path: root/Eigen/src/LU
diff options
context:
space:
mode:
authorGravatar Benoit Jacob <jacob.benoit.1@gmail.com>2010-02-25 21:07:30 -0500
committerGravatar Benoit Jacob <jacob.benoit.1@gmail.com>2010-02-25 21:07:30 -0500
commitb1c6c215a43850b2bc5bdc393ab5a1179e858024 (patch)
tree9ae1234383bef2204802606501a47bb5c05ec1d2 /Eigen/src/LU
parent769641bc58745fecc1fa4e537466a1fff48f4a8a (diff)
parent90e4a605ef920759a23cdbd24e6e7b69ce549162 (diff)
merge
Diffstat (limited to 'Eigen/src/LU')
-rw-r--r--Eigen/src/LU/FullPivLU.h47
-rw-r--r--Eigen/src/LU/Inverse.h4
-rw-r--r--Eigen/src/LU/PartialPivLU.h27
3 files changed, 66 insertions, 12 deletions
diff --git a/Eigen/src/LU/FullPivLU.h b/Eigen/src/LU/FullPivLU.h
index 72e878223..dea6ec41c 100644
--- a/Eigen/src/LU/FullPivLU.h
+++ b/Eigen/src/LU/FullPivLU.h
@@ -119,7 +119,7 @@ template<typename _MatrixType> class FullPivLU
* diagonal coefficient of U.
*/
RealScalar maxPivot() const { return m_maxpivot; }
-
+
/** \returns the permutation matrix P
*
* \sa permutationQ()
@@ -251,6 +251,7 @@ template<typename _MatrixType> class FullPivLU
{
m_usePrescribedThreshold = true;
m_prescribedThreshold = threshold;
+ return *this;
}
/** Allows to come back to the default behavior, letting Eigen use its default formula for
@@ -360,6 +361,8 @@ template<typename _MatrixType> class FullPivLU
(*this, MatrixType::Identity(m_lu.rows(), m_lu.cols()));
}
+ MatrixType reconstructedMatrix() const;
+
inline int rows() const { return m_lu.rows(); }
inline int cols() const { return m_lu.cols(); }
@@ -403,6 +406,7 @@ FullPivLU<MatrixType>& FullPivLU<MatrixType>::compute(const MatrixType& matrix)
m_nonzero_pivots = size; // the generic case is that in which all pivots are nonzero (invertible case)
m_maxpivot = RealScalar(0);
+ RealScalar cutoff(0);
for(int k = 0; k < size; ++k)
{
@@ -417,8 +421,14 @@ FullPivLU<MatrixType>& FullPivLU<MatrixType>::compute(const MatrixType& matrix)
row_of_biggest_in_corner += k; // correct the values! since they were computed in the corner,
col_of_biggest_in_corner += k; // need to add k to them.
- // if the pivot (hence the corner) is exactly zero, terminate to avoid generating nan/inf values
- if(biggest_in_corner == RealScalar(0))
+ // when k==0, biggest_in_corner is the biggest coeff absolute value in the original matrix
+ if(k == 0) cutoff = biggest_in_corner * NumTraits<Scalar>::epsilon();
+
+ // if the pivot (hence the corner) is "zero", terminate to avoid generating nan/inf values.
+ // Notice that using an exact comparison (biggest_in_corner==0) here, as Golub-van Loan do in
+ // their pseudo-code, results in numerical instability! The cutoff here has been validated
+ // by running the unit test 'lu' with many repetitions.
+ if(biggest_in_corner < cutoff)
{
// before exiting, make sure to initialize the still uninitialized transpositions
// in a sane state without destroying what we already have.
@@ -479,6 +489,31 @@ typename ei_traits<MatrixType>::Scalar FullPivLU<MatrixType>::determinant() cons
return Scalar(m_det_pq) * Scalar(m_lu.diagonal().prod());
}
+/** \returns the matrix represented by the decomposition,
+ * i.e., it returns the product: P^{-1} L U Q^{-1}.
+ * This function is provided for debug purpose. */
+template<typename MatrixType>
+MatrixType FullPivLU<MatrixType>::reconstructedMatrix() const
+{
+ ei_assert(m_isInitialized && "LU is not initialized.");
+ const int smalldim = std::min(m_lu.rows(), m_lu.cols());
+ // LU
+ MatrixType res(m_lu.rows(),m_lu.cols());
+ // FIXME the .toDenseMatrix() should not be needed...
+ res = m_lu.corner(TopLeft,m_lu.rows(),smalldim)
+ .template triangularView<UnitLower>().toDenseMatrix()
+ * m_lu.corner(TopLeft,smalldim,m_lu.cols())
+ .template triangularView<Upper>().toDenseMatrix();
+
+ // P^{-1}(LU)
+ res = m_p.inverse() * res;
+
+ // (P^{-1}LU)Q^{-1}
+ res = res * m_q.inverse();
+
+ return res;
+}
+
/********* Implementation of kernel() **************************************************/
template<typename _MatrixType>
@@ -630,7 +665,7 @@ struct ei_solve_retval<FullPivLU<_MatrixType>, Rhs>
return;
}
- typename Rhs::PlainMatrixType c(rhs().rows(), rhs().cols());
+ typename Rhs::PlainObject c(rhs().rows(), rhs().cols());
// Step 1
c = dec().permutationP() * rhs();
@@ -670,10 +705,10 @@ struct ei_solve_retval<FullPivLU<_MatrixType>, Rhs>
* \sa class FullPivLU
*/
template<typename Derived>
-inline const FullPivLU<typename MatrixBase<Derived>::PlainMatrixType>
+inline const FullPivLU<typename MatrixBase<Derived>::PlainObject>
MatrixBase<Derived>::fullPivLu() const
{
- return FullPivLU<PlainMatrixType>(eval());
+ return FullPivLU<PlainObject>(eval());
}
#endif // EIGEN_LU_H
diff --git a/Eigen/src/LU/Inverse.h b/Eigen/src/LU/Inverse.h
index 36392c8d8..e20da70d6 100644
--- a/Eigen/src/LU/Inverse.h
+++ b/Eigen/src/LU/Inverse.h
@@ -238,7 +238,7 @@ struct ei_compute_inverse_and_det_with_check<MatrixType, ResultType, 4>
template<typename MatrixType>
struct ei_traits<ei_inverse_impl<MatrixType> >
{
- typedef typename MatrixType::PlainMatrixType ReturnMatrixType;
+ typedef typename MatrixType::PlainObject ReturnType;
};
template<typename MatrixType>
@@ -327,7 +327,7 @@ inline void MatrixBase<Derived>::computeInverseAndDetWithCheck(
typedef typename ei_meta_if<
RowsAtCompileTime == 2,
typename ei_cleantype<typename ei_nested<Derived, 2>::type>::type,
- PlainMatrixType
+ PlainObject
>::ret MatrixType;
ei_compute_inverse_and_det_with_check<MatrixType, ResultType>::run
(derived(), absDeterminantThreshold, inverse, determinant, invertible);
diff --git a/Eigen/src/LU/PartialPivLU.h b/Eigen/src/LU/PartialPivLU.h
index 3925ac1b0..a60596668 100644
--- a/Eigen/src/LU/PartialPivLU.h
+++ b/Eigen/src/LU/PartialPivLU.h
@@ -165,6 +165,8 @@ template<typename _MatrixType> class PartialPivLU
*/
typename ei_traits<MatrixType>::Scalar determinant() const;
+ MatrixType reconstructedMatrix() const;
+
inline int rows() const { return m_lu.rows(); }
inline int cols() const { return m_lu.cols(); }
@@ -400,6 +402,23 @@ typename ei_traits<MatrixType>::Scalar PartialPivLU<MatrixType>::determinant() c
return Scalar(m_det_p) * m_lu.diagonal().prod();
}
+/** \returns the matrix represented by the decomposition,
+ * i.e., it returns the product: P^{-1} L U.
+ * This function is provided for debug purpose. */
+template<typename MatrixType>
+MatrixType PartialPivLU<MatrixType>::reconstructedMatrix() const
+{
+ ei_assert(m_isInitialized && "LU is not initialized.");
+ // LU
+ MatrixType res = m_lu.template triangularView<UnitLower>().toDenseMatrix()
+ * m_lu.template triangularView<Upper>();
+
+ // P^{-1}(LU)
+ res = m_p.inverse() * res;
+
+ return res;
+}
+
/***** Implementation of solve() *****************************************************/
template<typename _MatrixType, typename Rhs>
@@ -442,10 +461,10 @@ struct ei_solve_retval<PartialPivLU<_MatrixType>, Rhs>
* \sa class PartialPivLU
*/
template<typename Derived>
-inline const PartialPivLU<typename MatrixBase<Derived>::PlainMatrixType>
+inline const PartialPivLU<typename MatrixBase<Derived>::PlainObject>
MatrixBase<Derived>::partialPivLu() const
{
- return PartialPivLU<PlainMatrixType>(eval());
+ return PartialPivLU<PlainObject>(eval());
}
/** \lu_module
@@ -457,10 +476,10 @@ MatrixBase<Derived>::partialPivLu() const
* \sa class PartialPivLU
*/
template<typename Derived>
-inline const PartialPivLU<typename MatrixBase<Derived>::PlainMatrixType>
+inline const PartialPivLU<typename MatrixBase<Derived>::PlainObject>
MatrixBase<Derived>::lu() const
{
- return PartialPivLU<PlainMatrixType>(eval());
+ return PartialPivLU<PlainObject>(eval());
}
#endif // EIGEN_PARTIALLU_H