14#include "./InternalHeaderCheck.h"
19template <
typename MatrixType_,
typename PermutationIndex_>
20struct traits<FullPivLU<MatrixType_, PermutationIndex_> > : traits<MatrixType_> {
21 typedef MatrixXpr XprKind;
22 typedef SolverStorage StorageKind;
23 typedef PermutationIndex_ StorageIndex;
62template <
typename MatrixType_,
typename PermutationIndex_>
65 typedef MatrixType_ MatrixType;
71 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
72 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
74 using PermutationIndex = PermutationIndex_;
75 typedef typename internal::plain_row_type<MatrixType, PermutationIndex>::type IntRowVectorType;
76 typedef typename internal::plain_col_type<MatrixType, PermutationIndex>::type IntColVectorType;
79 typedef typename MatrixType::PlainObject PlainObject;
88 eigen_assert(m_isInitialized &&
"FullPivLU is not initialized.");
113 template <
typename InputType>
123 template <
typename InputType>
133 template <
typename InputType>
147 eigen_assert(m_isInitialized &&
"LU is not initialized.");
159 eigen_assert(m_isInitialized &&
"LU is not initialized.");
160 return m_nonzero_pivots;
172 EIGEN_DEVICE_FUNC
inline const PermutationPType&
permutationP()
const {
173 eigen_assert(m_isInitialized &&
"LU is not initialized.");
182 eigen_assert(m_isInitialized &&
"LU is not initialized.");
200 inline const internal::kernel_retval<FullPivLU>
kernel()
const {
201 eigen_assert(m_isInitialized &&
"LU is not initialized.");
202 return internal::kernel_retval<FullPivLU>(*
this);
224 inline const internal::image_retval<FullPivLU>
image(
const MatrixType& originalMatrix)
const {
225 eigen_assert(m_isInitialized &&
"LU is not initialized.");
226 return internal::image_retval<FullPivLU>(*
this, originalMatrix);
229#ifdef EIGEN_PARSED_BY_DOXYGEN
249 template <
typename Rhs>
257 eigen_assert(m_isInitialized &&
"FullPivLU is not initialized.");
259 return RealScalar(0);
261 return internal::rcond_estimate_helper(m_l1_norm, *
this);
279 typename internal::traits<MatrixType>::Scalar
determinant()
const;
299 m_usePrescribedThreshold =
true;
313 m_usePrescribedThreshold =
false;
322 eigen_assert(m_isInitialized || m_usePrescribedThreshold);
323 return m_usePrescribedThreshold ? m_prescribedThreshold
326 : NumTraits<Scalar>::epsilon() * RealScalar(m_lu.diagonalSize());
337 eigen_assert(m_isInitialized &&
"LU is not initialized.");
338 RealScalar premultiplied_threshold =
abs(m_maxpivot) *
threshold();
340 for (
Index i = 0; i < m_nonzero_pivots; ++i) result += (
abs(m_lu.coeff(i, i)) > premultiplied_threshold);
351 eigen_assert(m_isInitialized &&
"LU is not initialized.");
352 return cols() -
rank();
363 eigen_assert(m_isInitialized &&
"LU is not initialized.");
364 return rank() == cols();
375 eigen_assert(m_isInitialized &&
"LU is not initialized.");
376 return rank() == rows();
386 eigen_assert(m_isInitialized &&
"LU is not initialized.");
387 return isInjective() && (m_lu.rows() == m_lu.cols());
398 eigen_assert(m_isInitialized &&
"LU is not initialized.");
399 eigen_assert(m_lu.rows() == m_lu.cols() &&
"You can't take the inverse of a non-square matrix!");
405 EIGEN_DEVICE_FUNC
constexpr Index rows() const noexcept {
return m_lu.rows(); }
406 EIGEN_DEVICE_FUNC
constexpr Index cols() const noexcept {
return m_lu.cols(); }
408#ifndef EIGEN_PARSED_BY_DOXYGEN
409 template <
typename RhsType,
typename DstType>
410 void _solve_impl(
const RhsType& rhs, DstType& dst)
const;
412 template <
bool Conjugate,
typename RhsType,
typename DstType>
413 void _solve_impl_transposed(
const RhsType& rhs, DstType& dst)
const;
417 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
419 void computeInPlace();
422 PermutationPType m_p;
423 PermutationQType m_q;
424 IntColVectorType m_rowsTranspositions;
425 IntRowVectorType m_colsTranspositions;
426 Index m_nonzero_pivots;
427 RealScalar m_l1_norm;
428 RealScalar m_maxpivot, m_prescribedThreshold;
429 signed char m_det_pq;
430 bool m_isInitialized, m_usePrescribedThreshold;
433template <
typename MatrixType,
typename PermutationIndex>
436template <
typename MatrixType,
typename PermutationIndex>
441 m_rowsTranspositions(rows),
442 m_colsTranspositions(cols),
443 m_isInitialized(false),
444 m_usePrescribedThreshold(false) {}
446template <
typename MatrixType,
typename PermutationIndex>
447template <
typename InputType>
449 : m_lu(matrix.rows(), matrix.cols()),
452 m_rowsTranspositions(matrix.rows()),
453 m_colsTranspositions(matrix.cols()),
454 m_isInitialized(false),
455 m_usePrescribedThreshold(false) {
459template <
typename MatrixType,
typename PermutationIndex>
460template <
typename InputType>
465 m_rowsTranspositions(matrix.rows()),
466 m_colsTranspositions(matrix.cols()),
467 m_isInitialized(false),
468 m_usePrescribedThreshold(false) {
472template <
typename MatrixType,
typename PermutationIndex>
473void FullPivLU<MatrixType, PermutationIndex>::computeInPlace() {
474 eigen_assert(m_lu.rows() <= NumTraits<PermutationIndex>::highest() &&
475 m_lu.cols() <= NumTraits<PermutationIndex>::highest());
477 m_l1_norm = m_lu.cwiseAbs().colwise().sum().maxCoeff();
479 const Index size = m_lu.diagonalSize();
480 const Index rows = m_lu.rows();
481 const Index cols = m_lu.cols();
485 m_rowsTranspositions.resize(m_lu.rows());
486 m_colsTranspositions.resize(m_lu.cols());
487 Index number_of_transpositions = 0;
489 m_nonzero_pivots = size;
490 m_maxpivot = RealScalar(0);
492 for (
Index k = 0; k < size; ++k) {
496 Index row_of_biggest_in_corner, col_of_biggest_in_corner;
497 typedef internal::scalar_score_coeff_op<Scalar> Scoring;
498 typedef typename Scoring::result_type Score;
499 Score biggest_in_corner;
500 biggest_in_corner = m_lu.bottomRightCorner(rows - k, cols - k)
501 .unaryExpr(Scoring())
502 .maxCoeff(&row_of_biggest_in_corner, &col_of_biggest_in_corner);
503 row_of_biggest_in_corner += k;
504 col_of_biggest_in_corner += k;
506 if (numext::is_exactly_zero(biggest_in_corner)) {
509 m_nonzero_pivots = k;
510 for (
Index i = k; i < size; ++i) {
511 m_rowsTranspositions.coeffRef(i) = internal::convert_index<StorageIndex>(i);
512 m_colsTranspositions.coeffRef(i) = internal::convert_index<StorageIndex>(i);
517 RealScalar abs_pivot = internal::abs_knowing_score<Scalar>()(
518 m_lu(row_of_biggest_in_corner, col_of_biggest_in_corner), biggest_in_corner);
519 if (abs_pivot > m_maxpivot) m_maxpivot = abs_pivot;
524 m_rowsTranspositions.coeffRef(k) = internal::convert_index<StorageIndex>(row_of_biggest_in_corner);
525 m_colsTranspositions.coeffRef(k) = internal::convert_index<StorageIndex>(col_of_biggest_in_corner);
526 if (k != row_of_biggest_in_corner) {
527 m_lu.row(k).swap(m_lu.row(row_of_biggest_in_corner));
528 ++number_of_transpositions;
530 if (k != col_of_biggest_in_corner) {
531 m_lu.col(k).swap(m_lu.col(col_of_biggest_in_corner));
532 ++number_of_transpositions;
538 if (k < rows - 1) m_lu.col(k).tail(rows - k - 1) /= m_lu.coeff(k, k);
540 m_lu.block(k + 1, k + 1, rows - k - 1, cols - k - 1).noalias() -=
541 m_lu.col(k).tail(rows - k - 1) * m_lu.row(k).tail(cols - k - 1);
547 m_p.setIdentity(rows);
548 for (
Index k = size - 1; k >= 0; --k) m_p.applyTranspositionOnTheRight(k, m_rowsTranspositions.coeff(k));
550 m_q.setIdentity(cols);
551 for (
Index k = 0; k < size; ++k) m_q.applyTranspositionOnTheRight(k, m_colsTranspositions.coeff(k));
553 m_det_pq = (number_of_transpositions % 2) ? -1 : 1;
555 m_isInitialized =
true;
558template <
typename MatrixType,
typename PermutationIndex>
560 eigen_assert(m_isInitialized &&
"LU is not initialized.");
561 eigen_assert(m_lu.rows() == m_lu.cols() &&
"You can't take the determinant of a non-square matrix!");
562 return Scalar(m_det_pq) * Scalar(m_lu.diagonal().prod());
568template <
typename MatrixType,
typename PermutationIndex>
570 eigen_assert(m_isInitialized &&
"LU is not initialized.");
571 const Index smalldim = (std::min)(m_lu.rows(), m_lu.cols());
573 MatrixType res(m_lu.rows(), m_lu.cols());
575 res = m_lu.leftCols(smalldim).template triangularView<UnitLower>().toDenseMatrix() *
576 m_lu.topRows(smalldim).template triangularView<Upper>().toDenseMatrix();
579 res = m_p.inverse() * res;
582 res = res * m_q.inverse();
590template <
typename MatrixType_,
typename PermutationIndex_>
591struct kernel_retval<
FullPivLU<MatrixType_, PermutationIndex_> >
592 : kernel_retval_base<FullPivLU<MatrixType_, PermutationIndex_> > {
594 EIGEN_MAKE_KERNEL_HELPERS(DecompositionType)
597 MaxSmallDimAtCompileTime = min_size_prefer_fixed(MatrixType::MaxColsAtCompileTime, MatrixType::MaxRowsAtCompileTime)
600 template <
typename Dest>
601 void evalTo(Dest& dst)
const {
603 const Index cols = dec().
matrixLU().cols(), dimker = cols - rank();
628 Matrix<Index, Dynamic, 1, 0, MaxSmallDimAtCompileTime, 1> pivots(rank());
629 RealScalar premultiplied_threshold = dec().maxPivot() * dec().threshold();
631 for (
Index i = 0; i < dec().nonzeroPivots(); ++i)
632 if (
abs(dec().matrixLU().coeff(i, i)) > premultiplied_threshold) pivots.coeffRef(p++) = i;
633 eigen_internal_assert(p == rank());
639 Matrix<typename MatrixType::Scalar, Dynamic, Dynamic, traits<MatrixType>::Options, MaxSmallDimAtCompileTime,
640 MatrixType::MaxColsAtCompileTime>
641 m(dec().matrixLU().block(0, 0, rank(), cols));
642 for (
Index i = 0; i < rank(); ++i) {
643 if (i) m.row(i).head(i).setZero();
644 m.row(i).tail(cols - i) = dec().matrixLU().row(pivots.coeff(i)).tail(cols - i);
646 m.block(0, 0, rank(), rank());
647 m.block(0, 0, rank(), rank()).template triangularView<StrictlyLower>().setZero();
648 for (
Index i = 0; i < rank(); ++i) m.col(i).swap(m.col(pivots.coeff(i)));
653 m.topLeftCorner(rank(), rank()).template triangularView<Upper>().solveInPlace(m.topRightCorner(rank(), dimker));
656 for (
Index i = rank() - 1; i >= 0; --i) m.col(i).swap(m.col(pivots.coeff(i)));
659 for (
Index i = 0; i < rank(); ++i) dst.row(dec().permutationQ().indices().coeff(i)) = -m.row(i).tail(dimker);
660 for (
Index i = rank(); i < cols; ++i) dst.row(dec().permutationQ().indices().coeff(i)).setZero();
661 for (
Index k = 0; k < dimker; ++k) dst.coeffRef(dec().permutationQ().indices().coeff(rank() + k), k) = Scalar(1);
667template <
typename MatrixType_,
typename PermutationIndex_>
668struct image_retval<FullPivLU<MatrixType_, PermutationIndex_> >
669 : image_retval_base<FullPivLU<MatrixType_, PermutationIndex_> > {
670 using DecompositionType = FullPivLU<MatrixType_, PermutationIndex_>;
671 EIGEN_MAKE_IMAGE_HELPERS(DecompositionType)
674 MaxSmallDimAtCompileTime = min_size_prefer_fixed(MatrixType::MaxColsAtCompileTime, MatrixType::MaxRowsAtCompileTime)
677 template <
typename Dest>
678 void evalTo(Dest& dst)
const {
688 Matrix<Index, Dynamic, 1, 0, MaxSmallDimAtCompileTime, 1> pivots(rank());
689 RealScalar premultiplied_threshold = dec().maxPivot() * dec().threshold();
691 for (
Index i = 0; i < dec().nonzeroPivots(); ++i)
692 if (
abs(dec().matrixLU().coeff(i, i)) > premultiplied_threshold) pivots.coeffRef(p++) = i;
693 eigen_internal_assert(p == rank());
695 for (
Index i = 0; i < rank(); ++i)
696 dst.col(i) = originalMatrix().col(dec().permutationQ().indices().coeff(pivots.coeff(i)));
704#ifndef EIGEN_PARSED_BY_DOXYGEN
705template <
typename MatrixType_,
typename PermutationIndex_>
706template <
typename RhsType,
typename DstType>
716 const Index rows = this->rows(), cols = this->cols(), nonzero_pivots = this->rank();
717 const Index smalldim = (std::min)(rows, cols);
719 if (nonzero_pivots == 0) {
724 typename RhsType::PlainObject c(rhs.rows(), rhs.cols());
727 c = permutationP() * rhs;
730 m_lu.topLeftCorner(smalldim, smalldim).template triangularView<UnitLower>().solveInPlace(c.topRows(smalldim));
731 if (rows > cols) c.bottomRows(rows - cols).noalias() -= m_lu.bottomRows(rows - cols) * c.topRows(cols);
734 m_lu.topLeftCorner(nonzero_pivots, nonzero_pivots)
735 .template triangularView<Upper>()
736 .solveInPlace(c.topRows(nonzero_pivots));
739 for (
Index i = 0; i < nonzero_pivots; ++i) dst.row(permutationQ().indices().coeff(i)) = c.row(i);
740 for (
Index i = nonzero_pivots; i < m_lu.cols(); ++i) dst.row(permutationQ().indices().coeff(i)).setZero();
743template <
typename MatrixType_,
typename PermutationIndex_>
744template <
bool Conjugate,
typename RhsType,
typename DstType>
757 const Index rows = this->rows(), cols = this->cols(), nonzero_pivots = this->rank();
758 const Index smalldim = (std::min)(rows, cols);
760 if (nonzero_pivots == 0) {
765 typename RhsType::PlainObject c(rhs.rows(), rhs.cols());
768 c = permutationQ().inverse() * rhs;
771 m_lu.topLeftCorner(nonzero_pivots, nonzero_pivots)
772 .template triangularView<Upper>()
774 .template conjugateIf<Conjugate>()
775 .solveInPlace(c.topRows(nonzero_pivots));
778 m_lu.topLeftCorner(smalldim, smalldim)
779 .template triangularView<UnitLower>()
781 .template conjugateIf<Conjugate>()
782 .solveInPlace(c.topRows(smalldim));
785 PermutationPType invp = permutationP().inverse().eval();
786 for (
Index i = 0; i < smalldim; ++i) dst.row(invp.indices().coeff(i)) = c.row(i);
787 for (
Index i = smalldim; i < rows; ++i) dst.row(invp.indices().coeff(i)).setZero();
795template <
typename DstXprType,
typename MatrixType,
typename PermutationIndex>
797 DstXprType, Inverse<FullPivLU<MatrixType, PermutationIndex> >,
798 internal::assign_op<typename DstXprType::Scalar, typename FullPivLU<MatrixType, PermutationIndex>::Scalar>,
800 typedef FullPivLU<MatrixType, PermutationIndex> LuType;
801 typedef Inverse<LuType> SrcXprType;
802 static void run(DstXprType& dst,
const SrcXprType& src,
803 const internal::assign_op<typename DstXprType::Scalar, typename MatrixType::Scalar>&) {
804 dst = src.nestedExpression().
solve(MatrixType::Identity(src.rows(), src.cols()));
817template <
typename Derived>
818template <
typename PermutationIndex>
EvalReturnType eval() const
Definition DenseBase.h:386
LU decomposition of a matrix with complete pivoting, and related features.
Definition FullPivLU.h:63
FullPivLU(EigenBase< InputType > &matrix)
Constructs a LU factorization from a given matrix.
Definition FullPivLU.h:461
const internal::image_retval< FullPivLU > image(const MatrixType &originalMatrix) const
Definition FullPivLU.h:224
const PermutationPType & permutationP() const
Definition FullPivLU.h:172
ComputationInfo info() const
Reports whether the LU factorization was successful.
Definition FullPivLU.h:87
bool isInjective() const
Definition FullPivLU.h:362
bool isInvertible() const
Definition FullPivLU.h:385
internal::traits< MatrixType >::Scalar determinant() const
Definition FullPivLU.h:559
RealScalar rcond() const
Definition FullPivLU.h:256
Index nonzeroPivots() const
Definition FullPivLU.h:158
FullPivLU & setThreshold(Default_t)
Definition FullPivLU.h:312
const Solve< FullPivLU, Rhs > solve(const MatrixBase< Rhs > &b) const
MatrixType reconstructedMatrix() const
Definition FullPivLU.h:569
RealScalar maxPivot() const
Definition FullPivLU.h:166
Index rank() const
Definition FullPivLU.h:335
const Inverse< FullPivLU > inverse() const
Definition FullPivLU.h:397
const internal::kernel_retval< FullPivLU > kernel() const
Definition FullPivLU.h:200
FullPivLU & setThreshold(const RealScalar &threshold)
Definition FullPivLU.h:298
bool isSurjective() const
Definition FullPivLU.h:374
FullPivLU(const EigenBase< InputType > &matrix)
Definition FullPivLU.h:448
RealScalar threshold() const
Definition FullPivLU.h:321
const MatrixType & matrixLU() const
Definition FullPivLU.h:146
FullPivLU(Index rows, Index cols)
Default Constructor with memory preallocation.
Definition FullPivLU.h:437
const PermutationQType & permutationQ() const
Definition FullPivLU.h:181
FullPivLU & compute(const EigenBase< InputType > &matrix)
Definition FullPivLU.h:134
Index dimensionOfKernel() const
Definition FullPivLU.h:350
FullPivLU()
Default Constructor.
Definition FullPivLU.h:434
Expression of the inverse of another expression.
Definition Inverse.h:43
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:52
Permutation matrix.
Definition PermutationMatrix.h:283
Pseudo expression representing a solving operation.
Definition Solve.h:62
constexpr FullPivLU< MatrixType_, PermutationIndex_ > & derived()
SolverBase()
Definition SolverBase.h:105
const Solve< Derived, Rhs > solve(const MatrixBase< Rhs > &b) const
Definition SolverBase.h:114
ComputationInfo
Definition Constants.h:438
@ Success
Definition Constants.h:440
Namespace containing all symbols from the Eigen library.
Definition B01_Experimental.dox:1
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_abs_op< typename Derived::Scalar >, const Derived > abs(const Eigen::ArrayBase< Derived > &x)
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition Meta.h:82
Definition EigenBase.h:33
constexpr Derived & derived()
Definition EigenBase.h:49
Eigen::Index Index
The interface type of indices.
Definition EigenBase.h:43