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
00045 template<typename _MatrixType, int _UpLo> class LDLT
00046 {
00047 public:
00048 typedef _MatrixType MatrixType;
00049 enum {
00050 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
00051 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
00052 Options = MatrixType::Options & ~RowMajorBit,
00053 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
00054 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
00055 UpLo = _UpLo
00056 };
00057 typedef typename MatrixType::Scalar Scalar;
00058 typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
00059 typedef typename MatrixType::Index Index;
00060 typedef Matrix<Scalar, RowsAtCompileTime, 1, Options, MaxRowsAtCompileTime, 1> TmpMatrixType;
00061
00062 typedef Transpositions<RowsAtCompileTime, MaxRowsAtCompileTime> TranspositionType;
00063 typedef PermutationMatrix<RowsAtCompileTime, MaxRowsAtCompileTime> PermutationType;
00064
00065 typedef internal::LDLT_Traits<MatrixType,UpLo> Traits;
00066
00072 LDLT() : m_matrix(), m_transpositions(), m_isInitialized(false) {}
00073
00080 LDLT(Index size)
00081 : m_matrix(size, size),
00082 m_transpositions(size),
00083 m_temporary(size),
00084 m_isInitialized(false)
00085 {}
00086
00092 LDLT(const MatrixType& matrix)
00093 : m_matrix(matrix.rows(), matrix.cols()),
00094 m_transpositions(matrix.rows()),
00095 m_temporary(matrix.rows()),
00096 m_isInitialized(false)
00097 {
00098 compute(matrix);
00099 }
00100
00104 void setZero()
00105 {
00106 m_isInitialized = false;
00107 }
00108
00110 inline typename Traits::MatrixU matrixU() const
00111 {
00112 eigen_assert(m_isInitialized && "LDLT is not initialized.");
00113 return Traits::getU(m_matrix);
00114 }
00115
00117 inline typename Traits::MatrixL matrixL() const
00118 {
00119 eigen_assert(m_isInitialized && "LDLT is not initialized.");
00120 return Traits::getL(m_matrix);
00121 }
00122
00125 inline const TranspositionType& transpositionsP() const
00126 {
00127 eigen_assert(m_isInitialized && "LDLT is not initialized.");
00128 return m_transpositions;
00129 }
00130
00132 inline Diagonal<const MatrixType> vectorD() const
00133 {
00134 eigen_assert(m_isInitialized && "LDLT is not initialized.");
00135 return m_matrix.diagonal();
00136 }
00137
00139 inline bool isPositive() const
00140 {
00141 eigen_assert(m_isInitialized && "LDLT is not initialized.");
00142 return m_sign == 1;
00143 }
00144
00145 #ifdef EIGEN2_SUPPORT
00146 inline bool isPositiveDefinite() const
00147 {
00148 return isPositive();
00149 }
00150 #endif
00151
00153 inline bool isNegative(void) const
00154 {
00155 eigen_assert(m_isInitialized && "LDLT is not initialized.");
00156 return m_sign == -1;
00157 }
00158
00174 template<typename Rhs>
00175 inline const internal::solve_retval<LDLT, Rhs>
00176 solve(const MatrixBase<Rhs>& b) const
00177 {
00178 eigen_assert(m_isInitialized && "LDLT is not initialized.");
00179 eigen_assert(m_matrix.rows()==b.rows()
00180 && "LDLT::solve(): invalid number of rows of the right hand side matrix b");
00181 return internal::solve_retval<LDLT, Rhs>(*this, b.derived());
00182 }
00183
00184 #ifdef EIGEN2_SUPPORT
00185 template<typename OtherDerived, typename ResultType>
00186 bool solve(const MatrixBase<OtherDerived>& b, ResultType *result) const
00187 {
00188 *result = this->solve(b);
00189 return true;
00190 }
00191 #endif
00192
00193 template<typename Derived>
00194 bool solveInPlace(MatrixBase<Derived> &bAndX) const;
00195
00196 LDLT& compute(const MatrixType& matrix);
00197
00198 template <typename Derived>
00199 LDLT& rankUpdate(const MatrixBase<Derived>& w, const RealScalar& alpha=1);
00200
00205 inline const MatrixType& matrixLDLT() const
00206 {
00207 eigen_assert(m_isInitialized && "LDLT is not initialized.");
00208 return m_matrix;
00209 }
00210
00211 MatrixType reconstructedMatrix() const;
00212
00213 inline Index rows() const { return m_matrix.rows(); }
00214 inline Index cols() const { return m_matrix.cols(); }
00215
00221 ComputationInfo info() const
00222 {
00223 eigen_assert(m_isInitialized && "LDLT is not initialized.");
00224 return Success;
00225 }
00226
00227 protected:
00228
00235 MatrixType m_matrix;
00236 TranspositionType m_transpositions;
00237 TmpMatrixType m_temporary;
00238 int m_sign;
00239 bool m_isInitialized;
00240 };
00241
00242 namespace internal {
00243
00244 template<int UpLo> struct ldlt_inplace;
00245
00246 template<> struct ldlt_inplace<Lower>
00247 {
00248 template<typename MatrixType, typename TranspositionType, typename Workspace>
00249 static bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, int* sign=0)
00250 {
00251 using std::abs;
00252 typedef typename MatrixType::Scalar Scalar;
00253 typedef typename MatrixType::RealScalar RealScalar;
00254 typedef typename MatrixType::Index Index;
00255 eigen_assert(mat.rows()==mat.cols());
00256 const Index size = mat.rows();
00257
00258 if (size <= 1)
00259 {
00260 transpositions.setIdentity();
00261 if(sign)
00262 *sign = numext::real(mat.coeff(0,0))>0 ? 1:-1;
00263 return true;
00264 }
00265
00266 RealScalar cutoff(0), biggest_in_corner;
00267
00268 for (Index k = 0; k < size; ++k)
00269 {
00270
00271 Index index_of_biggest_in_corner;
00272 biggest_in_corner = mat.diagonal().tail(size-k).cwiseAbs().maxCoeff(&index_of_biggest_in_corner);
00273 index_of_biggest_in_corner += k;
00274
00275 if(k == 0)
00276 {
00277
00278
00279
00280 cutoff = abs(NumTraits<Scalar>::epsilon() * biggest_in_corner);
00281 }
00282
00283
00284 if(biggest_in_corner < cutoff)
00285 {
00286 for(Index i = k; i < size; i++) transpositions.coeffRef(i) = i;
00287 if(sign) *sign = 0;
00288 break;
00289 }
00290
00291 transpositions.coeffRef(k) = index_of_biggest_in_corner;
00292 if(k != index_of_biggest_in_corner)
00293 {
00294
00295
00296 Index s = size-index_of_biggest_in_corner-1;
00297 mat.row(k).head(k).swap(mat.row(index_of_biggest_in_corner).head(k));
00298 mat.col(k).tail(s).swap(mat.col(index_of_biggest_in_corner).tail(s));
00299 std::swap(mat.coeffRef(k,k),mat.coeffRef(index_of_biggest_in_corner,index_of_biggest_in_corner));
00300 for(int i=k+1;i<index_of_biggest_in_corner;++i)
00301 {
00302 Scalar tmp = mat.coeffRef(i,k);
00303 mat.coeffRef(i,k) = numext::conj(mat.coeffRef(index_of_biggest_in_corner,i));
00304 mat.coeffRef(index_of_biggest_in_corner,i) = numext::conj(tmp);
00305 }
00306 if(NumTraits<Scalar>::IsComplex)
00307 mat.coeffRef(index_of_biggest_in_corner,k) = numext::conj(mat.coeff(index_of_biggest_in_corner,k));
00308 }
00309
00310
00311
00312
00313
00314 Index rs = size - k - 1;
00315 Block<MatrixType,Dynamic,1> A21(mat,k+1,k,rs,1);
00316 Block<MatrixType,1,Dynamic> A10(mat,k,0,1,k);
00317 Block<MatrixType,Dynamic,Dynamic> A20(mat,k+1,0,rs,k);
00318
00319 if(k>0)
00320 {
00321 temp.head(k) = mat.diagonal().head(k).asDiagonal() * A10.adjoint();
00322 mat.coeffRef(k,k) -= (A10 * temp.head(k)).value();
00323 if(rs>0)
00324 A21.noalias() -= A20 * temp.head(k);
00325 }
00326 if((rs>0) && (abs(mat.coeffRef(k,k)) > cutoff))
00327 A21 /= mat.coeffRef(k,k);
00328
00329 if(sign)
00330 {
00331
00332 int newSign = numext::real(mat.diagonal().coeff(index_of_biggest_in_corner)) > 0;
00333 if(k == 0)
00334 *sign = newSign;
00335 else if(*sign != newSign)
00336 *sign = 0;
00337 }
00338 }
00339
00340 return true;
00341 }
00342
00343
00344
00345
00346
00347
00348
00349
00350 template<typename MatrixType, typename WDerived>
00351 static bool updateInPlace(MatrixType& mat, MatrixBase<WDerived>& w, const typename MatrixType::RealScalar& sigma=1)
00352 {
00353 using numext::isfinite;
00354 typedef typename MatrixType::Scalar Scalar;
00355 typedef typename MatrixType::RealScalar RealScalar;
00356 typedef typename MatrixType::Index Index;
00357
00358 const Index size = mat.rows();
00359 eigen_assert(mat.cols() == size && w.size()==size);
00360
00361 RealScalar alpha = 1;
00362
00363
00364 for (Index j = 0; j < size; j++)
00365 {
00366
00367 if (!(isfinite)(alpha))
00368 break;
00369
00370
00371 RealScalar dj = numext::real(mat.coeff(j,j));
00372 Scalar wj = w.coeff(j);
00373 RealScalar swj2 = sigma*numext::abs2(wj);
00374 RealScalar gamma = dj*alpha + swj2;
00375
00376 mat.coeffRef(j,j) += swj2/alpha;
00377 alpha += swj2/dj;
00378
00379
00380
00381 Index rs = size-j-1;
00382 w.tail(rs) -= wj * mat.col(j).tail(rs);
00383 if(gamma != 0)
00384 mat.col(j).tail(rs) += (sigma*numext::conj(wj)/gamma)*w.tail(rs);
00385 }
00386 return true;
00387 }
00388
00389 template<typename MatrixType, typename TranspositionType, typename Workspace, typename WType>
00390 static bool update(MatrixType& mat, const TranspositionType& transpositions, Workspace& tmp, const WType& w, const typename MatrixType::RealScalar& sigma=1)
00391 {
00392
00393 tmp = transpositions * w;
00394
00395 return ldlt_inplace<Lower>::updateInPlace(mat,tmp,sigma);
00396 }
00397 };
00398
00399 template<> struct ldlt_inplace<Upper>
00400 {
00401 template<typename MatrixType, typename TranspositionType, typename Workspace>
00402 static EIGEN_STRONG_INLINE bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, int* sign=0)
00403 {
00404 Transpose<MatrixType> matt(mat);
00405 return ldlt_inplace<Lower>::unblocked(matt, transpositions, temp, sign);
00406 }
00407
00408 template<typename MatrixType, typename TranspositionType, typename Workspace, typename WType>
00409 static EIGEN_STRONG_INLINE bool update(MatrixType& mat, TranspositionType& transpositions, Workspace& tmp, WType& w, const typename MatrixType::RealScalar& sigma=1)
00410 {
00411 Transpose<MatrixType> matt(mat);
00412 return ldlt_inplace<Lower>::update(matt, transpositions, tmp, w.conjugate(), sigma);
00413 }
00414 };
00415
00416 template<typename MatrixType> struct LDLT_Traits<MatrixType,Lower>
00417 {
00418 typedef const TriangularView<const MatrixType, UnitLower> MatrixL;
00419 typedef const TriangularView<const typename MatrixType::AdjointReturnType, UnitUpper> MatrixU;
00420 static inline MatrixL getL(const MatrixType& m) { return m; }
00421 static inline MatrixU getU(const MatrixType& m) { return m.adjoint(); }
00422 };
00423
00424 template<typename MatrixType> struct LDLT_Traits<MatrixType,Upper>
00425 {
00426 typedef const TriangularView<const typename MatrixType::AdjointReturnType, UnitLower> MatrixL;
00427 typedef const TriangularView<const MatrixType, UnitUpper> MatrixU;
00428 static inline MatrixL getL(const MatrixType& m) { return m.adjoint(); }
00429 static inline MatrixU getU(const MatrixType& m) { return m; }
00430 };
00431
00432 }
00433
00436 template<typename MatrixType, int _UpLo>
00437 LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::compute(const MatrixType& a)
00438 {
00439 eigen_assert(a.rows()==a.cols());
00440 const Index size = a.rows();
00441
00442 m_matrix = a;
00443
00444 m_transpositions.resize(size);
00445 m_isInitialized = false;
00446 m_temporary.resize(size);
00447
00448 internal::ldlt_inplace<UpLo>::unblocked(m_matrix, m_transpositions, m_temporary, &m_sign);
00449
00450 m_isInitialized = true;
00451 return *this;
00452 }
00453
00459 template<typename MatrixType, int _UpLo>
00460 template<typename Derived>
00461 LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::rankUpdate(const MatrixBase<Derived>& w, const typename NumTraits<typename MatrixType::Scalar>::Real& sigma)
00462 {
00463 const Index size = w.rows();
00464 if (m_isInitialized)
00465 {
00466 eigen_assert(m_matrix.rows()==size);
00467 }
00468 else
00469 {
00470 m_matrix.resize(size,size);
00471 m_matrix.setZero();
00472 m_transpositions.resize(size);
00473 for (Index i = 0; i < size; i++)
00474 m_transpositions.coeffRef(i) = i;
00475 m_temporary.resize(size);
00476 m_sign = sigma>=0 ? 1 : -1;
00477 m_isInitialized = true;
00478 }
00479
00480 internal::ldlt_inplace<UpLo>::update(m_matrix, m_transpositions, m_temporary, w, sigma);
00481
00482 return *this;
00483 }
00484
00485 namespace internal {
00486 template<typename _MatrixType, int _UpLo, typename Rhs>
00487 struct solve_retval<LDLT<_MatrixType,_UpLo>, Rhs>
00488 : solve_retval_base<LDLT<_MatrixType,_UpLo>, Rhs>
00489 {
00490 typedef LDLT<_MatrixType,_UpLo> LDLTType;
00491 EIGEN_MAKE_SOLVE_HELPERS(LDLTType,Rhs)
00492
00493 template<typename Dest> void evalTo(Dest& dst) const
00494 {
00495 eigen_assert(rhs().rows() == dec().matrixLDLT().rows());
00496
00497 dst = dec().transpositionsP() * rhs();
00498
00499
00500 dec().matrixL().solveInPlace(dst);
00501
00502
00503
00504 using std::abs;
00505 using std::max;
00506 typedef typename LDLTType::MatrixType MatrixType;
00507 typedef typename LDLTType::Scalar Scalar;
00508 typedef typename LDLTType::RealScalar RealScalar;
00509 const Diagonal<const MatrixType> vectorD = dec().vectorD();
00510 RealScalar tolerance = (max)(vectorD.array().abs().maxCoeff() * NumTraits<Scalar>::epsilon(),
00511 RealScalar(1) / NumTraits<RealScalar>::highest());
00512 for (Index i = 0; i < vectorD.size(); ++i) {
00513 if(abs(vectorD(i)) > tolerance)
00514 dst.row(i) /= vectorD(i);
00515 else
00516 dst.row(i).setZero();
00517 }
00518
00519
00520 dec().matrixU().solveInPlace(dst);
00521
00522
00523 dst = dec().transpositionsP().transpose() * dst;
00524 }
00525 };
00526 }
00527
00541 template<typename MatrixType,int _UpLo>
00542 template<typename Derived>
00543 bool LDLT<MatrixType,_UpLo>::solveInPlace(MatrixBase<Derived> &bAndX) const
00544 {
00545 eigen_assert(m_isInitialized && "LDLT is not initialized.");
00546 eigen_assert(m_matrix.rows() == bAndX.rows());
00547
00548 bAndX = this->solve(bAndX);
00549
00550 return true;
00551 }
00552
00556 template<typename MatrixType, int _UpLo>
00557 MatrixType LDLT<MatrixType,_UpLo>::reconstructedMatrix() const
00558 {
00559 eigen_assert(m_isInitialized && "LDLT is not initialized.");
00560 const Index size = m_matrix.rows();
00561 MatrixType res(size,size);
00562
00563
00564 res.setIdentity();
00565 res = transpositionsP() * res;
00566
00567 res = matrixU() * res;
00568
00569 res = vectorD().asDiagonal() * res;
00570
00571 res = matrixL() * res;
00572
00573 res = transpositionsP().transpose() * res;
00574
00575 return res;
00576 }
00577
00581 template<typename MatrixType, unsigned int UpLo>
00582 inline const LDLT<typename SelfAdjointView<MatrixType, UpLo>::PlainObject, UpLo>
00583 SelfAdjointView<MatrixType, UpLo>::ldlt() const
00584 {
00585 return LDLT<PlainObject,UpLo>(m_matrix);
00586 }
00587
00591 template<typename Derived>
00592 inline const LDLT<typename MatrixBase<Derived>::PlainObject>
00593 MatrixBase<Derived>::ldlt() const
00594 {
00595 return LDLT<PlainObject>(derived());
00596 }
00597
00598 }
00599
00600 #endif // EIGEN_LDLT_H