xref: /aosp_15_r20/external/eigen/Eigen/src/Cholesky/LLT.h (revision bf2c37156dfe67e5dfebd6d394bad8b2ab5804d4)
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