Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/eigen3/Eigen/src/Cholesky/LDLT.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // This file is part of Eigen, a lightweight C++ template library
0002 // for linear algebra.
0003 //
0004 // Copyright (C) 2008-2011 Gael Guennebaud <gael.guennebaud@inria.fr>
0005 // Copyright (C) 2009 Keir Mierle <mierle@gmail.com>
0006 // Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
0007 // Copyright (C) 2011 Timothy E. Holy <tim.holy@gmail.com >
0008 //
0009 // This Source Code Form is subject to the terms of the Mozilla
0010 // Public License v. 2.0. If a copy of the MPL was not distributed
0011 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
0012 
0013 #ifndef EIGEN_LDLT_H
0014 #define EIGEN_LDLT_H
0015 
0016 namespace Eigen {
0017 
0018 namespace internal {
0019   template<typename _MatrixType, int _UpLo> struct traits<LDLT<_MatrixType, _UpLo> >
0020    : traits<_MatrixType>
0021   {
0022     typedef MatrixXpr XprKind;
0023     typedef SolverStorage StorageKind;
0024     typedef int StorageIndex;
0025     enum { Flags = 0 };
0026   };
0027 
0028   template<typename MatrixType, int UpLo> struct LDLT_Traits;
0029 
0030   // PositiveSemiDef means positive semi-definite and non-zero; same for NegativeSemiDef
0031   enum SignMatrix { PositiveSemiDef, NegativeSemiDef, ZeroSign, Indefinite };
0032 }
0033 
0034 /** \ingroup Cholesky_Module
0035   *
0036   * \class LDLT
0037   *
0038   * \brief Robust Cholesky decomposition of a matrix with pivoting
0039   *
0040   * \tparam _MatrixType the type of the matrix of which to compute the LDL^T Cholesky decomposition
0041   * \tparam _UpLo the triangular part that will be used for the decompositon: Lower (default) or Upper.
0042   *             The other triangular part won't be read.
0043   *
0044   * Perform a robust Cholesky decomposition of a positive semidefinite or negative semidefinite
0045   * matrix \f$ A \f$ such that \f$ A =  P^TLDL^*P \f$, where P is a permutation matrix, L
0046   * is lower triangular with a unit diagonal and D is a diagonal matrix.
0047   *
0048   * The decomposition uses pivoting to ensure stability, so that D will have
0049   * zeros in the bottom right rank(A) - n submatrix. Avoiding the square root
0050   * on D also stabilizes the computation.
0051   *
0052   * Remember that Cholesky decompositions are not rank-revealing. Also, do not use a Cholesky
0053   * decomposition to determine whether a system of equations has a solution.
0054   *
0055   * This class supports the \link InplaceDecomposition inplace decomposition \endlink mechanism.
0056   *
0057   * \sa MatrixBase::ldlt(), SelfAdjointView::ldlt(), class LLT
0058   */
0059 template<typename _MatrixType, int _UpLo> class LDLT
0060         : public SolverBase<LDLT<_MatrixType, _UpLo> >
0061 {
0062   public:
0063     typedef _MatrixType MatrixType;
0064     typedef SolverBase<LDLT> Base;
0065     friend class SolverBase<LDLT>;
0066 
0067     EIGEN_GENERIC_PUBLIC_INTERFACE(LDLT)
0068     enum {
0069       MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
0070       MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
0071       UpLo = _UpLo
0072     };
0073     typedef Matrix<Scalar, RowsAtCompileTime, 1, 0, MaxRowsAtCompileTime, 1> TmpMatrixType;
0074 
0075     typedef Transpositions<RowsAtCompileTime, MaxRowsAtCompileTime> TranspositionType;
0076     typedef PermutationMatrix<RowsAtCompileTime, MaxRowsAtCompileTime> PermutationType;
0077 
0078     typedef internal::LDLT_Traits<MatrixType,UpLo> Traits;
0079 
0080     /** \brief Default Constructor.
0081       *
0082       * The default constructor is useful in cases in which the user intends to
0083       * perform decompositions via LDLT::compute(const MatrixType&).
0084       */
0085     LDLT()
0086       : m_matrix(),
0087         m_transpositions(),
0088         m_sign(internal::ZeroSign),
0089         m_isInitialized(false)
0090     {}
0091 
0092     /** \brief Default Constructor with memory preallocation
0093       *
0094       * Like the default constructor but with preallocation of the internal data
0095       * according to the specified problem \a size.
0096       * \sa LDLT()
0097       */
0098     explicit LDLT(Index size)
0099       : m_matrix(size, size),
0100         m_transpositions(size),
0101         m_temporary(size),
0102         m_sign(internal::ZeroSign),
0103         m_isInitialized(false)
0104     {}
0105 
0106     /** \brief Constructor with decomposition
0107       *
0108       * This calculates the decomposition for the input \a matrix.
0109       *
0110       * \sa LDLT(Index size)
0111       */
0112     template<typename InputType>
0113     explicit LDLT(const EigenBase<InputType>& matrix)
0114       : m_matrix(matrix.rows(), matrix.cols()),
0115         m_transpositions(matrix.rows()),
0116         m_temporary(matrix.rows()),
0117         m_sign(internal::ZeroSign),
0118         m_isInitialized(false)
0119     {
0120       compute(matrix.derived());
0121     }
0122 
0123     /** \brief Constructs a LDLT factorization from a given matrix
0124       *
0125       * This overloaded constructor is provided for \link InplaceDecomposition inplace decomposition \endlink when \c MatrixType is a Eigen::Ref.
0126       *
0127       * \sa LDLT(const EigenBase&)
0128       */
0129     template<typename InputType>
0130     explicit LDLT(EigenBase<InputType>& matrix)
0131       : m_matrix(matrix.derived()),
0132         m_transpositions(matrix.rows()),
0133         m_temporary(matrix.rows()),
0134         m_sign(internal::ZeroSign),
0135         m_isInitialized(false)
0136     {
0137       compute(matrix.derived());
0138     }
0139 
0140     /** Clear any existing decomposition
0141      * \sa rankUpdate(w,sigma)
0142      */
0143     void setZero()
0144     {
0145       m_isInitialized = false;
0146     }
0147 
0148     /** \returns a view of the upper triangular matrix U */
0149     inline typename Traits::MatrixU matrixU() const
0150     {
0151       eigen_assert(m_isInitialized && "LDLT is not initialized.");
0152       return Traits::getU(m_matrix);
0153     }
0154 
0155     /** \returns a view of the lower triangular matrix L */
0156     inline typename Traits::MatrixL matrixL() const
0157     {
0158       eigen_assert(m_isInitialized && "LDLT is not initialized.");
0159       return Traits::getL(m_matrix);
0160     }
0161 
0162     /** \returns the permutation matrix P as a transposition sequence.
0163       */
0164     inline const TranspositionType& transpositionsP() const
0165     {
0166       eigen_assert(m_isInitialized && "LDLT is not initialized.");
0167       return m_transpositions;
0168     }
0169 
0170     /** \returns the coefficients of the diagonal matrix D */
0171     inline Diagonal<const MatrixType> vectorD() const
0172     {
0173       eigen_assert(m_isInitialized && "LDLT is not initialized.");
0174       return m_matrix.diagonal();
0175     }
0176 
0177     /** \returns true if the matrix is positive (semidefinite) */
0178     inline bool isPositive() const
0179     {
0180       eigen_assert(m_isInitialized && "LDLT is not initialized.");
0181       return m_sign == internal::PositiveSemiDef || m_sign == internal::ZeroSign;
0182     }
0183 
0184     /** \returns true if the matrix is negative (semidefinite) */
0185     inline bool isNegative(void) const
0186     {
0187       eigen_assert(m_isInitialized && "LDLT is not initialized.");
0188       return m_sign == internal::NegativeSemiDef || m_sign == internal::ZeroSign;
0189     }
0190 
0191     #ifdef EIGEN_PARSED_BY_DOXYGEN
0192     /** \returns a solution x of \f$ A x = b \f$ using the current decomposition of A.
0193       *
0194       * This function also supports in-place solves using the syntax <tt>x = decompositionObject.solve(x)</tt> .
0195       *
0196       * \note_about_checking_solutions
0197       *
0198       * More precisely, this method solves \f$ A x = b \f$ using the decomposition \f$ A = P^T L D L^* P \f$
0199       * by solving the systems \f$ P^T y_1 = b \f$, \f$ L y_2 = y_1 \f$, \f$ D y_3 = y_2 \f$,
0200       * \f$ L^* y_4 = y_3 \f$ and \f$ P x = y_4 \f$ in succession. If the matrix \f$ A \f$ is singular, then
0201       * \f$ D \f$ will also be singular (all the other matrices are invertible). In that case, the
0202       * least-square solution of \f$ D y_3 = y_2 \f$ is computed. This does not mean that this function
0203       * computes the least-square solution of \f$ A x = b \f$ if \f$ A \f$ is singular.
0204       *
0205       * \sa MatrixBase::ldlt(), SelfAdjointView::ldlt()
0206       */
0207     template<typename Rhs>
0208     inline const Solve<LDLT, Rhs>
0209     solve(const MatrixBase<Rhs>& b) const;
0210     #endif
0211 
0212     template<typename Derived>
0213     bool solveInPlace(MatrixBase<Derived> &bAndX) const;
0214 
0215     template<typename InputType>
0216     LDLT& compute(const EigenBase<InputType>& matrix);
0217 
0218     /** \returns an estimate of the reciprocal condition number of the matrix of
0219      *  which \c *this is the LDLT decomposition.
0220      */
0221     RealScalar rcond() const
0222     {
0223       eigen_assert(m_isInitialized && "LDLT is not initialized.");
0224       return internal::rcond_estimate_helper(m_l1_norm, *this);
0225     }
0226 
0227     template <typename Derived>
0228     LDLT& rankUpdate(const MatrixBase<Derived>& w, const RealScalar& alpha=1);
0229 
0230     /** \returns the internal LDLT decomposition matrix
0231       *
0232       * TODO: document the storage layout
0233       */
0234     inline const MatrixType& matrixLDLT() const
0235     {
0236       eigen_assert(m_isInitialized && "LDLT is not initialized.");
0237       return m_matrix;
0238     }
0239 
0240     MatrixType reconstructedMatrix() const;
0241 
0242     /** \returns the adjoint of \c *this, that is, a const reference to the decomposition itself as the underlying matrix is self-adjoint.
0243       *
0244       * This method is provided for compatibility with other matrix decompositions, thus enabling generic code such as:
0245       * \code x = decomposition.adjoint().solve(b) \endcode
0246       */
0247     const LDLT& adjoint() const { return *this; };
0248 
0249     EIGEN_DEVICE_FUNC inline EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_matrix.rows(); }
0250     EIGEN_DEVICE_FUNC inline EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_matrix.cols(); }
0251 
0252     /** \brief Reports whether previous computation was successful.
0253       *
0254       * \returns \c Success if computation was successful,
0255       *          \c NumericalIssue if the factorization failed because of a zero pivot.
0256       */
0257     ComputationInfo info() const
0258     {
0259       eigen_assert(m_isInitialized && "LDLT is not initialized.");
0260       return m_info;
0261     }
0262 
0263     #ifndef EIGEN_PARSED_BY_DOXYGEN
0264     template<typename RhsType, typename DstType>
0265     void _solve_impl(const RhsType &rhs, DstType &dst) const;
0266 
0267     template<bool Conjugate, typename RhsType, typename DstType>
0268     void _solve_impl_transposed(const RhsType &rhs, DstType &dst) const;
0269     #endif
0270 
0271   protected:
0272 
0273     static void check_template_parameters()
0274     {
0275       EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
0276     }
0277 
0278     /** \internal
0279       * Used to compute and store the Cholesky decomposition A = L D L^* = U^* D U.
0280       * The strict upper part is used during the decomposition, the strict lower
0281       * part correspond to the coefficients of L (its diagonal is equal to 1 and
0282       * is not stored), and the diagonal entries correspond to D.
0283       */
0284     MatrixType m_matrix;
0285     RealScalar m_l1_norm;
0286     TranspositionType m_transpositions;
0287     TmpMatrixType m_temporary;
0288     internal::SignMatrix m_sign;
0289     bool m_isInitialized;
0290     ComputationInfo m_info;
0291 };
0292 
0293 namespace internal {
0294 
0295 template<int UpLo> struct ldlt_inplace;
0296 
0297 template<> struct ldlt_inplace<Lower>
0298 {
0299   template<typename MatrixType, typename TranspositionType, typename Workspace>
0300   static bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, SignMatrix& sign)
0301   {
0302     using std::abs;
0303     typedef typename MatrixType::Scalar Scalar;
0304     typedef typename MatrixType::RealScalar RealScalar;
0305     typedef typename TranspositionType::StorageIndex IndexType;
0306     eigen_assert(mat.rows()==mat.cols());
0307     const Index size = mat.rows();
0308     bool found_zero_pivot = false;
0309     bool ret = true;
0310 
0311     if (size <= 1)
0312     {
0313       transpositions.setIdentity();
0314       if(size==0) sign = ZeroSign;
0315       else if (numext::real(mat.coeff(0,0)) > static_cast<RealScalar>(0) ) sign = PositiveSemiDef;
0316       else if (numext::real(mat.coeff(0,0)) < static_cast<RealScalar>(0)) sign = NegativeSemiDef;
0317       else sign = ZeroSign;
0318       return true;
0319     }
0320 
0321     for (Index k = 0; k < size; ++k)
0322     {
0323       // Find largest diagonal element
0324       Index index_of_biggest_in_corner;
0325       mat.diagonal().tail(size-k).cwiseAbs().maxCoeff(&index_of_biggest_in_corner);
0326       index_of_biggest_in_corner += k;
0327 
0328       transpositions.coeffRef(k) = IndexType(index_of_biggest_in_corner);
0329       if(k != index_of_biggest_in_corner)
0330       {
0331         // apply the transposition while taking care to consider only
0332         // the lower triangular part
0333         Index s = size-index_of_biggest_in_corner-1; // trailing size after the biggest element
0334         mat.row(k).head(k).swap(mat.row(index_of_biggest_in_corner).head(k));
0335         mat.col(k).tail(s).swap(mat.col(index_of_biggest_in_corner).tail(s));
0336         std::swap(mat.coeffRef(k,k),mat.coeffRef(index_of_biggest_in_corner,index_of_biggest_in_corner));
0337         for(Index i=k+1;i<index_of_biggest_in_corner;++i)
0338         {
0339           Scalar tmp = mat.coeffRef(i,k);
0340           mat.coeffRef(i,k) = numext::conj(mat.coeffRef(index_of_biggest_in_corner,i));
0341           mat.coeffRef(index_of_biggest_in_corner,i) = numext::conj(tmp);
0342         }
0343         if(NumTraits<Scalar>::IsComplex)
0344           mat.coeffRef(index_of_biggest_in_corner,k) = numext::conj(mat.coeff(index_of_biggest_in_corner,k));
0345       }
0346 
0347       // partition the matrix:
0348       //       A00 |  -  |  -
0349       // lu  = A10 | A11 |  -
0350       //       A20 | A21 | A22
0351       Index rs = size - k - 1;
0352       Block<MatrixType,Dynamic,1> A21(mat,k+1,k,rs,1);
0353       Block<MatrixType,1,Dynamic> A10(mat,k,0,1,k);
0354       Block<MatrixType,Dynamic,Dynamic> A20(mat,k+1,0,rs,k);
0355 
0356       if(k>0)
0357       {
0358         temp.head(k) = mat.diagonal().real().head(k).asDiagonal() * A10.adjoint();
0359         mat.coeffRef(k,k) -= (A10 * temp.head(k)).value();
0360         if(rs>0)
0361           A21.noalias() -= A20 * temp.head(k);
0362       }
0363 
0364       // In some previous versions of Eigen (e.g., 3.2.1), the scaling was omitted if the pivot
0365       // was smaller than the cutoff value. However, since LDLT is not rank-revealing
0366       // we should only make sure that we do not introduce INF or NaN values.
0367       // Remark that LAPACK also uses 0 as the cutoff value.
0368       RealScalar realAkk = numext::real(mat.coeffRef(k,k));
0369       bool pivot_is_valid = (abs(realAkk) > RealScalar(0));
0370 
0371       if(k==0 && !pivot_is_valid)
0372       {
0373         // The entire diagonal is zero, there is nothing more to do
0374         // except filling the transpositions, and checking whether the matrix is zero.
0375         sign = ZeroSign;
0376         for(Index j = 0; j<size; ++j)
0377         {
0378           transpositions.coeffRef(j) = IndexType(j);
0379           ret = ret && (mat.col(j).tail(size-j-1).array()==Scalar(0)).all();
0380         }
0381         return ret;
0382       }
0383 
0384       if((rs>0) && pivot_is_valid)
0385         A21 /= realAkk;
0386       else if(rs>0)
0387         ret = ret && (A21.array()==Scalar(0)).all();
0388 
0389       if(found_zero_pivot && pivot_is_valid) ret = false; // factorization failed
0390       else if(!pivot_is_valid) found_zero_pivot = true;
0391 
0392       if (sign == PositiveSemiDef) {
0393         if (realAkk < static_cast<RealScalar>(0)) sign = Indefinite;
0394       } else if (sign == NegativeSemiDef) {
0395         if (realAkk > static_cast<RealScalar>(0)) sign = Indefinite;
0396       } else if (sign == ZeroSign) {
0397         if (realAkk > static_cast<RealScalar>(0)) sign = PositiveSemiDef;
0398         else if (realAkk < static_cast<RealScalar>(0)) sign = NegativeSemiDef;
0399       }
0400     }
0401 
0402     return ret;
0403   }
0404 
0405   // Reference for the algorithm: Davis and Hager, "Multiple Rank
0406   // Modifications of a Sparse Cholesky Factorization" (Algorithm 1)
0407   // Trivial rearrangements of their computations (Timothy E. Holy)
0408   // allow their algorithm to work for rank-1 updates even if the
0409   // original matrix is not of full rank.
0410   // Here only rank-1 updates are implemented, to reduce the
0411   // requirement for intermediate storage and improve accuracy
0412   template<typename MatrixType, typename WDerived>
0413   static bool updateInPlace(MatrixType& mat, MatrixBase<WDerived>& w, const typename MatrixType::RealScalar& sigma=1)
0414   {
0415     using numext::isfinite;
0416     typedef typename MatrixType::Scalar Scalar;
0417     typedef typename MatrixType::RealScalar RealScalar;
0418 
0419     const Index size = mat.rows();
0420     eigen_assert(mat.cols() == size && w.size()==size);
0421 
0422     RealScalar alpha = 1;
0423 
0424     // Apply the update
0425     for (Index j = 0; j < size; j++)
0426     {
0427       // Check for termination due to an original decomposition of low-rank
0428       if (!(isfinite)(alpha))
0429         break;
0430 
0431       // Update the diagonal terms
0432       RealScalar dj = numext::real(mat.coeff(j,j));
0433       Scalar wj = w.coeff(j);
0434       RealScalar swj2 = sigma*numext::abs2(wj);
0435       RealScalar gamma = dj*alpha + swj2;
0436 
0437       mat.coeffRef(j,j) += swj2/alpha;
0438       alpha += swj2/dj;
0439 
0440 
0441       // Update the terms of L
0442       Index rs = size-j-1;
0443       w.tail(rs) -= wj * mat.col(j).tail(rs);
0444       if(gamma != 0)
0445         mat.col(j).tail(rs) += (sigma*numext::conj(wj)/gamma)*w.tail(rs);
0446     }
0447     return true;
0448   }
0449 
0450   template<typename MatrixType, typename TranspositionType, typename Workspace, typename WType>
0451   static bool update(MatrixType& mat, const TranspositionType& transpositions, Workspace& tmp, const WType& w, const typename MatrixType::RealScalar& sigma=1)
0452   {
0453     // Apply the permutation to the input w
0454     tmp = transpositions * w;
0455 
0456     return ldlt_inplace<Lower>::updateInPlace(mat,tmp,sigma);
0457   }
0458 };
0459 
0460 template<> struct ldlt_inplace<Upper>
0461 {
0462   template<typename MatrixType, typename TranspositionType, typename Workspace>
0463   static EIGEN_STRONG_INLINE bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, SignMatrix& sign)
0464   {
0465     Transpose<MatrixType> matt(mat);
0466     return ldlt_inplace<Lower>::unblocked(matt, transpositions, temp, sign);
0467   }
0468 
0469   template<typename MatrixType, typename TranspositionType, typename Workspace, typename WType>
0470   static EIGEN_STRONG_INLINE bool update(MatrixType& mat, TranspositionType& transpositions, Workspace& tmp, WType& w, const typename MatrixType::RealScalar& sigma=1)
0471   {
0472     Transpose<MatrixType> matt(mat);
0473     return ldlt_inplace<Lower>::update(matt, transpositions, tmp, w.conjugate(), sigma);
0474   }
0475 };
0476 
0477 template<typename MatrixType> struct LDLT_Traits<MatrixType,Lower>
0478 {
0479   typedef const TriangularView<const MatrixType, UnitLower> MatrixL;
0480   typedef const TriangularView<const typename MatrixType::AdjointReturnType, UnitUpper> MatrixU;
0481   static inline MatrixL getL(const MatrixType& m) { return MatrixL(m); }
0482   static inline MatrixU getU(const MatrixType& m) { return MatrixU(m.adjoint()); }
0483 };
0484 
0485 template<typename MatrixType> struct LDLT_Traits<MatrixType,Upper>
0486 {
0487   typedef const TriangularView<const typename MatrixType::AdjointReturnType, UnitLower> MatrixL;
0488   typedef const TriangularView<const MatrixType, UnitUpper> MatrixU;
0489   static inline MatrixL getL(const MatrixType& m) { return MatrixL(m.adjoint()); }
0490   static inline MatrixU getU(const MatrixType& m) { return MatrixU(m); }
0491 };
0492 
0493 } // end namespace internal
0494 
0495 /** Compute / recompute the LDLT decomposition A = L D L^* = U^* D U of \a matrix
0496   */
0497 template<typename MatrixType, int _UpLo>
0498 template<typename InputType>
0499 LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::compute(const EigenBase<InputType>& a)
0500 {
0501   check_template_parameters();
0502 
0503   eigen_assert(a.rows()==a.cols());
0504   const Index size = a.rows();
0505 
0506   m_matrix = a.derived();
0507 
0508   // Compute matrix L1 norm = max abs column sum.
0509   m_l1_norm = RealScalar(0);
0510   // TODO move this code to SelfAdjointView
0511   for (Index col = 0; col < size; ++col) {
0512     RealScalar abs_col_sum;
0513     if (_UpLo == Lower)
0514       abs_col_sum = m_matrix.col(col).tail(size - col).template lpNorm<1>() + m_matrix.row(col).head(col).template lpNorm<1>();
0515     else
0516       abs_col_sum = m_matrix.col(col).head(col).template lpNorm<1>() + m_matrix.row(col).tail(size - col).template lpNorm<1>();
0517     if (abs_col_sum > m_l1_norm)
0518       m_l1_norm = abs_col_sum;
0519   }
0520 
0521   m_transpositions.resize(size);
0522   m_isInitialized = false;
0523   m_temporary.resize(size);
0524   m_sign = internal::ZeroSign;
0525 
0526   m_info = internal::ldlt_inplace<UpLo>::unblocked(m_matrix, m_transpositions, m_temporary, m_sign) ? Success : NumericalIssue;
0527 
0528   m_isInitialized = true;
0529   return *this;
0530 }
0531 
0532 /** Update the LDLT decomposition:  given A = L D L^T, efficiently compute the decomposition of A + sigma w w^T.
0533  * \param w a vector to be incorporated into the decomposition.
0534  * \param sigma a scalar, +1 for updates and -1 for "downdates," which correspond to removing previously-added column vectors. Optional; default value is +1.
0535  * \sa setZero()
0536   */
0537 template<typename MatrixType, int _UpLo>
0538 template<typename Derived>
0539 LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::rankUpdate(const MatrixBase<Derived>& w, const typename LDLT<MatrixType,_UpLo>::RealScalar& sigma)
0540 {
0541   typedef typename TranspositionType::StorageIndex IndexType;
0542   const Index size = w.rows();
0543   if (m_isInitialized)
0544   {
0545     eigen_assert(m_matrix.rows()==size);
0546   }
0547   else
0548   {
0549     m_matrix.resize(size,size);
0550     m_matrix.setZero();
0551     m_transpositions.resize(size);
0552     for (Index i = 0; i < size; i++)
0553       m_transpositions.coeffRef(i) = IndexType(i);
0554     m_temporary.resize(size);
0555     m_sign = sigma>=0 ? internal::PositiveSemiDef : internal::NegativeSemiDef;
0556     m_isInitialized = true;
0557   }
0558 
0559   internal::ldlt_inplace<UpLo>::update(m_matrix, m_transpositions, m_temporary, w, sigma);
0560 
0561   return *this;
0562 }
0563 
0564 #ifndef EIGEN_PARSED_BY_DOXYGEN
0565 template<typename _MatrixType, int _UpLo>
0566 template<typename RhsType, typename DstType>
0567 void LDLT<_MatrixType,_UpLo>::_solve_impl(const RhsType &rhs, DstType &dst) const
0568 {
0569   _solve_impl_transposed<true>(rhs, dst);
0570 }
0571 
0572 template<typename _MatrixType,int _UpLo>
0573 template<bool Conjugate, typename RhsType, typename DstType>
0574 void LDLT<_MatrixType,_UpLo>::_solve_impl_transposed(const RhsType &rhs, DstType &dst) const
0575 {
0576   // dst = P b
0577   dst = m_transpositions * rhs;
0578 
0579   // dst = L^-1 (P b)
0580   // dst = L^-*T (P b)
0581   matrixL().template conjugateIf<!Conjugate>().solveInPlace(dst);
0582 
0583   // dst = D^-* (L^-1 P b)
0584   // dst = D^-1 (L^-*T P b)
0585   // more precisely, use pseudo-inverse of D (see bug 241)
0586   using std::abs;
0587   const typename Diagonal<const MatrixType>::RealReturnType vecD(vectorD());
0588   // In some previous versions, tolerance was set to the max of 1/highest (or rather numeric_limits::min())
0589   // and the maximal diagonal entry * epsilon as motivated by LAPACK's xGELSS:
0590   // RealScalar tolerance = numext::maxi(vecD.array().abs().maxCoeff() * NumTraits<RealScalar>::epsilon(),RealScalar(1) / NumTraits<RealScalar>::highest());
0591   // However, LDLT is not rank revealing, and so adjusting the tolerance wrt to the highest
0592   // diagonal element is not well justified and leads to numerical issues in some cases.
0593   // Moreover, Lapack's xSYTRS routines use 0 for the tolerance.
0594   // Using numeric_limits::min() gives us more robustness to denormals.
0595   RealScalar tolerance = (std::numeric_limits<RealScalar>::min)();
0596   for (Index i = 0; i < vecD.size(); ++i)
0597   {
0598     if(abs(vecD(i)) > tolerance)
0599       dst.row(i) /= vecD(i);
0600     else
0601       dst.row(i).setZero();
0602   }
0603 
0604   // dst = L^-* (D^-* L^-1 P b)
0605   // dst = L^-T (D^-1 L^-*T P b)
0606   matrixL().transpose().template conjugateIf<Conjugate>().solveInPlace(dst);
0607 
0608   // dst = P^T (L^-* D^-* L^-1 P b) = A^-1 b
0609   // dst = P^-T (L^-T D^-1 L^-*T P b) = A^-1 b
0610   dst = m_transpositions.transpose() * dst;
0611 }
0612 #endif
0613 
0614 /** \internal use x = ldlt_object.solve(x);
0615   *
0616   * This is the \em in-place version of solve().
0617   *
0618   * \param bAndX represents both the right-hand side matrix b and result x.
0619   *
0620   * \returns true always! If you need to check for existence of solutions, use another decomposition like LU, QR, or SVD.
0621   *
0622   * This version avoids a copy when the right hand side matrix b is not
0623   * needed anymore.
0624   *
0625   * \sa LDLT::solve(), MatrixBase::ldlt()
0626   */
0627 template<typename MatrixType,int _UpLo>
0628 template<typename Derived>
0629 bool LDLT<MatrixType,_UpLo>::solveInPlace(MatrixBase<Derived> &bAndX) const
0630 {
0631   eigen_assert(m_isInitialized && "LDLT is not initialized.");
0632   eigen_assert(m_matrix.rows() == bAndX.rows());
0633 
0634   bAndX = this->solve(bAndX);
0635 
0636   return true;
0637 }
0638 
0639 /** \returns the matrix represented by the decomposition,
0640  * i.e., it returns the product: P^T L D L^* P.
0641  * This function is provided for debug purpose. */
0642 template<typename MatrixType, int _UpLo>
0643 MatrixType LDLT<MatrixType,_UpLo>::reconstructedMatrix() const
0644 {
0645   eigen_assert(m_isInitialized && "LDLT is not initialized.");
0646   const Index size = m_matrix.rows();
0647   MatrixType res(size,size);
0648 
0649   // P
0650   res.setIdentity();
0651   res = transpositionsP() * res;
0652   // L^* P
0653   res = matrixU() * res;
0654   // D(L^*P)
0655   res = vectorD().real().asDiagonal() * res;
0656   // L(DL^*P)
0657   res = matrixL() * res;
0658   // P^T (LDL^*P)
0659   res = transpositionsP().transpose() * res;
0660 
0661   return res;
0662 }
0663 
0664 /** \cholesky_module
0665   * \returns the Cholesky decomposition with full pivoting without square root of \c *this
0666   * \sa MatrixBase::ldlt()
0667   */
0668 template<typename MatrixType, unsigned int UpLo>
0669 inline const LDLT<typename SelfAdjointView<MatrixType, UpLo>::PlainObject, UpLo>
0670 SelfAdjointView<MatrixType, UpLo>::ldlt() const
0671 {
0672   return LDLT<PlainObject,UpLo>(m_matrix);
0673 }
0674 
0675 /** \cholesky_module
0676   * \returns the Cholesky decomposition with full pivoting without square root of \c *this
0677   * \sa SelfAdjointView::ldlt()
0678   */
0679 template<typename Derived>
0680 inline const LDLT<typename MatrixBase<Derived>::PlainObject>
0681 MatrixBase<Derived>::ldlt() const
0682 {
0683   return LDLT<PlainObject>(derived());
0684 }
0685 
0686 } // end namespace Eigen
0687 
0688 #endif // EIGEN_LDLT_H