00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef EIGEN_LDLT_H
00014 #define EIGEN_LDLT_H
00015
00016 namespace Eigen {
00017
00018 namespace internal {
00019 template<typename MatrixType, int UpLo> struct LDLT_Traits;
00020
00021
00022 enum SignMatrix { PositiveSemiDef, NegativeSemiDef, ZeroSign, Indefinite };
00023 }
00024
00048 template<typename _MatrixType, int _UpLo> class LDLT
00049 {
00050 public:
00051 typedef _MatrixType MatrixType;
00052 enum {
00053 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
00054 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
00055 Options = MatrixType::Options & ~RowMajorBit,
00056 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
00057 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
00058 UpLo = _UpLo
00059 };
00060 typedef typename MatrixType::Scalar Scalar;
00061 typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
00062 typedef typename MatrixType::Index Index;
00063 typedef Matrix<Scalar, RowsAtCompileTime, 1, Options, MaxRowsAtCompileTime, 1> TmpMatrixType;
00064
00065 typedef Transpositions<RowsAtCompileTime, MaxRowsAtCompileTime> TranspositionType;
00066 typedef PermutationMatrix<RowsAtCompileTime, MaxRowsAtCompileTime> PermutationType;
00067
00068 typedef internal::LDLT_Traits<MatrixType,UpLo> Traits;
00069
00075 LDLT()
00076 : m_matrix(),
00077 m_transpositions(),
00078 m_sign(internal::ZeroSign),
00079 m_isInitialized(false)
00080 {}
00081
00088 LDLT(Index size)
00089 : m_matrix(size, size),
00090 m_transpositions(size),
00091 m_temporary(size),
00092 m_sign(internal::ZeroSign),
00093 m_isInitialized(false)
00094 {}
00095
00101 LDLT(const MatrixType& matrix)
00102 : m_matrix(matrix.rows(), matrix.cols()),
00103 m_transpositions(matrix.rows()),
00104 m_temporary(matrix.rows()),
00105 m_sign(internal::ZeroSign),
00106 m_isInitialized(false)
00107 {
00108 compute(matrix);
00109 }
00110
00114 void setZero()
00115 {
00116 m_isInitialized = false;
00117 }
00118
00120 inline typename Traits::MatrixU matrixU() const
00121 {
00122 eigen_assert(m_isInitialized && "LDLT is not initialized.");
00123 return Traits::getU(m_matrix);
00124 }
00125
00127 inline typename Traits::MatrixL matrixL() const
00128 {
00129 eigen_assert(m_isInitialized && "LDLT is not initialized.");
00130 return Traits::getL(m_matrix);
00131 }
00132
00135 inline const TranspositionType& transpositionsP() const
00136 {
00137 eigen_assert(m_isInitialized && "LDLT is not initialized.");
00138 return m_transpositions;
00139 }
00140
00142 inline Diagonal<const MatrixType> vectorD() const
00143 {
00144 eigen_assert(m_isInitialized && "LDLT is not initialized.");
00145 return m_matrix.diagonal();
00146 }
00147
00149 inline bool isPositive() const
00150 {
00151 eigen_assert(m_isInitialized && "LDLT is not initialized.");
00152 return m_sign == internal::PositiveSemiDef || m_sign == internal::ZeroSign;
00153 }
00154
00155 #ifdef EIGEN2_SUPPORT
00156 inline bool isPositiveDefinite() const
00157 {
00158 return isPositive();
00159 }
00160 #endif
00161
00163 inline bool isNegative(void) const
00164 {
00165 eigen_assert(m_isInitialized && "LDLT is not initialized.");
00166 return m_sign == internal::NegativeSemiDef || m_sign == internal::ZeroSign;
00167 }
00168
00184 template<typename Rhs>
00185 inline const internal::solve_retval<LDLT, Rhs>
00186 solve(const MatrixBase<Rhs>& b) const
00187 {
00188 eigen_assert(m_isInitialized && "LDLT is not initialized.");
00189 eigen_assert(m_matrix.rows()==b.rows()
00190 && "LDLT::solve(): invalid number of rows of the right hand side matrix b");
00191 return internal::solve_retval<LDLT, Rhs>(*this, b.derived());
00192 }
00193
00194 #ifdef EIGEN2_SUPPORT
00195 template<typename OtherDerived, typename ResultType>
00196 bool solve(const MatrixBase<OtherDerived>& b, ResultType *result) const
00197 {
00198 *result = this->solve(b);
00199 return true;
00200 }
00201 #endif
00202
00203 template<typename Derived>
00204 bool solveInPlace(MatrixBase<Derived> &bAndX) const;
00205
00206 LDLT& compute(const MatrixType& matrix);
00207
00208 template <typename Derived>
00209 LDLT& rankUpdate(const MatrixBase<Derived>& w, const RealScalar& alpha=1);
00210
00215 inline const MatrixType& matrixLDLT() const
00216 {
00217 eigen_assert(m_isInitialized && "LDLT is not initialized.");
00218 return m_matrix;
00219 }
00220
00221 MatrixType reconstructedMatrix() const;
00222
00223 inline Index rows() const { return m_matrix.rows(); }
00224 inline Index cols() const { return m_matrix.cols(); }
00225
00231 ComputationInfo info() const
00232 {
00233 eigen_assert(m_isInitialized && "LDLT is not initialized.");
00234 return Success;
00235 }
00236
00237 protected:
00238
00239 static void check_template_parameters()
00240 {
00241 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
00242 }
00243
00250 MatrixType m_matrix;
00251 TranspositionType m_transpositions;
00252 TmpMatrixType m_temporary;
00253 internal::SignMatrix m_sign;
00254 bool m_isInitialized;
00255 };
00256
00257 namespace internal {
00258
00259 template<int UpLo> struct ldlt_inplace;
00260
00261 template<> struct ldlt_inplace<Lower>
00262 {
00263 template<typename MatrixType, typename TranspositionType, typename Workspace>
00264 static bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, SignMatrix& sign)
00265 {
00266 using std::abs;
00267 typedef typename MatrixType::Scalar Scalar;
00268 typedef typename MatrixType::RealScalar RealScalar;
00269 typedef typename MatrixType::Index Index;
00270 eigen_assert(mat.rows()==mat.cols());
00271 const Index size = mat.rows();
00272
00273 if (size <= 1)
00274 {
00275 transpositions.setIdentity();
00276 if (numext::real(mat.coeff(0,0)) > 0) sign = PositiveSemiDef;
00277 else if (numext::real(mat.coeff(0,0)) < 0) sign = NegativeSemiDef;
00278 else sign = ZeroSign;
00279 return true;
00280 }
00281
00282 for (Index k = 0; k < size; ++k)
00283 {
00284
00285 Index index_of_biggest_in_corner;
00286 mat.diagonal().tail(size-k).cwiseAbs().maxCoeff(&index_of_biggest_in_corner);
00287 index_of_biggest_in_corner += k;
00288
00289 transpositions.coeffRef(k) = index_of_biggest_in_corner;
00290 if(k != index_of_biggest_in_corner)
00291 {
00292
00293
00294 Index s = size-index_of_biggest_in_corner-1;
00295 mat.row(k).head(k).swap(mat.row(index_of_biggest_in_corner).head(k));
00296 mat.col(k).tail(s).swap(mat.col(index_of_biggest_in_corner).tail(s));
00297 std::swap(mat.coeffRef(k,k),mat.coeffRef(index_of_biggest_in_corner,index_of_biggest_in_corner));
00298 for(int i=k+1;i<index_of_biggest_in_corner;++i)
00299 {
00300 Scalar tmp = mat.coeffRef(i,k);
00301 mat.coeffRef(i,k) = numext::conj(mat.coeffRef(index_of_biggest_in_corner,i));
00302 mat.coeffRef(index_of_biggest_in_corner,i) = numext::conj(tmp);
00303 }
00304 if(NumTraits<Scalar>::IsComplex)
00305 mat.coeffRef(index_of_biggest_in_corner,k) = numext::conj(mat.coeff(index_of_biggest_in_corner,k));
00306 }
00307
00308
00309
00310
00311
00312 Index rs = size - k - 1;
00313 Block<MatrixType,Dynamic,1> A21(mat,k+1,k,rs,1);
00314 Block<MatrixType,1,Dynamic> A10(mat,k,0,1,k);
00315 Block<MatrixType,Dynamic,Dynamic> A20(mat,k+1,0,rs,k);
00316
00317 if(k>0)
00318 {
00319 temp.head(k) = mat.diagonal().real().head(k).asDiagonal() * A10.adjoint();
00320 mat.coeffRef(k,k) -= (A10 * temp.head(k)).value();
00321 if(rs>0)
00322 A21.noalias() -= A20 * temp.head(k);
00323 }
00324
00325
00326
00327
00328
00329 RealScalar realAkk = numext::real(mat.coeffRef(k,k));
00330 if((rs>0) && (abs(realAkk) > RealScalar(0)))
00331 A21 /= realAkk;
00332
00333 if (sign == PositiveSemiDef) {
00334 if (realAkk < 0) sign = Indefinite;
00335 } else if (sign == NegativeSemiDef) {
00336 if (realAkk > 0) sign = Indefinite;
00337 } else if (sign == ZeroSign) {
00338 if (realAkk > 0) sign = PositiveSemiDef;
00339 else if (realAkk < 0) sign = NegativeSemiDef;
00340 }
00341 }
00342
00343 return true;
00344 }
00345
00346
00347
00348
00349
00350
00351
00352
00353 template<typename MatrixType, typename WDerived>
00354 static bool updateInPlace(MatrixType& mat, MatrixBase<WDerived>& w, const typename MatrixType::RealScalar& sigma=1)
00355 {
00356 using numext::isfinite;
00357 typedef typename MatrixType::Scalar Scalar;
00358 typedef typename MatrixType::RealScalar RealScalar;
00359 typedef typename MatrixType::Index Index;
00360
00361 const Index size = mat.rows();
00362 eigen_assert(mat.cols() == size && w.size()==size);
00363
00364 RealScalar alpha = 1;
00365
00366
00367 for (Index j = 0; j < size; j++)
00368 {
00369
00370 if (!(isfinite)(alpha))
00371 break;
00372
00373
00374 RealScalar dj = numext::real(mat.coeff(j,j));
00375 Scalar wj = w.coeff(j);
00376 RealScalar swj2 = sigma*numext::abs2(wj);
00377 RealScalar gamma = dj*alpha + swj2;
00378
00379 mat.coeffRef(j,j) += swj2/alpha;
00380 alpha += swj2/dj;
00381
00382
00383
00384 Index rs = size-j-1;
00385 w.tail(rs) -= wj * mat.col(j).tail(rs);
00386 if(gamma != 0)
00387 mat.col(j).tail(rs) += (sigma*numext::conj(wj)/gamma)*w.tail(rs);
00388 }
00389 return true;
00390 }
00391
00392 template<typename MatrixType, typename TranspositionType, typename Workspace, typename WType>
00393 static bool update(MatrixType& mat, const TranspositionType& transpositions, Workspace& tmp, const WType& w, const typename MatrixType::RealScalar& sigma=1)
00394 {
00395
00396 tmp = transpositions * w;
00397
00398 return ldlt_inplace<Lower>::updateInPlace(mat,tmp,sigma);
00399 }
00400 };
00401
00402 template<> struct ldlt_inplace<Upper>
00403 {
00404 template<typename MatrixType, typename TranspositionType, typename Workspace>
00405 static EIGEN_STRONG_INLINE bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, SignMatrix& sign)
00406 {
00407 Transpose<MatrixType> matt(mat);
00408 return ldlt_inplace<Lower>::unblocked(matt, transpositions, temp, sign);
00409 }
00410
00411 template<typename MatrixType, typename TranspositionType, typename Workspace, typename WType>
00412 static EIGEN_STRONG_INLINE bool update(MatrixType& mat, TranspositionType& transpositions, Workspace& tmp, WType& w, const typename MatrixType::RealScalar& sigma=1)
00413 {
00414 Transpose<MatrixType> matt(mat);
00415 return ldlt_inplace<Lower>::update(matt, transpositions, tmp, w.conjugate(), sigma);
00416 }
00417 };
00418
00419 template<typename MatrixType> struct LDLT_Traits<MatrixType,Lower>
00420 {
00421 typedef const TriangularView<const MatrixType, UnitLower> MatrixL;
00422 typedef const TriangularView<const typename MatrixType::AdjointReturnType, UnitUpper> MatrixU;
00423 static inline MatrixL getL(const MatrixType& m) { return m; }
00424 static inline MatrixU getU(const MatrixType& m) { return m.adjoint(); }
00425 };
00426
00427 template<typename MatrixType> struct LDLT_Traits<MatrixType,Upper>
00428 {
00429 typedef const TriangularView<const typename MatrixType::AdjointReturnType, UnitLower> MatrixL;
00430 typedef const TriangularView<const MatrixType, UnitUpper> MatrixU;
00431 static inline MatrixL getL(const MatrixType& m) { return m.adjoint(); }
00432 static inline MatrixU getU(const MatrixType& m) { return m; }
00433 };
00434
00435 }
00436
00439 template<typename MatrixType, int _UpLo>
00440 LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::compute(const MatrixType& a)
00441 {
00442 check_template_parameters();
00443
00444 eigen_assert(a.rows()==a.cols());
00445 const Index size = a.rows();
00446
00447 m_matrix = a;
00448
00449 m_transpositions.resize(size);
00450 m_isInitialized = false;
00451 m_temporary.resize(size);
00452 m_sign = internal::ZeroSign;
00453
00454 internal::ldlt_inplace<UpLo>::unblocked(m_matrix, m_transpositions, m_temporary, m_sign);
00455
00456 m_isInitialized = true;
00457 return *this;
00458 }
00459
00465 template<typename MatrixType, int _UpLo>
00466 template<typename Derived>
00467 LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::rankUpdate(const MatrixBase<Derived>& w, const typename NumTraits<typename MatrixType::Scalar>::Real& sigma)
00468 {
00469 const Index size = w.rows();
00470 if (m_isInitialized)
00471 {
00472 eigen_assert(m_matrix.rows()==size);
00473 }
00474 else
00475 {
00476 m_matrix.resize(size,size);
00477 m_matrix.setZero();
00478 m_transpositions.resize(size);
00479 for (Index i = 0; i < size; i++)
00480 m_transpositions.coeffRef(i) = i;
00481 m_temporary.resize(size);
00482 m_sign = sigma>=0 ? internal::PositiveSemiDef : internal::NegativeSemiDef;
00483 m_isInitialized = true;
00484 }
00485
00486 internal::ldlt_inplace<UpLo>::update(m_matrix, m_transpositions, m_temporary, w, sigma);
00487
00488 return *this;
00489 }
00490
00491 namespace internal {
00492 template<typename _MatrixType, int _UpLo, typename Rhs>
00493 struct solve_retval<LDLT<_MatrixType,_UpLo>, Rhs>
00494 : solve_retval_base<LDLT<_MatrixType,_UpLo>, Rhs>
00495 {
00496 typedef LDLT<_MatrixType,_UpLo> LDLTType;
00497 EIGEN_MAKE_SOLVE_HELPERS(LDLTType,Rhs)
00498
00499 template<typename Dest> void evalTo(Dest& dst) const
00500 {
00501 eigen_assert(rhs().rows() == dec().matrixLDLT().rows());
00502
00503 dst = dec().transpositionsP() * rhs();
00504
00505
00506 dec().matrixL().solveInPlace(dst);
00507
00508
00509
00510 using std::abs;
00511 using std::max;
00512 typedef typename LDLTType::MatrixType MatrixType;
00513 typedef typename LDLTType::RealScalar RealScalar;
00514 const typename Diagonal<const MatrixType>::RealReturnType vectorD(dec().vectorD());
00515
00516
00517
00518
00519
00520
00521 RealScalar tolerance = RealScalar(1) / NumTraits<RealScalar>::highest();
00522
00523 for (Index i = 0; i < vectorD.size(); ++i) {
00524 if(abs(vectorD(i)) > tolerance)
00525 dst.row(i) /= vectorD(i);
00526 else
00527 dst.row(i).setZero();
00528 }
00529
00530
00531 dec().matrixU().solveInPlace(dst);
00532
00533
00534 dst = dec().transpositionsP().transpose() * dst;
00535 }
00536 };
00537 }
00538
00552 template<typename MatrixType,int _UpLo>
00553 template<typename Derived>
00554 bool LDLT<MatrixType,_UpLo>::solveInPlace(MatrixBase<Derived> &bAndX) const
00555 {
00556 eigen_assert(m_isInitialized && "LDLT is not initialized.");
00557 eigen_assert(m_matrix.rows() == bAndX.rows());
00558
00559 bAndX = this->solve(bAndX);
00560
00561 return true;
00562 }
00563
00567 template<typename MatrixType, int _UpLo>
00568 MatrixType LDLT<MatrixType,_UpLo>::reconstructedMatrix() const
00569 {
00570 eigen_assert(m_isInitialized && "LDLT is not initialized.");
00571 const Index size = m_matrix.rows();
00572 MatrixType res(size,size);
00573
00574
00575 res.setIdentity();
00576 res = transpositionsP() * res;
00577
00578 res = matrixU() * res;
00579
00580 res = vectorD().real().asDiagonal() * res;
00581
00582 res = matrixL() * res;
00583
00584 res = transpositionsP().transpose() * res;
00585
00586 return res;
00587 }
00588
00592 template<typename MatrixType, unsigned int UpLo>
00593 inline const LDLT<typename SelfAdjointView<MatrixType, UpLo>::PlainObject, UpLo>
00594 SelfAdjointView<MatrixType, UpLo>::ldlt() const
00595 {
00596 return LDLT<PlainObject,UpLo>(m_matrix);
00597 }
00598
00602 template<typename Derived>
00603 inline const LDLT<typename MatrixBase<Derived>::PlainObject>
00604 MatrixBase<Derived>::ldlt() const
00605 {
00606 return LDLT<PlainObject>(derived());
00607 }
00608
00609 }
00610
00611 #endif // EIGEN_LDLT_H