15#include "./InternalHeaderCheck.h"
20template <
typename DecompositionType>
22template <
typename DecompositionType>
25template <
typename MatrixType_,
typename PermutationIndex_>
26struct traits<FullPivLU<MatrixType_, PermutationIndex_> > : traits<MatrixType_> {
27 using XprKind = MatrixXpr;
28 using StorageKind = SolverStorage;
29 using StorageIndex = PermutationIndex_;
68template <
typename MatrixType_,
typename PermutationIndex_>
70 public RankRevealingBase<FullPivLU<MatrixType_, PermutationIndex_> > {
72 using MatrixType = MatrixType_;
74 using RankRevealingBase_ = RankRevealingBase<FullPivLU>;
76 friend class RankRevealingBase<
FullPivLU>;
89 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
90 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
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;
106 eigen_assert(m_isInitialized &&
"FullPivLU is not initialized.");
131 template <
typename InputType>
141 template <
typename InputType>
151 template <
typename InputType>
165 eigen_assert(m_isInitialized &&
"LU is not initialized.");
173 EIGEN_DEVICE_FUNC
inline const PermutationPType&
permutationP()
const {
174 eigen_assert(m_isInitialized &&
"LU is not initialized.");
183 eigen_assert(m_isInitialized &&
"LU is not initialized.");
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);
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);
230#ifdef EIGEN_PARSED_BY_DOXYGEN
250 template <
typename Rhs>
258 eigen_assert(m_isInitialized &&
"FullPivLU is not initialized.");
260 return RealScalar(0);
262 return internal::rcond_estimate_helper(m_l1_norm, *
this);
283 typename internal::traits<MatrixType>::Scalar
determinant()
const;
340 return abs(m_lu.coeff(i, i));
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!");
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(); }
361#ifndef EIGEN_PARSED_BY_DOXYGEN
362 template <
typename RhsType,
typename DstType>
363 void _solve_impl(
const RhsType& rhs, DstType& dst)
const;
365 template <
bool Conjugate,
typename RhsType,
typename DstType>
366 void _solve_impl_transposed(
const RhsType& rhs, DstType& dst)
const;
370 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
372 void computeInPlace();
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;
384template <
typename MatrixType,
typename PermutationIndex>
387template <
typename MatrixType,
typename PermutationIndex>
392 m_rowsTranspositions(rows),
393 m_colsTranspositions(cols),
394 m_isInitialized(false) {}
396template <
typename MatrixType,
typename PermutationIndex>
397template <
typename InputType>
399 : m_lu(matrix.rows(), matrix.cols()),
402 m_rowsTranspositions(matrix.rows()),
403 m_colsTranspositions(matrix.cols()),
404 m_isInitialized(false) {
408template <
typename MatrixType,
typename PermutationIndex>
409template <
typename InputType>
414 m_rowsTranspositions(matrix.rows()),
415 m_colsTranspositions(matrix.cols()),
416 m_isInitialized(false) {
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());
426 m_l1_norm = m_lu.cwiseAbs().colwise().sum().maxCoeff();
428 m_l1_norm = RealScalar(0);
430 const Index size = m_lu.diagonalSize();
431 const Index rows = m_lu.rows();
432 const Index cols = m_lu.cols();
436 m_rowsTranspositions.resize(m_lu.rows());
437 m_colsTranspositions.resize(m_lu.cols());
438 Index number_of_transpositions = 0;
440 this->m_nonzero_pivots = size;
441 this->m_maxpivot = RealScalar(0);
443 for (Index k = 0; k < size; ++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;
455 col_of_biggest_in_corner += k;
457 if (numext::is_exactly_zero(biggest_in_corner)) {
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);
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;
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;
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;
489 if (k < rows - 1) m_lu.col(k).tail(rows - k - 1) /= m_lu.coeff(k, k);
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);
498 m_p.setIdentity(rows);
499 for (Index k = size - 1; k >= 0; --k) m_p.applyTranspositionOnTheRight(k, m_rowsTranspositions.coeff(k));
501 m_q.setIdentity(cols);
502 for (Index k = 0; k < size; ++k) m_q.applyTranspositionOnTheRight(k, m_colsTranspositions.coeff(k));
504 m_det_pq = (number_of_transpositions % 2) ? -1 : 1;
506 m_isInitialized =
true;
509template <
typename MatrixType,
typename PermutationIndex>
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());
516template <
typename MatrixType,
typename PermutationIndex>
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);
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();
532template <
typename MatrixType,
typename PermutationIndex>
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);
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());
548 MatrixType res(m_lu.rows(), m_lu.cols());
550 res.noalias() = m_lu.leftCols(smalldim).template triangularView<UnitLower>().toDenseMatrix() *
551 m_lu.topRows(smalldim).template triangularView<Upper>().toDenseMatrix();
554 res = m_p.inverse() * res;
557 res = res * m_q.inverse();
565template <
typename MatrixType,
typename PermutationIndex>
567 constexpr int MaxSmallDimAtCompileTime =
568 min_size_prefer_fixed(MatrixType::MaxColsAtCompileTime, MatrixType::MaxRowsAtCompileTime);
570 const typename MatrixType::RealScalar premultiplied_threshold = dec.
maxPivot() * dec.
threshold();
573 if (numext::abs(dec.
matrixLU().coeff(i, i)) > premultiplied_threshold) pivots.coeffRef(p++) = i;
574 eigen_internal_assert(p == rank);
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>;
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;
592 static constexpr int MaxSmallDimAtCompileTime =
593 min_size_prefer_fixed(MatrixType::MaxColsAtCompileTime, MatrixType::MaxRowsAtCompileTime);
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) {}
598 Index rows()
const {
return m_dec.cols(); }
599 Index cols()
const {
return m_cols; }
601 template <
typename Dest>
602 void evalTo(Dest& dst)
const {
603 const Index cols = m_dec.matrixLU().cols(), dimker = cols - m_rank;
611 const auto pivots = fullpivlu_nonzero_pivots(m_dec, m_rank);
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);
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)));
630 m.topLeftCorner(m_rank, m_rank).template triangularView<Upper>().solveInPlace(m.topRightCorner(m_rank, dimker));
633 for (Index i = m_rank - 1; i >= 0; --i) m.col(i).swap(m.col(pivots.coeff(i)));
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);
642 const DecompositionType& m_dec;
643 Index m_rank, m_cols;
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>;
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_;
661 image_retval(
const DecompositionType& dec,
const MatrixType& originalMatrix)
662 : m_dec(dec), m_rank(dec.rank()), m_originalMatrix(originalMatrix) {}
664 Index rows()
const {
return m_dec.rows(); }
665 Index cols()
const {
return m_rank == 0 ? 1 : m_rank; }
667 template <
typename Dest>
668 void evalTo(Dest& dst)
const {
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)));
682 const DecompositionType& m_dec;
684 const MatrixType& m_originalMatrix;
691#ifndef EIGEN_PARSED_BY_DOXYGEN
692template <
typename MatrixType_,
typename PermutationIndex_>
693template <
typename RhsType,
typename DstType>
703 const Index rows = this->rows(), cols = this->cols(), nonzero_pivots = this->rank();
704 const Index smalldim = (std::min)(rows, cols);
706 if (nonzero_pivots == 0) {
711 typename RhsType::PlainObject c(rhs.rows(), rhs.cols());
714 c = permutationP() * rhs;
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);
721 m_lu.topLeftCorner(nonzero_pivots, nonzero_pivots)
722 .template triangularView<Upper>()
723 .solveInPlace(c.topRows(nonzero_pivots));
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();
730template <
typename MatrixType_,
typename PermutationIndex_>
731template <
bool Conjugate,
typename RhsType,
typename DstType>
744 const Index rows = this->rows(), cols = this->cols(), nonzero_pivots = this->rank();
745 const Index smalldim = (std::min)(rows, cols);
747 if (nonzero_pivots == 0) {
752 typename RhsType::PlainObject c(rhs.rows(), rhs.cols());
755 c = permutationQ().inverse() * rhs;
758 m_lu.topLeftCorner(nonzero_pivots, nonzero_pivots)
759 .template triangularView<Upper>()
761 .template conjugateIf<Conjugate>()
762 .solveInPlace(c.topRows(nonzero_pivots));
765 m_lu.topLeftCorner(smalldim, smalldim)
766 .template triangularView<UnitLower>()
768 .template conjugateIf<Conjugate>()
769 .solveInPlace(c.topRows(smalldim));
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();
782template <
typename DstXprType,
typename MatrixType,
typename PermutationIndex>
784 DstXprType, Inverse<FullPivLU<MatrixType, PermutationIndex> >,
785 internal::assign_op<typename DstXprType::Scalar, typename FullPivLU<MatrixType, PermutationIndex>::Scalar>,
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()));
804template <
typename Derived>
805template <
typename PermutationIndex>
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