diff options
author | Benoit Jacob <jacob.benoit.1@gmail.com> | 2010-02-25 21:07:30 -0500 |
---|---|---|
committer | Benoit Jacob <jacob.benoit.1@gmail.com> | 2010-02-25 21:07:30 -0500 |
commit | b1c6c215a43850b2bc5bdc393ab5a1179e858024 (patch) | |
tree | 9ae1234383bef2204802606501a47bb5c05ec1d2 /Eigen/src/LU | |
parent | 769641bc58745fecc1fa4e537466a1fff48f4a8a (diff) | |
parent | 90e4a605ef920759a23cdbd24e6e7b69ce549162 (diff) |
merge
Diffstat (limited to 'Eigen/src/LU')
-rw-r--r-- | Eigen/src/LU/FullPivLU.h | 47 | ||||
-rw-r--r-- | Eigen/src/LU/Inverse.h | 4 | ||||
-rw-r--r-- | Eigen/src/LU/PartialPivLU.h | 27 |
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 |