xref: /aosp_15_r20/external/eigen/Eigen/src/LU/FullPivLU.h (revision bf2c37156dfe67e5dfebd6d394bad8b2ab5804d4)
1*bf2c3715SXin Li // This file is part of Eigen, a lightweight C++ template library
2*bf2c3715SXin Li // for linear algebra.
3*bf2c3715SXin Li //
4*bf2c3715SXin Li // Copyright (C) 2006-2009 Benoit Jacob <[email protected]>
5*bf2c3715SXin Li //
6*bf2c3715SXin Li // This Source Code Form is subject to the terms of the Mozilla
7*bf2c3715SXin Li // Public License v. 2.0. If a copy of the MPL was not distributed
8*bf2c3715SXin Li // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9*bf2c3715SXin Li 
10*bf2c3715SXin Li #ifndef EIGEN_LU_H
11*bf2c3715SXin Li #define EIGEN_LU_H
12*bf2c3715SXin Li 
13*bf2c3715SXin Li namespace Eigen {
14*bf2c3715SXin Li 
15*bf2c3715SXin Li namespace internal {
16*bf2c3715SXin Li template<typename _MatrixType> struct traits<FullPivLU<_MatrixType> >
17*bf2c3715SXin Li  : traits<_MatrixType>
18*bf2c3715SXin Li {
19*bf2c3715SXin Li   typedef MatrixXpr XprKind;
20*bf2c3715SXin Li   typedef SolverStorage StorageKind;
21*bf2c3715SXin Li   typedef int StorageIndex;
22*bf2c3715SXin Li   enum { Flags = 0 };
23*bf2c3715SXin Li };
24*bf2c3715SXin Li 
25*bf2c3715SXin Li } // end namespace internal
26*bf2c3715SXin Li 
27*bf2c3715SXin Li /** \ingroup LU_Module
28*bf2c3715SXin Li   *
29*bf2c3715SXin Li   * \class FullPivLU
30*bf2c3715SXin Li   *
31*bf2c3715SXin Li   * \brief LU decomposition of a matrix with complete pivoting, and related features
32*bf2c3715SXin Li   *
33*bf2c3715SXin Li   * \tparam _MatrixType the type of the matrix of which we are computing the LU decomposition
34*bf2c3715SXin Li   *
35*bf2c3715SXin Li   * This class represents a LU decomposition of any matrix, with complete pivoting: the matrix A is
36*bf2c3715SXin Li   * decomposed as \f$ A = P^{-1} L U Q^{-1} \f$ where L is unit-lower-triangular, U is
37*bf2c3715SXin Li   * upper-triangular, and P and Q are permutation matrices. This is a rank-revealing LU
38*bf2c3715SXin Li   * decomposition. The eigenvalues (diagonal coefficients) of U are sorted in such a way that any
39*bf2c3715SXin Li   * zeros are at the end.
40*bf2c3715SXin Li   *
41*bf2c3715SXin Li   * This decomposition provides the generic approach to solving systems of linear equations, computing
42*bf2c3715SXin Li   * the rank, invertibility, inverse, kernel, and determinant.
43*bf2c3715SXin Li   *
44*bf2c3715SXin Li   * This LU decomposition is very stable and well tested with large matrices. However there are use cases where the SVD
45*bf2c3715SXin Li   * decomposition is inherently more stable and/or flexible. For example, when computing the kernel of a matrix,
46*bf2c3715SXin Li   * working with the SVD allows to select the smallest singular values of the matrix, something that
47*bf2c3715SXin Li   * the LU decomposition doesn't see.
48*bf2c3715SXin Li   *
49*bf2c3715SXin Li   * The data of the LU decomposition can be directly accessed through the methods matrixLU(),
50*bf2c3715SXin Li   * permutationP(), permutationQ().
51*bf2c3715SXin Li   *
52*bf2c3715SXin Li   * As an example, here is how the original matrix can be retrieved:
53*bf2c3715SXin Li   * \include class_FullPivLU.cpp
54*bf2c3715SXin Li   * Output: \verbinclude class_FullPivLU.out
55*bf2c3715SXin Li   *
56*bf2c3715SXin Li   * This class supports the \link InplaceDecomposition inplace decomposition \endlink mechanism.
57*bf2c3715SXin Li   *
58*bf2c3715SXin Li   * \sa MatrixBase::fullPivLu(), MatrixBase::determinant(), MatrixBase::inverse()
59*bf2c3715SXin Li   */
60*bf2c3715SXin Li template<typename _MatrixType> class FullPivLU
61*bf2c3715SXin Li   : public SolverBase<FullPivLU<_MatrixType> >
62*bf2c3715SXin Li {
63*bf2c3715SXin Li   public:
64*bf2c3715SXin Li     typedef _MatrixType MatrixType;
65*bf2c3715SXin Li     typedef SolverBase<FullPivLU> Base;
66*bf2c3715SXin Li     friend class SolverBase<FullPivLU>;
67*bf2c3715SXin Li 
68*bf2c3715SXin Li     EIGEN_GENERIC_PUBLIC_INTERFACE(FullPivLU)
69*bf2c3715SXin Li     enum {
70*bf2c3715SXin Li       MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
71*bf2c3715SXin Li       MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
72*bf2c3715SXin Li     };
73*bf2c3715SXin Li     typedef typename internal::plain_row_type<MatrixType, StorageIndex>::type IntRowVectorType;
74*bf2c3715SXin Li     typedef typename internal::plain_col_type<MatrixType, StorageIndex>::type IntColVectorType;
75*bf2c3715SXin Li     typedef PermutationMatrix<ColsAtCompileTime, MaxColsAtCompileTime> PermutationQType;
76*bf2c3715SXin Li     typedef PermutationMatrix<RowsAtCompileTime, MaxRowsAtCompileTime> PermutationPType;
77*bf2c3715SXin Li     typedef typename MatrixType::PlainObject PlainObject;
78*bf2c3715SXin Li 
79*bf2c3715SXin Li     /**
80*bf2c3715SXin Li       * \brief Default Constructor.
81*bf2c3715SXin Li       *
82*bf2c3715SXin Li       * The default constructor is useful in cases in which the user intends to
83*bf2c3715SXin Li       * perform decompositions via LU::compute(const MatrixType&).
84*bf2c3715SXin Li       */
85*bf2c3715SXin Li     FullPivLU();
86*bf2c3715SXin Li 
87*bf2c3715SXin Li     /** \brief Default Constructor with memory preallocation
88*bf2c3715SXin Li       *
89*bf2c3715SXin Li       * Like the default constructor but with preallocation of the internal data
90*bf2c3715SXin Li       * according to the specified problem \a size.
91*bf2c3715SXin Li       * \sa FullPivLU()
92*bf2c3715SXin Li       */
93*bf2c3715SXin Li     FullPivLU(Index rows, Index cols);
94*bf2c3715SXin Li 
95*bf2c3715SXin Li     /** Constructor.
96*bf2c3715SXin Li       *
97*bf2c3715SXin Li       * \param matrix the matrix of which to compute the LU decomposition.
98*bf2c3715SXin Li       *               It is required to be nonzero.
99*bf2c3715SXin Li       */
100*bf2c3715SXin Li     template<typename InputType>
101*bf2c3715SXin Li     explicit FullPivLU(const EigenBase<InputType>& matrix);
102*bf2c3715SXin Li 
103*bf2c3715SXin Li     /** \brief Constructs a LU factorization from a given matrix
104*bf2c3715SXin Li       *
105*bf2c3715SXin Li       * This overloaded constructor is provided for \link InplaceDecomposition inplace decomposition \endlink when \c MatrixType is a Eigen::Ref.
106*bf2c3715SXin Li       *
107*bf2c3715SXin Li       * \sa FullPivLU(const EigenBase&)
108*bf2c3715SXin Li       */
109*bf2c3715SXin Li     template<typename InputType>
110*bf2c3715SXin Li     explicit FullPivLU(EigenBase<InputType>& matrix);
111*bf2c3715SXin Li 
112*bf2c3715SXin Li     /** Computes the LU decomposition of the given matrix.
113*bf2c3715SXin Li       *
114*bf2c3715SXin Li       * \param matrix the matrix of which to compute the LU decomposition.
115*bf2c3715SXin Li       *               It is required to be nonzero.
116*bf2c3715SXin Li       *
117*bf2c3715SXin Li       * \returns a reference to *this
118*bf2c3715SXin Li       */
119*bf2c3715SXin Li     template<typename InputType>
120*bf2c3715SXin Li     FullPivLU& compute(const EigenBase<InputType>& matrix) {
121*bf2c3715SXin Li       m_lu = matrix.derived();
122*bf2c3715SXin Li       computeInPlace();
123*bf2c3715SXin Li       return *this;
124*bf2c3715SXin Li     }
125*bf2c3715SXin Li 
126*bf2c3715SXin Li     /** \returns the LU decomposition matrix: the upper-triangular part is U, the
127*bf2c3715SXin Li       * unit-lower-triangular part is L (at least for square matrices; in the non-square
128*bf2c3715SXin Li       * case, special care is needed, see the documentation of class FullPivLU).
129*bf2c3715SXin Li       *
130*bf2c3715SXin Li       * \sa matrixL(), matrixU()
131*bf2c3715SXin Li       */
132*bf2c3715SXin Li     inline const MatrixType& matrixLU() const
133*bf2c3715SXin Li     {
134*bf2c3715SXin Li       eigen_assert(m_isInitialized && "LU is not initialized.");
135*bf2c3715SXin Li       return m_lu;
136*bf2c3715SXin Li     }
137*bf2c3715SXin Li 
138*bf2c3715SXin Li     /** \returns the number of nonzero pivots in the LU decomposition.
139*bf2c3715SXin Li       * Here nonzero is meant in the exact sense, not in a fuzzy sense.
140*bf2c3715SXin Li       * So that notion isn't really intrinsically interesting, but it is
141*bf2c3715SXin Li       * still useful when implementing algorithms.
142*bf2c3715SXin Li       *
143*bf2c3715SXin Li       * \sa rank()
144*bf2c3715SXin Li       */
145*bf2c3715SXin Li     inline Index nonzeroPivots() const
146*bf2c3715SXin Li     {
147*bf2c3715SXin Li       eigen_assert(m_isInitialized && "LU is not initialized.");
148*bf2c3715SXin Li       return m_nonzero_pivots;
149*bf2c3715SXin Li     }
150*bf2c3715SXin Li 
151*bf2c3715SXin Li     /** \returns the absolute value of the biggest pivot, i.e. the biggest
152*bf2c3715SXin Li       *          diagonal coefficient of U.
153*bf2c3715SXin Li       */
154*bf2c3715SXin Li     RealScalar maxPivot() const { return m_maxpivot; }
155*bf2c3715SXin Li 
156*bf2c3715SXin Li     /** \returns the permutation matrix P
157*bf2c3715SXin Li       *
158*bf2c3715SXin Li       * \sa permutationQ()
159*bf2c3715SXin Li       */
160*bf2c3715SXin Li     EIGEN_DEVICE_FUNC inline const PermutationPType& permutationP() const
161*bf2c3715SXin Li     {
162*bf2c3715SXin Li       eigen_assert(m_isInitialized && "LU is not initialized.");
163*bf2c3715SXin Li       return m_p;
164*bf2c3715SXin Li     }
165*bf2c3715SXin Li 
166*bf2c3715SXin Li     /** \returns the permutation matrix Q
167*bf2c3715SXin Li       *
168*bf2c3715SXin Li       * \sa permutationP()
169*bf2c3715SXin Li       */
170*bf2c3715SXin Li     inline const PermutationQType& permutationQ() const
171*bf2c3715SXin Li     {
172*bf2c3715SXin Li       eigen_assert(m_isInitialized && "LU is not initialized.");
173*bf2c3715SXin Li       return m_q;
174*bf2c3715SXin Li     }
175*bf2c3715SXin Li 
176*bf2c3715SXin Li     /** \returns the kernel of the matrix, also called its null-space. The columns of the returned matrix
177*bf2c3715SXin Li       * will form a basis of the kernel.
178*bf2c3715SXin Li       *
179*bf2c3715SXin Li       * \note If the kernel has dimension zero, then the returned matrix is a column-vector filled with zeros.
180*bf2c3715SXin Li       *
181*bf2c3715SXin Li       * \note This method has to determine which pivots should be considered nonzero.
182*bf2c3715SXin Li       *       For that, it uses the threshold value that you can control by calling
183*bf2c3715SXin Li       *       setThreshold(const RealScalar&).
184*bf2c3715SXin Li       *
185*bf2c3715SXin Li       * Example: \include FullPivLU_kernel.cpp
186*bf2c3715SXin Li       * Output: \verbinclude FullPivLU_kernel.out
187*bf2c3715SXin Li       *
188*bf2c3715SXin Li       * \sa image()
189*bf2c3715SXin Li       */
190*bf2c3715SXin Li     inline const internal::kernel_retval<FullPivLU> kernel() const
191*bf2c3715SXin Li     {
192*bf2c3715SXin Li       eigen_assert(m_isInitialized && "LU is not initialized.");
193*bf2c3715SXin Li       return internal::kernel_retval<FullPivLU>(*this);
194*bf2c3715SXin Li     }
195*bf2c3715SXin Li 
196*bf2c3715SXin Li     /** \returns the image of the matrix, also called its column-space. The columns of the returned matrix
197*bf2c3715SXin Li       * will form a basis of the image (column-space).
198*bf2c3715SXin Li       *
199*bf2c3715SXin Li       * \param originalMatrix the original matrix, of which *this is the LU decomposition.
200*bf2c3715SXin Li       *                       The reason why it is needed to pass it here, is that this allows
201*bf2c3715SXin Li       *                       a large optimization, as otherwise this method would need to reconstruct it
202*bf2c3715SXin Li       *                       from the LU decomposition.
203*bf2c3715SXin Li       *
204*bf2c3715SXin Li       * \note If the image has dimension zero, then the returned matrix is a column-vector filled with zeros.
205*bf2c3715SXin Li       *
206*bf2c3715SXin Li       * \note This method has to determine which pivots should be considered nonzero.
207*bf2c3715SXin Li       *       For that, it uses the threshold value that you can control by calling
208*bf2c3715SXin Li       *       setThreshold(const RealScalar&).
209*bf2c3715SXin Li       *
210*bf2c3715SXin Li       * Example: \include FullPivLU_image.cpp
211*bf2c3715SXin Li       * Output: \verbinclude FullPivLU_image.out
212*bf2c3715SXin Li       *
213*bf2c3715SXin Li       * \sa kernel()
214*bf2c3715SXin Li       */
215*bf2c3715SXin Li     inline const internal::image_retval<FullPivLU>
216*bf2c3715SXin Li       image(const MatrixType& originalMatrix) const
217*bf2c3715SXin Li     {
218*bf2c3715SXin Li       eigen_assert(m_isInitialized && "LU is not initialized.");
219*bf2c3715SXin Li       return internal::image_retval<FullPivLU>(*this, originalMatrix);
220*bf2c3715SXin Li     }
221*bf2c3715SXin Li 
222*bf2c3715SXin Li     #ifdef EIGEN_PARSED_BY_DOXYGEN
223*bf2c3715SXin Li     /** \return a solution x to the equation Ax=b, where A is the matrix of which
224*bf2c3715SXin Li       * *this is the LU decomposition.
225*bf2c3715SXin Li       *
226*bf2c3715SXin Li       * \param b the right-hand-side of the equation to solve. Can be a vector or a matrix,
227*bf2c3715SXin Li       *          the only requirement in order for the equation to make sense is that
228*bf2c3715SXin Li       *          b.rows()==A.rows(), where A is the matrix of which *this is the LU decomposition.
229*bf2c3715SXin Li       *
230*bf2c3715SXin Li       * \returns a solution.
231*bf2c3715SXin Li       *
232*bf2c3715SXin Li       * \note_about_checking_solutions
233*bf2c3715SXin Li       *
234*bf2c3715SXin Li       * \note_about_arbitrary_choice_of_solution
235*bf2c3715SXin Li       * \note_about_using_kernel_to_study_multiple_solutions
236*bf2c3715SXin Li       *
237*bf2c3715SXin Li       * Example: \include FullPivLU_solve.cpp
238*bf2c3715SXin Li       * Output: \verbinclude FullPivLU_solve.out
239*bf2c3715SXin Li       *
240*bf2c3715SXin Li       * \sa TriangularView::solve(), kernel(), inverse()
241*bf2c3715SXin Li       */
242*bf2c3715SXin Li     template<typename Rhs>
243*bf2c3715SXin Li     inline const Solve<FullPivLU, Rhs>
244*bf2c3715SXin Li     solve(const MatrixBase<Rhs>& b) const;
245*bf2c3715SXin Li     #endif
246*bf2c3715SXin Li 
247*bf2c3715SXin Li     /** \returns an estimate of the reciprocal condition number of the matrix of which \c *this is
248*bf2c3715SXin Li         the LU decomposition.
249*bf2c3715SXin Li       */
250*bf2c3715SXin Li     inline RealScalar rcond() const
251*bf2c3715SXin Li     {
252*bf2c3715SXin Li       eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
253*bf2c3715SXin Li       return internal::rcond_estimate_helper(m_l1_norm, *this);
254*bf2c3715SXin Li     }
255*bf2c3715SXin Li 
256*bf2c3715SXin Li     /** \returns the determinant of the matrix of which
257*bf2c3715SXin Li       * *this is the LU decomposition. It has only linear complexity
258*bf2c3715SXin Li       * (that is, O(n) where n is the dimension of the square matrix)
259*bf2c3715SXin Li       * as the LU decomposition has already been computed.
260*bf2c3715SXin Li       *
261*bf2c3715SXin Li       * \note This is only for square matrices.
262*bf2c3715SXin Li       *
263*bf2c3715SXin Li       * \note For fixed-size matrices of size up to 4, MatrixBase::determinant() offers
264*bf2c3715SXin Li       *       optimized paths.
265*bf2c3715SXin Li       *
266*bf2c3715SXin Li       * \warning a determinant can be very big or small, so for matrices
267*bf2c3715SXin Li       * of large enough dimension, there is a risk of overflow/underflow.
268*bf2c3715SXin Li       *
269*bf2c3715SXin Li       * \sa MatrixBase::determinant()
270*bf2c3715SXin Li       */
271*bf2c3715SXin Li     typename internal::traits<MatrixType>::Scalar determinant() const;
272*bf2c3715SXin Li 
273*bf2c3715SXin Li     /** Allows to prescribe a threshold to be used by certain methods, such as rank(),
274*bf2c3715SXin Li       * who need to determine when pivots are to be considered nonzero. This is not used for the
275*bf2c3715SXin Li       * LU decomposition itself.
276*bf2c3715SXin Li       *
277*bf2c3715SXin Li       * When it needs to get the threshold value, Eigen calls threshold(). By default, this
278*bf2c3715SXin Li       * uses a formula to automatically determine a reasonable threshold.
279*bf2c3715SXin Li       * Once you have called the present method setThreshold(const RealScalar&),
280*bf2c3715SXin Li       * your value is used instead.
281*bf2c3715SXin Li       *
282*bf2c3715SXin Li       * \param threshold The new value to use as the threshold.
283*bf2c3715SXin Li       *
284*bf2c3715SXin Li       * A pivot will be considered nonzero if its absolute value is strictly greater than
285*bf2c3715SXin Li       *  \f$ \vert pivot \vert \leqslant threshold \times \vert maxpivot \vert \f$
286*bf2c3715SXin Li       * where maxpivot is the biggest pivot.
287*bf2c3715SXin Li       *
288*bf2c3715SXin Li       * If you want to come back to the default behavior, call setThreshold(Default_t)
289*bf2c3715SXin Li       */
290*bf2c3715SXin Li     FullPivLU& setThreshold(const RealScalar& threshold)
291*bf2c3715SXin Li     {
292*bf2c3715SXin Li       m_usePrescribedThreshold = true;
293*bf2c3715SXin Li       m_prescribedThreshold = threshold;
294*bf2c3715SXin Li       return *this;
295*bf2c3715SXin Li     }
296*bf2c3715SXin Li 
297*bf2c3715SXin Li     /** Allows to come back to the default behavior, letting Eigen use its default formula for
298*bf2c3715SXin Li       * determining the threshold.
299*bf2c3715SXin Li       *
300*bf2c3715SXin Li       * You should pass the special object Eigen::Default as parameter here.
301*bf2c3715SXin Li       * \code lu.setThreshold(Eigen::Default); \endcode
302*bf2c3715SXin Li       *
303*bf2c3715SXin Li       * See the documentation of setThreshold(const RealScalar&).
304*bf2c3715SXin Li       */
305*bf2c3715SXin Li     FullPivLU& setThreshold(Default_t)
306*bf2c3715SXin Li     {
307*bf2c3715SXin Li       m_usePrescribedThreshold = false;
308*bf2c3715SXin Li       return *this;
309*bf2c3715SXin Li     }
310*bf2c3715SXin Li 
311*bf2c3715SXin Li     /** Returns the threshold that will be used by certain methods such as rank().
312*bf2c3715SXin Li       *
313*bf2c3715SXin Li       * See the documentation of setThreshold(const RealScalar&).
314*bf2c3715SXin Li       */
315*bf2c3715SXin Li     RealScalar threshold() const
316*bf2c3715SXin Li     {
317*bf2c3715SXin Li       eigen_assert(m_isInitialized || m_usePrescribedThreshold);
318*bf2c3715SXin Li       return m_usePrescribedThreshold ? m_prescribedThreshold
319*bf2c3715SXin Li       // this formula comes from experimenting (see "LU precision tuning" thread on the list)
320*bf2c3715SXin Li       // and turns out to be identical to Higham's formula used already in LDLt.
321*bf2c3715SXin Li           : NumTraits<Scalar>::epsilon() * RealScalar(m_lu.diagonalSize());
322*bf2c3715SXin Li     }
323*bf2c3715SXin Li 
324*bf2c3715SXin Li     /** \returns the rank of the matrix of which *this is the LU decomposition.
325*bf2c3715SXin Li       *
326*bf2c3715SXin Li       * \note This method has to determine which pivots should be considered nonzero.
327*bf2c3715SXin Li       *       For that, it uses the threshold value that you can control by calling
328*bf2c3715SXin Li       *       setThreshold(const RealScalar&).
329*bf2c3715SXin Li       */
330*bf2c3715SXin Li     inline Index rank() const
331*bf2c3715SXin Li     {
332*bf2c3715SXin Li       using std::abs;
333*bf2c3715SXin Li       eigen_assert(m_isInitialized && "LU is not initialized.");
334*bf2c3715SXin Li       RealScalar premultiplied_threshold = abs(m_maxpivot) * threshold();
335*bf2c3715SXin Li       Index result = 0;
336*bf2c3715SXin Li       for(Index i = 0; i < m_nonzero_pivots; ++i)
337*bf2c3715SXin Li         result += (abs(m_lu.coeff(i,i)) > premultiplied_threshold);
338*bf2c3715SXin Li       return result;
339*bf2c3715SXin Li     }
340*bf2c3715SXin Li 
341*bf2c3715SXin Li     /** \returns the dimension of the kernel of the matrix of which *this is the LU decomposition.
342*bf2c3715SXin Li       *
343*bf2c3715SXin Li       * \note This method has to determine which pivots should be considered nonzero.
344*bf2c3715SXin Li       *       For that, it uses the threshold value that you can control by calling
345*bf2c3715SXin Li       *       setThreshold(const RealScalar&).
346*bf2c3715SXin Li       */
347*bf2c3715SXin Li     inline Index dimensionOfKernel() const
348*bf2c3715SXin Li     {
349*bf2c3715SXin Li       eigen_assert(m_isInitialized && "LU is not initialized.");
350*bf2c3715SXin Li       return cols() - rank();
351*bf2c3715SXin Li     }
352*bf2c3715SXin Li 
353*bf2c3715SXin Li     /** \returns true if the matrix of which *this is the LU decomposition represents an injective
354*bf2c3715SXin Li       *          linear map, i.e. has trivial kernel; false otherwise.
355*bf2c3715SXin Li       *
356*bf2c3715SXin Li       * \note This method has to determine which pivots should be considered nonzero.
357*bf2c3715SXin Li       *       For that, it uses the threshold value that you can control by calling
358*bf2c3715SXin Li       *       setThreshold(const RealScalar&).
359*bf2c3715SXin Li       */
360*bf2c3715SXin Li     inline bool isInjective() const
361*bf2c3715SXin Li     {
362*bf2c3715SXin Li       eigen_assert(m_isInitialized && "LU is not initialized.");
363*bf2c3715SXin Li       return rank() == cols();
364*bf2c3715SXin Li     }
365*bf2c3715SXin Li 
366*bf2c3715SXin Li     /** \returns true if the matrix of which *this is the LU decomposition represents a surjective
367*bf2c3715SXin Li       *          linear map; false otherwise.
368*bf2c3715SXin Li       *
369*bf2c3715SXin Li       * \note This method has to determine which pivots should be considered nonzero.
370*bf2c3715SXin Li       *       For that, it uses the threshold value that you can control by calling
371*bf2c3715SXin Li       *       setThreshold(const RealScalar&).
372*bf2c3715SXin Li       */
373*bf2c3715SXin Li     inline bool isSurjective() const
374*bf2c3715SXin Li     {
375*bf2c3715SXin Li       eigen_assert(m_isInitialized && "LU is not initialized.");
376*bf2c3715SXin Li       return rank() == rows();
377*bf2c3715SXin Li     }
378*bf2c3715SXin Li 
379*bf2c3715SXin Li     /** \returns true if the matrix of which *this is the LU decomposition is invertible.
380*bf2c3715SXin Li       *
381*bf2c3715SXin Li       * \note This method has to determine which pivots should be considered nonzero.
382*bf2c3715SXin Li       *       For that, it uses the threshold value that you can control by calling
383*bf2c3715SXin Li       *       setThreshold(const RealScalar&).
384*bf2c3715SXin Li       */
385*bf2c3715SXin Li     inline bool isInvertible() const
386*bf2c3715SXin Li     {
387*bf2c3715SXin Li       eigen_assert(m_isInitialized && "LU is not initialized.");
388*bf2c3715SXin Li       return isInjective() && (m_lu.rows() == m_lu.cols());
389*bf2c3715SXin Li     }
390*bf2c3715SXin Li 
391*bf2c3715SXin Li     /** \returns the inverse of the matrix of which *this is the LU decomposition.
392*bf2c3715SXin Li       *
393*bf2c3715SXin Li       * \note If this matrix is not invertible, the returned matrix has undefined coefficients.
394*bf2c3715SXin Li       *       Use isInvertible() to first determine whether this matrix is invertible.
395*bf2c3715SXin Li       *
396*bf2c3715SXin Li       * \sa MatrixBase::inverse()
397*bf2c3715SXin Li       */
398*bf2c3715SXin Li     inline const Inverse<FullPivLU> inverse() const
399*bf2c3715SXin Li     {
400*bf2c3715SXin Li       eigen_assert(m_isInitialized && "LU is not initialized.");
401*bf2c3715SXin Li       eigen_assert(m_lu.rows() == m_lu.cols() && "You can't take the inverse of a non-square matrix!");
402*bf2c3715SXin Li       return Inverse<FullPivLU>(*this);
403*bf2c3715SXin Li     }
404*bf2c3715SXin Li 
405*bf2c3715SXin Li     MatrixType reconstructedMatrix() const;
406*bf2c3715SXin Li 
407*bf2c3715SXin Li     EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
408*bf2c3715SXin Li     inline Index rows() const EIGEN_NOEXCEPT { return m_lu.rows(); }
409*bf2c3715SXin Li     EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
410*bf2c3715SXin Li     inline Index cols() const EIGEN_NOEXCEPT { return m_lu.cols(); }
411*bf2c3715SXin Li 
412*bf2c3715SXin Li     #ifndef EIGEN_PARSED_BY_DOXYGEN
413*bf2c3715SXin Li     template<typename RhsType, typename DstType>
414*bf2c3715SXin Li     void _solve_impl(const RhsType &rhs, DstType &dst) const;
415*bf2c3715SXin Li 
416*bf2c3715SXin Li     template<bool Conjugate, typename RhsType, typename DstType>
417*bf2c3715SXin Li     void _solve_impl_transposed(const RhsType &rhs, DstType &dst) const;
418*bf2c3715SXin Li     #endif
419*bf2c3715SXin Li 
420*bf2c3715SXin Li   protected:
421*bf2c3715SXin Li 
422*bf2c3715SXin Li     static void check_template_parameters()
423*bf2c3715SXin Li     {
424*bf2c3715SXin Li       EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
425*bf2c3715SXin Li     }
426*bf2c3715SXin Li 
427*bf2c3715SXin Li     void computeInPlace();
428*bf2c3715SXin Li 
429*bf2c3715SXin Li     MatrixType m_lu;
430*bf2c3715SXin Li     PermutationPType m_p;
431*bf2c3715SXin Li     PermutationQType m_q;
432*bf2c3715SXin Li     IntColVectorType m_rowsTranspositions;
433*bf2c3715SXin Li     IntRowVectorType m_colsTranspositions;
434*bf2c3715SXin Li     Index m_nonzero_pivots;
435*bf2c3715SXin Li     RealScalar m_l1_norm;
436*bf2c3715SXin Li     RealScalar m_maxpivot, m_prescribedThreshold;
437*bf2c3715SXin Li     signed char m_det_pq;
438*bf2c3715SXin Li     bool m_isInitialized, m_usePrescribedThreshold;
439*bf2c3715SXin Li };
440*bf2c3715SXin Li 
441*bf2c3715SXin Li template<typename MatrixType>
442*bf2c3715SXin Li FullPivLU<MatrixType>::FullPivLU()
443*bf2c3715SXin Li   : m_isInitialized(false), m_usePrescribedThreshold(false)
444*bf2c3715SXin Li {
445*bf2c3715SXin Li }
446*bf2c3715SXin Li 
447*bf2c3715SXin Li template<typename MatrixType>
448*bf2c3715SXin Li FullPivLU<MatrixType>::FullPivLU(Index rows, Index cols)
449*bf2c3715SXin Li   : m_lu(rows, cols),
450*bf2c3715SXin Li     m_p(rows),
451*bf2c3715SXin Li     m_q(cols),
452*bf2c3715SXin Li     m_rowsTranspositions(rows),
453*bf2c3715SXin Li     m_colsTranspositions(cols),
454*bf2c3715SXin Li     m_isInitialized(false),
455*bf2c3715SXin Li     m_usePrescribedThreshold(false)
456*bf2c3715SXin Li {
457*bf2c3715SXin Li }
458*bf2c3715SXin Li 
459*bf2c3715SXin Li template<typename MatrixType>
460*bf2c3715SXin Li template<typename InputType>
461*bf2c3715SXin Li FullPivLU<MatrixType>::FullPivLU(const EigenBase<InputType>& matrix)
462*bf2c3715SXin Li   : m_lu(matrix.rows(), matrix.cols()),
463*bf2c3715SXin Li     m_p(matrix.rows()),
464*bf2c3715SXin Li     m_q(matrix.cols()),
465*bf2c3715SXin Li     m_rowsTranspositions(matrix.rows()),
466*bf2c3715SXin Li     m_colsTranspositions(matrix.cols()),
467*bf2c3715SXin Li     m_isInitialized(false),
468*bf2c3715SXin Li     m_usePrescribedThreshold(false)
469*bf2c3715SXin Li {
470*bf2c3715SXin Li   compute(matrix.derived());
471*bf2c3715SXin Li }
472*bf2c3715SXin Li 
473*bf2c3715SXin Li template<typename MatrixType>
474*bf2c3715SXin Li template<typename InputType>
475*bf2c3715SXin Li FullPivLU<MatrixType>::FullPivLU(EigenBase<InputType>& matrix)
476*bf2c3715SXin Li   : m_lu(matrix.derived()),
477*bf2c3715SXin Li     m_p(matrix.rows()),
478*bf2c3715SXin Li     m_q(matrix.cols()),
479*bf2c3715SXin Li     m_rowsTranspositions(matrix.rows()),
480*bf2c3715SXin Li     m_colsTranspositions(matrix.cols()),
481*bf2c3715SXin Li     m_isInitialized(false),
482*bf2c3715SXin Li     m_usePrescribedThreshold(false)
483*bf2c3715SXin Li {
484*bf2c3715SXin Li   computeInPlace();
485*bf2c3715SXin Li }
486*bf2c3715SXin Li 
487*bf2c3715SXin Li template<typename MatrixType>
488*bf2c3715SXin Li void FullPivLU<MatrixType>::computeInPlace()
489*bf2c3715SXin Li {
490*bf2c3715SXin Li   check_template_parameters();
491*bf2c3715SXin Li 
492*bf2c3715SXin Li   // the permutations are stored as int indices, so just to be sure:
493*bf2c3715SXin Li   eigen_assert(m_lu.rows()<=NumTraits<int>::highest() && m_lu.cols()<=NumTraits<int>::highest());
494*bf2c3715SXin Li 
495*bf2c3715SXin Li   m_l1_norm = m_lu.cwiseAbs().colwise().sum().maxCoeff();
496*bf2c3715SXin Li 
497*bf2c3715SXin Li   const Index size = m_lu.diagonalSize();
498*bf2c3715SXin Li   const Index rows = m_lu.rows();
499*bf2c3715SXin Li   const Index cols = m_lu.cols();
500*bf2c3715SXin Li 
501*bf2c3715SXin Li   // will store the transpositions, before we accumulate them at the end.
502*bf2c3715SXin Li   // can't accumulate on-the-fly because that will be done in reverse order for the rows.
503*bf2c3715SXin Li   m_rowsTranspositions.resize(m_lu.rows());
504*bf2c3715SXin Li   m_colsTranspositions.resize(m_lu.cols());
505*bf2c3715SXin Li   Index number_of_transpositions = 0; // number of NONTRIVIAL transpositions, i.e. m_rowsTranspositions[i]!=i
506*bf2c3715SXin Li 
507*bf2c3715SXin Li   m_nonzero_pivots = size; // the generic case is that in which all pivots are nonzero (invertible case)
508*bf2c3715SXin Li   m_maxpivot = RealScalar(0);
509*bf2c3715SXin Li 
510*bf2c3715SXin Li   for(Index k = 0; k < size; ++k)
511*bf2c3715SXin Li   {
512*bf2c3715SXin Li     // First, we need to find the pivot.
513*bf2c3715SXin Li 
514*bf2c3715SXin Li     // biggest coefficient in the remaining bottom-right corner (starting at row k, col k)
515*bf2c3715SXin Li     Index row_of_biggest_in_corner, col_of_biggest_in_corner;
516*bf2c3715SXin Li     typedef internal::scalar_score_coeff_op<Scalar> Scoring;
517*bf2c3715SXin Li     typedef typename Scoring::result_type Score;
518*bf2c3715SXin Li     Score biggest_in_corner;
519*bf2c3715SXin Li     biggest_in_corner = m_lu.bottomRightCorner(rows-k, cols-k)
520*bf2c3715SXin Li                         .unaryExpr(Scoring())
521*bf2c3715SXin Li                         .maxCoeff(&row_of_biggest_in_corner, &col_of_biggest_in_corner);
522*bf2c3715SXin Li     row_of_biggest_in_corner += k; // correct the values! since they were computed in the corner,
523*bf2c3715SXin Li     col_of_biggest_in_corner += k; // need to add k to them.
524*bf2c3715SXin Li 
525*bf2c3715SXin Li     if(biggest_in_corner==Score(0))
526*bf2c3715SXin Li     {
527*bf2c3715SXin Li       // before exiting, make sure to initialize the still uninitialized transpositions
528*bf2c3715SXin Li       // in a sane state without destroying what we already have.
529*bf2c3715SXin Li       m_nonzero_pivots = k;
530*bf2c3715SXin Li       for(Index i = k; i < size; ++i)
531*bf2c3715SXin Li       {
532*bf2c3715SXin Li         m_rowsTranspositions.coeffRef(i) = internal::convert_index<StorageIndex>(i);
533*bf2c3715SXin Li         m_colsTranspositions.coeffRef(i) = internal::convert_index<StorageIndex>(i);
534*bf2c3715SXin Li       }
535*bf2c3715SXin Li       break;
536*bf2c3715SXin Li     }
537*bf2c3715SXin Li 
538*bf2c3715SXin Li     RealScalar abs_pivot = internal::abs_knowing_score<Scalar>()(m_lu(row_of_biggest_in_corner, col_of_biggest_in_corner), biggest_in_corner);
539*bf2c3715SXin Li     if(abs_pivot > m_maxpivot) m_maxpivot = abs_pivot;
540*bf2c3715SXin Li 
541*bf2c3715SXin Li     // Now that we've found the pivot, we need to apply the row/col swaps to
542*bf2c3715SXin Li     // bring it to the location (k,k).
543*bf2c3715SXin Li 
544*bf2c3715SXin Li     m_rowsTranspositions.coeffRef(k) = internal::convert_index<StorageIndex>(row_of_biggest_in_corner);
545*bf2c3715SXin Li     m_colsTranspositions.coeffRef(k) = internal::convert_index<StorageIndex>(col_of_biggest_in_corner);
546*bf2c3715SXin Li     if(k != row_of_biggest_in_corner) {
547*bf2c3715SXin Li       m_lu.row(k).swap(m_lu.row(row_of_biggest_in_corner));
548*bf2c3715SXin Li       ++number_of_transpositions;
549*bf2c3715SXin Li     }
550*bf2c3715SXin Li     if(k != col_of_biggest_in_corner) {
551*bf2c3715SXin Li       m_lu.col(k).swap(m_lu.col(col_of_biggest_in_corner));
552*bf2c3715SXin Li       ++number_of_transpositions;
553*bf2c3715SXin Li     }
554*bf2c3715SXin Li 
555*bf2c3715SXin Li     // Now that the pivot is at the right location, we update the remaining
556*bf2c3715SXin Li     // bottom-right corner by Gaussian elimination.
557*bf2c3715SXin Li 
558*bf2c3715SXin Li     if(k<rows-1)
559*bf2c3715SXin Li       m_lu.col(k).tail(rows-k-1) /= m_lu.coeff(k,k);
560*bf2c3715SXin Li     if(k<size-1)
561*bf2c3715SXin Li       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);
562*bf2c3715SXin Li   }
563*bf2c3715SXin Li 
564*bf2c3715SXin Li   // the main loop is over, we still have to accumulate the transpositions to find the
565*bf2c3715SXin Li   // permutations P and Q
566*bf2c3715SXin Li 
567*bf2c3715SXin Li   m_p.setIdentity(rows);
568*bf2c3715SXin Li   for(Index k = size-1; k >= 0; --k)
569*bf2c3715SXin Li     m_p.applyTranspositionOnTheRight(k, m_rowsTranspositions.coeff(k));
570*bf2c3715SXin Li 
571*bf2c3715SXin Li   m_q.setIdentity(cols);
572*bf2c3715SXin Li   for(Index k = 0; k < size; ++k)
573*bf2c3715SXin Li     m_q.applyTranspositionOnTheRight(k, m_colsTranspositions.coeff(k));
574*bf2c3715SXin Li 
575*bf2c3715SXin Li   m_det_pq = (number_of_transpositions%2) ? -1 : 1;
576*bf2c3715SXin Li 
577*bf2c3715SXin Li   m_isInitialized = true;
578*bf2c3715SXin Li }
579*bf2c3715SXin Li 
580*bf2c3715SXin Li template<typename MatrixType>
581*bf2c3715SXin Li typename internal::traits<MatrixType>::Scalar FullPivLU<MatrixType>::determinant() const
582*bf2c3715SXin Li {
583*bf2c3715SXin Li   eigen_assert(m_isInitialized && "LU is not initialized.");
584*bf2c3715SXin Li   eigen_assert(m_lu.rows() == m_lu.cols() && "You can't take the determinant of a non-square matrix!");
585*bf2c3715SXin Li   return Scalar(m_det_pq) * Scalar(m_lu.diagonal().prod());
586*bf2c3715SXin Li }
587*bf2c3715SXin Li 
588*bf2c3715SXin Li /** \returns the matrix represented by the decomposition,
589*bf2c3715SXin Li  * i.e., it returns the product: \f$ P^{-1} L U Q^{-1} \f$.
590*bf2c3715SXin Li  * This function is provided for debug purposes. */
591*bf2c3715SXin Li template<typename MatrixType>
592*bf2c3715SXin Li MatrixType FullPivLU<MatrixType>::reconstructedMatrix() const
593*bf2c3715SXin Li {
594*bf2c3715SXin Li   eigen_assert(m_isInitialized && "LU is not initialized.");
595*bf2c3715SXin Li   const Index smalldim = (std::min)(m_lu.rows(), m_lu.cols());
596*bf2c3715SXin Li   // LU
597*bf2c3715SXin Li   MatrixType res(m_lu.rows(),m_lu.cols());
598*bf2c3715SXin Li   // FIXME the .toDenseMatrix() should not be needed...
599*bf2c3715SXin Li   res = m_lu.leftCols(smalldim)
600*bf2c3715SXin Li             .template triangularView<UnitLower>().toDenseMatrix()
601*bf2c3715SXin Li       * m_lu.topRows(smalldim)
602*bf2c3715SXin Li             .template triangularView<Upper>().toDenseMatrix();
603*bf2c3715SXin Li 
604*bf2c3715SXin Li   // P^{-1}(LU)
605*bf2c3715SXin Li   res = m_p.inverse() * res;
606*bf2c3715SXin Li 
607*bf2c3715SXin Li   // (P^{-1}LU)Q^{-1}
608*bf2c3715SXin Li   res = res * m_q.inverse();
609*bf2c3715SXin Li 
610*bf2c3715SXin Li   return res;
611*bf2c3715SXin Li }
612*bf2c3715SXin Li 
613*bf2c3715SXin Li /********* Implementation of kernel() **************************************************/
614*bf2c3715SXin Li 
615*bf2c3715SXin Li namespace internal {
616*bf2c3715SXin Li template<typename _MatrixType>
617*bf2c3715SXin Li struct kernel_retval<FullPivLU<_MatrixType> >
618*bf2c3715SXin Li   : kernel_retval_base<FullPivLU<_MatrixType> >
619*bf2c3715SXin Li {
620*bf2c3715SXin Li   EIGEN_MAKE_KERNEL_HELPERS(FullPivLU<_MatrixType>)
621*bf2c3715SXin Li 
622*bf2c3715SXin Li   enum { MaxSmallDimAtCompileTime = EIGEN_SIZE_MIN_PREFER_FIXED(
623*bf2c3715SXin Li             MatrixType::MaxColsAtCompileTime,
624*bf2c3715SXin Li             MatrixType::MaxRowsAtCompileTime)
625*bf2c3715SXin Li   };
626*bf2c3715SXin Li 
627*bf2c3715SXin Li   template<typename Dest> void evalTo(Dest& dst) const
628*bf2c3715SXin Li   {
629*bf2c3715SXin Li     using std::abs;
630*bf2c3715SXin Li     const Index cols = dec().matrixLU().cols(), dimker = cols - rank();
631*bf2c3715SXin Li     if(dimker == 0)
632*bf2c3715SXin Li     {
633*bf2c3715SXin Li       // The Kernel is just {0}, so it doesn't have a basis properly speaking, but let's
634*bf2c3715SXin Li       // avoid crashing/asserting as that depends on floating point calculations. Let's
635*bf2c3715SXin Li       // just return a single column vector filled with zeros.
636*bf2c3715SXin Li       dst.setZero();
637*bf2c3715SXin Li       return;
638*bf2c3715SXin Li     }
639*bf2c3715SXin Li 
640*bf2c3715SXin Li     /* Let us use the following lemma:
641*bf2c3715SXin Li       *
642*bf2c3715SXin Li       * Lemma: If the matrix A has the LU decomposition PAQ = LU,
643*bf2c3715SXin Li       * then Ker A = Q(Ker U).
644*bf2c3715SXin Li       *
645*bf2c3715SXin Li       * Proof: trivial: just keep in mind that P, Q, L are invertible.
646*bf2c3715SXin Li       */
647*bf2c3715SXin Li 
648*bf2c3715SXin Li     /* Thus, all we need to do is to compute Ker U, and then apply Q.
649*bf2c3715SXin Li       *
650*bf2c3715SXin Li       * U is upper triangular, with eigenvalues sorted so that any zeros appear at the end.
651*bf2c3715SXin Li       * Thus, the diagonal of U ends with exactly
652*bf2c3715SXin Li       * dimKer zero's. Let us use that to construct dimKer linearly
653*bf2c3715SXin Li       * independent vectors in Ker U.
654*bf2c3715SXin Li       */
655*bf2c3715SXin Li 
656*bf2c3715SXin Li     Matrix<Index, Dynamic, 1, 0, MaxSmallDimAtCompileTime, 1> pivots(rank());
657*bf2c3715SXin Li     RealScalar premultiplied_threshold = dec().maxPivot() * dec().threshold();
658*bf2c3715SXin Li     Index p = 0;
659*bf2c3715SXin Li     for(Index i = 0; i < dec().nonzeroPivots(); ++i)
660*bf2c3715SXin Li       if(abs(dec().matrixLU().coeff(i,i)) > premultiplied_threshold)
661*bf2c3715SXin Li         pivots.coeffRef(p++) = i;
662*bf2c3715SXin Li     eigen_internal_assert(p == rank());
663*bf2c3715SXin Li 
664*bf2c3715SXin Li     // we construct a temporaty trapezoid matrix m, by taking the U matrix and
665*bf2c3715SXin Li     // permuting the rows and cols to bring the nonnegligible pivots to the top of
666*bf2c3715SXin Li     // the main diagonal. We need that to be able to apply our triangular solvers.
667*bf2c3715SXin Li     // FIXME when we get triangularView-for-rectangular-matrices, this can be simplified
668*bf2c3715SXin Li     Matrix<typename MatrixType::Scalar, Dynamic, Dynamic, MatrixType::Options,
669*bf2c3715SXin Li            MaxSmallDimAtCompileTime, MatrixType::MaxColsAtCompileTime>
670*bf2c3715SXin Li       m(dec().matrixLU().block(0, 0, rank(), cols));
671*bf2c3715SXin Li     for(Index i = 0; i < rank(); ++i)
672*bf2c3715SXin Li     {
673*bf2c3715SXin Li       if(i) m.row(i).head(i).setZero();
674*bf2c3715SXin Li       m.row(i).tail(cols-i) = dec().matrixLU().row(pivots.coeff(i)).tail(cols-i);
675*bf2c3715SXin Li     }
676*bf2c3715SXin Li     m.block(0, 0, rank(), rank());
677*bf2c3715SXin Li     m.block(0, 0, rank(), rank()).template triangularView<StrictlyLower>().setZero();
678*bf2c3715SXin Li     for(Index i = 0; i < rank(); ++i)
679*bf2c3715SXin Li       m.col(i).swap(m.col(pivots.coeff(i)));
680*bf2c3715SXin Li 
681*bf2c3715SXin Li     // ok, we have our trapezoid matrix, we can apply the triangular solver.
682*bf2c3715SXin Li     // notice that the math behind this suggests that we should apply this to the
683*bf2c3715SXin Li     // negative of the RHS, but for performance we just put the negative sign elsewhere, see below.
684*bf2c3715SXin Li     m.topLeftCorner(rank(), rank())
685*bf2c3715SXin Li      .template triangularView<Upper>().solveInPlace(
686*bf2c3715SXin Li         m.topRightCorner(rank(), dimker)
687*bf2c3715SXin Li       );
688*bf2c3715SXin Li 
689*bf2c3715SXin Li     // now we must undo the column permutation that we had applied!
690*bf2c3715SXin Li     for(Index i = rank()-1; i >= 0; --i)
691*bf2c3715SXin Li       m.col(i).swap(m.col(pivots.coeff(i)));
692*bf2c3715SXin Li 
693*bf2c3715SXin Li     // see the negative sign in the next line, that's what we were talking about above.
694*bf2c3715SXin Li     for(Index i = 0; i < rank(); ++i) dst.row(dec().permutationQ().indices().coeff(i)) = -m.row(i).tail(dimker);
695*bf2c3715SXin Li     for(Index i = rank(); i < cols; ++i) dst.row(dec().permutationQ().indices().coeff(i)).setZero();
696*bf2c3715SXin Li     for(Index k = 0; k < dimker; ++k) dst.coeffRef(dec().permutationQ().indices().coeff(rank()+k), k) = Scalar(1);
697*bf2c3715SXin Li   }
698*bf2c3715SXin Li };
699*bf2c3715SXin Li 
700*bf2c3715SXin Li /***** Implementation of image() *****************************************************/
701*bf2c3715SXin Li 
702*bf2c3715SXin Li template<typename _MatrixType>
703*bf2c3715SXin Li struct image_retval<FullPivLU<_MatrixType> >
704*bf2c3715SXin Li   : image_retval_base<FullPivLU<_MatrixType> >
705*bf2c3715SXin Li {
706*bf2c3715SXin Li   EIGEN_MAKE_IMAGE_HELPERS(FullPivLU<_MatrixType>)
707*bf2c3715SXin Li 
708*bf2c3715SXin Li   enum { MaxSmallDimAtCompileTime = EIGEN_SIZE_MIN_PREFER_FIXED(
709*bf2c3715SXin Li             MatrixType::MaxColsAtCompileTime,
710*bf2c3715SXin Li             MatrixType::MaxRowsAtCompileTime)
711*bf2c3715SXin Li   };
712*bf2c3715SXin Li 
713*bf2c3715SXin Li   template<typename Dest> void evalTo(Dest& dst) const
714*bf2c3715SXin Li   {
715*bf2c3715SXin Li     using std::abs;
716*bf2c3715SXin Li     if(rank() == 0)
717*bf2c3715SXin Li     {
718*bf2c3715SXin Li       // The Image is just {0}, so it doesn't have a basis properly speaking, but let's
719*bf2c3715SXin Li       // avoid crashing/asserting as that depends on floating point calculations. Let's
720*bf2c3715SXin Li       // just return a single column vector filled with zeros.
721*bf2c3715SXin Li       dst.setZero();
722*bf2c3715SXin Li       return;
723*bf2c3715SXin Li     }
724*bf2c3715SXin Li 
725*bf2c3715SXin Li     Matrix<Index, Dynamic, 1, 0, MaxSmallDimAtCompileTime, 1> pivots(rank());
726*bf2c3715SXin Li     RealScalar premultiplied_threshold = dec().maxPivot() * dec().threshold();
727*bf2c3715SXin Li     Index p = 0;
728*bf2c3715SXin Li     for(Index i = 0; i < dec().nonzeroPivots(); ++i)
729*bf2c3715SXin Li       if(abs(dec().matrixLU().coeff(i,i)) > premultiplied_threshold)
730*bf2c3715SXin Li         pivots.coeffRef(p++) = i;
731*bf2c3715SXin Li     eigen_internal_assert(p == rank());
732*bf2c3715SXin Li 
733*bf2c3715SXin Li     for(Index i = 0; i < rank(); ++i)
734*bf2c3715SXin Li       dst.col(i) = originalMatrix().col(dec().permutationQ().indices().coeff(pivots.coeff(i)));
735*bf2c3715SXin Li   }
736*bf2c3715SXin Li };
737*bf2c3715SXin Li 
738*bf2c3715SXin Li /***** Implementation of solve() *****************************************************/
739*bf2c3715SXin Li 
740*bf2c3715SXin Li } // end namespace internal
741*bf2c3715SXin Li 
742*bf2c3715SXin Li #ifndef EIGEN_PARSED_BY_DOXYGEN
743*bf2c3715SXin Li template<typename _MatrixType>
744*bf2c3715SXin Li template<typename RhsType, typename DstType>
745*bf2c3715SXin Li void FullPivLU<_MatrixType>::_solve_impl(const RhsType &rhs, DstType &dst) const
746*bf2c3715SXin Li {
747*bf2c3715SXin Li   /* The decomposition PAQ = LU can be rewritten as A = P^{-1} L U Q^{-1}.
748*bf2c3715SXin Li   * So we proceed as follows:
749*bf2c3715SXin Li   * Step 1: compute c = P * rhs.
750*bf2c3715SXin Li   * Step 2: replace c by the solution x to Lx = c. Exists because L is invertible.
751*bf2c3715SXin Li   * Step 3: replace c by the solution x to Ux = c. May or may not exist.
752*bf2c3715SXin Li   * Step 4: result = Q * c;
753*bf2c3715SXin Li   */
754*bf2c3715SXin Li 
755*bf2c3715SXin Li   const Index rows = this->rows(),
756*bf2c3715SXin Li               cols = this->cols(),
757*bf2c3715SXin Li               nonzero_pivots = this->rank();
758*bf2c3715SXin Li   const Index smalldim = (std::min)(rows, cols);
759*bf2c3715SXin Li 
760*bf2c3715SXin Li   if(nonzero_pivots == 0)
761*bf2c3715SXin Li   {
762*bf2c3715SXin Li     dst.setZero();
763*bf2c3715SXin Li     return;
764*bf2c3715SXin Li   }
765*bf2c3715SXin Li 
766*bf2c3715SXin Li   typename RhsType::PlainObject c(rhs.rows(), rhs.cols());
767*bf2c3715SXin Li 
768*bf2c3715SXin Li   // Step 1
769*bf2c3715SXin Li   c = permutationP() * rhs;
770*bf2c3715SXin Li 
771*bf2c3715SXin Li   // Step 2
772*bf2c3715SXin Li   m_lu.topLeftCorner(smalldim,smalldim)
773*bf2c3715SXin Li       .template triangularView<UnitLower>()
774*bf2c3715SXin Li       .solveInPlace(c.topRows(smalldim));
775*bf2c3715SXin Li   if(rows>cols)
776*bf2c3715SXin Li     c.bottomRows(rows-cols) -= m_lu.bottomRows(rows-cols) * c.topRows(cols);
777*bf2c3715SXin Li 
778*bf2c3715SXin Li   // Step 3
779*bf2c3715SXin Li   m_lu.topLeftCorner(nonzero_pivots, nonzero_pivots)
780*bf2c3715SXin Li       .template triangularView<Upper>()
781*bf2c3715SXin Li       .solveInPlace(c.topRows(nonzero_pivots));
782*bf2c3715SXin Li 
783*bf2c3715SXin Li   // Step 4
784*bf2c3715SXin Li   for(Index i = 0; i < nonzero_pivots; ++i)
785*bf2c3715SXin Li     dst.row(permutationQ().indices().coeff(i)) = c.row(i);
786*bf2c3715SXin Li   for(Index i = nonzero_pivots; i < m_lu.cols(); ++i)
787*bf2c3715SXin Li     dst.row(permutationQ().indices().coeff(i)).setZero();
788*bf2c3715SXin Li }
789*bf2c3715SXin Li 
790*bf2c3715SXin Li template<typename _MatrixType>
791*bf2c3715SXin Li template<bool Conjugate, typename RhsType, typename DstType>
792*bf2c3715SXin Li void FullPivLU<_MatrixType>::_solve_impl_transposed(const RhsType &rhs, DstType &dst) const
793*bf2c3715SXin Li {
794*bf2c3715SXin Li   /* The decomposition PAQ = LU can be rewritten as A = P^{-1} L U Q^{-1},
795*bf2c3715SXin Li    * and since permutations are real and unitary, we can write this
796*bf2c3715SXin Li    * as   A^T = Q U^T L^T P,
797*bf2c3715SXin Li    * So we proceed as follows:
798*bf2c3715SXin Li    * Step 1: compute c = Q^T rhs.
799*bf2c3715SXin Li    * Step 2: replace c by the solution x to U^T x = c. May or may not exist.
800*bf2c3715SXin Li    * Step 3: replace c by the solution x to L^T x = c.
801*bf2c3715SXin Li    * Step 4: result = P^T c.
802*bf2c3715SXin Li    * If Conjugate is true, replace "^T" by "^*" above.
803*bf2c3715SXin Li    */
804*bf2c3715SXin Li 
805*bf2c3715SXin Li   const Index rows = this->rows(), cols = this->cols(),
806*bf2c3715SXin Li     nonzero_pivots = this->rank();
807*bf2c3715SXin Li   const Index smalldim = (std::min)(rows, cols);
808*bf2c3715SXin Li 
809*bf2c3715SXin Li   if(nonzero_pivots == 0)
810*bf2c3715SXin Li   {
811*bf2c3715SXin Li     dst.setZero();
812*bf2c3715SXin Li     return;
813*bf2c3715SXin Li   }
814*bf2c3715SXin Li 
815*bf2c3715SXin Li   typename RhsType::PlainObject c(rhs.rows(), rhs.cols());
816*bf2c3715SXin Li 
817*bf2c3715SXin Li   // Step 1
818*bf2c3715SXin Li   c = permutationQ().inverse() * rhs;
819*bf2c3715SXin Li 
820*bf2c3715SXin Li   // Step 2
821*bf2c3715SXin Li   m_lu.topLeftCorner(nonzero_pivots, nonzero_pivots)
822*bf2c3715SXin Li       .template triangularView<Upper>()
823*bf2c3715SXin Li       .transpose()
824*bf2c3715SXin Li       .template conjugateIf<Conjugate>()
825*bf2c3715SXin Li       .solveInPlace(c.topRows(nonzero_pivots));
826*bf2c3715SXin Li 
827*bf2c3715SXin Li   // Step 3
828*bf2c3715SXin Li   m_lu.topLeftCorner(smalldim, smalldim)
829*bf2c3715SXin Li       .template triangularView<UnitLower>()
830*bf2c3715SXin Li       .transpose()
831*bf2c3715SXin Li       .template conjugateIf<Conjugate>()
832*bf2c3715SXin Li       .solveInPlace(c.topRows(smalldim));
833*bf2c3715SXin Li 
834*bf2c3715SXin Li   // Step 4
835*bf2c3715SXin Li   PermutationPType invp = permutationP().inverse().eval();
836*bf2c3715SXin Li   for(Index i = 0; i < smalldim; ++i)
837*bf2c3715SXin Li     dst.row(invp.indices().coeff(i)) = c.row(i);
838*bf2c3715SXin Li   for(Index i = smalldim; i < rows; ++i)
839*bf2c3715SXin Li     dst.row(invp.indices().coeff(i)).setZero();
840*bf2c3715SXin Li }
841*bf2c3715SXin Li 
842*bf2c3715SXin Li #endif
843*bf2c3715SXin Li 
844*bf2c3715SXin Li namespace internal {
845*bf2c3715SXin Li 
846*bf2c3715SXin Li 
847*bf2c3715SXin Li /***** Implementation of inverse() *****************************************************/
848*bf2c3715SXin Li template<typename DstXprType, typename MatrixType>
849*bf2c3715SXin Li struct Assignment<DstXprType, Inverse<FullPivLU<MatrixType> >, internal::assign_op<typename DstXprType::Scalar,typename FullPivLU<MatrixType>::Scalar>, Dense2Dense>
850*bf2c3715SXin Li {
851*bf2c3715SXin Li   typedef FullPivLU<MatrixType> LuType;
852*bf2c3715SXin Li   typedef Inverse<LuType> SrcXprType;
853*bf2c3715SXin Li   static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<typename DstXprType::Scalar,typename MatrixType::Scalar> &)
854*bf2c3715SXin Li   {
855*bf2c3715SXin Li     dst = src.nestedExpression().solve(MatrixType::Identity(src.rows(), src.cols()));
856*bf2c3715SXin Li   }
857*bf2c3715SXin Li };
858*bf2c3715SXin Li } // end namespace internal
859*bf2c3715SXin Li 
860*bf2c3715SXin Li /******* MatrixBase methods *****************************************************************/
861*bf2c3715SXin Li 
862*bf2c3715SXin Li /** \lu_module
863*bf2c3715SXin Li   *
864*bf2c3715SXin Li   * \return the full-pivoting LU decomposition of \c *this.
865*bf2c3715SXin Li   *
866*bf2c3715SXin Li   * \sa class FullPivLU
867*bf2c3715SXin Li   */
868*bf2c3715SXin Li template<typename Derived>
869*bf2c3715SXin Li inline const FullPivLU<typename MatrixBase<Derived>::PlainObject>
870*bf2c3715SXin Li MatrixBase<Derived>::fullPivLu() const
871*bf2c3715SXin Li {
872*bf2c3715SXin Li   return FullPivLU<PlainObject>(eval());
873*bf2c3715SXin Li }
874*bf2c3715SXin Li 
875*bf2c3715SXin Li } // end namespace Eigen
876*bf2c3715SXin Li 
877*bf2c3715SXin Li #endif // EIGEN_LU_H
878