1*bf2c3715SXin Li // This file is part of Eigen, a lightweight C++ template library 2*bf2c3715SXin Li // for linear algebra. 3*bf2c3715SXin Li // 4*bf2c3715SXin Li // Copyright (C) 2008 Gael Guennebaud <[email protected]> 5*bf2c3715SXin Li // 6*bf2c3715SXin Li // This Source Code Form is subject to the terms of the Mozilla 7*bf2c3715SXin Li // Public License v. 2.0. If a copy of the MPL was not distributed 8*bf2c3715SXin Li // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 9*bf2c3715SXin Li 10*bf2c3715SXin Li #ifndef EIGEN_LLT_H 11*bf2c3715SXin Li #define EIGEN_LLT_H 12*bf2c3715SXin Li 13*bf2c3715SXin Li namespace Eigen { 14*bf2c3715SXin Li 15*bf2c3715SXin Li namespace internal{ 16*bf2c3715SXin Li 17*bf2c3715SXin Li template<typename _MatrixType, int _UpLo> struct traits<LLT<_MatrixType, _UpLo> > 18*bf2c3715SXin Li : traits<_MatrixType> 19*bf2c3715SXin Li { 20*bf2c3715SXin Li typedef MatrixXpr XprKind; 21*bf2c3715SXin Li typedef SolverStorage StorageKind; 22*bf2c3715SXin Li typedef int StorageIndex; 23*bf2c3715SXin Li enum { Flags = 0 }; 24*bf2c3715SXin Li }; 25*bf2c3715SXin Li 26*bf2c3715SXin Li template<typename MatrixType, int UpLo> struct LLT_Traits; 27*bf2c3715SXin Li } 28*bf2c3715SXin Li 29*bf2c3715SXin Li /** \ingroup Cholesky_Module 30*bf2c3715SXin Li * 31*bf2c3715SXin Li * \class LLT 32*bf2c3715SXin Li * 33*bf2c3715SXin Li * \brief Standard Cholesky decomposition (LL^T) of a matrix and associated features 34*bf2c3715SXin Li * 35*bf2c3715SXin Li * \tparam _MatrixType the type of the matrix of which we are computing the LL^T Cholesky decomposition 36*bf2c3715SXin Li * \tparam _UpLo the triangular part that will be used for the decompositon: Lower (default) or Upper. 37*bf2c3715SXin Li * The other triangular part won't be read. 38*bf2c3715SXin Li * 39*bf2c3715SXin Li * This class performs a LL^T Cholesky decomposition of a symmetric, positive definite 40*bf2c3715SXin Li * matrix A such that A = LL^* = U^*U, where L is lower triangular. 41*bf2c3715SXin Li * 42*bf2c3715SXin Li * While the Cholesky decomposition is particularly useful to solve selfadjoint problems like D^*D x = b, 43*bf2c3715SXin Li * for that purpose, we recommend the Cholesky decomposition without square root which is more stable 44*bf2c3715SXin Li * and even faster. Nevertheless, this standard Cholesky decomposition remains useful in many other 45*bf2c3715SXin Li * situations like generalised eigen problems with hermitian matrices. 46*bf2c3715SXin Li * 47*bf2c3715SXin Li * Remember that Cholesky decompositions are not rank-revealing. This LLT decomposition is only stable on positive definite matrices, 48*bf2c3715SXin Li * use LDLT instead for the semidefinite case. Also, do not use a Cholesky decomposition to determine whether a system of equations 49*bf2c3715SXin Li * has a solution. 50*bf2c3715SXin Li * 51*bf2c3715SXin Li * Example: \include LLT_example.cpp 52*bf2c3715SXin Li * Output: \verbinclude LLT_example.out 53*bf2c3715SXin Li * 54*bf2c3715SXin Li * \b Performance: for best performance, it is recommended to use a column-major storage format 55*bf2c3715SXin Li * with the Lower triangular part (the default), or, equivalently, a row-major storage format 56*bf2c3715SXin Li * with the Upper triangular part. Otherwise, you might get a 20% slowdown for the full factorization 57*bf2c3715SXin Li * step, and rank-updates can be up to 3 times slower. 58*bf2c3715SXin Li * 59*bf2c3715SXin Li * This class supports the \link InplaceDecomposition inplace decomposition \endlink mechanism. 60*bf2c3715SXin Li * 61*bf2c3715SXin Li * Note that during the decomposition, only the lower (or upper, as defined by _UpLo) triangular part of A is considered. 62*bf2c3715SXin Li * Therefore, the strict lower part does not have to store correct values. 63*bf2c3715SXin Li * 64*bf2c3715SXin Li * \sa MatrixBase::llt(), SelfAdjointView::llt(), class LDLT 65*bf2c3715SXin Li */ 66*bf2c3715SXin Li template<typename _MatrixType, int _UpLo> class LLT 67*bf2c3715SXin Li : public SolverBase<LLT<_MatrixType, _UpLo> > 68*bf2c3715SXin Li { 69*bf2c3715SXin Li public: 70*bf2c3715SXin Li typedef _MatrixType MatrixType; 71*bf2c3715SXin Li typedef SolverBase<LLT> Base; 72*bf2c3715SXin Li friend class SolverBase<LLT>; 73*bf2c3715SXin Li 74*bf2c3715SXin Li EIGEN_GENERIC_PUBLIC_INTERFACE(LLT) 75*bf2c3715SXin Li enum { 76*bf2c3715SXin Li MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime 77*bf2c3715SXin Li }; 78*bf2c3715SXin Li 79*bf2c3715SXin Li enum { 80*bf2c3715SXin Li PacketSize = internal::packet_traits<Scalar>::size, 81*bf2c3715SXin Li AlignmentMask = int(PacketSize)-1, 82*bf2c3715SXin Li UpLo = _UpLo 83*bf2c3715SXin Li }; 84*bf2c3715SXin Li 85*bf2c3715SXin Li typedef internal::LLT_Traits<MatrixType,UpLo> Traits; 86*bf2c3715SXin Li 87*bf2c3715SXin Li /** 88*bf2c3715SXin Li * \brief Default Constructor. 89*bf2c3715SXin Li * 90*bf2c3715SXin Li * The default constructor is useful in cases in which the user intends to 91*bf2c3715SXin Li * perform decompositions via LLT::compute(const MatrixType&). 92*bf2c3715SXin Li */ 93*bf2c3715SXin Li LLT() : m_matrix(), m_isInitialized(false) {} 94*bf2c3715SXin Li 95*bf2c3715SXin Li /** \brief Default Constructor with memory preallocation 96*bf2c3715SXin Li * 97*bf2c3715SXin Li * Like the default constructor but with preallocation of the internal data 98*bf2c3715SXin Li * according to the specified problem \a size. 99*bf2c3715SXin Li * \sa LLT() 100*bf2c3715SXin Li */ 101*bf2c3715SXin Li explicit LLT(Index size) : m_matrix(size, size), 102*bf2c3715SXin Li m_isInitialized(false) {} 103*bf2c3715SXin Li 104*bf2c3715SXin Li template<typename InputType> 105*bf2c3715SXin Li explicit LLT(const EigenBase<InputType>& matrix) 106*bf2c3715SXin Li : m_matrix(matrix.rows(), matrix.cols()), 107*bf2c3715SXin Li m_isInitialized(false) 108*bf2c3715SXin Li { 109*bf2c3715SXin Li compute(matrix.derived()); 110*bf2c3715SXin Li } 111*bf2c3715SXin Li 112*bf2c3715SXin Li /** \brief Constructs a LLT factorization from a given matrix 113*bf2c3715SXin Li * 114*bf2c3715SXin Li * This overloaded constructor is provided for \link InplaceDecomposition inplace decomposition \endlink when 115*bf2c3715SXin Li * \c MatrixType is a Eigen::Ref. 116*bf2c3715SXin Li * 117*bf2c3715SXin Li * \sa LLT(const EigenBase&) 118*bf2c3715SXin Li */ 119*bf2c3715SXin Li template<typename InputType> 120*bf2c3715SXin Li explicit LLT(EigenBase<InputType>& matrix) 121*bf2c3715SXin Li : m_matrix(matrix.derived()), 122*bf2c3715SXin Li m_isInitialized(false) 123*bf2c3715SXin Li { 124*bf2c3715SXin Li compute(matrix.derived()); 125*bf2c3715SXin Li } 126*bf2c3715SXin Li 127*bf2c3715SXin Li /** \returns a view of the upper triangular matrix U */ 128*bf2c3715SXin Li inline typename Traits::MatrixU matrixU() const 129*bf2c3715SXin Li { 130*bf2c3715SXin Li eigen_assert(m_isInitialized && "LLT is not initialized."); 131*bf2c3715SXin Li return Traits::getU(m_matrix); 132*bf2c3715SXin Li } 133*bf2c3715SXin Li 134*bf2c3715SXin Li /** \returns a view of the lower triangular matrix L */ 135*bf2c3715SXin Li inline typename Traits::MatrixL matrixL() const 136*bf2c3715SXin Li { 137*bf2c3715SXin Li eigen_assert(m_isInitialized && "LLT is not initialized."); 138*bf2c3715SXin Li return Traits::getL(m_matrix); 139*bf2c3715SXin Li } 140*bf2c3715SXin Li 141*bf2c3715SXin Li #ifdef EIGEN_PARSED_BY_DOXYGEN 142*bf2c3715SXin Li /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A. 143*bf2c3715SXin Li * 144*bf2c3715SXin Li * Since this LLT class assumes anyway that the matrix A is invertible, the solution 145*bf2c3715SXin Li * theoretically exists and is unique regardless of b. 146*bf2c3715SXin Li * 147*bf2c3715SXin Li * Example: \include LLT_solve.cpp 148*bf2c3715SXin Li * Output: \verbinclude LLT_solve.out 149*bf2c3715SXin Li * 150*bf2c3715SXin Li * \sa solveInPlace(), MatrixBase::llt(), SelfAdjointView::llt() 151*bf2c3715SXin Li */ 152*bf2c3715SXin Li template<typename Rhs> 153*bf2c3715SXin Li inline const Solve<LLT, Rhs> 154*bf2c3715SXin Li solve(const MatrixBase<Rhs>& b) const; 155*bf2c3715SXin Li #endif 156*bf2c3715SXin Li 157*bf2c3715SXin Li template<typename Derived> 158*bf2c3715SXin Li void solveInPlace(const MatrixBase<Derived> &bAndX) const; 159*bf2c3715SXin Li 160*bf2c3715SXin Li template<typename InputType> 161*bf2c3715SXin Li LLT& compute(const EigenBase<InputType>& matrix); 162*bf2c3715SXin Li 163*bf2c3715SXin Li /** \returns an estimate of the reciprocal condition number of the matrix of 164*bf2c3715SXin Li * which \c *this is the Cholesky decomposition. 165*bf2c3715SXin Li */ 166*bf2c3715SXin Li RealScalar rcond() const 167*bf2c3715SXin Li { 168*bf2c3715SXin Li eigen_assert(m_isInitialized && "LLT is not initialized."); 169*bf2c3715SXin Li eigen_assert(m_info == Success && "LLT failed because matrix appears to be negative"); 170*bf2c3715SXin Li return internal::rcond_estimate_helper(m_l1_norm, *this); 171*bf2c3715SXin Li } 172*bf2c3715SXin Li 173*bf2c3715SXin Li /** \returns the LLT decomposition matrix 174*bf2c3715SXin Li * 175*bf2c3715SXin Li * TODO: document the storage layout 176*bf2c3715SXin Li */ 177*bf2c3715SXin Li inline const MatrixType& matrixLLT() const 178*bf2c3715SXin Li { 179*bf2c3715SXin Li eigen_assert(m_isInitialized && "LLT is not initialized."); 180*bf2c3715SXin Li return m_matrix; 181*bf2c3715SXin Li } 182*bf2c3715SXin Li 183*bf2c3715SXin Li MatrixType reconstructedMatrix() const; 184*bf2c3715SXin Li 185*bf2c3715SXin Li 186*bf2c3715SXin Li /** \brief Reports whether previous computation was successful. 187*bf2c3715SXin Li * 188*bf2c3715SXin Li * \returns \c Success if computation was successful, 189*bf2c3715SXin Li * \c NumericalIssue if the matrix.appears not to be positive definite. 190*bf2c3715SXin Li */ 191*bf2c3715SXin Li ComputationInfo info() const 192*bf2c3715SXin Li { 193*bf2c3715SXin Li eigen_assert(m_isInitialized && "LLT is not initialized."); 194*bf2c3715SXin Li return m_info; 195*bf2c3715SXin Li } 196*bf2c3715SXin Li 197*bf2c3715SXin Li /** \returns the adjoint of \c *this, that is, a const reference to the decomposition itself as the underlying matrix is self-adjoint. 198*bf2c3715SXin Li * 199*bf2c3715SXin Li * This method is provided for compatibility with other matrix decompositions, thus enabling generic code such as: 200*bf2c3715SXin Li * \code x = decomposition.adjoint().solve(b) \endcode 201*bf2c3715SXin Li */ 202*bf2c3715SXin Li const LLT& adjoint() const EIGEN_NOEXCEPT { return *this; }; 203*bf2c3715SXin Li 204*bf2c3715SXin Li inline EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_matrix.rows(); } 205*bf2c3715SXin Li inline EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_matrix.cols(); } 206*bf2c3715SXin Li 207*bf2c3715SXin Li template<typename VectorType> 208*bf2c3715SXin Li LLT & rankUpdate(const VectorType& vec, const RealScalar& sigma = 1); 209*bf2c3715SXin Li 210*bf2c3715SXin Li #ifndef EIGEN_PARSED_BY_DOXYGEN 211*bf2c3715SXin Li template<typename RhsType, typename DstType> 212*bf2c3715SXin Li void _solve_impl(const RhsType &rhs, DstType &dst) const; 213*bf2c3715SXin Li 214*bf2c3715SXin Li template<bool Conjugate, typename RhsType, typename DstType> 215*bf2c3715SXin Li void _solve_impl_transposed(const RhsType &rhs, DstType &dst) const; 216*bf2c3715SXin Li #endif 217*bf2c3715SXin Li 218*bf2c3715SXin Li protected: 219*bf2c3715SXin Li 220*bf2c3715SXin Li static void check_template_parameters() 221*bf2c3715SXin Li { 222*bf2c3715SXin Li EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar); 223*bf2c3715SXin Li } 224*bf2c3715SXin Li 225*bf2c3715SXin Li /** \internal 226*bf2c3715SXin Li * Used to compute and store L 227*bf2c3715SXin Li * The strict upper part is not used and even not initialized. 228*bf2c3715SXin Li */ 229*bf2c3715SXin Li MatrixType m_matrix; 230*bf2c3715SXin Li RealScalar m_l1_norm; 231*bf2c3715SXin Li bool m_isInitialized; 232*bf2c3715SXin Li ComputationInfo m_info; 233*bf2c3715SXin Li }; 234*bf2c3715SXin Li 235*bf2c3715SXin Li namespace internal { 236*bf2c3715SXin Li 237*bf2c3715SXin Li template<typename Scalar, int UpLo> struct llt_inplace; 238*bf2c3715SXin Li 239*bf2c3715SXin Li template<typename MatrixType, typename VectorType> 240*bf2c3715SXin Li static Index llt_rank_update_lower(MatrixType& mat, const VectorType& vec, const typename MatrixType::RealScalar& sigma) 241*bf2c3715SXin Li { 242*bf2c3715SXin Li using std::sqrt; 243*bf2c3715SXin Li typedef typename MatrixType::Scalar Scalar; 244*bf2c3715SXin Li typedef typename MatrixType::RealScalar RealScalar; 245*bf2c3715SXin Li typedef typename MatrixType::ColXpr ColXpr; 246*bf2c3715SXin Li typedef typename internal::remove_all<ColXpr>::type ColXprCleaned; 247*bf2c3715SXin Li typedef typename ColXprCleaned::SegmentReturnType ColXprSegment; 248*bf2c3715SXin Li typedef Matrix<Scalar,Dynamic,1> TempVectorType; 249*bf2c3715SXin Li typedef typename TempVectorType::SegmentReturnType TempVecSegment; 250*bf2c3715SXin Li 251*bf2c3715SXin Li Index n = mat.cols(); 252*bf2c3715SXin Li eigen_assert(mat.rows()==n && vec.size()==n); 253*bf2c3715SXin Li 254*bf2c3715SXin Li TempVectorType temp; 255*bf2c3715SXin Li 256*bf2c3715SXin Li if(sigma>0) 257*bf2c3715SXin Li { 258*bf2c3715SXin Li // This version is based on Givens rotations. 259*bf2c3715SXin Li // It is faster than the other one below, but only works for updates, 260*bf2c3715SXin Li // i.e., for sigma > 0 261*bf2c3715SXin Li temp = sqrt(sigma) * vec; 262*bf2c3715SXin Li 263*bf2c3715SXin Li for(Index i=0; i<n; ++i) 264*bf2c3715SXin Li { 265*bf2c3715SXin Li JacobiRotation<Scalar> g; 266*bf2c3715SXin Li g.makeGivens(mat(i,i), -temp(i), &mat(i,i)); 267*bf2c3715SXin Li 268*bf2c3715SXin Li Index rs = n-i-1; 269*bf2c3715SXin Li if(rs>0) 270*bf2c3715SXin Li { 271*bf2c3715SXin Li ColXprSegment x(mat.col(i).tail(rs)); 272*bf2c3715SXin Li TempVecSegment y(temp.tail(rs)); 273*bf2c3715SXin Li apply_rotation_in_the_plane(x, y, g); 274*bf2c3715SXin Li } 275*bf2c3715SXin Li } 276*bf2c3715SXin Li } 277*bf2c3715SXin Li else 278*bf2c3715SXin Li { 279*bf2c3715SXin Li temp = vec; 280*bf2c3715SXin Li RealScalar beta = 1; 281*bf2c3715SXin Li for(Index j=0; j<n; ++j) 282*bf2c3715SXin Li { 283*bf2c3715SXin Li RealScalar Ljj = numext::real(mat.coeff(j,j)); 284*bf2c3715SXin Li RealScalar dj = numext::abs2(Ljj); 285*bf2c3715SXin Li Scalar wj = temp.coeff(j); 286*bf2c3715SXin Li RealScalar swj2 = sigma*numext::abs2(wj); 287*bf2c3715SXin Li RealScalar gamma = dj*beta + swj2; 288*bf2c3715SXin Li 289*bf2c3715SXin Li RealScalar x = dj + swj2/beta; 290*bf2c3715SXin Li if (x<=RealScalar(0)) 291*bf2c3715SXin Li return j; 292*bf2c3715SXin Li RealScalar nLjj = sqrt(x); 293*bf2c3715SXin Li mat.coeffRef(j,j) = nLjj; 294*bf2c3715SXin Li beta += swj2/dj; 295*bf2c3715SXin Li 296*bf2c3715SXin Li // Update the terms of L 297*bf2c3715SXin Li Index rs = n-j-1; 298*bf2c3715SXin Li if(rs) 299*bf2c3715SXin Li { 300*bf2c3715SXin Li temp.tail(rs) -= (wj/Ljj) * mat.col(j).tail(rs); 301*bf2c3715SXin Li if(gamma != 0) 302*bf2c3715SXin Li mat.col(j).tail(rs) = (nLjj/Ljj) * mat.col(j).tail(rs) + (nLjj * sigma*numext::conj(wj)/gamma)*temp.tail(rs); 303*bf2c3715SXin Li } 304*bf2c3715SXin Li } 305*bf2c3715SXin Li } 306*bf2c3715SXin Li return -1; 307*bf2c3715SXin Li } 308*bf2c3715SXin Li 309*bf2c3715SXin Li template<typename Scalar> struct llt_inplace<Scalar, Lower> 310*bf2c3715SXin Li { 311*bf2c3715SXin Li typedef typename NumTraits<Scalar>::Real RealScalar; 312*bf2c3715SXin Li template<typename MatrixType> 313*bf2c3715SXin Li static Index unblocked(MatrixType& mat) 314*bf2c3715SXin Li { 315*bf2c3715SXin Li using std::sqrt; 316*bf2c3715SXin Li 317*bf2c3715SXin Li eigen_assert(mat.rows()==mat.cols()); 318*bf2c3715SXin Li const Index size = mat.rows(); 319*bf2c3715SXin Li for(Index k = 0; k < size; ++k) 320*bf2c3715SXin Li { 321*bf2c3715SXin Li Index rs = size-k-1; // remaining size 322*bf2c3715SXin Li 323*bf2c3715SXin Li Block<MatrixType,Dynamic,1> A21(mat,k+1,k,rs,1); 324*bf2c3715SXin Li Block<MatrixType,1,Dynamic> A10(mat,k,0,1,k); 325*bf2c3715SXin Li Block<MatrixType,Dynamic,Dynamic> A20(mat,k+1,0,rs,k); 326*bf2c3715SXin Li 327*bf2c3715SXin Li RealScalar x = numext::real(mat.coeff(k,k)); 328*bf2c3715SXin Li if (k>0) x -= A10.squaredNorm(); 329*bf2c3715SXin Li if (x<=RealScalar(0)) 330*bf2c3715SXin Li return k; 331*bf2c3715SXin Li mat.coeffRef(k,k) = x = sqrt(x); 332*bf2c3715SXin Li if (k>0 && rs>0) A21.noalias() -= A20 * A10.adjoint(); 333*bf2c3715SXin Li if (rs>0) A21 /= x; 334*bf2c3715SXin Li } 335*bf2c3715SXin Li return -1; 336*bf2c3715SXin Li } 337*bf2c3715SXin Li 338*bf2c3715SXin Li template<typename MatrixType> 339*bf2c3715SXin Li static Index blocked(MatrixType& m) 340*bf2c3715SXin Li { 341*bf2c3715SXin Li eigen_assert(m.rows()==m.cols()); 342*bf2c3715SXin Li Index size = m.rows(); 343*bf2c3715SXin Li if(size<32) 344*bf2c3715SXin Li return unblocked(m); 345*bf2c3715SXin Li 346*bf2c3715SXin Li Index blockSize = size/8; 347*bf2c3715SXin Li blockSize = (blockSize/16)*16; 348*bf2c3715SXin Li blockSize = (std::min)((std::max)(blockSize,Index(8)), Index(128)); 349*bf2c3715SXin Li 350*bf2c3715SXin Li for (Index k=0; k<size; k+=blockSize) 351*bf2c3715SXin Li { 352*bf2c3715SXin Li // partition the matrix: 353*bf2c3715SXin Li // A00 | - | - 354*bf2c3715SXin Li // lu = A10 | A11 | - 355*bf2c3715SXin Li // A20 | A21 | A22 356*bf2c3715SXin Li Index bs = (std::min)(blockSize, size-k); 357*bf2c3715SXin Li Index rs = size - k - bs; 358*bf2c3715SXin Li Block<MatrixType,Dynamic,Dynamic> A11(m,k, k, bs,bs); 359*bf2c3715SXin Li Block<MatrixType,Dynamic,Dynamic> A21(m,k+bs,k, rs,bs); 360*bf2c3715SXin Li Block<MatrixType,Dynamic,Dynamic> A22(m,k+bs,k+bs,rs,rs); 361*bf2c3715SXin Li 362*bf2c3715SXin Li Index ret; 363*bf2c3715SXin Li if((ret=unblocked(A11))>=0) return k+ret; 364*bf2c3715SXin Li if(rs>0) A11.adjoint().template triangularView<Upper>().template solveInPlace<OnTheRight>(A21); 365*bf2c3715SXin Li if(rs>0) A22.template selfadjointView<Lower>().rankUpdate(A21,typename NumTraits<RealScalar>::Literal(-1)); // bottleneck 366*bf2c3715SXin Li } 367*bf2c3715SXin Li return -1; 368*bf2c3715SXin Li } 369*bf2c3715SXin Li 370*bf2c3715SXin Li template<typename MatrixType, typename VectorType> 371*bf2c3715SXin Li static Index rankUpdate(MatrixType& mat, const VectorType& vec, const RealScalar& sigma) 372*bf2c3715SXin Li { 373*bf2c3715SXin Li return Eigen::internal::llt_rank_update_lower(mat, vec, sigma); 374*bf2c3715SXin Li } 375*bf2c3715SXin Li }; 376*bf2c3715SXin Li 377*bf2c3715SXin Li template<typename Scalar> struct llt_inplace<Scalar, Upper> 378*bf2c3715SXin Li { 379*bf2c3715SXin Li typedef typename NumTraits<Scalar>::Real RealScalar; 380*bf2c3715SXin Li 381*bf2c3715SXin Li template<typename MatrixType> 382*bf2c3715SXin Li static EIGEN_STRONG_INLINE Index unblocked(MatrixType& mat) 383*bf2c3715SXin Li { 384*bf2c3715SXin Li Transpose<MatrixType> matt(mat); 385*bf2c3715SXin Li return llt_inplace<Scalar, Lower>::unblocked(matt); 386*bf2c3715SXin Li } 387*bf2c3715SXin Li template<typename MatrixType> 388*bf2c3715SXin Li static EIGEN_STRONG_INLINE Index blocked(MatrixType& mat) 389*bf2c3715SXin Li { 390*bf2c3715SXin Li Transpose<MatrixType> matt(mat); 391*bf2c3715SXin Li return llt_inplace<Scalar, Lower>::blocked(matt); 392*bf2c3715SXin Li } 393*bf2c3715SXin Li template<typename MatrixType, typename VectorType> 394*bf2c3715SXin Li static Index rankUpdate(MatrixType& mat, const VectorType& vec, const RealScalar& sigma) 395*bf2c3715SXin Li { 396*bf2c3715SXin Li Transpose<MatrixType> matt(mat); 397*bf2c3715SXin Li return llt_inplace<Scalar, Lower>::rankUpdate(matt, vec.conjugate(), sigma); 398*bf2c3715SXin Li } 399*bf2c3715SXin Li }; 400*bf2c3715SXin Li 401*bf2c3715SXin Li template<typename MatrixType> struct LLT_Traits<MatrixType,Lower> 402*bf2c3715SXin Li { 403*bf2c3715SXin Li typedef const TriangularView<const MatrixType, Lower> MatrixL; 404*bf2c3715SXin Li typedef const TriangularView<const typename MatrixType::AdjointReturnType, Upper> MatrixU; 405*bf2c3715SXin Li static inline MatrixL getL(const MatrixType& m) { return MatrixL(m); } 406*bf2c3715SXin Li static inline MatrixU getU(const MatrixType& m) { return MatrixU(m.adjoint()); } 407*bf2c3715SXin Li static bool inplace_decomposition(MatrixType& m) 408*bf2c3715SXin Li { return llt_inplace<typename MatrixType::Scalar, Lower>::blocked(m)==-1; } 409*bf2c3715SXin Li }; 410*bf2c3715SXin Li 411*bf2c3715SXin Li template<typename MatrixType> struct LLT_Traits<MatrixType,Upper> 412*bf2c3715SXin Li { 413*bf2c3715SXin Li typedef const TriangularView<const typename MatrixType::AdjointReturnType, Lower> MatrixL; 414*bf2c3715SXin Li typedef const TriangularView<const MatrixType, Upper> MatrixU; 415*bf2c3715SXin Li static inline MatrixL getL(const MatrixType& m) { return MatrixL(m.adjoint()); } 416*bf2c3715SXin Li static inline MatrixU getU(const MatrixType& m) { return MatrixU(m); } 417*bf2c3715SXin Li static bool inplace_decomposition(MatrixType& m) 418*bf2c3715SXin Li { return llt_inplace<typename MatrixType::Scalar, Upper>::blocked(m)==-1; } 419*bf2c3715SXin Li }; 420*bf2c3715SXin Li 421*bf2c3715SXin Li } // end namespace internal 422*bf2c3715SXin Li 423*bf2c3715SXin Li /** Computes / recomputes the Cholesky decomposition A = LL^* = U^*U of \a matrix 424*bf2c3715SXin Li * 425*bf2c3715SXin Li * \returns a reference to *this 426*bf2c3715SXin Li * 427*bf2c3715SXin Li * Example: \include TutorialLinAlgComputeTwice.cpp 428*bf2c3715SXin Li * Output: \verbinclude TutorialLinAlgComputeTwice.out 429*bf2c3715SXin Li */ 430*bf2c3715SXin Li template<typename MatrixType, int _UpLo> 431*bf2c3715SXin Li template<typename InputType> 432*bf2c3715SXin Li LLT<MatrixType,_UpLo>& LLT<MatrixType,_UpLo>::compute(const EigenBase<InputType>& a) 433*bf2c3715SXin Li { 434*bf2c3715SXin Li check_template_parameters(); 435*bf2c3715SXin Li 436*bf2c3715SXin Li eigen_assert(a.rows()==a.cols()); 437*bf2c3715SXin Li const Index size = a.rows(); 438*bf2c3715SXin Li m_matrix.resize(size, size); 439*bf2c3715SXin Li if (!internal::is_same_dense(m_matrix, a.derived())) 440*bf2c3715SXin Li m_matrix = a.derived(); 441*bf2c3715SXin Li 442*bf2c3715SXin Li // Compute matrix L1 norm = max abs column sum. 443*bf2c3715SXin Li m_l1_norm = RealScalar(0); 444*bf2c3715SXin Li // TODO move this code to SelfAdjointView 445*bf2c3715SXin Li for (Index col = 0; col < size; ++col) { 446*bf2c3715SXin Li RealScalar abs_col_sum; 447*bf2c3715SXin Li if (_UpLo == Lower) 448*bf2c3715SXin Li abs_col_sum = m_matrix.col(col).tail(size - col).template lpNorm<1>() + m_matrix.row(col).head(col).template lpNorm<1>(); 449*bf2c3715SXin Li else 450*bf2c3715SXin Li abs_col_sum = m_matrix.col(col).head(col).template lpNorm<1>() + m_matrix.row(col).tail(size - col).template lpNorm<1>(); 451*bf2c3715SXin Li if (abs_col_sum > m_l1_norm) 452*bf2c3715SXin Li m_l1_norm = abs_col_sum; 453*bf2c3715SXin Li } 454*bf2c3715SXin Li 455*bf2c3715SXin Li m_isInitialized = true; 456*bf2c3715SXin Li bool ok = Traits::inplace_decomposition(m_matrix); 457*bf2c3715SXin Li m_info = ok ? Success : NumericalIssue; 458*bf2c3715SXin Li 459*bf2c3715SXin Li return *this; 460*bf2c3715SXin Li } 461*bf2c3715SXin Li 462*bf2c3715SXin Li /** Performs a rank one update (or dowdate) of the current decomposition. 463*bf2c3715SXin Li * If A = LL^* before the rank one update, 464*bf2c3715SXin Li * then after it we have LL^* = A + sigma * v v^* where \a v must be a vector 465*bf2c3715SXin Li * of same dimension. 466*bf2c3715SXin Li */ 467*bf2c3715SXin Li template<typename _MatrixType, int _UpLo> 468*bf2c3715SXin Li template<typename VectorType> 469*bf2c3715SXin Li LLT<_MatrixType,_UpLo> & LLT<_MatrixType,_UpLo>::rankUpdate(const VectorType& v, const RealScalar& sigma) 470*bf2c3715SXin Li { 471*bf2c3715SXin Li EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorType); 472*bf2c3715SXin Li eigen_assert(v.size()==m_matrix.cols()); 473*bf2c3715SXin Li eigen_assert(m_isInitialized); 474*bf2c3715SXin Li if(internal::llt_inplace<typename MatrixType::Scalar, UpLo>::rankUpdate(m_matrix,v,sigma)>=0) 475*bf2c3715SXin Li m_info = NumericalIssue; 476*bf2c3715SXin Li else 477*bf2c3715SXin Li m_info = Success; 478*bf2c3715SXin Li 479*bf2c3715SXin Li return *this; 480*bf2c3715SXin Li } 481*bf2c3715SXin Li 482*bf2c3715SXin Li #ifndef EIGEN_PARSED_BY_DOXYGEN 483*bf2c3715SXin Li template<typename _MatrixType,int _UpLo> 484*bf2c3715SXin Li template<typename RhsType, typename DstType> 485*bf2c3715SXin Li void LLT<_MatrixType,_UpLo>::_solve_impl(const RhsType &rhs, DstType &dst) const 486*bf2c3715SXin Li { 487*bf2c3715SXin Li _solve_impl_transposed<true>(rhs, dst); 488*bf2c3715SXin Li } 489*bf2c3715SXin Li 490*bf2c3715SXin Li template<typename _MatrixType,int _UpLo> 491*bf2c3715SXin Li template<bool Conjugate, typename RhsType, typename DstType> 492*bf2c3715SXin Li void LLT<_MatrixType,_UpLo>::_solve_impl_transposed(const RhsType &rhs, DstType &dst) const 493*bf2c3715SXin Li { 494*bf2c3715SXin Li dst = rhs; 495*bf2c3715SXin Li 496*bf2c3715SXin Li matrixL().template conjugateIf<!Conjugate>().solveInPlace(dst); 497*bf2c3715SXin Li matrixU().template conjugateIf<!Conjugate>().solveInPlace(dst); 498*bf2c3715SXin Li } 499*bf2c3715SXin Li #endif 500*bf2c3715SXin Li 501*bf2c3715SXin Li /** \internal use x = llt_object.solve(x); 502*bf2c3715SXin Li * 503*bf2c3715SXin Li * This is the \em in-place version of solve(). 504*bf2c3715SXin Li * 505*bf2c3715SXin Li * \param bAndX represents both the right-hand side matrix b and result x. 506*bf2c3715SXin Li * 507*bf2c3715SXin Li * This version avoids a copy when the right hand side matrix b is not needed anymore. 508*bf2c3715SXin Li * 509*bf2c3715SXin Li * \warning The parameter is only marked 'const' to make the C++ compiler accept a temporary expression here. 510*bf2c3715SXin Li * This function will const_cast it, so constness isn't honored here. 511*bf2c3715SXin Li * 512*bf2c3715SXin Li * \sa LLT::solve(), MatrixBase::llt() 513*bf2c3715SXin Li */ 514*bf2c3715SXin Li template<typename MatrixType, int _UpLo> 515*bf2c3715SXin Li template<typename Derived> 516*bf2c3715SXin Li void LLT<MatrixType,_UpLo>::solveInPlace(const MatrixBase<Derived> &bAndX) const 517*bf2c3715SXin Li { 518*bf2c3715SXin Li eigen_assert(m_isInitialized && "LLT is not initialized."); 519*bf2c3715SXin Li eigen_assert(m_matrix.rows()==bAndX.rows()); 520*bf2c3715SXin Li matrixL().solveInPlace(bAndX); 521*bf2c3715SXin Li matrixU().solveInPlace(bAndX); 522*bf2c3715SXin Li } 523*bf2c3715SXin Li 524*bf2c3715SXin Li /** \returns the matrix represented by the decomposition, 525*bf2c3715SXin Li * i.e., it returns the product: L L^*. 526*bf2c3715SXin Li * This function is provided for debug purpose. */ 527*bf2c3715SXin Li template<typename MatrixType, int _UpLo> 528*bf2c3715SXin Li MatrixType LLT<MatrixType,_UpLo>::reconstructedMatrix() const 529*bf2c3715SXin Li { 530*bf2c3715SXin Li eigen_assert(m_isInitialized && "LLT is not initialized."); 531*bf2c3715SXin Li return matrixL() * matrixL().adjoint().toDenseMatrix(); 532*bf2c3715SXin Li } 533*bf2c3715SXin Li 534*bf2c3715SXin Li /** \cholesky_module 535*bf2c3715SXin Li * \returns the LLT decomposition of \c *this 536*bf2c3715SXin Li * \sa SelfAdjointView::llt() 537*bf2c3715SXin Li */ 538*bf2c3715SXin Li template<typename Derived> 539*bf2c3715SXin Li inline const LLT<typename MatrixBase<Derived>::PlainObject> 540*bf2c3715SXin Li MatrixBase<Derived>::llt() const 541*bf2c3715SXin Li { 542*bf2c3715SXin Li return LLT<PlainObject>(derived()); 543*bf2c3715SXin Li } 544*bf2c3715SXin Li 545*bf2c3715SXin Li /** \cholesky_module 546*bf2c3715SXin Li * \returns the LLT decomposition of \c *this 547*bf2c3715SXin Li * \sa SelfAdjointView::llt() 548*bf2c3715SXin Li */ 549*bf2c3715SXin Li template<typename MatrixType, unsigned int UpLo> 550*bf2c3715SXin Li inline const LLT<typename SelfAdjointView<MatrixType, UpLo>::PlainObject, UpLo> 551*bf2c3715SXin Li SelfAdjointView<MatrixType, UpLo>::llt() const 552*bf2c3715SXin Li { 553*bf2c3715SXin Li return LLT<PlainObject,UpLo>(m_matrix); 554*bf2c3715SXin Li } 555*bf2c3715SXin Li 556*bf2c3715SXin Li } // end namespace Eigen 557*bf2c3715SXin Li 558*bf2c3715SXin Li #endif // EIGEN_LLT_H 559