Eigen  5.0.1
 
Loading...
Searching...
No Matches
PartialPivLU.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2006-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
5// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
6//
7// This Source Code Form is subject to the terms of the Mozilla
8// Public License v. 2.0. If a copy of the MPL was not distributed
9// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10// SPDX-License-Identifier: MPL-2.0
11
12#ifndef EIGEN_PARTIALLU_H
13#define EIGEN_PARTIALLU_H
14
15// IWYU pragma: private
16#include "./InternalHeaderCheck.h"
17
18namespace Eigen {
19
20namespace internal {
21template <typename MatrixType_, typename PermutationIndex_>
22struct traits<PartialPivLU<MatrixType_, PermutationIndex_> > : traits<MatrixType_> {
23 using XprKind = MatrixXpr;
24 using StorageKind = SolverStorage;
25 using StorageIndex = PermutationIndex_;
26 using BaseTraits = traits<MatrixType_>;
27 enum { Flags = BaseTraits::Flags & RowMajorBit, CoeffReadCost = Dynamic };
28};
29
30} // end namespace internal
31
66template <typename MatrixType_, typename PermutationIndex_>
67class PartialPivLU : public SolverBase<PartialPivLU<MatrixType_, PermutationIndex_> > {
68 public:
69 using MatrixType = MatrixType_;
70 using Base = SolverBase<PartialPivLU>;
71 friend class SolverBase<PartialPivLU>;
72
73 EIGEN_GENERIC_PUBLIC_INTERFACE(PartialPivLU)
74 enum {
75 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
76 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
77 };
78 using PermutationIndex = PermutationIndex_;
81 using PlainObject = typename MatrixType::PlainObject;
82
90 eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
91 return Success;
92 }
93
101
109
117 template <typename InputType>
118 explicit PartialPivLU(const EigenBase<InputType>& matrix);
119
127 template <typename InputType>
129
130 template <typename InputType>
131 PartialPivLU& compute(const EigenBase<InputType>& matrix) {
132 m_lu = matrix.derived();
133 compute();
134 return *this;
135 }
136
143 inline const MatrixType& matrixLU() const {
144 eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
145 return m_lu;
146 }
147
150 inline const PermutationType& permutationP() const {
151 eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
152 return m_p;
153 }
154
155#ifdef EIGEN_PARSED_BY_DOXYGEN
173 template <typename Rhs>
175#endif
176
180 inline RealScalar rcond() const {
181 eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
182 return internal::rcond_estimate_helper(m_l1_norm, *this);
183 }
184
193 eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
194 return Inverse<PartialPivLU>(*this);
195 }
196
213 Scalar determinant() const;
214
230 RealScalar absDeterminant() const;
231
244 RealScalar logAbsDeterminant() const;
245
258 Scalar signDeterminant() const;
259
260 MatrixType reconstructedMatrix() const;
261
262 constexpr Index rows() const noexcept { return m_lu.rows(); }
263 constexpr Index cols() const noexcept { return m_lu.cols(); }
264
265#ifndef EIGEN_PARSED_BY_DOXYGEN
266 template <typename RhsType, typename DstType>
267 EIGEN_DEVICE_FUNC void _solve_impl(const RhsType& rhs, DstType& dst) const {
268 /* The decomposition PA = LU can be rewritten as A = P^{-1} L U.
269 * So we proceed as follows:
270 * Step 1: compute c = Pb.
271 * Step 2: replace c by the solution x to Lx = c.
272 * Step 3: replace c by the solution x to Ux = c.
273 */
274
275 // Step 1
276 dst = permutationP() * rhs;
277
278 // Step 2
279 m_lu.template triangularView<UnitLower>().solveInPlace(dst);
280
281 // Step 3
282 m_lu.template triangularView<Upper>().solveInPlace(dst);
283 }
284
285 template <bool Conjugate, typename RhsType, typename DstType>
286 EIGEN_DEVICE_FUNC void _solve_impl_transposed(const RhsType& rhs, DstType& dst) const {
287 /* The decomposition PA = LU can be rewritten as A^T = U^T L^T P.
288 * So we proceed as follows:
289 * Step 1: compute c as the solution to L^T c = b
290 * Step 2: replace c by the solution x to U^T x = c.
291 * Step 3: update c = P^-1 c.
292 */
293
294 eigen_assert(rhs.rows() == m_lu.cols());
295
296 // Step 1
297 dst = m_lu.template triangularView<Upper>().transpose().template conjugateIf<Conjugate>().solve(rhs);
298 // Step 2
299 m_lu.template triangularView<UnitLower>().transpose().template conjugateIf<Conjugate>().solveInPlace(dst);
300 // Step 3
301 dst = permutationP().transpose() * dst;
302 }
303#endif
304
305 protected:
306 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
307
308 void compute();
309
310 MatrixType m_lu;
311 PermutationType m_p;
312 TranspositionType m_rowsTranspositions;
313 RealScalar m_l1_norm;
314 signed char m_det_p;
315 bool m_isInitialized;
316};
317
318template <typename MatrixType, typename PermutationIndex>
320 : m_lu(), m_p(), m_rowsTranspositions(), m_l1_norm(0), m_det_p(0), m_isInitialized(false) {}
321
322template <typename MatrixType, typename PermutationIndex>
324 : m_lu(size, size), m_p(size), m_rowsTranspositions(size), m_l1_norm(0), m_det_p(0), m_isInitialized(false) {}
325
326template <typename MatrixType, typename PermutationIndex>
327template <typename InputType>
329 : m_lu(matrix.rows(), matrix.cols()),
330 m_p(matrix.rows()),
331 m_rowsTranspositions(matrix.rows()),
332 m_l1_norm(0),
333 m_det_p(0),
334 m_isInitialized(false) {
335 compute(matrix.derived());
336}
337
338template <typename MatrixType, typename PermutationIndex>
339template <typename InputType>
341 : m_lu(matrix.derived()),
342 m_p(matrix.rows()),
343 m_rowsTranspositions(matrix.rows()),
344 m_l1_norm(0),
345 m_det_p(0),
346 m_isInitialized(false) {
347 compute();
348}
349
350namespace internal {
351
354template <int K, int Size, bool Last = (K == Size - 1)>
355struct unrolled_partial_lu_step {
356 template <typename MatrixTypeRef, typename PivIndex>
357 static EIGEN_STRONG_INLINE void run(MatrixTypeRef& lu, PivIndex* row_transpositions, PivIndex& nb_transpositions,
358 Index& first_zero_pivot) {
359 using Scalar = typename MatrixTypeRef::Scalar;
360 using Scoring = scalar_score_coeff_op<Scalar>;
361 using Score = typename Scoring::result_type;
362 constexpr int Remaining = Size - K - 1;
363
364 Index row_of_biggest_in_col;
365 const Score biggest_in_corner =
366 lu.col(K).template tail<Size - K>().unaryExpr(Scoring()).maxCoeff(&row_of_biggest_in_col);
367 row_of_biggest_in_col += K;
368 row_transpositions[K] = PivIndex(row_of_biggest_in_col);
369 if (!numext::is_exactly_zero(biggest_in_corner)) {
370 if (K != row_of_biggest_in_col) {
371 lu.row(K).swap(lu.row(row_of_biggest_in_col));
372 ++nb_transpositions;
373 }
374 lu.col(K).template tail<Remaining>() /= lu.coeff(K, K);
375 } else if (first_zero_pivot == -1) {
376 first_zero_pivot = K;
377 }
378 lu.template bottomRightCorner<Remaining, Remaining>().noalias() -=
379 lu.col(K).template tail<Remaining>() * lu.row(K).template tail<Remaining>();
380 unrolled_partial_lu_step<K + 1, Size>::run(lu, row_transpositions, nb_transpositions, first_zero_pivot);
381 }
382};
383
384template <int K, int Size>
385struct unrolled_partial_lu_step<K, Size, /*Last=*/true> {
386 template <typename MatrixTypeRef, typename PivIndex>
387 static EIGEN_STRONG_INLINE void run(MatrixTypeRef& lu, PivIndex* row_transpositions, PivIndex&,
388 Index& first_zero_pivot) {
389 using Scoring = scalar_score_coeff_op<typename MatrixTypeRef::Scalar>;
390 row_transpositions[K] = PivIndex(K);
391 if (numext::is_exactly_zero(Scoring()(lu.coeff(K, K))) && first_zero_pivot == -1) first_zero_pivot = K;
392 }
393};
394
396template <bool Unroll, int Size>
397struct unrolled_partial_lu {
398 template <typename MatrixTypeRef, typename PivIndex>
399 static EIGEN_STRONG_INLINE bool run(MatrixTypeRef&, PivIndex*, PivIndex&, Index&) {
400 return false;
401 }
402};
403
404template <int Size>
405struct unrolled_partial_lu<true, Size> {
406 template <typename MatrixTypeRef, typename PivIndex>
407 static EIGEN_STRONG_INLINE bool run(MatrixTypeRef& lu, PivIndex* row_transpositions, PivIndex& nb_transpositions,
408 Index& first_zero_pivot) {
409 nb_transpositions = 0;
410 first_zero_pivot = -1;
411 unrolled_partial_lu_step<0, Size>::run(lu, row_transpositions, nb_transpositions, first_zero_pivot);
412 return true;
413 }
414};
415
417template <typename Scalar, int StorageOrder, typename PivIndex, int SizeAtCompileTime = Dynamic>
418struct generic_partial_lu_impl {
419 static constexpr int UnBlockedBound = 16;
420 static constexpr bool UnBlockedAtCompileTime = SizeAtCompileTime != Dynamic && SizeAtCompileTime <= UnBlockedBound;
421 static constexpr int ActualSizeAtCompileTime = UnBlockedAtCompileTime ? SizeAtCompileTime : Dynamic;
422 // Unrolling gives the pivot search, scaling and update of every step compile-time extents; runtime-sized blocks'
423 // vectorized loops cost more than their arithmetic (1.5-4.6x for 3x3 to 6x6 double, gcc and clang, AVX2). At 16,
424 // gcc's unrolled code is slower than the loop.
425 static constexpr int UnrolledBound = 12;
426 static constexpr bool UnrolledAtCompileTime = UnBlockedAtCompileTime && SizeAtCompileTime <= UnrolledBound;
427 // Remaining rows and columns at compile-time:
428 static constexpr int RRows = SizeAtCompileTime == 2 ? 1 : Dynamic;
429 static constexpr int RCols = SizeAtCompileTime == 2 ? 1 : Dynamic;
430 using MatrixType = Matrix<Scalar, ActualSizeAtCompileTime, ActualSizeAtCompileTime, StorageOrder>;
431 using MatrixTypeRef = Ref<MatrixType>;
432 using BlockType = Ref<Matrix<Scalar, Dynamic, Dynamic, StorageOrder>>;
433 using RealScalar = typename MatrixType::RealScalar;
434
435 static void apply_row_transpositions(BlockType& matrix, Index first, Index count, const PivIndex* transpositions) {
436 EIGEN_IF_CONSTEXPR (StorageOrder == ColMajor) {
437 // Keep the pivot rows of one column in cache, even when the outer stride maps every column to the same set.
438 for (Index j = 0; j < matrix.cols(); ++j)
439 for (Index i = first; i < first + count; ++i)
440 numext::swap(matrix.coeffRef(i, j), matrix.coeffRef(transpositions[i], j));
441 } else {
442 for (Index i = first; i < first + count; ++i) matrix.row(i).swap(matrix.row(transpositions[i]));
443 }
444 }
445
456 static Index unblocked_lu(MatrixTypeRef& lu, PivIndex* row_transpositions, PivIndex& nb_transpositions) {
457 using Scoring = scalar_score_coeff_op<Scalar>;
458 using Score = typename Scoring::result_type;
459 {
460 Index first_zero_pivot;
461 if (unrolled_partial_lu<UnrolledAtCompileTime, SizeAtCompileTime>::run(lu, row_transpositions, nb_transpositions,
462 first_zero_pivot))
463 return first_zero_pivot;
464 }
465 const Index rows = lu.rows();
466 const Index cols = lu.cols();
467 const Index size = (std::min)(rows, cols);
468 // For small compile-time matrices and square runtime matrices it is worth processing the last row separately:
469 // speedup: +100% for 2x2, +10% for others.
470 const bool process_last_row_separately = UnBlockedAtCompileTime || rows == cols;
471 const Index endk = process_last_row_separately ? size - 1 : size;
472 nb_transpositions = 0;
473 Index first_zero_pivot = -1;
474 for (Index k = 0; k < endk; ++k) {
475 int rrows = internal::convert_index<int>(rows - k - 1);
476 int rcols = internal::convert_index<int>(cols - k - 1);
477
478 Index row_of_biggest_in_col;
479 Score biggest_in_corner = lu.col(k).tail(rows - k).unaryExpr(Scoring()).maxCoeff(&row_of_biggest_in_col);
480 row_of_biggest_in_col += k;
481
482 row_transpositions[k] = PivIndex(row_of_biggest_in_col);
483
484 if (!numext::is_exactly_zero(biggest_in_corner)) {
485 if (k != row_of_biggest_in_col) {
486 lu.row(k).swap(lu.row(row_of_biggest_in_col));
487 ++nb_transpositions;
488 }
489
490 lu.col(k).tail(fix<RRows>(rrows)) /= lu.coeff(k, k);
491 } else if (first_zero_pivot == -1) {
492 // the pivot is exactly zero, we record the index of the first pivot which is exactly 0,
493 // and continue the factorization such we still have P A = L U
494 first_zero_pivot = k;
495 }
496
497 // Skip the trailing update for rectangular panels with no remaining columns.
498 if (rrows > 0 && rcols > 0)
499 lu.bottomRightCorner(fix<RRows>(rrows), fix<RCols>(rcols)).noalias() -=
500 lu.col(k).tail(fix<RRows>(rrows)) * lu.row(k).tail(fix<RCols>(rcols));
501 }
502
503 // special handling of the last entry
504 if (process_last_row_separately) {
505 Index k = endk;
506 row_transpositions[k] = PivIndex(k);
507 if (numext::is_exactly_zero(Scoring()(lu(k, k))) && first_zero_pivot == -1) first_zero_pivot = k;
508 }
509
510 return first_zero_pivot;
511 }
512
528 static Index blocked_lu(Index rows, Index cols, Scalar* lu_data, Index luStride, PivIndex* row_transpositions,
529 PivIndex& nb_transpositions, Index maxBlockSize = 256) {
530 MatrixTypeRef lu = MatrixType::Map(lu_data, rows, cols, OuterStride<>(luStride));
531
532 const Index size = (std::min)(rows, cols);
533
534 // if the matrix is too small, no blocking:
535 EIGEN_IF_CONSTEXPR (UnBlockedAtCompileTime) {
536 return unblocked_lu(lu, row_transpositions, nb_transpositions);
537 } else if (size <= UnBlockedBound) {
538 return unblocked_lu(lu, row_transpositions, nb_transpositions);
539 }
540
541 // automatically adjust the number of subdivisions to the size
542 // of the matrix so that there is enough sub blocks:
543 Index blockSize;
544 {
545 blockSize = size / 8;
546 blockSize = (blockSize / 16) * 16;
547 blockSize = (std::min)((std::max)(blockSize, Index(8)), maxBlockSize);
548 }
549
550 nb_transpositions = 0;
551 Index first_zero_pivot = -1;
552 for (Index k = 0; k < size; k += blockSize) {
553 Index bs = (std::min)(size - k, blockSize); // actual size of the block
554 Index trows = rows - k - bs; // trailing rows
555 Index tsize = cols - k - bs; // trailing columns
556
557 // partition the matrix:
558 // A00 | A01 | A02
559 // lu = A_0 | A_1 | A_2 = A10 | A11 | A12
560 // A20 | A21 | A22
561 BlockType A_2 = lu.block(0, k + bs, rows, tsize);
562 BlockType A11 = lu.block(k, k, bs, bs);
563 BlockType A12 = lu.block(k, k + bs, bs, tsize);
564 BlockType A21 = lu.block(k + bs, k, trows, bs);
565 BlockType A22 = lu.block(k + bs, k + bs, trows, tsize);
566
567 PivIndex nb_transpositions_in_panel;
568 // recursively call the blocked LU algorithm on [A11^T A21^T]^T
569 // with a very small blocking size:
570 Index ret = blocked_lu(trows + bs, bs, &lu.coeffRef(k, k), luStride, row_transpositions + k,
571 nb_transpositions_in_panel, 16);
572 if (ret >= 0 && first_zero_pivot == -1) first_zero_pivot = k + ret;
573
574 nb_transpositions += nb_transpositions_in_panel;
575 // update permutations and apply them to A_0
576 if (k > 0) {
577 BlockType A_0 = lu.block(0, 0, rows, k);
578 for (Index i = k; i < k + bs; ++i) row_transpositions[i] += internal::convert_index<PivIndex>(k);
579 apply_row_transpositions(A_0, k, bs, row_transpositions);
580 }
581
582 if (tsize) {
583 // apply permutations to A_2
584 apply_row_transpositions(A_2, k, bs, row_transpositions);
585
586 // A12 = A11^-1 A12
587 A11.template triangularView<UnitLower>().solveInPlace(A12);
588
589 A22.noalias() -= A21 * A12;
590 }
591 }
592 return first_zero_pivot;
593 }
594};
595
596template <typename Scalar, int StorageOrder, typename PivIndex, int SizeAtCompileTime = Dynamic>
597struct partial_lu_impl : generic_partial_lu_impl<Scalar, StorageOrder, PivIndex, SizeAtCompileTime> {};
598
601template <typename MatrixType, typename TranspositionType>
602void partial_lu_inplace(MatrixType& lu, TranspositionType& row_transpositions,
603 typename TranspositionType::StorageIndex& nb_transpositions) {
604 // Special-case of zero matrix.
605 if (lu.rows() == 0 || lu.cols() == 0) {
606 nb_transpositions = 0;
607 return;
608 }
609 eigen_assert(lu.cols() == row_transpositions.size());
610 eigen_assert(row_transpositions.size() < 2 ||
611 (&row_transpositions.coeffRef(1) - &row_transpositions.coeffRef(0)) == 1);
612
613 partial_lu_impl<typename MatrixType::Scalar, MatrixType::Flags & RowMajorBit ? RowMajor : ColMajor,
614 typename TranspositionType::StorageIndex,
615 internal::min_size_prefer_fixed(MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime)>::
616 blocked_lu(lu.rows(), lu.cols(), &lu.coeffRef(0, 0), lu.outerStride(), &row_transpositions.coeffRef(0),
617 nb_transpositions);
618}
619
623template <typename Derived>
624typename traits<Derived>::Scalar partial_lu_determinant(const Derived& m) {
625 using Scalar = typename traits<Derived>::Scalar;
626 if (m.rows() == 0) return Scalar(1);
627 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
628
629 using PlainObject = typename plain_matrix_type<Derived>::type;
630 using TranspositionType =
631 Transpositions<PlainObject::RowsAtCompileTime, PlainObject::MaxRowsAtCompileTime, DefaultPermutationIndex>;
632
633 eigen_assert(m.rows() < NumTraits<DefaultPermutationIndex>::highest());
634 PlainObject lu(m);
635
636 TranspositionType row_transpositions(lu.rows());
637 typename TranspositionType::StorageIndex nb_transpositions;
638 partial_lu_inplace(lu, row_transpositions, nb_transpositions);
639
640 return Scalar((nb_transpositions % 2) ? -1 : 1) * lu.diagonal().prod();
641}
642
643} // end namespace internal
644
645template <typename MatrixType, typename PermutationIndex>
646void PartialPivLU<MatrixType, PermutationIndex>::compute() {
647 eigen_assert(m_lu.rows() < NumTraits<PermutationIndex>::highest());
648
649 if (m_lu.cols() > 0)
650 m_l1_norm = m_lu.cwiseAbs().colwise().sum().maxCoeff();
651 else
652 m_l1_norm = RealScalar(0);
653
654 eigen_assert(m_lu.rows() == m_lu.cols() && "PartialPivLU is only for square (and moreover invertible) matrices");
655 const Index size = m_lu.rows();
656
657 m_rowsTranspositions.resize(size);
658
659 typename TranspositionType::StorageIndex nb_transpositions;
660 internal::partial_lu_inplace(m_lu, m_rowsTranspositions, nb_transpositions);
661 m_det_p = (nb_transpositions % 2) ? -1 : 1;
662
663 m_p = m_rowsTranspositions;
664
665 m_isInitialized = true;
666}
667
668template <typename MatrixType, typename PermutationIndex>
669typename PartialPivLU<MatrixType, PermutationIndex>::Scalar PartialPivLU<MatrixType, PermutationIndex>::determinant()
670 const {
671 eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
672 return Scalar(m_det_p) * m_lu.diagonal().prod();
673}
674
675template <typename MatrixType, typename PermutationIndex>
678 eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
679 return numext::abs(m_lu.diagonal().prod());
680}
681
682template <typename MatrixType, typename PermutationIndex>
685 eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
686 return m_lu.diagonal().cwiseAbs().array().log().sum();
687}
688
689template <typename MatrixType, typename PermutationIndex>
690typename PartialPivLU<MatrixType, PermutationIndex>::Scalar
692 eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
693 return Scalar(m_det_p) * m_lu.diagonal().array().sign().prod();
694}
695
699template <typename MatrixType, typename PermutationIndex>
701 eigen_assert(m_isInitialized && "LU is not initialized.");
702 // LU
703 MatrixType res = m_lu.template triangularView<UnitLower>().toDenseMatrix() * m_lu.template triangularView<Upper>();
704
705 // P^{-1}(LU)
706 res = m_p.inverse() * res;
707
708 return res;
709}
710
711/***** Implementation details *****************************************************/
712
713namespace internal {
714
715/***** Implementation of inverse() *****************************************************/
716template <typename DstXprType, typename MatrixType, typename PermutationIndex>
717struct Assignment<
718 DstXprType, Inverse<PartialPivLU<MatrixType, PermutationIndex> >,
719 internal::assign_op<typename DstXprType::Scalar, typename PartialPivLU<MatrixType, PermutationIndex>::Scalar>,
720 Dense2Dense> {
722 using SrcXprType = Inverse<LuType>;
723 static void run(DstXprType& dst, const SrcXprType& src,
724 const internal::assign_op<typename DstXprType::Scalar, typename LuType::Scalar>&) {
725 dst = src.nestedExpression().solve(MatrixType::Identity(src.rows(), src.cols()));
726 }
727};
728} // end namespace internal
729
730/******** MatrixBase methods *******/
731
738template <typename Derived>
739template <typename PermutationIndex>
740inline PartialPivLU<typename MatrixBase<Derived>::PlainObject, PermutationIndex> MatrixBase<Derived>::partialPivLu()
741 const {
743}
744
753template <typename Derived>
754template <typename PermutationIndex>
755inline PartialPivLU<typename MatrixBase<Derived>::PlainObject, PermutationIndex> MatrixBase<Derived>::lu() const {
757}
758
759} // end namespace Eigen
760
761#endif // EIGEN_PARTIALLU_H
EvalReturnType eval() const
Definition DenseBase.h:385
Expression of the inverse of another expression.
Definition Inverse.h:44
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:53
LU decomposition of a matrix with partial pivoting, and related features.
Definition PartialPivLU.h:67
PartialPivLU(Index size)
Default Constructor with memory preallocation.
Definition PartialPivLU.h:323
RealScalar logAbsDeterminant() const
Definition PartialPivLU.h:684
Solve< PartialPivLU, Rhs > solve(const MatrixBase< Rhs > &b) const
MatrixType reconstructedMatrix() const
Definition PartialPivLU.h:700
Scalar signDeterminant() const
Definition PartialPivLU.h:691
const MatrixType & matrixLU() const
Definition PartialPivLU.h:143
ComputationInfo info() const
Reports whether the LU factorization was successful.
Definition PartialPivLU.h:89
RealScalar rcond() const
Definition PartialPivLU.h:180
PartialPivLU(const EigenBase< InputType > &matrix)
Definition PartialPivLU.h:328
PartialPivLU()
Default Constructor.
Definition PartialPivLU.h:319
const PermutationType & permutationP() const
Definition PartialPivLU.h:150
PartialPivLU(EigenBase< InputType > &matrix)
Definition PartialPivLU.h:340
Inverse< PartialPivLU > inverse() const
Definition PartialPivLU.h:192
Scalar determinant() const
Definition PartialPivLU.h:669
RealScalar absDeterminant() const
Definition PartialPivLU.h:677
InverseReturnType transpose() const
Definition PermutationMatrix.h:234
Permutation matrix.
Definition PermutationMatrix.h:346
Pseudo expression representing a solving operation.
Definition Solve.h:63
constexpr PartialPivLU< MatrixType_, PermutationIndex_ > & derived()
Represents a sequence of transpositions (row/column interchange)
Definition Transpositions.h:144
static const auto fix()
ComputationInfo
Definition Constants.h:455
@ Success
Definition Constants.h:457
@ ColMajor
Definition Constants.h:319
@ RowMajor
Definition Constants.h:321
constexpr unsigned int RowMajorBit
Definition Constants.h:71
Definition EigenBase.h:34
constexpr Derived & derived()
Definition EigenBase.h:50
constexpr Index size() const noexcept
Definition EigenBase.h:65
Eigen::Index Index
The interface type of indices.
Definition EigenBase.h:44