Eigen  5.0.1
 
Loading...
Searching...
No Matches
FullPivLU.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//
6// This Source Code Form is subject to the terms of the Mozilla
7// Public License v. 2.0. If a copy of the MPL was not distributed
8// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9// SPDX-License-Identifier: MPL-2.0
10
11#ifndef EIGEN_LU_H
12#define EIGEN_LU_H
13
14// IWYU pragma: private
15#include "./InternalHeaderCheck.h"
16
17namespace Eigen {
18
19namespace internal {
20template <typename DecompositionType>
21struct kernel_retval;
22template <typename DecompositionType>
23struct image_retval;
24
25template <typename MatrixType_, typename PermutationIndex_>
26struct traits<FullPivLU<MatrixType_, PermutationIndex_> > : traits<MatrixType_> {
27 using XprKind = MatrixXpr;
28 using StorageKind = SolverStorage;
29 using StorageIndex = PermutationIndex_;
30 enum { Flags = 0 };
31};
32
33} // end namespace internal
34
68template <typename MatrixType_, typename PermutationIndex_>
69class FullPivLU : public SolverBase<FullPivLU<MatrixType_, PermutationIndex_> >,
70 public RankRevealingBase<FullPivLU<MatrixType_, PermutationIndex_> > {
71 public:
72 using MatrixType = MatrixType_;
73 using Base = SolverBase<FullPivLU>;
74 using RankRevealingBase_ = RankRevealingBase<FullPivLU>;
75 friend class SolverBase<FullPivLU>;
76 friend class RankRevealingBase<FullPivLU>;
86
87 EIGEN_GENERIC_PUBLIC_INTERFACE(FullPivLU)
88 enum {
89 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
90 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
91 };
92 using PermutationIndex = PermutationIndex_;
93 using IntRowVectorType = typename internal::plain_row_type<MatrixType, PermutationIndex>::type;
94 using IntColVectorType = typename internal::plain_col_type<MatrixType, PermutationIndex>::type;
97 using PlainObject = typename MatrixType::PlainObject;
98
106 eigen_assert(m_isInitialized && "FullPivLU is not initialized.");
107 return Success;
108 }
109
117
124 FullPivLU(Index rows, Index cols);
125
131 template <typename InputType>
132 explicit FullPivLU(const EigenBase<InputType>& matrix);
133
141 template <typename InputType>
143
151 template <typename InputType>
153 m_lu = matrix.derived();
154 computeInPlace();
155 return *this;
156 }
157
164 inline const MatrixType& matrixLU() const {
165 eigen_assert(m_isInitialized && "LU is not initialized.");
166 return m_lu;
167 }
168
173 EIGEN_DEVICE_FUNC inline const PermutationPType& permutationP() const {
174 eigen_assert(m_isInitialized && "LU is not initialized.");
175 return m_p;
176 }
177
182 inline const PermutationQType& permutationQ() const {
183 eigen_assert(m_isInitialized && "LU is not initialized.");
184 return m_q;
185 }
186
201 inline const internal::kernel_retval<FullPivLU> kernel() const {
202 eigen_assert(m_isInitialized && "LU is not initialized.");
203 return internal::kernel_retval<FullPivLU>(*this);
204 }
205
225 inline const internal::image_retval<FullPivLU> image(const MatrixType& originalMatrix) const {
226 eigen_assert(m_isInitialized && "LU is not initialized.");
227 return internal::image_retval<FullPivLU>(*this, originalMatrix);
228 }
229
230#ifdef EIGEN_PARSED_BY_DOXYGEN
250 template <typename Rhs>
252#endif
253
257 inline RealScalar rcond() const {
258 eigen_assert(m_isInitialized && "FullPivLU is not initialized.");
259 if (!isInvertible()) {
260 return RealScalar(0);
261 }
262 return internal::rcond_estimate_helper(m_l1_norm, *this);
263 }
264
283 typename internal::traits<MatrixType>::Scalar determinant() const;
284
302 RealScalar absDeterminant() const;
303
318 RealScalar logAbsDeterminant() const;
319
335 Scalar signDeterminant() const;
336
338 RealScalar pivotCoeff(Index i) const {
339 using std::abs;
340 return abs(m_lu.coeff(i, i));
341 }
342
351 eigen_assert(m_isInitialized && "LU is not initialized.");
352 eigen_assert(m_lu.rows() == m_lu.cols() && "You can't take the inverse of a non-square matrix!");
353 return Inverse<FullPivLU>(*this);
354 }
355
356 MatrixType reconstructedMatrix() const;
357
358 EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_lu.rows(); }
359 EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_lu.cols(); }
360
361#ifndef EIGEN_PARSED_BY_DOXYGEN
362 template <typename RhsType, typename DstType>
363 void _solve_impl(const RhsType& rhs, DstType& dst) const;
364
365 template <bool Conjugate, typename RhsType, typename DstType>
366 void _solve_impl_transposed(const RhsType& rhs, DstType& dst) const;
367#endif
368
369 protected:
370 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
371
372 void computeInPlace();
373
374 MatrixType m_lu;
375 PermutationPType m_p;
376 PermutationQType m_q;
377 IntColVectorType m_rowsTranspositions;
378 IntRowVectorType m_colsTranspositions;
379 RealScalar m_l1_norm;
380 signed char m_det_pq;
381 bool m_isInitialized;
382};
383
384template <typename MatrixType, typename PermutationIndex>
386
387template <typename MatrixType, typename PermutationIndex>
389 : m_lu(rows, cols),
390 m_p(rows),
391 m_q(cols),
392 m_rowsTranspositions(rows),
393 m_colsTranspositions(cols),
394 m_isInitialized(false) {}
395
396template <typename MatrixType, typename PermutationIndex>
397template <typename InputType>
399 : m_lu(matrix.rows(), matrix.cols()),
400 m_p(matrix.rows()),
401 m_q(matrix.cols()),
402 m_rowsTranspositions(matrix.rows()),
403 m_colsTranspositions(matrix.cols()),
404 m_isInitialized(false) {
405 compute(matrix.derived());
406}
407
408template <typename MatrixType, typename PermutationIndex>
409template <typename InputType>
411 : m_lu(matrix.derived()),
412 m_p(matrix.rows()),
413 m_q(matrix.cols()),
414 m_rowsTranspositions(matrix.rows()),
415 m_colsTranspositions(matrix.cols()),
416 m_isInitialized(false) {
417 computeInPlace();
418}
419
420template <typename MatrixType, typename PermutationIndex>
421void FullPivLU<MatrixType, PermutationIndex>::computeInPlace() {
422 eigen_assert(m_lu.rows() <= NumTraits<PermutationIndex>::highest() &&
423 m_lu.cols() <= NumTraits<PermutationIndex>::highest());
424
425 if (m_lu.cols() > 0)
426 m_l1_norm = m_lu.cwiseAbs().colwise().sum().maxCoeff();
427 else
428 m_l1_norm = RealScalar(0);
429
430 const Index size = m_lu.diagonalSize();
431 const Index rows = m_lu.rows();
432 const Index cols = m_lu.cols();
433
434 // will store the transpositions, before we accumulate them at the end.
435 // can't accumulate on-the-fly because that will be done in reverse order for the rows.
436 m_rowsTranspositions.resize(m_lu.rows());
437 m_colsTranspositions.resize(m_lu.cols());
438 Index number_of_transpositions = 0; // number of NONTRIVIAL transpositions, i.e. m_rowsTranspositions[i]!=i
439
440 this->m_nonzero_pivots = size; // the generic case is that in which all pivots are nonzero (invertible case)
441 this->m_maxpivot = RealScalar(0);
442
443 for (Index k = 0; k < size; ++k) {
444 // First, we need to find the pivot.
445
446 // biggest coefficient in the remaining bottom-right corner (starting at row k, col k)
447 Index row_of_biggest_in_corner, col_of_biggest_in_corner;
448 using Scoring = internal::scalar_score_coeff_op<Scalar>;
449 using Score = typename Scoring::result_type;
450 Score biggest_in_corner;
451 biggest_in_corner = m_lu.bottomRightCorner(rows - k, cols - k)
452 .unaryExpr(Scoring())
453 .maxCoeff(&row_of_biggest_in_corner, &col_of_biggest_in_corner);
454 row_of_biggest_in_corner += k; // correct the values! since they were computed in the corner,
455 col_of_biggest_in_corner += k; // need to add k to them.
456
457 if (numext::is_exactly_zero(biggest_in_corner)) {
458 // before exiting, make sure to initialize the still uninitialized transpositions
459 // in a sane state without destroying what we already have.
460 this->m_nonzero_pivots = k;
461 for (Index i = k; i < size; ++i) {
462 m_rowsTranspositions.coeffRef(i) = internal::convert_index<StorageIndex>(i);
463 m_colsTranspositions.coeffRef(i) = internal::convert_index<StorageIndex>(i);
464 }
465 break;
466 }
467
468 RealScalar abs_pivot = internal::abs_knowing_score<Scalar>()(
469 m_lu(row_of_biggest_in_corner, col_of_biggest_in_corner), biggest_in_corner);
470 if (abs_pivot > this->m_maxpivot) this->m_maxpivot = abs_pivot;
471
472 // Now that we've found the pivot, we need to apply the row/col swaps to
473 // bring it to the location (k,k).
474
475 m_rowsTranspositions.coeffRef(k) = internal::convert_index<StorageIndex>(row_of_biggest_in_corner);
476 m_colsTranspositions.coeffRef(k) = internal::convert_index<StorageIndex>(col_of_biggest_in_corner);
477 if (k != row_of_biggest_in_corner) {
478 m_lu.row(k).swap(m_lu.row(row_of_biggest_in_corner));
479 ++number_of_transpositions;
480 }
481 if (k != col_of_biggest_in_corner) {
482 m_lu.col(k).swap(m_lu.col(col_of_biggest_in_corner));
483 ++number_of_transpositions;
484 }
485
486 // Now that the pivot is at the right location, we update the remaining
487 // bottom-right corner by Gaussian elimination.
488
489 if (k < rows - 1) m_lu.col(k).tail(rows - k - 1) /= m_lu.coeff(k, k);
490 if (k < size - 1)
491 m_lu.block(k + 1, k + 1, rows - k - 1, cols - k - 1).noalias() -=
492 m_lu.col(k).tail(rows - k - 1) * m_lu.row(k).tail(cols - k - 1);
493 }
494
495 // the main loop is over, we still have to accumulate the transpositions to find the
496 // permutations P and Q
497
498 m_p.setIdentity(rows);
499 for (Index k = size - 1; k >= 0; --k) m_p.applyTranspositionOnTheRight(k, m_rowsTranspositions.coeff(k));
500
501 m_q.setIdentity(cols);
502 for (Index k = 0; k < size; ++k) m_q.applyTranspositionOnTheRight(k, m_colsTranspositions.coeff(k));
503
504 m_det_pq = (number_of_transpositions % 2) ? -1 : 1;
505
506 m_isInitialized = true;
507}
508
509template <typename MatrixType, typename PermutationIndex>
510typename internal::traits<MatrixType>::Scalar FullPivLU<MatrixType, PermutationIndex>::determinant() const {
511 eigen_assert(m_isInitialized && "LU is not initialized.");
512 eigen_assert(m_lu.rows() == m_lu.cols() && "You can't take the determinant of a non-square matrix!");
513 return Scalar(m_det_pq) * Scalar(m_lu.diagonal().prod());
514}
515
516template <typename MatrixType, typename PermutationIndex>
517typename FullPivLU<MatrixType, PermutationIndex>::RealScalar FullPivLU<MatrixType, PermutationIndex>::absDeterminant()
518 const {
519 eigen_assert(m_isInitialized && "LU is not initialized.");
520 eigen_assert(m_lu.rows() == m_lu.cols() && "You can't take the determinant of a non-square matrix!");
521 return isInjective() ? numext::abs(m_lu.diagonal().prod()) : RealScalar(0);
522}
523
524template <typename MatrixType, typename PermutationIndex>
525typename FullPivLU<MatrixType, PermutationIndex>::RealScalar
527 eigen_assert(m_isInitialized && "LU is not initialized.");
528 eigen_assert(m_lu.rows() == m_lu.cols() && "You can't take the determinant of a non-square matrix!");
529 return isInjective() ? m_lu.diagonal().cwiseAbs().array().log().sum() : -NumTraits<RealScalar>::infinity();
530}
531
532template <typename MatrixType, typename PermutationIndex>
533typename FullPivLU<MatrixType, PermutationIndex>::Scalar FullPivLU<MatrixType, PermutationIndex>::signDeterminant()
534 const {
535 eigen_assert(m_isInitialized && "LU is not initialized.");
536 eigen_assert(m_lu.rows() == m_lu.cols() && "You can't take the determinant of a non-square matrix!");
537 return isInjective() ? Scalar(m_det_pq) * m_lu.diagonal().array().sign().prod() : Scalar(0);
538}
539
543template <typename MatrixType, typename PermutationIndex>
545 eigen_assert(m_isInitialized && "LU is not initialized.");
546 const Index smalldim = (std::min)(m_lu.rows(), m_lu.cols());
547 // LU
548 MatrixType res(m_lu.rows(), m_lu.cols());
549 // FIXME: the .toDenseMatrix() calls should not be needed.
550 res.noalias() = m_lu.leftCols(smalldim).template triangularView<UnitLower>().toDenseMatrix() *
551 m_lu.topRows(smalldim).template triangularView<Upper>().toDenseMatrix();
552
553 // P^{-1}(LU)
554 res = m_p.inverse() * res;
555
556 // (P^{-1}LU)Q^{-1}
557 res = res * m_q.inverse();
558
559 return res;
560}
561
562/********* Implementation of kernel() **************************************************/
563
564namespace internal {
565template <typename MatrixType, typename PermutationIndex>
566auto fullpivlu_nonzero_pivots(const FullPivLU<MatrixType, PermutationIndex>& dec, Index rank) {
567 constexpr int MaxSmallDimAtCompileTime =
568 min_size_prefer_fixed(MatrixType::MaxColsAtCompileTime, MatrixType::MaxRowsAtCompileTime);
570 const typename MatrixType::RealScalar premultiplied_threshold = dec.maxPivot() * dec.threshold();
571 Index p = 0;
572 for (Index i = 0; i < dec.nonzeroPivots(); ++i)
573 if (numext::abs(dec.matrixLU().coeff(i, i)) > premultiplied_threshold) pivots.coeffRef(p++) = i;
574 eigen_internal_assert(p == rank);
575 return pivots;
576}
577
578template <typename MatrixType_, typename PermutationIndex_>
579struct traits<kernel_retval<FullPivLU<MatrixType_, PermutationIndex_>>> {
580 using ReturnType = Matrix<typename MatrixType_::Scalar, MatrixType_::ColsAtCompileTime, Dynamic,
581 plain_object_options<MatrixType_>::value, MatrixType_::MaxColsAtCompileTime,
582 MatrixType_::MaxColsAtCompileTime>;
583};
584
585template <typename MatrixType_, typename PermutationIndex_>
586struct kernel_retval<FullPivLU<MatrixType_, PermutationIndex_>>
587 : ReturnByValue<kernel_retval<FullPivLU<MatrixType_, PermutationIndex_>>> {
588 using DecompositionType = FullPivLU<MatrixType_, PermutationIndex_>;
589 using MatrixType = MatrixType_;
590 using Scalar = typename MatrixType::Scalar;
591
592 static constexpr int MaxSmallDimAtCompileTime =
593 min_size_prefer_fixed(MatrixType::MaxColsAtCompileTime, MatrixType::MaxRowsAtCompileTime);
594
595 explicit kernel_retval(const DecompositionType& dec)
596 : m_dec(dec), m_rank(dec.rank()), m_cols(m_rank == dec.cols() ? 1 : dec.cols() - m_rank) {}
597
598 Index rows() const { return m_dec.cols(); }
599 Index cols() const { return m_cols; }
600
601 template <typename Dest>
602 void evalTo(Dest& dst) const {
603 const Index cols = m_dec.matrixLU().cols(), dimker = cols - m_rank;
604 if (dimker == 0) {
605 // Represent the zero space by a single zero column.
606 dst.setZero();
607 return;
608 }
609
610 // PAQ = LU implies ker(A) = Q ker(U).
611 const auto pivots = fullpivlu_nonzero_pivots(m_dec, m_rank);
612
613 // Construct a temporary trapezoid matrix m by taking the U matrix and permuting
614 // the rows and cols to bring the nonnegligible pivots to the top of the main diagonal.
615 // This is needed to apply our triangular solvers.
616 // FIXME: simplify once triangularView supports rectangular matrices.
617 Matrix<typename MatrixType::Scalar, Dynamic, Dynamic, plain_object_options<MatrixType>::value,
618 MaxSmallDimAtCompileTime, MatrixType::MaxColsAtCompileTime>
619 m(m_dec.matrixLU().block(0, 0, m_rank, cols));
620 for (Index i = 0; i < m_rank; ++i) {
621 if (i) m.row(i).head(i).setZero();
622 m.row(i).tail(cols - i) = m_dec.matrixLU().row(pivots.coeff(i)).tail(cols - i);
623 }
624 m.block(0, 0, m_rank, m_rank).template triangularView<StrictlyLower>().setZero();
625 for (Index i = 0; i < m_rank; ++i) m.col(i).swap(m.col(pivots.coeff(i)));
626
627 // ok, we have our trapezoid matrix, we can apply the triangular solver.
628 // notice that the math behind this suggests that we should apply this to the
629 // negative of the RHS, but for performance we just put the negative sign elsewhere, see below.
630 m.topLeftCorner(m_rank, m_rank).template triangularView<Upper>().solveInPlace(m.topRightCorner(m_rank, dimker));
631
632 // now we must undo the column permutation that we had applied!
633 for (Index i = m_rank - 1; i >= 0; --i) m.col(i).swap(m.col(pivots.coeff(i)));
634
635 // see the negative sign in the next line, that's what we were talking about above.
636 for (Index i = 0; i < m_rank; ++i) dst.row(m_dec.permutationQ().indices().coeff(i)) = -m.row(i).tail(dimker);
637 for (Index i = m_rank; i < cols; ++i) dst.row(m_dec.permutationQ().indices().coeff(i)).setZero();
638 for (Index k = 0; k < dimker; ++k) dst.coeffRef(m_dec.permutationQ().indices().coeff(m_rank + k), k) = Scalar(1);
639 }
640
641 private:
642 const DecompositionType& m_dec;
643 Index m_rank, m_cols;
644};
645
646/***** Implementation of image() *****************************************************/
647
648template <typename MatrixType_, typename PermutationIndex_>
649struct traits<image_retval<FullPivLU<MatrixType_, PermutationIndex_>>> {
650 using ReturnType = Matrix<typename MatrixType_::Scalar, MatrixType_::RowsAtCompileTime, Dynamic,
651 plain_object_options<MatrixType_>::value, MatrixType_::MaxRowsAtCompileTime,
652 MatrixType_::MaxColsAtCompileTime>;
653};
654
655template <typename MatrixType_, typename PermutationIndex_>
656struct image_retval<FullPivLU<MatrixType_, PermutationIndex_>>
657 : ReturnByValue<image_retval<FullPivLU<MatrixType_, PermutationIndex_>>> {
658 using DecompositionType = FullPivLU<MatrixType_, PermutationIndex_>;
659 using MatrixType = MatrixType_;
660
661 image_retval(const DecompositionType& dec, const MatrixType& originalMatrix)
662 : m_dec(dec), m_rank(dec.rank()), m_originalMatrix(originalMatrix) {}
663
664 Index rows() const { return m_dec.rows(); }
665 Index cols() const { return m_rank == 0 ? 1 : m_rank; }
666
667 template <typename Dest>
668 void evalTo(Dest& dst) const {
669 if (m_rank == 0) {
670 // Represent the zero space by a single zero column.
671 dst.setZero();
672 return;
673 }
674
675 // Select pivots before writing: dst may overlap an inplace decomposition's storage.
676 const auto pivots = fullpivlu_nonzero_pivots(m_dec, m_rank);
677 for (Index i = 0; i < m_rank; ++i)
678 dst.col(i) = m_originalMatrix.col(m_dec.permutationQ().indices().coeff(pivots.coeff(i)));
679 }
680
681 private:
682 const DecompositionType& m_dec;
683 Index m_rank;
684 const MatrixType& m_originalMatrix;
685};
686
687/***** Implementation of solve() *****************************************************/
688
689} // end namespace internal
690
691#ifndef EIGEN_PARSED_BY_DOXYGEN
692template <typename MatrixType_, typename PermutationIndex_>
693template <typename RhsType, typename DstType>
694void FullPivLU<MatrixType_, PermutationIndex_>::_solve_impl(const RhsType& rhs, DstType& dst) const {
695 /* The decomposition PAQ = LU can be rewritten as A = P^{-1} L U Q^{-1}.
696 * So we proceed as follows:
697 * Step 1: compute c = P * rhs.
698 * Step 2: replace c by the solution x to Lx = c. Exists because L is invertible.
699 * Step 3: replace c by the solution x to Ux = c. May or may not exist.
700 * Step 4: result = Q * c;
701 */
702
703 const Index rows = this->rows(), cols = this->cols(), nonzero_pivots = this->rank();
704 const Index smalldim = (std::min)(rows, cols);
705
706 if (nonzero_pivots == 0) {
707 dst.setZero();
708 return;
709 }
710
711 typename RhsType::PlainObject c(rhs.rows(), rhs.cols());
712
713 // Step 1
714 c = permutationP() * rhs;
715
716 // Step 2
717 m_lu.topLeftCorner(smalldim, smalldim).template triangularView<UnitLower>().solveInPlace(c.topRows(smalldim));
718 if (rows > cols) c.bottomRows(rows - cols).noalias() -= m_lu.bottomRows(rows - cols) * c.topRows(cols);
719
720 // Step 3
721 m_lu.topLeftCorner(nonzero_pivots, nonzero_pivots)
722 .template triangularView<Upper>()
723 .solveInPlace(c.topRows(nonzero_pivots));
724
725 // Step 4
726 for (Index i = 0; i < nonzero_pivots; ++i) dst.row(permutationQ().indices().coeff(i)) = c.row(i);
727 for (Index i = nonzero_pivots; i < m_lu.cols(); ++i) dst.row(permutationQ().indices().coeff(i)).setZero();
728}
729
730template <typename MatrixType_, typename PermutationIndex_>
731template <bool Conjugate, typename RhsType, typename DstType>
732void FullPivLU<MatrixType_, PermutationIndex_>::_solve_impl_transposed(const RhsType& rhs, DstType& dst) const {
733 /* The decomposition PAQ = LU can be rewritten as A = P^{-1} L U Q^{-1},
734 * and since permutations are real and unitary, we can write this
735 * as A^T = Q U^T L^T P,
736 * So we proceed as follows:
737 * Step 1: compute c = Q^T rhs.
738 * Step 2: replace c by the solution x to U^T x = c. May or may not exist.
739 * Step 3: replace c by the solution x to L^T x = c.
740 * Step 4: result = P^T c.
741 * If Conjugate is true, replace "^T" by "^*" above.
742 */
743
744 const Index rows = this->rows(), cols = this->cols(), nonzero_pivots = this->rank();
745 const Index smalldim = (std::min)(rows, cols);
746
747 if (nonzero_pivots == 0) {
748 dst.setZero();
749 return;
750 }
751
752 typename RhsType::PlainObject c(rhs.rows(), rhs.cols());
753
754 // Step 1
755 c = permutationQ().inverse() * rhs;
756
757 // Step 2
758 m_lu.topLeftCorner(nonzero_pivots, nonzero_pivots)
759 .template triangularView<Upper>()
760 .transpose()
761 .template conjugateIf<Conjugate>()
762 .solveInPlace(c.topRows(nonzero_pivots));
763
764 // Step 3
765 m_lu.topLeftCorner(smalldim, smalldim)
766 .template triangularView<UnitLower>()
767 .transpose()
768 .template conjugateIf<Conjugate>()
769 .solveInPlace(c.topRows(smalldim));
770
771 // Step 4
772 PermutationPType invp = permutationP().inverse().eval();
773 for (Index i = 0; i < smalldim; ++i) dst.row(invp.indices().coeff(i)) = c.row(i);
774 for (Index i = smalldim; i < rows; ++i) dst.row(invp.indices().coeff(i)).setZero();
775}
776
777#endif
778
779namespace internal {
780
781/***** Implementation of inverse() *****************************************************/
782template <typename DstXprType, typename MatrixType, typename PermutationIndex>
783struct Assignment<
784 DstXprType, Inverse<FullPivLU<MatrixType, PermutationIndex> >,
785 internal::assign_op<typename DstXprType::Scalar, typename FullPivLU<MatrixType, PermutationIndex>::Scalar>,
786 Dense2Dense> {
787 using LuType = FullPivLU<MatrixType, PermutationIndex>;
788 using SrcXprType = Inverse<LuType>;
789 static void run(DstXprType& dst, const SrcXprType& src,
790 const internal::assign_op<typename DstXprType::Scalar, typename MatrixType::Scalar>&) {
791 dst = src.nestedExpression().solve(MatrixType::Identity(src.rows(), src.cols()));
792 }
793};
794} // end namespace internal
795
796/******* MatrixBase methods *****************************************************************/
797
804template <typename Derived>
805template <typename PermutationIndex>
806inline FullPivLU<typename MatrixBase<Derived>::PlainObject, PermutationIndex> MatrixBase<Derived>::fullPivLu() const {
808}
809
810} // end namespace Eigen
811
812#endif // EIGEN_LU_H
EvalReturnType eval() const
Definition DenseBase.h:385
LU decomposition of a matrix with complete pivoting, and related features.
Definition FullPivLU.h:70
FullPivLU(EigenBase< InputType > &matrix)
Constructs a LU factorization from a given matrix.
Definition FullPivLU.h:410
const internal::image_retval< FullPivLU > image(const MatrixType &originalMatrix) const
Definition FullPivLU.h:225
RealScalar threshold() const
Definition RankRevealingBase.h:80
const PermutationPType & permutationP() const
Definition FullPivLU.h:173
ComputationInfo info() const
Reports whether the LU factorization was successful.
Definition FullPivLU.h:105
Scalar signDeterminant() const
Definition FullPivLU.h:533
RealScalar pivotCoeff(Index i) const
Definition FullPivLU.h:338
internal::traits< MatrixType >::Scalar determinant() const
Definition FullPivLU.h:510
Index nonzeroPivots() const
Definition RankRevealingBase.h:157
RealScalar rcond() const
Definition FullPivLU.h:257
bool isInvertible() const
Definition RankRevealingBase.h:145
Inverse< FullPivLU > inverse() const
Definition FullPivLU.h:350
MatrixType reconstructedMatrix() const
Definition FullPivLU.h:544
RealScalar absDeterminant() const
Definition FullPivLU.h:517
RealScalar logAbsDeterminant() const
Definition FullPivLU.h:526
bool isInjective() const
Definition RankRevealingBase.h:122
const internal::kernel_retval< FullPivLU > kernel() const
Definition FullPivLU.h:201
RealScalar maxPivot() const
Definition RankRevealingBase.h:165
FullPivLU(const EigenBase< InputType > &matrix)
Definition FullPivLU.h:398
const MatrixType & matrixLU() const
Definition FullPivLU.h:164
Solve< FullPivLU, Rhs > solve(const MatrixBase< Rhs > &b) const
FullPivLU(Index rows, Index cols)
Default Constructor with memory preallocation.
Definition FullPivLU.h:388
const PermutationQType & permutationQ() const
Definition FullPivLU.h:182
FullPivLU & compute(const EigenBase< InputType > &matrix)
Definition FullPivLU.h:152
FullPivLU()
Default Constructor.
Definition FullPivLU.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
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:188
Permutation matrix.
Definition PermutationMatrix.h:346
Index dimensionOfKernel() const
Definition RankRevealingBase.h:110
bool isInjective() const
Definition RankRevealingBase.h:122
bool isSurjective() const
Definition RankRevealingBase.h:134
FullPivLU & setThreshold(const RealScalar &threshold)
Definition RankRevealingBase.h:57
Index nonzeroPivots() const
Definition RankRevealingBase.h:157
RealScalar threshold() const
Definition RankRevealingBase.h:80
RealScalar maxPivot() const
Definition RankRevealingBase.h:165
Index rank() const
Definition RankRevealingBase.h:95
bool isInvertible() const
Definition RankRevealingBase.h:145
Pseudo expression representing a solving operation.
Definition Solve.h:63
constexpr FullPivLU< MatrixType_, PermutationIndex_ > & derived()
ComputationInfo
Definition Constants.h:455
@ Success
Definition Constants.h:457
Definition EigenBase.h:34
constexpr Derived & derived()
Definition EigenBase.h:50
Eigen::Index Index
The interface type of indices.
Definition EigenBase.h:44