Eigen  5.0.1
 
Loading...
Searching...
No Matches
LDLT.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2008-2011 Gael Guennebaud <gael.guennebaud@inria.fr>
5// Copyright (C) 2009 Keir Mierle <mierle@gmail.com>
6// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
7// Copyright (C) 2011 Timothy E. Holy <tim.holy@gmail.com >
8//
9// This Source Code Form is subject to the terms of the Mozilla
10// Public License v. 2.0. If a copy of the MPL was not distributed
11// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
12// SPDX-License-Identifier: MPL-2.0
13
14#ifndef EIGEN_LDLT_H
15#define EIGEN_LDLT_H
16
17// IWYU pragma: private
18#include "./InternalHeaderCheck.h"
19
20namespace Eigen {
21
22namespace internal {
23template <typename MatrixType_, int UpLo_>
24struct traits<LDLT<MatrixType_, UpLo_> > : traits<MatrixType_> {
25 using XprKind = MatrixXpr;
26 using StorageKind = SolverStorage;
27 using StorageIndex = int;
28 enum { Flags = 0 };
29};
30
31template <typename MatrixType, int UpLo>
32struct LDLT_Traits;
33
34// PositiveSemiDef means positive semi-definite and non-zero; same for NegativeSemiDef
35enum SignMatrix { PositiveSemiDef, NegativeSemiDef, ZeroSign, Indefinite };
36} // namespace internal
37
66template <typename MatrixType_, int UpLo_>
67class LDLT : public SolverBase<LDLT<MatrixType_, UpLo_> > {
68 public:
69 using MatrixType = MatrixType_;
70 using Base = SolverBase<LDLT>;
71 friend class SolverBase<LDLT>;
72
73 EIGEN_GENERIC_PUBLIC_INTERFACE(LDLT)
74 enum {
75 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
76 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
77 UpLo = UpLo_
78 };
80
83
84 using Traits = internal::LDLT_Traits<MatrixType, UpLo>;
85
92 : m_matrix(),
93 m_l1_norm(0),
94 m_transpositions(),
95 m_sign(internal::ZeroSign),
96 m_isInitialized(false),
97 m_info(InvalidInput) {}
98
105 explicit LDLT(Index size)
106 : m_matrix(size, size),
107 m_l1_norm(0),
108 m_transpositions(size),
109 m_temporary(size),
110 m_sign(internal::ZeroSign),
111 m_isInitialized(false),
112 m_info(InvalidInput) {}
113
120 template <typename InputType>
121 explicit LDLT(const EigenBase<InputType>& matrix)
122 : m_matrix(matrix.rows(), matrix.cols()),
123 m_l1_norm(0),
124 m_transpositions(matrix.rows()),
125 m_temporary(matrix.rows()),
126 m_sign(internal::ZeroSign),
127 m_isInitialized(false),
128 m_info(InvalidInput) {
129 compute(matrix.derived());
130 }
131
139 template <typename InputType>
140 explicit LDLT(EigenBase<InputType>& matrix)
141 : m_matrix(matrix.derived()),
142 m_l1_norm(0),
143 m_transpositions(matrix.rows()),
144 m_temporary(matrix.rows()),
145 m_sign(internal::ZeroSign),
146 m_isInitialized(false),
147 m_info(InvalidInput) {
148 compute(matrix.derived());
149 }
150
154 void setZero() { m_isInitialized = false; }
155
157 inline typename Traits::MatrixU matrixU() const {
158 eigen_assert(m_isInitialized && "LDLT is not initialized.");
159 return Traits::getU(m_matrix);
160 }
161
163 inline typename Traits::MatrixL matrixL() const {
164 eigen_assert(m_isInitialized && "LDLT is not initialized.");
165 return Traits::getL(m_matrix);
166 }
167
170 inline const TranspositionType& transpositionsP() const {
171 eigen_assert(m_isInitialized && "LDLT is not initialized.");
172 return m_transpositions;
173 }
174
177 eigen_assert(m_isInitialized && "LDLT is not initialized.");
178 return m_matrix.diagonal();
179 }
180
182 inline bool isPositive() const {
183 eigen_assert(m_isInitialized && "LDLT is not initialized.");
184 return m_sign == internal::PositiveSemiDef || m_sign == internal::ZeroSign;
185 }
186
188 inline bool isNegative(void) const {
189 eigen_assert(m_isInitialized && "LDLT is not initialized.");
190 return m_sign == internal::NegativeSemiDef || m_sign == internal::ZeroSign;
191 }
192
193#ifdef EIGEN_PARSED_BY_DOXYGEN
209 template <typename Rhs>
210 inline Solve<LDLT, Rhs> solve(const MatrixBase<Rhs>& b) const;
211#endif
212
213 template <typename Derived>
214 bool solveInPlace(MatrixBase<Derived>& bAndX) const;
215
216 template <typename InputType>
217 LDLT& compute(const EigenBase<InputType>& matrix);
218
222 RealScalar rcond() const {
223 eigen_assert(m_isInitialized && "LDLT is not initialized.");
224 return internal::rcond_estimate_helper(m_l1_norm, *this);
225 }
226
227 template <typename Derived>
228 LDLT& rankUpdate(const MatrixBase<Derived>& w, const RealScalar& alpha = 1);
229
245 Scalar determinant() const;
246
260 RealScalar absDeterminant() const;
261
275 RealScalar logAbsDeterminant() const;
276
287 Scalar signDeterminant() const;
288
293 inline const MatrixType& matrixLDLT() const {
294 eigen_assert(m_isInitialized && "LDLT is not initialized.");
295 return m_matrix;
296 }
297
298 MatrixType reconstructedMatrix() const;
299
306 const LDLT& adjoint() const { return *this; }
307
308 EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_matrix.rows(); }
309 EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_matrix.cols(); }
310
317 eigen_assert(m_isInitialized && "LDLT is not initialized.");
318 return m_info;
319 }
320
321#ifndef EIGEN_PARSED_BY_DOXYGEN
322 template <typename RhsType, typename DstType>
323 void _solve_impl(const RhsType& rhs, DstType& dst) const;
324
325 template <bool Conjugate, typename RhsType, typename DstType>
326 void _solve_impl_transposed(const RhsType& rhs, DstType& dst) const;
327#endif
328
329 protected:
330 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
331
332
338 MatrixType m_matrix;
339 RealScalar m_l1_norm;
340 TranspositionType m_transpositions;
341 TmpMatrixType m_temporary;
342 internal::SignMatrix m_sign;
343 bool m_isInitialized;
344 ComputationInfo m_info;
345};
346
347namespace internal {
348
349template <int UpLo>
350struct ldlt_inplace;
351
352template <>
353struct ldlt_inplace<Lower> {
354 template <typename MatrixType, typename TranspositionType, typename Workspace>
355 static bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, SignMatrix& sign) {
356 using std::abs;
357 using Scalar = typename MatrixType::Scalar;
358 using RealScalar = typename MatrixType::RealScalar;
359 using IndexType = typename TranspositionType::StorageIndex;
360 eigen_assert(mat.rows() == mat.cols());
361 const Index size = mat.rows();
362 bool found_zero_pivot = false;
363 bool ret = true;
364
365 if (size <= 1) {
366 transpositions.setIdentity();
367 if (size == 0)
368 sign = ZeroSign;
369 else if (numext::real(mat.coeff(0, 0)) > static_cast<RealScalar>(0))
370 sign = PositiveSemiDef;
371 else if (numext::real(mat.coeff(0, 0)) < static_cast<RealScalar>(0))
372 sign = NegativeSemiDef;
373 else
374 sign = ZeroSign;
375 return true;
376 }
377
378 for (Index k = 0; k < size; ++k) {
379 // Find largest diagonal element
380 Index index_of_biggest_in_corner;
381 mat.diagonal().tail(size - k).cwiseAbs().maxCoeff(&index_of_biggest_in_corner);
382 index_of_biggest_in_corner += k;
383
384 transpositions.coeffRef(k) = IndexType(index_of_biggest_in_corner);
385 if (k != index_of_biggest_in_corner) {
386 // apply the transposition while taking care to consider only
387 // the lower triangular part
388 Index s = size - index_of_biggest_in_corner - 1; // trailing size after the biggest element
389 mat.row(k).head(k).swap(mat.row(index_of_biggest_in_corner).head(k));
390 mat.col(k).tail(s).swap(mat.col(index_of_biggest_in_corner).tail(s));
391 std::swap(mat.coeffRef(k, k), mat.coeffRef(index_of_biggest_in_corner, index_of_biggest_in_corner));
392 for (Index i = k + 1; i < index_of_biggest_in_corner; ++i) {
393 Scalar tmp = mat.coeffRef(i, k);
394 mat.coeffRef(i, k) = numext::conj(mat.coeffRef(index_of_biggest_in_corner, i));
395 mat.coeffRef(index_of_biggest_in_corner, i) = numext::conj(tmp);
396 }
397 EIGEN_IF_CONSTEXPR (NumTraits<Scalar>::IsComplex)
398 mat.coeffRef(index_of_biggest_in_corner, k) = numext::conj(mat.coeff(index_of_biggest_in_corner, k));
399 }
400
401 // partition the matrix:
402 // A00 | - | -
403 // lu = A10 | A11 | -
404 // A20 | A21 | A22
405 Index rs = size - k - 1;
406 Block<MatrixType, Dynamic, 1> A21(mat, k + 1, k, rs, 1);
407 Block<MatrixType, 1, Dynamic> A10(mat, k, 0, 1, k);
408 Block<MatrixType, Dynamic, Dynamic> A20(mat, k + 1, 0, rs, k);
409
410 if (k > 0) {
411 temp.head(k) = mat.diagonal().real().head(k).asDiagonal() * A10.adjoint();
412 mat.coeffRef(k, k) -= (A10 * temp.head(k)).value();
413 if (rs > 0) A21.noalias() -= A20 * temp.head(k);
414 }
415
416 // In some previous versions of Eigen (e.g., 3.2.1), the scaling was omitted if the pivot
417 // was smaller than the cutoff value. However, since LDLT is not rank-revealing
418 // we should only make sure that we do not introduce INF or NaN values.
419 // Remark that LAPACK also uses 0 as the cutoff value.
420 RealScalar realAkk = numext::real(mat.coeffRef(k, k));
421 bool pivot_is_valid = (abs(realAkk) > RealScalar(0));
422
423 if (k == 0 && !pivot_is_valid) {
424 // The entire diagonal is zero, there is nothing more to do
425 // except filling the transpositions, and checking whether the matrix is zero.
426 sign = ZeroSign;
427 for (Index j = 0; j < size; ++j) {
428 transpositions.coeffRef(j) = IndexType(j);
429 ret = ret && (mat.col(j).tail(size - j - 1).array() == Scalar(0)).all();
430 }
431 return ret;
432 }
433
434 if ((rs > 0) && pivot_is_valid)
435 A21 /= realAkk;
436 else if (rs > 0)
437 ret = ret && (A21.array() == Scalar(0)).all();
438
439 if (found_zero_pivot && pivot_is_valid)
440 ret = false; // factorization failed
441 else if (!pivot_is_valid)
442 found_zero_pivot = true;
443
444 if (sign == PositiveSemiDef) {
445 if (realAkk < static_cast<RealScalar>(0)) sign = Indefinite;
446 } else if (sign == NegativeSemiDef) {
447 if (realAkk > static_cast<RealScalar>(0)) sign = Indefinite;
448 } else if (sign == ZeroSign) {
449 if (realAkk > static_cast<RealScalar>(0))
450 sign = PositiveSemiDef;
451 else if (realAkk < static_cast<RealScalar>(0))
452 sign = NegativeSemiDef;
453 }
454 }
455
456 return ret;
457 }
458
459 // Reference for the algorithm: Davis and Hager, "Multiple Rank
460 // Modifications of a Sparse Cholesky Factorization" (Algorithm 1)
461 // Trivial rearrangements of their computations (Timothy E. Holy)
462 // allow their algorithm to work for rank-1 updates even if the
463 // original matrix is not of full rank.
464 // Here only rank-1 updates are implemented, to reduce the
465 // requirement for intermediate storage and improve accuracy
466 template <typename MatrixType, typename WDerived>
467 static bool updateInPlace(MatrixType& mat, MatrixBase<WDerived>& w,
468 const typename MatrixType::RealScalar& sigma = 1) {
469 using numext::isfinite;
470 using Scalar = typename MatrixType::Scalar;
471 using RealScalar = typename MatrixType::RealScalar;
472
473 const Index size = mat.rows();
474 eigen_assert(mat.cols() == size && w.size() == size);
475
476 RealScalar alpha = 1;
477
478 // Apply the update
479 for (Index j = 0; j < size; j++) {
480 // Check for termination due to an original decomposition of low-rank
481 if (!(isfinite)(alpha)) break;
482
483 // Update the diagonal terms
484 RealScalar dj = numext::real(mat.coeff(j, j));
485 Scalar wj = w.coeff(j);
486 RealScalar swj2 = sigma * numext::abs2(wj);
487 RealScalar gamma = dj * alpha + swj2;
488
489 // A zero contribution leaves both quantities unchanged, but spelling that out as an addition of swj2/alpha and
490 // swj2/dj evaluates 0/0 when alpha or the pivot is zero. The resulting NaN reaches the termination test above
491 // on the next iteration, which reads it as a low-rank signal and abandons the remainder of the update. Skip the
492 // no-op instead. A zero pivot with a nonzero contribution still yields an infinite alpha, so genuine low-rank
493 // termination is unaffected.
494 if (!numext::is_exactly_zero(swj2)) {
495 mat.coeffRef(j, j) += swj2 / alpha;
496 alpha += swj2 / dj;
497 }
498
499 // Update the terms of L
500 Index rs = size - j - 1;
501 w.tail(rs) -= wj * mat.col(j).tail(rs);
502 if (!numext::is_exactly_zero(gamma)) mat.col(j).tail(rs) += (sigma * numext::conj(wj) / gamma) * w.tail(rs);
503 }
504 return true;
505 }
506
507 template <typename MatrixType, typename TranspositionType, typename Workspace, typename WType>
508 static bool update(MatrixType& mat, const TranspositionType& transpositions, Workspace& tmp, const WType& w,
509 const typename MatrixType::RealScalar& sigma = 1) {
510 // Apply the permutation to the input w
511 tmp = transpositions * w;
512
513 return ldlt_inplace<Lower>::updateInPlace(mat, tmp, sigma);
514 }
515};
516
517template <>
518struct ldlt_inplace<Upper> {
519 template <typename MatrixType, typename TranspositionType, typename Workspace>
520 static EIGEN_STRONG_INLINE bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp,
521 SignMatrix& sign) {
522 Transpose<MatrixType> matt(mat);
523 return ldlt_inplace<Lower>::unblocked(matt, transpositions, temp, sign);
524 }
525
526 template <typename MatrixType, typename TranspositionType, typename Workspace, typename WType>
527 static EIGEN_STRONG_INLINE bool update(MatrixType& mat, TranspositionType& transpositions, Workspace& tmp, WType& w,
528 const typename MatrixType::RealScalar& sigma = 1) {
529 Transpose<MatrixType> matt(mat);
530 return ldlt_inplace<Lower>::update(matt, transpositions, tmp, w.conjugate(), sigma);
531 }
532};
533
534template <typename MatrixType>
535struct LDLT_Traits<MatrixType, Lower> {
536 using MatrixL = const TriangularView<const MatrixType, UnitLower>;
537 using MatrixU = const TriangularView<const typename MatrixType::AdjointReturnType, UnitUpper>;
538 static inline MatrixL getL(const MatrixType& m) { return MatrixL(m); }
539 static inline MatrixU getU(const MatrixType& m) { return MatrixU(m.adjoint()); }
540};
541
542template <typename MatrixType>
543struct LDLT_Traits<MatrixType, Upper> {
544 using MatrixL = const TriangularView<const typename MatrixType::AdjointReturnType, UnitLower>;
545 using MatrixU = const TriangularView<const MatrixType, UnitUpper>;
546 static inline MatrixL getL(const MatrixType& m) { return MatrixL(m.adjoint()); }
547 static inline MatrixU getU(const MatrixType& m) { return MatrixU(m); }
548};
549
550} // end namespace internal
551
554template <typename MatrixType, int UpLo_>
555template <typename InputType>
556LDLT<MatrixType, UpLo_>& LDLT<MatrixType, UpLo_>::compute(const EigenBase<InputType>& a) {
557 eigen_assert(a.rows() == a.cols());
558 const Index size = a.rows();
559
560 m_matrix = a.derived();
561
562 // Compute matrix L1 norm = max abs column sum over the implicit self-adjoint matrix.
563 m_l1_norm = m_matrix.template selfadjointView<UpLo_>().l1Norm();
564
565 m_transpositions.resize(size);
566 m_isInitialized = false;
567 m_temporary.resize(size);
568 m_sign = internal::ZeroSign;
569
570 m_info = internal::ldlt_inplace<UpLo>::unblocked(m_matrix, m_transpositions, m_temporary, m_sign) ? Success
572
573 m_isInitialized = true;
574 return *this;
575}
576
596template <typename MatrixType, int UpLo_>
597template <typename Derived>
598LDLT<MatrixType, UpLo_>& LDLT<MatrixType, UpLo_>::rankUpdate(
599 const MatrixBase<Derived>& w, const typename LDLT<MatrixType, UpLo_>::RealScalar& sigma) {
600 using IndexType = typename TranspositionType::StorageIndex;
601 const Index size = w.rows();
602 if (m_isInitialized) {
603 eigen_assert(m_matrix.rows() == size);
604 } else {
605 m_matrix.resize(size, size);
606 m_matrix.setZero();
607 m_transpositions.resize(size);
608 for (Index i = 0; i < size; i++) m_transpositions.coeffRef(i) = IndexType(i);
609 m_temporary.resize(size);
610 m_sign = sigma >= 0 ? internal::PositiveSemiDef : internal::NegativeSemiDef;
611 m_isInitialized = true;
612 // Assigned here rather than after the branch: updating an existing factorization keeps the status it already has.
613 m_info = Success;
614 }
615
616 internal::ldlt_inplace<UpLo>::update(m_matrix, m_transpositions, m_temporary, w, sigma);
617
618 return *this;
619}
620
621// A = P^T L D L^* P with L unit lower triangular and D real diagonal, so det(A) = prod(D_ii).
622
623template <typename MatrixType_, int UpLo_>
624typename LDLT<MatrixType_, UpLo_>::Scalar LDLT<MatrixType_, UpLo_>::determinant() const {
625 eigen_assert(m_isInitialized && "LDLT is not initialized.");
626 eigen_assert(m_info == Success && "LDLT failed because of a zero pivot.");
627 return Scalar(vectorD().real().prod());
628}
629
630template <typename MatrixType_, int UpLo_>
632 eigen_assert(m_isInitialized && "LDLT is not initialized.");
633 eigen_assert(m_info == Success && "LDLT failed because of a zero pivot.");
634 return numext::abs(vectorD().real().prod());
635}
636
637template <typename MatrixType_, int UpLo_>
639 eigen_assert(m_isInitialized && "LDLT is not initialized.");
640 eigen_assert(m_info == Success && "LDLT failed because of a zero pivot.");
641 return vectorD().real().cwiseAbs().array().log().sum();
642}
643
644template <typename MatrixType_, int UpLo_>
645typename LDLT<MatrixType_, UpLo_>::Scalar LDLT<MatrixType_, UpLo_>::signDeterminant() const {
646 eigen_assert(m_isInitialized && "LDLT is not initialized.");
647 eigen_assert(m_info == Success && "LDLT failed because of a zero pivot.");
648 return Scalar(vectorD().real().array().sign().prod());
649}
650
651#ifndef EIGEN_PARSED_BY_DOXYGEN
652template <typename MatrixType_, int UpLo_>
653template <typename RhsType, typename DstType>
654void LDLT<MatrixType_, UpLo_>::_solve_impl(const RhsType& rhs, DstType& dst) const {
655 _solve_impl_transposed<true>(rhs, dst);
656}
657
658template <typename MatrixType_, int UpLo_>
659template <bool Conjugate, typename RhsType, typename DstType>
660void LDLT<MatrixType_, UpLo_>::_solve_impl_transposed(const RhsType& rhs, DstType& dst) const {
661 // dst = P b
662 dst = m_transpositions * rhs;
663
664 // dst = L^-1 (P b)
665 // dst = L^-*T (P b)
666 matrixL().template conjugateIf<!Conjugate>().solveInPlace(dst);
667
668 // dst = D^-* (L^-1 P b)
669 // dst = D^-1 (L^-*T P b)
670 // more precisely, use pseudo-inverse of D (see bug 241)
671 using std::abs;
672 const typename Diagonal<const MatrixType>::RealReturnType vecD(vectorD());
673 // In some previous versions, tolerance was set to the max of 1/highest (or rather numeric_limits::min())
674 // and the maximal diagonal entry * epsilon as motivated by LAPACK's xGELSS:
675 // RealScalar tolerance = numext::maxi(vecD.array().abs().maxCoeff() * NumTraits<RealScalar>::epsilon(),RealScalar(1)
676 // / NumTraits<RealScalar>::highest()); However, LDLT is not rank revealing, and so adjusting the tolerance wrt to the
677 // highest diagonal element is not well justified and leads to numerical issues in some cases. Moreover, Lapack's
678 // xSYTRS routines use 0 for the tolerance. Using numeric_limits::min() gives us more robustness to denormals.
679 RealScalar tolerance = (std::numeric_limits<RealScalar>::min)();
680 for (Index i = 0; i < vecD.size(); ++i) {
681 if (abs(vecD(i)) > tolerance)
682 dst.row(i) /= vecD(i);
683 else
684 dst.row(i).setZero();
685 }
686
687 // dst = L^-* (D^-* L^-1 P b)
688 // dst = L^-T (D^-1 L^-*T P b)
689 matrixL().transpose().template conjugateIf<Conjugate>().solveInPlace(dst);
690
691 // dst = P^T (L^-* D^-* L^-1 P b) = A^-1 b
692 // dst = P^-T (L^-T D^-1 L^-*T P b) = A^-1 b
693 dst = m_transpositions.transpose() * dst;
694}
695#endif
696
710template <typename MatrixType, int UpLo_>
711template <typename Derived>
712bool LDLT<MatrixType, UpLo_>::solveInPlace(MatrixBase<Derived>& bAndX) const {
713 eigen_assert(m_isInitialized && "LDLT is not initialized.");
714 eigen_assert(m_matrix.rows() == bAndX.rows());
715
716 bAndX = this->solve(bAndX);
717
718 return true;
719}
720
724template <typename MatrixType, int UpLo_>
726 eigen_assert(m_isInitialized && "LDLT is not initialized.");
727 const Index size = m_matrix.rows();
728 MatrixType res(size, size);
729
730 // P
731 res.setIdentity();
732 res = transpositionsP() * res;
733 // L^* P
734 res = matrixU() * res;
735 // D(L^*P)
736 res = vectorD().real().asDiagonal() * res;
737 // L(DL^*P)
738 res = matrixL() * res;
739 // P^T (LDL^*P)
740 res = transpositionsP().transpose() * res;
741
742 return res;
743}
744
749template <typename MatrixType, unsigned int UpLo>
754
759template <typename Derived>
763
764} // end namespace Eigen
765
766#endif // EIGEN_LDLT_H
Expression of a diagonal/subdiagonal/superdiagonal in a matrix.
Definition Diagonal.h:78
Robust Cholesky decomposition of a matrix with pivoting.
Definition LDLT.h:67
const TranspositionType & transpositionsP() const
Definition LDLT.h:170
Solve< LDLT, Rhs > solve(const MatrixBase< Rhs > &b) const
Traits::MatrixL matrixL() const
Definition LDLT.h:163
Diagonal< const MatrixType > vectorD() const
Definition LDLT.h:176
Scalar determinant() const
Definition LDLT.h:624
void setZero()
Definition LDLT.h:154
const MatrixType & matrixLDLT() const
Definition LDLT.h:293
RealScalar rcond() const
Definition LDLT.h:222
bool isNegative(void) const
Definition LDLT.h:188
LDLT()
Default Constructor.
Definition LDLT.h:91
bool isPositive() const
Definition LDLT.h:182
Scalar signDeterminant() const
Definition LDLT.h:645
LDLT(const EigenBase< InputType > &matrix)
Constructor with decomposition.
Definition LDLT.h:121
RealScalar absDeterminant() const
Definition LDLT.h:631
LDLT(Index size)
Default Constructor with memory preallocation.
Definition LDLT.h:105
LDLT(EigenBase< InputType > &matrix)
Constructs a LDLT factorization from a given matrix.
Definition LDLT.h:140
MatrixType reconstructedMatrix() const
Definition LDLT.h:725
ComputationInfo info() const
Reports whether previous computation was successful.
Definition LDLT.h:316
const LDLT & adjoint() const
Definition LDLT.h:306
Traits::MatrixU matrixU() const
Definition LDLT.h:157
RealScalar logAbsDeterminant() const
Definition LDLT.h:638
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:53
LDLT< PlainObject > ldlt() const
Definition LDLT.h:760
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:188
Permutation matrix.
Definition PermutationMatrix.h:346
LDLT< PlainObject, UpLo > ldlt() const
Definition LDLT.h:750
Pseudo expression representing a solving operation.
Definition Solve.h:63
constexpr LDLT< MatrixType_, UpLo_ > & derived()
Represents a sequence of transpositions (row/column interchange)
Definition Transpositions.h:144
ComputationInfo
Definition Constants.h:455
@ Lower
Definition Constants.h:212
@ Upper
Definition Constants.h:214
@ NumericalIssue
Definition Constants.h:459
@ InvalidInput
Definition Constants.h:464
@ Success
Definition Constants.h:457
Definition EigenBase.h:34
constexpr Derived & derived()
Definition EigenBase.h:50
constexpr Index size() const noexcept
Definition EigenBase.h:65