Medial Code Documentation
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
10#ifndef EIGEN_LU_H
11#define EIGEN_LU_H
12
13namespace Eigen {
14
15namespace internal {
16template<typename _MatrixType> struct traits<FullPivLU<_MatrixType> >
17 : traits<_MatrixType>
18{
19 typedef MatrixXpr XprKind;
21 enum { Flags = 0 };
22};
23
24} // end namespace internal
25
57template<typename _MatrixType> class FullPivLU
58 : public SolverBase<FullPivLU<_MatrixType> >
59{
60 public:
61 typedef _MatrixType MatrixType;
63
64 EIGEN_GENERIC_PUBLIC_INTERFACE(FullPivLU)
65 // FIXME StorageIndex defined in EIGEN_GENERIC_PUBLIC_INTERFACE should be int
66 enum {
67 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
68 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
69 };
74 typedef typename MatrixType::PlainObject PlainObject;
75
82 FullPivLU();
83
90 FullPivLU(Index rows, Index cols);
91
97 template<typename InputType>
98 explicit FullPivLU(const EigenBase<InputType>& matrix);
99
107 template<typename InputType>
109
116 inline const MatrixType& matrixLU() const
117 {
118 eigen_assert(m_isInitialized && "LU is not initialized.");
119 return m_lu;
120 }
121
129 inline Index nonzeroPivots() const
130 {
131 eigen_assert(m_isInitialized && "LU is not initialized.");
132 return m_nonzero_pivots;
133 }
134
138 RealScalar maxPivot() const { return m_maxpivot; }
139
144 inline const PermutationPType& permutationP() const
145 {
146 eigen_assert(m_isInitialized && "LU is not initialized.");
147 return m_p;
148 }
149
154 inline const PermutationQType& permutationQ() const
155 {
156 eigen_assert(m_isInitialized && "LU is not initialized.");
157 return m_q;
158 }
159
175 {
176 eigen_assert(m_isInitialized && "LU is not initialized.");
178 }
179
200 image(const MatrixType& originalMatrix) const
201 {
202 eigen_assert(m_isInitialized && "LU is not initialized.");
203 return internal::image_retval<FullPivLU>(*this, originalMatrix);
204 }
205
225 // FIXME this is a copy-paste of the base-class member to add the isInitialized assertion.
226 template<typename Rhs>
227 inline const Solve<FullPivLU, Rhs>
228 solve(const MatrixBase<Rhs>& b) const
229 {
230 eigen_assert(m_isInitialized && "LU is not initialized.");
231 return Solve<FullPivLU, Rhs>(*this, b.derived());
232 }
233
250
268 FullPivLU& setThreshold(const RealScalar& threshold)
269 {
270 m_usePrescribedThreshold = true;
271 m_prescribedThreshold = threshold;
272 return *this;
273 }
274
284 {
285 m_usePrescribedThreshold = false;
286 return *this;
287 }
288
293 RealScalar threshold() const
294 {
295 eigen_assert(m_isInitialized || m_usePrescribedThreshold);
296 return m_usePrescribedThreshold ? m_prescribedThreshold
297 // this formula comes from experimenting (see "LU precision tuning" thread on the list)
298 // and turns out to be identical to Higham's formula used already in LDLt.
299 : NumTraits<Scalar>::epsilon() * m_lu.diagonalSize();
300 }
301
308 inline Index rank() const
309 {
310 using std::abs;
311 eigen_assert(m_isInitialized && "LU is not initialized.");
312 RealScalar premultiplied_threshold = abs(m_maxpivot) * threshold();
313 Index result = 0;
314 for(Index i = 0; i < m_nonzero_pivots; ++i)
315 result += (abs(m_lu.coeff(i,i)) > premultiplied_threshold);
316 return result;
317 }
318
326 {
327 eigen_assert(m_isInitialized && "LU is not initialized.");
328 return cols() - rank();
329 }
330
338 inline bool isInjective() const
339 {
340 eigen_assert(m_isInitialized && "LU is not initialized.");
341 return rank() == cols();
342 }
343
351 inline bool isSurjective() const
352 {
353 eigen_assert(m_isInitialized && "LU is not initialized.");
354 return rank() == rows();
355 }
356
363 inline bool isInvertible() const
364 {
365 eigen_assert(m_isInitialized && "LU is not initialized.");
366 return isInjective() && (m_lu.rows() == m_lu.cols());
367 }
368
376 inline const Inverse<FullPivLU> inverse() const
377 {
378 eigen_assert(m_isInitialized && "LU is not initialized.");
379 eigen_assert(m_lu.rows() == m_lu.cols() && "You can't take the inverse of a non-square matrix!");
380 return Inverse<FullPivLU>(*this);
381 }
382
383 MatrixType reconstructedMatrix() const;
384
385 inline Index rows() const { return m_lu.rows(); }
386 inline Index cols() const { return m_lu.cols(); }
387
388 #ifndef EIGEN_PARSED_BY_DOXYGEN
389 template<typename RhsType, typename DstType>
390 EIGEN_DEVICE_FUNC
391 void _solve_impl(const RhsType &rhs, DstType &dst) const;
392
393 template<bool Conjugate, typename RhsType, typename DstType>
394 EIGEN_DEVICE_FUNC
395 void _solve_impl_transposed(const RhsType &rhs, DstType &dst) const;
396 #endif
397
398 protected:
399
400 static void check_template_parameters()
401 {
402 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
403 }
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_det_pq, m_nonzero_pivots;
413 RealScalar m_maxpivot, m_prescribedThreshold;
414 bool m_isInitialized, m_usePrescribedThreshold;
415};
416
417template<typename MatrixType>
419 : m_isInitialized(false), m_usePrescribedThreshold(false)
420{
421}
422
423template<typename MatrixType>
425 : m_lu(rows, cols),
426 m_p(rows),
427 m_q(cols),
428 m_rowsTranspositions(rows),
429 m_colsTranspositions(cols),
430 m_isInitialized(false),
431 m_usePrescribedThreshold(false)
432{
433}
434
435template<typename MatrixType>
436template<typename InputType>
438 : m_lu(matrix.rows(), matrix.cols()),
439 m_p(matrix.rows()),
440 m_q(matrix.cols()),
441 m_rowsTranspositions(matrix.rows()),
442 m_colsTranspositions(matrix.cols()),
443 m_isInitialized(false),
444 m_usePrescribedThreshold(false)
445{
446 compute(matrix.derived());
447}
448
449template<typename MatrixType>
450template<typename InputType>
452{
453 check_template_parameters();
454
455 // the permutations are stored as int indices, so just to be sure:
456 eigen_assert(matrix.rows()<=NumTraits<int>::highest() && matrix.cols()<=NumTraits<int>::highest());
457
458 m_isInitialized = true;
459 m_lu = matrix.derived();
460
461 computeInPlace();
462
463 return *this;
464}
465
466template<typename MatrixType>
467void FullPivLU<MatrixType>::computeInPlace()
468{
469 const Index size = m_lu.diagonalSize();
470 const Index rows = m_lu.rows();
471 const Index cols = m_lu.cols();
472
473 // will store the transpositions, before we accumulate them at the end.
474 // can't accumulate on-the-fly because that will be done in reverse order for the rows.
475 m_rowsTranspositions.resize(m_lu.rows());
476 m_colsTranspositions.resize(m_lu.cols());
477 Index number_of_transpositions = 0; // number of NONTRIVIAL transpositions, i.e. m_rowsTranspositions[i]!=i
478
479 m_nonzero_pivots = size; // the generic case is that in which all pivots are nonzero (invertible case)
480 m_maxpivot = RealScalar(0);
481
482 for(Index k = 0; k < size; ++k)
483 {
484 // First, we need to find the pivot.
485
486 // biggest coefficient in the remaining bottom-right corner (starting at row k, col k)
487 Index row_of_biggest_in_corner, col_of_biggest_in_corner;
488 typedef internal::scalar_score_coeff_op<Scalar> Scoring;
489 typedef typename Scoring::result_type Score;
490 Score biggest_in_corner;
491 biggest_in_corner = m_lu.bottomRightCorner(rows-k, cols-k)
492 .unaryExpr(Scoring())
493 .maxCoeff(&row_of_biggest_in_corner, &col_of_biggest_in_corner);
494 row_of_biggest_in_corner += k; // correct the values! since they were computed in the corner,
495 col_of_biggest_in_corner += k; // need to add k to them.
496
497 if(biggest_in_corner==Score(0))
498 {
499 // before exiting, make sure to initialize the still uninitialized transpositions
500 // in a sane state without destroying what we already have.
501 m_nonzero_pivots = k;
502 for(Index i = k; i < size; ++i)
503 {
504 m_rowsTranspositions.coeffRef(i) = i;
505 m_colsTranspositions.coeffRef(i) = i;
506 }
507 break;
508 }
509
510 RealScalar abs_pivot = internal::abs_knowing_score<Scalar>()(m_lu(row_of_biggest_in_corner, col_of_biggest_in_corner), biggest_in_corner);
511 if(abs_pivot > m_maxpivot) m_maxpivot = abs_pivot;
512
513 // Now that we've found the pivot, we need to apply the row/col swaps to
514 // bring it to the location (k,k).
515
516 m_rowsTranspositions.coeffRef(k) = row_of_biggest_in_corner;
517 m_colsTranspositions.coeffRef(k) = col_of_biggest_in_corner;
518 if(k != row_of_biggest_in_corner) {
519 m_lu.row(k).swap(m_lu.row(row_of_biggest_in_corner));
520 ++number_of_transpositions;
521 }
522 if(k != col_of_biggest_in_corner) {
523 m_lu.col(k).swap(m_lu.col(col_of_biggest_in_corner));
524 ++number_of_transpositions;
525 }
526
527 // Now that the pivot is at the right location, we update the remaining
528 // bottom-right corner by Gaussian elimination.
529
530 if(k<rows-1)
531 m_lu.col(k).tail(rows-k-1) /= m_lu.coeff(k,k);
532 if(k<size-1)
533 m_lu.block(k+1,k+1,rows-k-1,cols-k-1).noalias() -= m_lu.col(k).tail(rows-k-1) * m_lu.row(k).tail(cols-k-1);
534 }
535
536 // the main loop is over, we still have to accumulate the transpositions to find the
537 // permutations P and Q
538
539 m_p.setIdentity(rows);
540 for(Index k = size-1; k >= 0; --k)
541 m_p.applyTranspositionOnTheRight(k, m_rowsTranspositions.coeff(k));
542
543 m_q.setIdentity(cols);
544 for(Index k = 0; k < size; ++k)
545 m_q.applyTranspositionOnTheRight(k, m_colsTranspositions.coeff(k));
546
547 m_det_pq = (number_of_transpositions%2) ? -1 : 1;
548}
549
550template<typename MatrixType>
552{
553 eigen_assert(m_isInitialized && "LU is not initialized.");
554 eigen_assert(m_lu.rows() == m_lu.cols() && "You can't take the determinant of a non-square matrix!");
555 return Scalar(m_det_pq) * Scalar(m_lu.diagonal().prod());
556}
557
561template<typename MatrixType>
563{
564 eigen_assert(m_isInitialized && "LU is not initialized.");
565 const Index smalldim = (std::min)(m_lu.rows(), m_lu.cols());
566 // LU
567 MatrixType res(m_lu.rows(),m_lu.cols());
568 // FIXME the .toDenseMatrix() should not be needed...
569 res = m_lu.leftCols(smalldim)
570 .template triangularView<UnitLower>().toDenseMatrix()
571 * m_lu.topRows(smalldim)
572 .template triangularView<Upper>().toDenseMatrix();
573
574 // P^{-1}(LU)
575 res = m_p.inverse() * res;
576
577 // (P^{-1}LU)Q^{-1}
578 res = res * m_q.inverse();
579
580 return res;
581}
582
583/********* Implementation of kernel() **************************************************/
584
585namespace internal {
586template<typename _MatrixType>
587struct kernel_retval<FullPivLU<_MatrixType> >
588 : kernel_retval_base<FullPivLU<_MatrixType> >
589{
590 EIGEN_MAKE_KERNEL_HELPERS(FullPivLU<_MatrixType>)
591
592 enum { MaxSmallDimAtCompileTime = EIGEN_SIZE_MIN_PREFER_FIXED(
593 MatrixType::MaxColsAtCompileTime,
594 MatrixType::MaxRowsAtCompileTime)
595 };
596
597 template<typename Dest> void evalTo(Dest& dst) const
598 {
599 using std::abs;
600 const Index cols = dec().matrixLU().cols(), dimker = cols - rank();
601 if(dimker == 0)
602 {
603 // The Kernel is just {0}, so it doesn't have a basis properly speaking, but let's
604 // avoid crashing/asserting as that depends on floating point calculations. Let's
605 // just return a single column vector filled with zeros.
606 dst.setZero();
607 return;
608 }
609
610 /* Let us use the following lemma:
611 *
612 * Lemma: If the matrix A has the LU decomposition PAQ = LU,
613 * then Ker A = Q(Ker U).
614 *
615 * Proof: trivial: just keep in mind that P, Q, L are invertible.
616 */
617
618 /* Thus, all we need to do is to compute Ker U, and then apply Q.
619 *
620 * U is upper triangular, with eigenvalues sorted so that any zeros appear at the end.
621 * Thus, the diagonal of U ends with exactly
622 * dimKer zero's. Let us use that to construct dimKer linearly
623 * independent vectors in Ker U.
624 */
625
627 RealScalar premultiplied_threshold = dec().maxPivot() * dec().threshold();
628 Index p = 0;
629 for(Index i = 0; i < dec().nonzeroPivots(); ++i)
630 if(abs(dec().matrixLU().coeff(i,i)) > premultiplied_threshold)
631 pivots.coeffRef(p++) = i;
632 eigen_internal_assert(p == rank());
633
634 // we construct a temporaty trapezoid matrix m, by taking the U matrix and
635 // permuting the rows and cols to bring the nonnegligible pivots to the top of
636 // the main diagonal. We need that to be able to apply our triangular solvers.
637 // FIXME when we get triangularView-for-rectangular-matrices, this can be simplified
638 Matrix<typename MatrixType::Scalar, Dynamic, Dynamic, MatrixType::Options,
639 MaxSmallDimAtCompileTime, MatrixType::MaxColsAtCompileTime>
640 m(dec().matrixLU().block(0, 0, rank(), cols));
641 for(Index i = 0; i < rank(); ++i)
642 {
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);
645 }
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)
649 m.col(i).swap(m.col(pivots.coeff(i)));
650
651 // ok, we have our trapezoid matrix, we can apply the triangular solver.
652 // notice that the math behind this suggests that we should apply this to the
653 // negative of the RHS, but for performance we just put the negative sign elsewhere, see below.
654 m.topLeftCorner(rank(), rank())
655 .template triangularView<Upper>().solveInPlace(
656 m.topRightCorner(rank(), dimker)
657 );
658
659 // now we must undo the column permutation that we had applied!
660 for(Index i = rank()-1; i >= 0; --i)
661 m.col(i).swap(m.col(pivots.coeff(i)));
662
663 // see the negative sign in the next line, that's what we were talking about above.
664 for(Index i = 0; i < rank(); ++i) dst.row(dec().permutationQ().indices().coeff(i)) = -m.row(i).tail(dimker);
665 for(Index i = rank(); i < cols; ++i) dst.row(dec().permutationQ().indices().coeff(i)).setZero();
666 for(Index k = 0; k < dimker; ++k) dst.coeffRef(dec().permutationQ().indices().coeff(rank()+k), k) = Scalar(1);
667 }
668};
669
670/***** Implementation of image() *****************************************************/
671
672template<typename _MatrixType>
673struct image_retval<FullPivLU<_MatrixType> >
674 : image_retval_base<FullPivLU<_MatrixType> >
675{
676 EIGEN_MAKE_IMAGE_HELPERS(FullPivLU<_MatrixType>)
677
678 enum { MaxSmallDimAtCompileTime = EIGEN_SIZE_MIN_PREFER_FIXED(
679 MatrixType::MaxColsAtCompileTime,
680 MatrixType::MaxRowsAtCompileTime)
681 };
682
683 template<typename Dest> void evalTo(Dest& dst) const
684 {
685 using std::abs;
686 if(rank() == 0)
687 {
688 // The Image is just {0}, so it doesn't have a basis properly speaking, but let's
689 // avoid crashing/asserting as that depends on floating point calculations. Let's
690 // just return a single column vector filled with zeros.
691 dst.setZero();
692 return;
693 }
694
696 RealScalar premultiplied_threshold = dec().maxPivot() * dec().threshold();
697 Index p = 0;
698 for(Index i = 0; i < dec().nonzeroPivots(); ++i)
699 if(abs(dec().matrixLU().coeff(i,i)) > premultiplied_threshold)
700 pivots.coeffRef(p++) = i;
701 eigen_internal_assert(p == rank());
702
703 for(Index i = 0; i < rank(); ++i)
704 dst.col(i) = originalMatrix().col(dec().permutationQ().indices().coeff(pivots.coeff(i)));
705 }
706};
707
708/***** Implementation of solve() *****************************************************/
709
710} // end namespace internal
711
712#ifndef EIGEN_PARSED_BY_DOXYGEN
713template<typename _MatrixType>
714template<typename RhsType, typename DstType>
716{
717 /* The decomposition PAQ = LU can be rewritten as A = P^{-1} L U Q^{-1}.
718 * So we proceed as follows:
719 * Step 1: compute c = P * rhs.
720 * Step 2: replace c by the solution x to Lx = c. Exists because L is invertible.
721 * Step 3: replace c by the solution x to Ux = c. May or may not exist.
722 * Step 4: result = Q * c;
723 */
724
725 const Index rows = this->rows(),
726 cols = this->cols(),
727 nonzero_pivots = this->rank();
728 eigen_assert(rhs.rows() == rows);
729 const Index smalldim = (std::min)(rows, cols);
730
731 if(nonzero_pivots == 0)
732 {
733 dst.setZero();
734 return;
735 }
736
737 typename RhsType::PlainObject c(rhs.rows(), rhs.cols());
738
739 // Step 1
740 c = permutationP() * rhs;
741
742 // Step 2
743 m_lu.topLeftCorner(smalldim,smalldim)
744 .template triangularView<UnitLower>()
745 .solveInPlace(c.topRows(smalldim));
746 if(rows>cols)
747 c.bottomRows(rows-cols) -= m_lu.bottomRows(rows-cols) * c.topRows(cols);
748
749 // Step 3
750 m_lu.topLeftCorner(nonzero_pivots, nonzero_pivots)
751 .template triangularView<Upper>()
752 .solveInPlace(c.topRows(nonzero_pivots));
753
754 // Step 4
755 for(Index i = 0; i < nonzero_pivots; ++i)
756 dst.row(permutationQ().indices().coeff(i)) = c.row(i);
757 for(Index i = nonzero_pivots; i < m_lu.cols(); ++i)
758 dst.row(permutationQ().indices().coeff(i)).setZero();
759}
760
761template<typename _MatrixType>
762template<bool Conjugate, typename RhsType, typename DstType>
763void FullPivLU<_MatrixType>::_solve_impl_transposed(const RhsType &rhs, DstType &dst) const
764{
765 /* The decomposition PAQ = LU can be rewritten as A = P^{-1} L U Q^{-1},
766 * and since permutations are real and unitary, we can write this
767 * as A^T = Q U^T L^T P,
768 * So we proceed as follows:
769 * Step 1: compute c = Q^T rhs.
770 * Step 2: replace c by the solution x to U^T x = c. May or may not exist.
771 * Step 3: replace c by the solution x to L^T x = c.
772 * Step 4: result = P^T c.
773 * If Conjugate is true, replace "^T" by "^*" above.
774 */
775
776 const Index rows = this->rows(), cols = this->cols(),
777 nonzero_pivots = this->rank();
778 eigen_assert(rhs.rows() == cols);
779 const Index smalldim = (std::min)(rows, cols);
780
781 if(nonzero_pivots == 0)
782 {
783 dst.setZero();
784 return;
785 }
786
787 typename RhsType::PlainObject c(rhs.rows(), rhs.cols());
788
789 // Step 1
790 c = permutationQ().inverse() * rhs;
791
792 if (Conjugate) {
793 // Step 2
794 m_lu.topLeftCorner(nonzero_pivots, nonzero_pivots)
795 .template triangularView<Upper>()
796 .adjoint()
797 .solveInPlace(c.topRows(nonzero_pivots));
798 // Step 3
799 m_lu.topLeftCorner(smalldim, smalldim)
800 .template triangularView<UnitLower>()
801 .adjoint()
802 .solveInPlace(c.topRows(smalldim));
803 } else {
804 // Step 2
805 m_lu.topLeftCorner(nonzero_pivots, nonzero_pivots)
806 .template triangularView<Upper>()
807 .transpose()
808 .solveInPlace(c.topRows(nonzero_pivots));
809 // Step 3
810 m_lu.topLeftCorner(smalldim, smalldim)
811 .template triangularView<UnitLower>()
812 .transpose()
813 .solveInPlace(c.topRows(smalldim));
814 }
815
816 // Step 4
817 PermutationPType invp = permutationP().inverse().eval();
818 for(Index i = 0; i < smalldim; ++i)
819 dst.row(invp.indices().coeff(i)) = c.row(i);
820 for(Index i = smalldim; i < rows; ++i)
821 dst.row(invp.indices().coeff(i)).setZero();
822}
823
824#endif
825
826namespace internal {
827
828
829/***** Implementation of inverse() *****************************************************/
830template<typename DstXprType, typename MatrixType, typename Scalar>
831struct Assignment<DstXprType, Inverse<FullPivLU<MatrixType> >, internal::assign_op<Scalar>, Dense2Dense, Scalar>
832{
835 static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<Scalar> &)
836 {
837 dst = src.nestedExpression().solve(MatrixType::Identity(src.rows(), src.cols()));
838 }
839};
840} // end namespace internal
841
842/******* MatrixBase methods *****************************************************************/
843
850#ifndef __CUDACC__
851template<typename Derived>
854{
855 return FullPivLU<PlainObject>(eval());
856}
857#endif
858
859} // end namespace Eigen
860
861#endif // EIGEN_LU_H
LU decomposition of a matrix with complete pivoting, and related features.
Definition FullPivLU.h:59
MatrixType reconstructedMatrix() const
Definition FullPivLU.h:562
bool isSurjective() const
Definition FullPivLU.h:351
FullPivLU & setThreshold(Default_t)
Allows to come back to the default behavior, letting Eigen use its default formula for determining th...
Definition FullPivLU.h:283
const internal::kernel_retval< FullPivLU > kernel() const
Definition FullPivLU.h:174
Index dimensionOfKernel() const
Definition FullPivLU.h:325
Index rank() const
Definition FullPivLU.h:308
internal::traits< MatrixType >::Scalar determinant() const
Definition FullPivLU.h:551
const Solve< FullPivLU, Rhs > solve(const MatrixBase< Rhs > &b) const
Definition FullPivLU.h:228
const PermutationPType & permutationP() const
Definition FullPivLU.h:144
Index nonzeroPivots() const
Definition FullPivLU.h:129
bool isInjective() const
Definition FullPivLU.h:338
FullPivLU & setThreshold(const RealScalar &threshold)
Allows to prescribe a threshold to be used by certain methods, such as rank(), who need to determine ...
Definition FullPivLU.h:268
RealScalar maxPivot() const
Definition FullPivLU.h:138
const Inverse< FullPivLU > inverse() const
Definition FullPivLU.h:376
const MatrixType & matrixLU() const
Definition FullPivLU.h:116
RealScalar threshold() const
Returns the threshold that will be used by certain methods such as rank().
Definition FullPivLU.h:293
const PermutationQType & permutationQ() const
Definition FullPivLU.h:154
FullPivLU & compute(const EigenBase< InputType > &matrix)
Computes the LU decomposition of the given matrix.
const internal::image_retval< FullPivLU > image(const MatrixType &originalMatrix) const
Definition FullPivLU.h:200
FullPivLU()
Default Constructor.
Definition FullPivLU.h:418
bool isInvertible() const
Definition FullPivLU.h:363
Expression of the inverse of another expression.
Definition Inverse.h:44
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:50
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:180
Pseudo expression representing a solving operation.
Definition Solve.h:63
A base class for matrix decomposition and solvers.
Definition SolverBase.h:42
Eigen::Index Index
The interface type of indices.
Definition EigenBase.h:37
The type used to identify a matrix expression.
Definition Constants.h:505
Holds information about the various numeric (i.e.
Definition NumTraits.h:108
The type used to identify a general solver (foctored) storage.
Definition Constants.h:496
Definition AssignEvaluator.h:684
Definition AssignEvaluator.h:674
Definition AssignmentFunctors.h:21
Definition ForwardDeclarations.h:142
Definition ForwardDeclarations.h:140
Definition ForwardDeclarations.h:17
Definition Meta.h:30