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;
102 template <
typename InputType>
112 template <
typename InputType>
122 template <
typename InputType>
136 eigen_assert(m_isInitialized &&
"LU is not initialized.");
148 eigen_assert(m_isInitialized &&
"LU is not initialized.");
149 return m_nonzero_pivots;
162 eigen_assert(m_isInitialized &&
"LU is not initialized.");
171 eigen_assert(m_isInitialized &&
"LU is not initialized.");
189 inline const internal::kernel_retval<FullPivLU>
kernel()
const {
190 eigen_assert(m_isInitialized &&
"LU is not initialized.");
191 return internal::kernel_retval<FullPivLU>(*
this);
213 inline const internal::image_retval<FullPivLU>
image(
const MatrixType& originalMatrix)
const {
214 eigen_assert(m_isInitialized &&
"LU is not initialized.");
215 return internal::image_retval<FullPivLU>(*
this, originalMatrix);
218#ifdef EIGEN_PARSED_BY_DOXYGEN
238 template <
typename Rhs>
246 eigen_assert(m_isInitialized &&
"PartialPivLU is not initialized.");
247 return internal::rcond_estimate_helper(m_l1_norm, *
this);
265 typename internal::traits<MatrixType>::Scalar
determinant()
const;
285 m_usePrescribedThreshold =
true;
299 m_usePrescribedThreshold =
false;
308 eigen_assert(m_isInitialized || m_usePrescribedThreshold);
309 return m_usePrescribedThreshold ? m_prescribedThreshold
323 eigen_assert(m_isInitialized &&
"LU is not initialized.");
324 RealScalar premultiplied_threshold =
abs(m_maxpivot) *
threshold();
326 for (
Index i = 0; i < m_nonzero_pivots; ++i) result += (
abs(m_lu.coeff(i, i)) > premultiplied_threshold);
337 eigen_assert(m_isInitialized &&
"LU is not initialized.");
338 return cols() -
rank();
349 eigen_assert(m_isInitialized &&
"LU is not initialized.");
350 return rank() == cols();
361 eigen_assert(m_isInitialized &&
"LU is not initialized.");
362 return rank() == rows();
372 eigen_assert(m_isInitialized &&
"LU is not initialized.");
373 return isInjective() && (m_lu.rows() == m_lu.cols());
384 eigen_assert(m_isInitialized &&
"LU is not initialized.");
385 eigen_assert(m_lu.rows() == m_lu.cols() &&
"You can't take the inverse of a non-square matrix!");
391 EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
inline Index rows() const EIGEN_NOEXCEPT {
return m_lu.rows(); }
392 EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
inline Index cols() const EIGEN_NOEXCEPT {
return m_lu.cols(); }
394#ifndef EIGEN_PARSED_BY_DOXYGEN
395 template <
typename RhsType,
typename DstType>
396 void _solve_impl(
const RhsType& rhs, DstType& dst)
const;
398 template <
bool Conjugate,
typename RhsType,
typename DstType>
399 void _solve_impl_transposed(
const RhsType& rhs, DstType& dst)
const;
403 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
405 void computeInPlace();
408 PermutationPType m_p;
409 PermutationQType m_q;
410 IntColVectorType m_rowsTranspositions;
411 IntRowVectorType m_colsTranspositions;
412 Index m_nonzero_pivots;
413 RealScalar m_l1_norm;
414 RealScalar m_maxpivot, m_prescribedThreshold;
415 signed char m_det_pq;
416 bool m_isInitialized, m_usePrescribedThreshold;
419template <
typename MatrixType,
typename PermutationIndex>
422template <
typename MatrixType,
typename PermutationIndex>
427 m_rowsTranspositions(rows),
428 m_colsTranspositions(cols),
429 m_isInitialized(false),
430 m_usePrescribedThreshold(false) {}
432template <
typename MatrixType,
typename PermutationIndex>
433template <
typename InputType>
435 : m_lu(matrix.rows(), matrix.cols()),
438 m_rowsTranspositions(matrix.rows()),
439 m_colsTranspositions(matrix.cols()),
440 m_isInitialized(false),
441 m_usePrescribedThreshold(false) {
445template <
typename MatrixType,
typename PermutationIndex>
446template <
typename InputType>
448 : m_lu(matrix.derived()),
451 m_rowsTranspositions(matrix.rows()),
452 m_colsTranspositions(matrix.cols()),
453 m_isInitialized(false),
454 m_usePrescribedThreshold(false) {
458template <
typename MatrixType,
typename PermutationIndex>
463 m_l1_norm = m_lu.cwiseAbs().colwise().sum().maxCoeff();
465 const Index size = m_lu.diagonalSize();
466 const Index rows = m_lu.rows();
467 const Index cols = m_lu.cols();
471 m_rowsTranspositions.resize(m_lu.rows());
472 m_colsTranspositions.resize(m_lu.cols());
473 Index number_of_transpositions = 0;
475 m_nonzero_pivots = size;
476 m_maxpivot = RealScalar(0);
478 for (
Index k = 0; k < size; ++k) {
482 Index row_of_biggest_in_corner, col_of_biggest_in_corner;
483 typedef internal::scalar_score_coeff_op<Scalar> Scoring;
484 typedef typename Scoring::result_type Score;
485 Score biggest_in_corner;
486 biggest_in_corner = m_lu.bottomRightCorner(rows - k, cols - k)
487 .unaryExpr(Scoring())
488 .maxCoeff(&row_of_biggest_in_corner, &col_of_biggest_in_corner);
489 row_of_biggest_in_corner += k;
490 col_of_biggest_in_corner += k;
492 if (numext::is_exactly_zero(biggest_in_corner)) {
495 m_nonzero_pivots = k;
496 for (
Index i = k; i < size; ++i) {
497 m_rowsTranspositions.coeffRef(i) = internal::convert_index<StorageIndex>(i);
498 m_colsTranspositions.coeffRef(i) = internal::convert_index<StorageIndex>(i);
503 RealScalar abs_pivot = internal::abs_knowing_score<Scalar>()(
504 m_lu(row_of_biggest_in_corner, col_of_biggest_in_corner), biggest_in_corner);
505 if (abs_pivot > m_maxpivot) m_maxpivot = abs_pivot;
510 m_rowsTranspositions.coeffRef(k) = internal::convert_index<StorageIndex>(row_of_biggest_in_corner);
511 m_colsTranspositions.coeffRef(k) = internal::convert_index<StorageIndex>(col_of_biggest_in_corner);
512 if (k != row_of_biggest_in_corner) {
513 m_lu.row(k).swap(m_lu.row(row_of_biggest_in_corner));
514 ++number_of_transpositions;
516 if (k != col_of_biggest_in_corner) {
517 m_lu.col(k).swap(m_lu.col(col_of_biggest_in_corner));
518 ++number_of_transpositions;
524 if (k < rows - 1) m_lu.col(k).tail(rows - k - 1) /= m_lu.coeff(k, k);
526 m_lu.block(k + 1, k + 1, rows - k - 1, cols - k - 1).noalias() -=
527 m_lu.col(k).tail(rows - k - 1) * m_lu.row(k).tail(cols - k - 1);
533 m_p.setIdentity(rows);
534 for (Index k = size - 1; k >= 0; --k) m_p.applyTranspositionOnTheRight(k, m_rowsTranspositions.coeff(k));
536 m_q.setIdentity(cols);
537 for (Index k = 0; k < size; ++k) m_q.applyTranspositionOnTheRight(k, m_colsTranspositions.coeff(k));
539 m_det_pq = (number_of_transpositions % 2) ? -1 : 1;
541 m_isInitialized =
true;
544template <
typename MatrixType,
typename PermutationIndex>
546 eigen_assert(m_isInitialized &&
"LU is not initialized.");
547 eigen_assert(m_lu.rows() == m_lu.cols() &&
"You can't take the determinant of a non-square matrix!");
548 return Scalar(m_det_pq) * Scalar(m_lu.diagonal().prod());
554template <
typename MatrixType,
typename PermutationIndex>
556 eigen_assert(m_isInitialized &&
"LU is not initialized.");
557 const Index smalldim = (std::min)(m_lu.rows(), m_lu.cols());
559 MatrixType res(m_lu.rows(), m_lu.cols());
561 res = m_lu.leftCols(smalldim).template triangularView<UnitLower>().toDenseMatrix() *
562 m_lu.topRows(smalldim).template triangularView<Upper>().toDenseMatrix();
565 res = m_p.inverse() * res;
568 res = res * m_q.inverse();
576template <
typename MatrixType_,
typename PermutationIndex_>
577struct kernel_retval<
FullPivLU<MatrixType_, PermutationIndex_> >
578 : kernel_retval_base<FullPivLU<MatrixType_, PermutationIndex_> > {
580 EIGEN_MAKE_KERNEL_HELPERS(DecompositionType)
583 MaxSmallDimAtCompileTime = min_size_prefer_fixed(MatrixType::MaxColsAtCompileTime, MatrixType::MaxRowsAtCompileTime)
586 template <
typename Dest>
587 void evalTo(Dest& dst)
const {
589 const Index cols = dec().matrixLU().cols(), dimker = cols - rank();
614 Matrix<Index, Dynamic, 1, 0, MaxSmallDimAtCompileTime, 1> pivots(rank());
615 RealScalar premultiplied_threshold = dec().maxPivot() * dec().threshold();
617 for (Index i = 0; i < dec().nonzeroPivots(); ++i)
618 if (abs(dec().matrixLU().coeff(i, i)) > premultiplied_threshold) pivots.coeffRef(p++) = i;
619 eigen_internal_assert(p == rank());
625 Matrix<typename MatrixType::Scalar, Dynamic, Dynamic, traits<MatrixType>::Options, MaxSmallDimAtCompileTime,
626 MatrixType::MaxColsAtCompileTime>
627 m(dec().matrixLU().block(0, 0, rank(), cols));
628 for (Index i = 0; i < rank(); ++i) {
629 if (i) m.row(i).head(i).setZero();
630 m.row(i).tail(cols - i) = dec().matrixLU().row(pivots.coeff(i)).tail(cols - i);
632 m.block(0, 0, rank(), rank());
633 m.block(0, 0, rank(), rank()).template triangularView<StrictlyLower>().setZero();
634 for (Index i = 0; i < rank(); ++i) m.col(i).swap(m.col(pivots.coeff(i)));
639 m.topLeftCorner(rank(), rank()).
template triangularView<Upper>().solveInPlace(m.topRightCorner(rank(), dimker));
642 for (Index i = rank() - 1; i >= 0; --i) m.col(i).swap(m.col(pivots.coeff(i)));
645 for (Index i = 0; i < rank(); ++i) dst.row(dec().permutationQ().indices().coeff(i)) = -m.row(i).tail(dimker);
646 for (Index i = rank(); i < cols; ++i) dst.row(dec().permutationQ().indices().coeff(i)).setZero();
647 for (Index k = 0; k < dimker; ++k) dst.coeffRef(dec().permutationQ().indices().coeff(rank() + k), k) = Scalar(1);
653template <
typename MatrixType_,
typename PermutationIndex_>
654struct image_retval<FullPivLU<MatrixType_, PermutationIndex_> >
655 : image_retval_base<FullPivLU<MatrixType_, PermutationIndex_> > {
656 using DecompositionType = FullPivLU<MatrixType_, PermutationIndex_>;
657 EIGEN_MAKE_IMAGE_HELPERS(DecompositionType)
660 MaxSmallDimAtCompileTime = min_size_prefer_fixed(MatrixType::MaxColsAtCompileTime, MatrixType::MaxRowsAtCompileTime)
663 template <
typename Dest>
664 void evalTo(Dest& dst)
const {
674 Matrix<Index, Dynamic, 1, 0, MaxSmallDimAtCompileTime, 1> pivots(rank());
675 RealScalar premultiplied_threshold = dec().maxPivot() * dec().threshold();
677 for (Index i = 0; i < dec().nonzeroPivots(); ++i)
678 if (abs(dec().matrixLU().coeff(i, i)) > premultiplied_threshold) pivots.coeffRef(p++) = i;
679 eigen_internal_assert(p == rank());
681 for (Index i = 0; i < rank(); ++i)
682 dst.col(i) = originalMatrix().col(dec().permutationQ().indices().coeff(pivots.coeff(i)));
690#ifndef EIGEN_PARSED_BY_DOXYGEN
691template <
typename MatrixType_,
typename PermutationIndex_>
692template <
typename RhsType,
typename DstType>
693void FullPivLU<MatrixType_, PermutationIndex_>::_solve_impl(
const RhsType& rhs, DstType& dst)
const {
702 const Index rows = this->rows(), cols = this->cols(), nonzero_pivots = this->rank();
703 const Index smalldim = (std::min)(rows, cols);
705 if (nonzero_pivots == 0) {
710 typename RhsType::PlainObject c(rhs.rows(), rhs.cols());
713 c = permutationP() * rhs;
716 m_lu.topLeftCorner(smalldim, smalldim).template triangularView<UnitLower>().solveInPlace(c.topRows(smalldim));
717 if (rows > cols) c.bottomRows(rows - cols) -= m_lu.bottomRows(rows - cols) * c.topRows(cols);
720 m_lu.topLeftCorner(nonzero_pivots, nonzero_pivots)
721 .template triangularView<Upper>()
722 .solveInPlace(c.topRows(nonzero_pivots));
725 for (Index i = 0; i < nonzero_pivots; ++i) dst.row(permutationQ().indices().coeff(i)) = c.row(i);
726 for (Index i = nonzero_pivots; i < m_lu.cols(); ++i) dst.row(permutationQ().indices().coeff(i)).setZero();
729template <
typename MatrixType_,
typename PermutationIndex_>
730template <
bool Conjugate,
typename RhsType,
typename DstType>
731void FullPivLU<MatrixType_, PermutationIndex_>::_solve_impl_transposed(
const RhsType& rhs, DstType& dst)
const {
743 const Index rows = this->rows(), cols = this->cols(), nonzero_pivots = this->rank();
744 const Index smalldim = (std::min)(rows, cols);
746 if (nonzero_pivots == 0) {
751 typename RhsType::PlainObject c(rhs.rows(), rhs.cols());
754 c = permutationQ().inverse() * rhs;
757 m_lu.topLeftCorner(nonzero_pivots, nonzero_pivots)
758 .template triangularView<Upper>()
760 .template conjugateIf<Conjugate>()
761 .solveInPlace(c.topRows(nonzero_pivots));
764 m_lu.topLeftCorner(smalldim, smalldim)
765 .template triangularView<UnitLower>()
767 .template conjugateIf<Conjugate>()
768 .solveInPlace(c.topRows(smalldim));
771 PermutationPType invp = permutationP().inverse().eval();
772 for (Index i = 0; i < smalldim; ++i) dst.row(invp.indices().coeff(i)) = c.row(i);
773 for (Index i = smalldim; i < rows; ++i) dst.row(invp.indices().coeff(i)).setZero();
781template <
typename DstXprType,
typename MatrixType,
typename PermutationIndex>
783 DstXprType, Inverse<FullPivLU<MatrixType, PermutationIndex> >,
784 internal::assign_op<typename DstXprType::Scalar, typename FullPivLU<MatrixType, PermutationIndex>::Scalar>,
786 typedef FullPivLU<MatrixType, PermutationIndex> LuType;
787 typedef Inverse<LuType> SrcXprType;
788 static void run(DstXprType& dst,
const SrcXprType& src,
789 const internal::assign_op<typename DstXprType::Scalar, typename MatrixType::Scalar>&) {
790 dst = src.nestedExpression().
solve(MatrixType::Identity(src.rows(), src.cols()));
803template <
typename Derived>
804template <
typename PermutationIndex>
LU decomposition of a matrix with complete pivoting, and related features.
Definition FullPivLU.h:63
const internal::image_retval< FullPivLU > image(const MatrixType &originalMatrix) const
Definition FullPivLU.h:213
const PermutationPType & permutationP() const
Definition FullPivLU.h:161
bool isInjective() const
Definition FullPivLU.h:348
bool isInvertible() const
Definition FullPivLU.h:371
internal::traits< MatrixType >::Scalar determinant() const
Definition FullPivLU.h:545
RealScalar rcond() const
Definition FullPivLU.h:245
Index nonzeroPivots() const
Definition FullPivLU.h:147
FullPivLU & setThreshold(Default_t)
Definition FullPivLU.h:298
const Solve< FullPivLU, Rhs > solve(const MatrixBase< Rhs > &b) const
MatrixType reconstructedMatrix() const
Definition FullPivLU.h:555
RealScalar maxPivot() const
Definition FullPivLU.h:155
Index rank() const
Definition FullPivLU.h:321
const Inverse< FullPivLU > inverse() const
Definition FullPivLU.h:383
const internal::kernel_retval< FullPivLU > kernel() const
Definition FullPivLU.h:189
FullPivLU & setThreshold(const RealScalar &threshold)
Definition FullPivLU.h:284
bool isSurjective() const
Definition FullPivLU.h:360
RealScalar threshold() const
Definition FullPivLU.h:307
const MatrixType & matrixLU() const
Definition FullPivLU.h:135
const PermutationQType & permutationQ() const
Definition FullPivLU.h:170
FullPivLU & compute(const EigenBase< InputType > &matrix)
Definition FullPivLU.h:123
Index dimensionOfKernel() const
Definition FullPivLU.h:336
FullPivLU()
Default Constructor.
Definition FullPivLU.h:420
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:280
Pseudo expression representing a solving operation.
Definition Solve.h:62
A base class for matrix decomposition and solvers.
Definition SolverBase.h:72
const Solve< Derived, Rhs > solve(const MatrixBase< Rhs > &b) const
Definition SolverBase.h:106
Namespace containing all symbols from the Eigen library.
Definition Core:137
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:83
Definition EigenBase.h:33
Derived & derived()
Definition EigenBase.h:49
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition Meta.h:523