Eigen  3.2.92
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 
13 namespace Eigen {
14 
15 namespace internal {
16 template<typename _MatrixType> struct traits<FullPivLU<_MatrixType> >
17  : traits<_MatrixType>
18 {
19  typedef MatrixXpr XprKind;
20  typedef SolverStorage StorageKind;
21  enum { Flags = 0 };
22 };
23 
24 } // end namespace internal
25 
57 template<typename _MatrixType> class FullPivLU
58  : public SolverBase<FullPivLU<_MatrixType> >
59 {
60  public:
61  typedef _MatrixType MatrixType;
62  typedef SolverBase<FullPivLU> Base;
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  };
70  typedef typename internal::plain_row_type<MatrixType, StorageIndex>::type IntRowVectorType;
71  typedef typename internal::plain_col_type<MatrixType, StorageIndex>::type IntColVectorType;
72  typedef PermutationMatrix<ColsAtCompileTime, MaxColsAtCompileTime> PermutationQType;
73  typedef PermutationMatrix<RowsAtCompileTime, MaxRowsAtCompileTime> PermutationPType;
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>
108  FullPivLU& compute(const EigenBase<InputType>& matrix);
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 
174  inline const internal::kernel_retval<FullPivLU> kernel() const
175  {
176  eigen_assert(m_isInitialized && "LU is not initialized.");
177  return internal::kernel_retval<FullPivLU>(*this);
178  }
179 
199  inline const internal::image_retval<FullPivLU>
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 
249  typename internal::traits<MatrixType>::Scalar determinant() const;
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 
325  inline Index dimensionOfKernel() const
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 
417 template<typename MatrixType>
419  : m_isInitialized(false), m_usePrescribedThreshold(false)
420 {
421 }
422 
423 template<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 
435 template<typename MatrixType>
436 template<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 
449 template<typename MatrixType>
450 template<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 
466 template<typename MatrixType>
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 
550 template<typename MatrixType>
551 typename internal::traits<MatrixType>::Scalar FullPivLU<MatrixType>::determinant() const
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 
561 template<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 
585 namespace internal {
586 template<typename _MatrixType>
587 struct 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 
672 template<typename _MatrixType>
673 struct 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
713 template<typename _MatrixType>
714 template<typename RhsType, typename DstType>
715 void FullPivLU<_MatrixType>::_solve_impl(const RhsType &rhs, DstType &dst) const
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 
761 template<typename _MatrixType>
762 template<bool Conjugate, typename RhsType, typename DstType>
763 void 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 
826 namespace internal {
827 
828 
829 /***** Implementation of inverse() *****************************************************/
830 template<typename DstXprType, typename MatrixType, typename Scalar>
831 struct Assignment<DstXprType, Inverse<FullPivLU<MatrixType> >, internal::assign_op<Scalar>, Dense2Dense, Scalar>
832 {
833  typedef FullPivLU<MatrixType> LuType;
834  typedef Inverse<LuType> SrcXprType;
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__
851 template<typename Derived>
854 {
855  return FullPivLU<PlainObject>(eval());
856 }
857 #endif
858 
859 } // end namespace Eigen
860 
861 #endif // EIGEN_LU_H
bool isInjective() const
Definition: FullPivLU.h:338
const internal::image_retval< FullPivLU > image(const MatrixType &originalMatrix) const
Definition: FullPivLU.h:200
FullPivLU & setThreshold(const RealScalar &threshold)
Definition: FullPivLU.h:268
internal::traits< MatrixType >::Scalar determinant() const
Definition: FullPivLU.h:551
FullPivLU & compute(const EigenBase< InputType > &matrix)
Derived & applyTranspositionOnTheRight(Index i, Index j)
Definition: PermutationMatrix.h:186
AdjointReturnType adjoint() const
Definition: SolverBase.h:109
Definition: LDLT.h:16
Holds information about the various numeric (i.e. scalar) types allowed by Eigen. ...
Definition: NumTraits.h:107
Derived & derived()
Definition: EigenBase.h:44
Eigen::Index Index
The interface type of indices.
Definition: EigenBase.h:37
Index rows() const
Definition: EigenBase.h:58
RealScalar threshold() const
Definition: FullPivLU.h:293
Index nonzeroPivots() const
Definition: FullPivLU.h:129
Definition: EigenBase.h:28
Expression of the inverse of another expression.
Definition: Inverse.h:43
bool isSurjective() const
Definition: FullPivLU.h:351
FullPivLU & setThreshold(Default_t)
Definition: FullPivLU.h:283
const PermutationQType & permutationQ() const
Definition: FullPivLU.h:154
void setIdentity()
Definition: PermutationMatrix.h:143
MatrixType reconstructedMatrix() const
Definition: FullPivLU.h:562
ConstTransposeReturnType transpose() const
Definition: SolverBase.h:90
const PermutationPType & permutationP() const
Definition: FullPivLU.h:144
InverseReturnType inverse() const
Definition: PermutationMatrix.h:197
Definition: Eigen_Colamd.h:54
Index cols() const
Definition: EigenBase.h:61
LU decomposition of a matrix with complete pivoting, and related features.
Definition: ForwardDeclarations.h:247
bool isInvertible() const
Definition: FullPivLU.h:363
const FullPivLU< PlainObject > fullPivLu() const
Definition: FullPivLU.h:853
const IndicesType & indices() const
Definition: PermutationMatrix.h:390
FullPivLU()
Default Constructor.
Definition: FullPivLU.h:418
Index rank() const
Definition: FullPivLU.h:308
const MatrixType & matrixLU() const
Definition: FullPivLU.h:116
Pseudo expression representing a solving operation.
Definition: Solve.h:62
The matrix class, also used for vectors and row-vectors.
Definition: Matrix.h:178
const Inverse< FullPivLU > inverse() const
Definition: FullPivLU.h:376
Index dimensionOfKernel() const
Definition: FullPivLU.h:325
RealScalar maxPivot() const
Definition: FullPivLU.h:138
Base class for all dense matrices, vectors, and expressions.
Definition: MatrixBase.h:48
const Solve< FullPivLU, Rhs > solve(const MatrixBase< Rhs > &b) const
Definition: FullPivLU.h:228
Index size() const
Definition: EigenBase.h:65
const internal::kernel_retval< FullPivLU > kernel() const
Definition: FullPivLU.h:174