Eigen  3.4.90 (git rev 5a9f66fb35d03a4da9ef8976e67a61b30aa16dcf)
 
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 <[email protected]>
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
10#ifndef EIGEN_LU_H
11#define EIGEN_LU_H
12
13// IWYU pragma: private
14#include "./InternalHeaderCheck.h"
15
16namespace Eigen {
17
18namespace internal {
19template <typename MatrixType_, typename PermutationIndex_>
20struct traits<FullPivLU<MatrixType_, PermutationIndex_> > : traits<MatrixType_> {
21 typedef MatrixXpr XprKind;
22 typedef SolverStorage StorageKind;
23 typedef PermutationIndex_ StorageIndex;
24 enum { Flags = 0 };
25};
26
27} // end namespace internal
28
62template <typename MatrixType_, typename PermutationIndex_>
63class FullPivLU : public SolverBase<FullPivLU<MatrixType_, PermutationIndex_> > {
64 public:
65 typedef MatrixType_ MatrixType;
67 friend class SolverBase<FullPivLU>;
68
69 EIGEN_GENERIC_PUBLIC_INTERFACE(FullPivLU)
70 enum {
71 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
72 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
73 };
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;
80
87 FullPivLU();
88
95 FullPivLU(Index rows, Index cols);
96
102 template <typename InputType>
103 explicit FullPivLU(const EigenBase<InputType>& matrix);
104
112 template <typename InputType>
113 explicit FullPivLU(EigenBase<InputType>& matrix);
114
122 template <typename InputType>
124 m_lu = matrix.derived();
125 computeInPlace();
126 return *this;
127 }
128
135 inline const MatrixType& matrixLU() const {
136 eigen_assert(m_isInitialized && "LU is not initialized.");
137 return m_lu;
138 }
139
147 inline Index nonzeroPivots() const {
148 eigen_assert(m_isInitialized && "LU is not initialized.");
149 return m_nonzero_pivots;
150 }
151
155 RealScalar maxPivot() const { return m_maxpivot; }
156
161 EIGEN_DEVICE_FUNC inline const PermutationPType& permutationP() const {
162 eigen_assert(m_isInitialized && "LU is not initialized.");
163 return m_p;
164 }
165
170 inline const PermutationQType& permutationQ() const {
171 eigen_assert(m_isInitialized && "LU is not initialized.");
172 return m_q;
173 }
174
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);
192 }
193
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);
216 }
217
218#ifdef EIGEN_PARSED_BY_DOXYGEN
238 template <typename Rhs>
239 inline const Solve<FullPivLU, Rhs> solve(const MatrixBase<Rhs>& b) const;
240#endif
241
245 inline RealScalar rcond() const {
246 eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
247 return internal::rcond_estimate_helper(m_l1_norm, *this);
248 }
249
265 typename internal::traits<MatrixType>::Scalar determinant() const;
266
284 FullPivLU& setThreshold(const RealScalar& threshold) {
285 m_usePrescribedThreshold = true;
286 m_prescribedThreshold = threshold;
287 return *this;
288 }
289
299 m_usePrescribedThreshold = false;
300 return *this;
301 }
302
307 RealScalar threshold() const {
308 eigen_assert(m_isInitialized || m_usePrescribedThreshold);
309 return m_usePrescribedThreshold ? m_prescribedThreshold
310 // this formula comes from experimenting (see "LU precision tuning" thread on the
311 // list) and turns out to be identical to Higham's formula used already in LDLt.
312 : NumTraits<Scalar>::epsilon() * RealScalar(m_lu.diagonalSize());
313 }
314
321 inline Index rank() const {
322 using std::abs;
323 eigen_assert(m_isInitialized && "LU is not initialized.");
324 RealScalar premultiplied_threshold = abs(m_maxpivot) * threshold();
325 Index result = 0;
326 for (Index i = 0; i < m_nonzero_pivots; ++i) result += (abs(m_lu.coeff(i, i)) > premultiplied_threshold);
327 return result;
328 }
329
336 inline Index dimensionOfKernel() const {
337 eigen_assert(m_isInitialized && "LU is not initialized.");
338 return cols() - rank();
339 }
340
348 inline bool isInjective() const {
349 eigen_assert(m_isInitialized && "LU is not initialized.");
350 return rank() == cols();
351 }
352
360 inline bool isSurjective() const {
361 eigen_assert(m_isInitialized && "LU is not initialized.");
362 return rank() == rows();
363 }
364
371 inline bool isInvertible() const {
372 eigen_assert(m_isInitialized && "LU is not initialized.");
373 return isInjective() && (m_lu.rows() == m_lu.cols());
374 }
375
383 inline const Inverse<FullPivLU> inverse() const {
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!");
386 return Inverse<FullPivLU>(*this);
387 }
388
389 MatrixType reconstructedMatrix() const;
390
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(); }
393
394#ifndef EIGEN_PARSED_BY_DOXYGEN
395 template <typename RhsType, typename DstType>
396 void _solve_impl(const RhsType& rhs, DstType& dst) const;
397
398 template <bool Conjugate, typename RhsType, typename DstType>
399 void _solve_impl_transposed(const RhsType& rhs, DstType& dst) const;
400#endif
401
402 protected:
403 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
404
405 void computeInPlace();
406
407 MatrixType m_lu;
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;
417};
418
419template <typename MatrixType, typename PermutationIndex>
420FullPivLU<MatrixType, PermutationIndex>::FullPivLU() : m_isInitialized(false), m_usePrescribedThreshold(false) {}
421
422template <typename MatrixType, typename PermutationIndex>
424 : m_lu(rows, cols),
425 m_p(rows),
426 m_q(cols),
427 m_rowsTranspositions(rows),
428 m_colsTranspositions(cols),
429 m_isInitialized(false),
430 m_usePrescribedThreshold(false) {}
431
432template <typename MatrixType, typename PermutationIndex>
433template <typename InputType>
435 : m_lu(matrix.rows(), matrix.cols()),
436 m_p(matrix.rows()),
437 m_q(matrix.cols()),
438 m_rowsTranspositions(matrix.rows()),
439 m_colsTranspositions(matrix.cols()),
440 m_isInitialized(false),
441 m_usePrescribedThreshold(false) {
442 compute(matrix.derived());
443}
444
445template <typename MatrixType, typename PermutationIndex>
446template <typename InputType>
448 : m_lu(matrix.derived()),
449 m_p(matrix.rows()),
450 m_q(matrix.cols()),
451 m_rowsTranspositions(matrix.rows()),
452 m_colsTranspositions(matrix.cols()),
453 m_isInitialized(false),
454 m_usePrescribedThreshold(false) {
455 computeInPlace();
456}
457
458template <typename MatrixType, typename PermutationIndex>
460 eigen_assert(m_lu.rows() <= NumTraits<PermutationIndex>::highest() &&
461 m_lu.cols() <= NumTraits<PermutationIndex>::highest());
462
463 m_l1_norm = m_lu.cwiseAbs().colwise().sum().maxCoeff();
464
465 const Index size = m_lu.diagonalSize();
466 const Index rows = m_lu.rows();
467 const Index cols = m_lu.cols();
468
469 // will store the transpositions, before we accumulate them at the end.
470 // can't accumulate on-the-fly because that will be done in reverse order for the rows.
471 m_rowsTranspositions.resize(m_lu.rows());
472 m_colsTranspositions.resize(m_lu.cols());
473 Index number_of_transpositions = 0; // number of NONTRIVIAL transpositions, i.e. m_rowsTranspositions[i]!=i
474
475 m_nonzero_pivots = size; // the generic case is that in which all pivots are nonzero (invertible case)
476 m_maxpivot = RealScalar(0);
477
478 for (Index k = 0; k < size; ++k) {
479 // First, we need to find the pivot.
480
481 // biggest coefficient in the remaining bottom-right corner (starting at row k, col 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; // correct the values! since they were computed in the corner,
490 col_of_biggest_in_corner += k; // need to add k to them.
491
492 if (numext::is_exactly_zero(biggest_in_corner)) {
493 // before exiting, make sure to initialize the still uninitialized transpositions
494 // in a sane state without destroying what we already have.
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);
499 }
500 break;
501 }
502
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;
506
507 // Now that we've found the pivot, we need to apply the row/col swaps to
508 // bring it to the location (k,k).
509
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;
515 }
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;
519 }
520
521 // Now that the pivot is at the right location, we update the remaining
522 // bottom-right corner by Gaussian elimination.
523
524 if (k < rows - 1) m_lu.col(k).tail(rows - k - 1) /= m_lu.coeff(k, k);
525 if (k < size - 1)
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);
528 }
529
530 // the main loop is over, we still have to accumulate the transpositions to find the
531 // permutations P and Q
532
533 m_p.setIdentity(rows);
534 for (Index k = size - 1; k >= 0; --k) m_p.applyTranspositionOnTheRight(k, m_rowsTranspositions.coeff(k));
535
536 m_q.setIdentity(cols);
537 for (Index k = 0; k < size; ++k) m_q.applyTranspositionOnTheRight(k, m_colsTranspositions.coeff(k));
538
539 m_det_pq = (number_of_transpositions % 2) ? -1 : 1;
540
541 m_isInitialized = true;
542}
543
544template <typename MatrixType, typename PermutationIndex>
545typename internal::traits<MatrixType>::Scalar FullPivLU<MatrixType, PermutationIndex>::determinant() const {
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());
549}
550
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());
558 // LU
559 MatrixType res(m_lu.rows(), m_lu.cols());
560 // FIXME the .toDenseMatrix() should not be needed...
561 res = m_lu.leftCols(smalldim).template triangularView<UnitLower>().toDenseMatrix() *
562 m_lu.topRows(smalldim).template triangularView<Upper>().toDenseMatrix();
563
564 // P^{-1}(LU)
565 res = m_p.inverse() * res;
566
567 // (P^{-1}LU)Q^{-1}
568 res = res * m_q.inverse();
569
570 return res;
571}
572
573/********* Implementation of kernel() **************************************************/
574
575namespace internal {
576template <typename MatrixType_, typename PermutationIndex_>
577struct kernel_retval<FullPivLU<MatrixType_, PermutationIndex_> >
578 : kernel_retval_base<FullPivLU<MatrixType_, PermutationIndex_> > {
579 using DecompositionType = FullPivLU<MatrixType_, PermutationIndex_>;
580 EIGEN_MAKE_KERNEL_HELPERS(DecompositionType)
581
582 enum {
583 MaxSmallDimAtCompileTime = min_size_prefer_fixed(MatrixType::MaxColsAtCompileTime, MatrixType::MaxRowsAtCompileTime)
584 };
585
586 template <typename Dest>
587 void evalTo(Dest& dst) const {
588 using std::abs;
589 const Index cols = dec().matrixLU().cols(), dimker = cols - rank();
590 if (dimker == 0) {
591 // The Kernel is just {0}, so it doesn't have a basis properly speaking, but let's
592 // avoid crashing/asserting as that depends on floating point calculations. Let's
593 // just return a single column vector filled with zeros.
594 dst.setZero();
595 return;
596 }
597
598 /* Let us use the following lemma:
599 *
600 * Lemma: If the matrix A has the LU decomposition PAQ = LU,
601 * then Ker A = Q(Ker U).
602 *
603 * Proof: trivial: just keep in mind that P, Q, L are invertible.
604 */
605
606 /* Thus, all we need to do is to compute Ker U, and then apply Q.
607 *
608 * U is upper triangular, with eigenvalues sorted so that any zeros appear at the end.
609 * Thus, the diagonal of U ends with exactly
610 * dimKer zero's. Let us use that to construct dimKer linearly
611 * independent vectors in Ker U.
612 */
613
614 Matrix<Index, Dynamic, 1, 0, MaxSmallDimAtCompileTime, 1> pivots(rank());
615 RealScalar premultiplied_threshold = dec().maxPivot() * dec().threshold();
616 Index p = 0;
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());
620
621 // we construct a temporaty trapezoid matrix m, by taking the U matrix and
622 // permuting the rows and cols to bring the nonnegligible pivots to the top of
623 // the main diagonal. We need that to be able to apply our triangular solvers.
624 // FIXME when we get triangularView-for-rectangular-matrices, this can be simplified
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);
631 }
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)));
635
636 // ok, we have our trapezoid matrix, we can apply the triangular solver.
637 // notice that the math behind this suggests that we should apply this to the
638 // negative of the RHS, but for performance we just put the negative sign elsewhere, see below.
639 m.topLeftCorner(rank(), rank()).template triangularView<Upper>().solveInPlace(m.topRightCorner(rank(), dimker));
640
641 // now we must undo the column permutation that we had applied!
642 for (Index i = rank() - 1; i >= 0; --i) m.col(i).swap(m.col(pivots.coeff(i)));
643
644 // see the negative sign in the next line, that's what we were talking about above.
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);
648 }
649};
650
651/***** Implementation of image() *****************************************************/
652
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)
658
659 enum {
660 MaxSmallDimAtCompileTime = min_size_prefer_fixed(MatrixType::MaxColsAtCompileTime, MatrixType::MaxRowsAtCompileTime)
661 };
662
663 template <typename Dest>
664 void evalTo(Dest& dst) const {
665 using std::abs;
666 if (rank() == 0) {
667 // The Image is just {0}, so it doesn't have a basis properly speaking, but let's
668 // avoid crashing/asserting as that depends on floating point calculations. Let's
669 // just return a single column vector filled with zeros.
670 dst.setZero();
671 return;
672 }
673
674 Matrix<Index, Dynamic, 1, 0, MaxSmallDimAtCompileTime, 1> pivots(rank());
675 RealScalar premultiplied_threshold = dec().maxPivot() * dec().threshold();
676 Index p = 0;
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());
680
681 for (Index i = 0; i < rank(); ++i)
682 dst.col(i) = originalMatrix().col(dec().permutationQ().indices().coeff(pivots.coeff(i)));
683 }
684};
685
686/***** Implementation of solve() *****************************************************/
687
688} // end namespace internal
689
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 {
694 /* The decomposition PAQ = LU can be rewritten as A = P^{-1} L U Q^{-1}.
695 * So we proceed as follows:
696 * Step 1: compute c = P * rhs.
697 * Step 2: replace c by the solution x to Lx = c. Exists because L is invertible.
698 * Step 3: replace c by the solution x to Ux = c. May or may not exist.
699 * Step 4: result = Q * c;
700 */
701
702 const Index rows = this->rows(), cols = this->cols(), nonzero_pivots = this->rank();
703 const Index smalldim = (std::min)(rows, cols);
704
705 if (nonzero_pivots == 0) {
706 dst.setZero();
707 return;
708 }
709
710 typename RhsType::PlainObject c(rhs.rows(), rhs.cols());
711
712 // Step 1
713 c = permutationP() * rhs;
714
715 // Step 2
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);
718
719 // Step 3
720 m_lu.topLeftCorner(nonzero_pivots, nonzero_pivots)
721 .template triangularView<Upper>()
722 .solveInPlace(c.topRows(nonzero_pivots));
723
724 // Step 4
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();
727}
728
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 {
732 /* The decomposition PAQ = LU can be rewritten as A = P^{-1} L U Q^{-1},
733 * and since permutations are real and unitary, we can write this
734 * as A^T = Q U^T L^T P,
735 * So we proceed as follows:
736 * Step 1: compute c = Q^T rhs.
737 * Step 2: replace c by the solution x to U^T x = c. May or may not exist.
738 * Step 3: replace c by the solution x to L^T x = c.
739 * Step 4: result = P^T c.
740 * If Conjugate is true, replace "^T" by "^*" above.
741 */
742
743 const Index rows = this->rows(), cols = this->cols(), nonzero_pivots = this->rank();
744 const Index smalldim = (std::min)(rows, cols);
745
746 if (nonzero_pivots == 0) {
747 dst.setZero();
748 return;
749 }
750
751 typename RhsType::PlainObject c(rhs.rows(), rhs.cols());
752
753 // Step 1
754 c = permutationQ().inverse() * rhs;
755
756 // Step 2
757 m_lu.topLeftCorner(nonzero_pivots, nonzero_pivots)
758 .template triangularView<Upper>()
759 .transpose()
760 .template conjugateIf<Conjugate>()
761 .solveInPlace(c.topRows(nonzero_pivots));
762
763 // Step 3
764 m_lu.topLeftCorner(smalldim, smalldim)
765 .template triangularView<UnitLower>()
766 .transpose()
767 .template conjugateIf<Conjugate>()
768 .solveInPlace(c.topRows(smalldim));
769
770 // Step 4
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();
774}
775
776#endif
777
778namespace internal {
779
780/***** Implementation of inverse() *****************************************************/
781template <typename DstXprType, typename MatrixType, typename PermutationIndex>
782struct Assignment<
783 DstXprType, Inverse<FullPivLU<MatrixType, PermutationIndex> >,
784 internal::assign_op<typename DstXprType::Scalar, typename FullPivLU<MatrixType, PermutationIndex>::Scalar>,
785 Dense2Dense> {
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()));
791 }
792};
793} // end namespace internal
794
795/******* MatrixBase methods *****************************************************************/
796
803template <typename Derived>
804template <typename PermutationIndex>
809
810} // end namespace Eigen
811
812#endif // EIGEN_LU_H
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