xref: /aosp_15_r20/external/eigen/Eigen/src/LU/InverseImpl.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) 2008-2010 Benoit Jacob <[email protected]>
5*bf2c3715SXin Li // Copyright (C) 2014 Gael Guennebaud <[email protected]>
6*bf2c3715SXin Li //
7*bf2c3715SXin Li // This Source Code Form is subject to the terms of the Mozilla
8*bf2c3715SXin Li // Public License v. 2.0. If a copy of the MPL was not distributed
9*bf2c3715SXin Li // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10*bf2c3715SXin Li 
11*bf2c3715SXin Li #ifndef EIGEN_INVERSE_IMPL_H
12*bf2c3715SXin Li #define EIGEN_INVERSE_IMPL_H
13*bf2c3715SXin Li 
14*bf2c3715SXin Li namespace Eigen {
15*bf2c3715SXin Li 
16*bf2c3715SXin Li namespace internal {
17*bf2c3715SXin Li 
18*bf2c3715SXin Li /**********************************
19*bf2c3715SXin Li *** General case implementation ***
20*bf2c3715SXin Li **********************************/
21*bf2c3715SXin Li 
22*bf2c3715SXin Li template<typename MatrixType, typename ResultType, int Size = MatrixType::RowsAtCompileTime>
23*bf2c3715SXin Li struct compute_inverse
24*bf2c3715SXin Li {
25*bf2c3715SXin Li   EIGEN_DEVICE_FUNC
runcompute_inverse26*bf2c3715SXin Li   static inline void run(const MatrixType& matrix, ResultType& result)
27*bf2c3715SXin Li   {
28*bf2c3715SXin Li     result = matrix.partialPivLu().inverse();
29*bf2c3715SXin Li   }
30*bf2c3715SXin Li };
31*bf2c3715SXin Li 
32*bf2c3715SXin Li template<typename MatrixType, typename ResultType, int Size = MatrixType::RowsAtCompileTime>
33*bf2c3715SXin Li struct compute_inverse_and_det_with_check { /* nothing! general case not supported. */ };
34*bf2c3715SXin Li 
35*bf2c3715SXin Li /****************************
36*bf2c3715SXin Li *** Size 1 implementation ***
37*bf2c3715SXin Li ****************************/
38*bf2c3715SXin Li 
39*bf2c3715SXin Li template<typename MatrixType, typename ResultType>
40*bf2c3715SXin Li struct compute_inverse<MatrixType, ResultType, 1>
41*bf2c3715SXin Li {
42*bf2c3715SXin Li   EIGEN_DEVICE_FUNC
43*bf2c3715SXin Li   static inline void run(const MatrixType& matrix, ResultType& result)
44*bf2c3715SXin Li   {
45*bf2c3715SXin Li     typedef typename MatrixType::Scalar Scalar;
46*bf2c3715SXin Li     internal::evaluator<MatrixType> matrixEval(matrix);
47*bf2c3715SXin Li     result.coeffRef(0,0) = Scalar(1) / matrixEval.coeff(0,0);
48*bf2c3715SXin Li   }
49*bf2c3715SXin Li };
50*bf2c3715SXin Li 
51*bf2c3715SXin Li template<typename MatrixType, typename ResultType>
52*bf2c3715SXin Li struct compute_inverse_and_det_with_check<MatrixType, ResultType, 1>
53*bf2c3715SXin Li {
54*bf2c3715SXin Li   EIGEN_DEVICE_FUNC
55*bf2c3715SXin Li   static inline void run(
56*bf2c3715SXin Li     const MatrixType& matrix,
57*bf2c3715SXin Li     const typename MatrixType::RealScalar& absDeterminantThreshold,
58*bf2c3715SXin Li     ResultType& result,
59*bf2c3715SXin Li     typename ResultType::Scalar& determinant,
60*bf2c3715SXin Li     bool& invertible
61*bf2c3715SXin Li   )
62*bf2c3715SXin Li   {
63*bf2c3715SXin Li     using std::abs;
64*bf2c3715SXin Li     determinant = matrix.coeff(0,0);
65*bf2c3715SXin Li     invertible = abs(determinant) > absDeterminantThreshold;
66*bf2c3715SXin Li     if(invertible) result.coeffRef(0,0) = typename ResultType::Scalar(1) / determinant;
67*bf2c3715SXin Li   }
68*bf2c3715SXin Li };
69*bf2c3715SXin Li 
70*bf2c3715SXin Li /****************************
71*bf2c3715SXin Li *** Size 2 implementation ***
72*bf2c3715SXin Li ****************************/
73*bf2c3715SXin Li 
74*bf2c3715SXin Li template<typename MatrixType, typename ResultType>
75*bf2c3715SXin Li EIGEN_DEVICE_FUNC
76*bf2c3715SXin Li inline void compute_inverse_size2_helper(
77*bf2c3715SXin Li     const MatrixType& matrix, const typename ResultType::Scalar& invdet,
78*bf2c3715SXin Li     ResultType& result)
79*bf2c3715SXin Li {
80*bf2c3715SXin Li   typename ResultType::Scalar temp = matrix.coeff(0,0);
81*bf2c3715SXin Li   result.coeffRef(0,0) =  matrix.coeff(1,1) * invdet;
82*bf2c3715SXin Li   result.coeffRef(1,0) = -matrix.coeff(1,0) * invdet;
83*bf2c3715SXin Li   result.coeffRef(0,1) = -matrix.coeff(0,1) * invdet;
84*bf2c3715SXin Li   result.coeffRef(1,1) =  temp * invdet;
85*bf2c3715SXin Li }
86*bf2c3715SXin Li 
87*bf2c3715SXin Li template<typename MatrixType, typename ResultType>
88*bf2c3715SXin Li struct compute_inverse<MatrixType, ResultType, 2>
89*bf2c3715SXin Li {
90*bf2c3715SXin Li   EIGEN_DEVICE_FUNC
91*bf2c3715SXin Li   static inline void run(const MatrixType& matrix, ResultType& result)
92*bf2c3715SXin Li   {
93*bf2c3715SXin Li     typedef typename ResultType::Scalar Scalar;
94*bf2c3715SXin Li     const Scalar invdet = typename MatrixType::Scalar(1) / matrix.determinant();
95*bf2c3715SXin Li     compute_inverse_size2_helper(matrix, invdet, result);
96*bf2c3715SXin Li   }
97*bf2c3715SXin Li };
98*bf2c3715SXin Li 
99*bf2c3715SXin Li template<typename MatrixType, typename ResultType>
100*bf2c3715SXin Li struct compute_inverse_and_det_with_check<MatrixType, ResultType, 2>
101*bf2c3715SXin Li {
102*bf2c3715SXin Li   EIGEN_DEVICE_FUNC
103*bf2c3715SXin Li   static inline void run(
104*bf2c3715SXin Li     const MatrixType& matrix,
105*bf2c3715SXin Li     const typename MatrixType::RealScalar& absDeterminantThreshold,
106*bf2c3715SXin Li     ResultType& inverse,
107*bf2c3715SXin Li     typename ResultType::Scalar& determinant,
108*bf2c3715SXin Li     bool& invertible
109*bf2c3715SXin Li   )
110*bf2c3715SXin Li   {
111*bf2c3715SXin Li     using std::abs;
112*bf2c3715SXin Li     typedef typename ResultType::Scalar Scalar;
113*bf2c3715SXin Li     determinant = matrix.determinant();
114*bf2c3715SXin Li     invertible = abs(determinant) > absDeterminantThreshold;
115*bf2c3715SXin Li     if(!invertible) return;
116*bf2c3715SXin Li     const Scalar invdet = Scalar(1) / determinant;
117*bf2c3715SXin Li     compute_inverse_size2_helper(matrix, invdet, inverse);
118*bf2c3715SXin Li   }
119*bf2c3715SXin Li };
120*bf2c3715SXin Li 
121*bf2c3715SXin Li /****************************
122*bf2c3715SXin Li *** Size 3 implementation ***
123*bf2c3715SXin Li ****************************/
124*bf2c3715SXin Li 
125*bf2c3715SXin Li template<typename MatrixType, int i, int j>
126*bf2c3715SXin Li EIGEN_DEVICE_FUNC
127*bf2c3715SXin Li inline typename MatrixType::Scalar cofactor_3x3(const MatrixType& m)
128*bf2c3715SXin Li {
129*bf2c3715SXin Li   enum {
130*bf2c3715SXin Li     i1 = (i+1) % 3,
131*bf2c3715SXin Li     i2 = (i+2) % 3,
132*bf2c3715SXin Li     j1 = (j+1) % 3,
133*bf2c3715SXin Li     j2 = (j+2) % 3
134*bf2c3715SXin Li   };
135*bf2c3715SXin Li   return m.coeff(i1, j1) * m.coeff(i2, j2)
136*bf2c3715SXin Li        - m.coeff(i1, j2) * m.coeff(i2, j1);
137*bf2c3715SXin Li }
138*bf2c3715SXin Li 
139*bf2c3715SXin Li template<typename MatrixType, typename ResultType>
140*bf2c3715SXin Li EIGEN_DEVICE_FUNC
141*bf2c3715SXin Li inline void compute_inverse_size3_helper(
142*bf2c3715SXin Li     const MatrixType& matrix,
143*bf2c3715SXin Li     const typename ResultType::Scalar& invdet,
144*bf2c3715SXin Li     const Matrix<typename ResultType::Scalar,3,1>& cofactors_col0,
145*bf2c3715SXin Li     ResultType& result)
146*bf2c3715SXin Li {
147*bf2c3715SXin Li   // Compute cofactors in a way that avoids aliasing issues.
148*bf2c3715SXin Li   typedef typename ResultType::Scalar Scalar;
149*bf2c3715SXin Li   const Scalar c01 = cofactor_3x3<MatrixType,0,1>(matrix) * invdet;
150*bf2c3715SXin Li   const Scalar c11 = cofactor_3x3<MatrixType,1,1>(matrix) * invdet;
151*bf2c3715SXin Li   const Scalar c02 = cofactor_3x3<MatrixType,0,2>(matrix) * invdet;
152*bf2c3715SXin Li   result.coeffRef(1,2) =  cofactor_3x3<MatrixType,2,1>(matrix) * invdet;
153*bf2c3715SXin Li   result.coeffRef(2,1) =  cofactor_3x3<MatrixType,1,2>(matrix) * invdet;
154*bf2c3715SXin Li   result.coeffRef(2,2) =  cofactor_3x3<MatrixType,2,2>(matrix) * invdet;
155*bf2c3715SXin Li   result.coeffRef(1,0) =  c01;
156*bf2c3715SXin Li   result.coeffRef(1,1) =  c11;
157*bf2c3715SXin Li   result.coeffRef(2,0) =  c02;
158*bf2c3715SXin Li   result.row(0) = cofactors_col0 * invdet;
159*bf2c3715SXin Li }
160*bf2c3715SXin Li 
161*bf2c3715SXin Li template<typename MatrixType, typename ResultType>
162*bf2c3715SXin Li struct compute_inverse<MatrixType, ResultType, 3>
163*bf2c3715SXin Li {
164*bf2c3715SXin Li   EIGEN_DEVICE_FUNC
165*bf2c3715SXin Li   static inline void run(const MatrixType& matrix, ResultType& result)
166*bf2c3715SXin Li   {
167*bf2c3715SXin Li     typedef typename ResultType::Scalar Scalar;
168*bf2c3715SXin Li     Matrix<typename MatrixType::Scalar,3,1> cofactors_col0;
169*bf2c3715SXin Li     cofactors_col0.coeffRef(0) =  cofactor_3x3<MatrixType,0,0>(matrix);
170*bf2c3715SXin Li     cofactors_col0.coeffRef(1) =  cofactor_3x3<MatrixType,1,0>(matrix);
171*bf2c3715SXin Li     cofactors_col0.coeffRef(2) =  cofactor_3x3<MatrixType,2,0>(matrix);
172*bf2c3715SXin Li     const Scalar det = (cofactors_col0.cwiseProduct(matrix.col(0))).sum();
173*bf2c3715SXin Li     const Scalar invdet = Scalar(1) / det;
174*bf2c3715SXin Li     compute_inverse_size3_helper(matrix, invdet, cofactors_col0, result);
175*bf2c3715SXin Li   }
176*bf2c3715SXin Li };
177*bf2c3715SXin Li 
178*bf2c3715SXin Li template<typename MatrixType, typename ResultType>
179*bf2c3715SXin Li struct compute_inverse_and_det_with_check<MatrixType, ResultType, 3>
180*bf2c3715SXin Li {
181*bf2c3715SXin Li   EIGEN_DEVICE_FUNC
182*bf2c3715SXin Li   static inline void run(
183*bf2c3715SXin Li     const MatrixType& matrix,
184*bf2c3715SXin Li     const typename MatrixType::RealScalar& absDeterminantThreshold,
185*bf2c3715SXin Li     ResultType& inverse,
186*bf2c3715SXin Li     typename ResultType::Scalar& determinant,
187*bf2c3715SXin Li     bool& invertible
188*bf2c3715SXin Li   )
189*bf2c3715SXin Li   {
190*bf2c3715SXin Li     typedef typename ResultType::Scalar Scalar;
191*bf2c3715SXin Li     Matrix<Scalar,3,1> cofactors_col0;
192*bf2c3715SXin Li     cofactors_col0.coeffRef(0) =  cofactor_3x3<MatrixType,0,0>(matrix);
193*bf2c3715SXin Li     cofactors_col0.coeffRef(1) =  cofactor_3x3<MatrixType,1,0>(matrix);
194*bf2c3715SXin Li     cofactors_col0.coeffRef(2) =  cofactor_3x3<MatrixType,2,0>(matrix);
195*bf2c3715SXin Li     determinant = (cofactors_col0.cwiseProduct(matrix.col(0))).sum();
196*bf2c3715SXin Li     invertible = Eigen::numext::abs(determinant) > absDeterminantThreshold;
197*bf2c3715SXin Li     if(!invertible) return;
198*bf2c3715SXin Li     const Scalar invdet = Scalar(1) / determinant;
199*bf2c3715SXin Li     compute_inverse_size3_helper(matrix, invdet, cofactors_col0, inverse);
200*bf2c3715SXin Li   }
201*bf2c3715SXin Li };
202*bf2c3715SXin Li 
203*bf2c3715SXin Li /****************************
204*bf2c3715SXin Li *** Size 4 implementation ***
205*bf2c3715SXin Li ****************************/
206*bf2c3715SXin Li 
207*bf2c3715SXin Li template<typename Derived>
208*bf2c3715SXin Li EIGEN_DEVICE_FUNC
209*bf2c3715SXin Li inline const typename Derived::Scalar general_det3_helper
210*bf2c3715SXin Li (const MatrixBase<Derived>& matrix, int i1, int i2, int i3, int j1, int j2, int j3)
211*bf2c3715SXin Li {
212*bf2c3715SXin Li   return matrix.coeff(i1,j1)
213*bf2c3715SXin Li          * (matrix.coeff(i2,j2) * matrix.coeff(i3,j3) - matrix.coeff(i2,j3) * matrix.coeff(i3,j2));
214*bf2c3715SXin Li }
215*bf2c3715SXin Li 
216*bf2c3715SXin Li template<typename MatrixType, int i, int j>
217*bf2c3715SXin Li EIGEN_DEVICE_FUNC
218*bf2c3715SXin Li inline typename MatrixType::Scalar cofactor_4x4(const MatrixType& matrix)
219*bf2c3715SXin Li {
220*bf2c3715SXin Li   enum {
221*bf2c3715SXin Li     i1 = (i+1) % 4,
222*bf2c3715SXin Li     i2 = (i+2) % 4,
223*bf2c3715SXin Li     i3 = (i+3) % 4,
224*bf2c3715SXin Li     j1 = (j+1) % 4,
225*bf2c3715SXin Li     j2 = (j+2) % 4,
226*bf2c3715SXin Li     j3 = (j+3) % 4
227*bf2c3715SXin Li   };
228*bf2c3715SXin Li   return general_det3_helper(matrix, i1, i2, i3, j1, j2, j3)
229*bf2c3715SXin Li        + general_det3_helper(matrix, i2, i3, i1, j1, j2, j3)
230*bf2c3715SXin Li        + general_det3_helper(matrix, i3, i1, i2, j1, j2, j3);
231*bf2c3715SXin Li }
232*bf2c3715SXin Li 
233*bf2c3715SXin Li template<int Arch, typename Scalar, typename MatrixType, typename ResultType>
234*bf2c3715SXin Li struct compute_inverse_size4
235*bf2c3715SXin Li {
236*bf2c3715SXin Li   EIGEN_DEVICE_FUNC
237*bf2c3715SXin Li   static void run(const MatrixType& matrix, ResultType& result)
238*bf2c3715SXin Li   {
239*bf2c3715SXin Li     result.coeffRef(0,0) =  cofactor_4x4<MatrixType,0,0>(matrix);
240*bf2c3715SXin Li     result.coeffRef(1,0) = -cofactor_4x4<MatrixType,0,1>(matrix);
241*bf2c3715SXin Li     result.coeffRef(2,0) =  cofactor_4x4<MatrixType,0,2>(matrix);
242*bf2c3715SXin Li     result.coeffRef(3,0) = -cofactor_4x4<MatrixType,0,3>(matrix);
243*bf2c3715SXin Li     result.coeffRef(0,2) =  cofactor_4x4<MatrixType,2,0>(matrix);
244*bf2c3715SXin Li     result.coeffRef(1,2) = -cofactor_4x4<MatrixType,2,1>(matrix);
245*bf2c3715SXin Li     result.coeffRef(2,2) =  cofactor_4x4<MatrixType,2,2>(matrix);
246*bf2c3715SXin Li     result.coeffRef(3,2) = -cofactor_4x4<MatrixType,2,3>(matrix);
247*bf2c3715SXin Li     result.coeffRef(0,1) = -cofactor_4x4<MatrixType,1,0>(matrix);
248*bf2c3715SXin Li     result.coeffRef(1,1) =  cofactor_4x4<MatrixType,1,1>(matrix);
249*bf2c3715SXin Li     result.coeffRef(2,1) = -cofactor_4x4<MatrixType,1,2>(matrix);
250*bf2c3715SXin Li     result.coeffRef(3,1) =  cofactor_4x4<MatrixType,1,3>(matrix);
251*bf2c3715SXin Li     result.coeffRef(0,3) = -cofactor_4x4<MatrixType,3,0>(matrix);
252*bf2c3715SXin Li     result.coeffRef(1,3) =  cofactor_4x4<MatrixType,3,1>(matrix);
253*bf2c3715SXin Li     result.coeffRef(2,3) = -cofactor_4x4<MatrixType,3,2>(matrix);
254*bf2c3715SXin Li     result.coeffRef(3,3) =  cofactor_4x4<MatrixType,3,3>(matrix);
255*bf2c3715SXin Li     result /= (matrix.col(0).cwiseProduct(result.row(0).transpose())).sum();
256*bf2c3715SXin Li   }
257*bf2c3715SXin Li };
258*bf2c3715SXin Li 
259*bf2c3715SXin Li template<typename MatrixType, typename ResultType>
260*bf2c3715SXin Li struct compute_inverse<MatrixType, ResultType, 4>
261*bf2c3715SXin Li  : compute_inverse_size4<Architecture::Target, typename MatrixType::Scalar,
262*bf2c3715SXin Li                             MatrixType, ResultType>
263*bf2c3715SXin Li {
264*bf2c3715SXin Li };
265*bf2c3715SXin Li 
266*bf2c3715SXin Li template<typename MatrixType, typename ResultType>
267*bf2c3715SXin Li struct compute_inverse_and_det_with_check<MatrixType, ResultType, 4>
268*bf2c3715SXin Li {
269*bf2c3715SXin Li   EIGEN_DEVICE_FUNC
270*bf2c3715SXin Li   static inline void run(
271*bf2c3715SXin Li     const MatrixType& matrix,
272*bf2c3715SXin Li     const typename MatrixType::RealScalar& absDeterminantThreshold,
273*bf2c3715SXin Li     ResultType& inverse,
274*bf2c3715SXin Li     typename ResultType::Scalar& determinant,
275*bf2c3715SXin Li     bool& invertible
276*bf2c3715SXin Li   )
277*bf2c3715SXin Li   {
278*bf2c3715SXin Li     using std::abs;
279*bf2c3715SXin Li     determinant = matrix.determinant();
280*bf2c3715SXin Li     invertible = abs(determinant) > absDeterminantThreshold;
281*bf2c3715SXin Li     if(invertible && extract_data(matrix) != extract_data(inverse)) {
282*bf2c3715SXin Li       compute_inverse<MatrixType, ResultType>::run(matrix, inverse);
283*bf2c3715SXin Li     }
284*bf2c3715SXin Li     else if(invertible) {
285*bf2c3715SXin Li       MatrixType matrix_t = matrix;
286*bf2c3715SXin Li       compute_inverse<MatrixType, ResultType>::run(matrix_t, inverse);
287*bf2c3715SXin Li     }
288*bf2c3715SXin Li   }
289*bf2c3715SXin Li };
290*bf2c3715SXin Li 
291*bf2c3715SXin Li /*************************
292*bf2c3715SXin Li *** MatrixBase methods ***
293*bf2c3715SXin Li *************************/
294*bf2c3715SXin Li 
295*bf2c3715SXin Li } // end namespace internal
296*bf2c3715SXin Li 
297*bf2c3715SXin Li namespace internal {
298*bf2c3715SXin Li 
299*bf2c3715SXin Li // Specialization for "dense = dense_xpr.inverse()"
300*bf2c3715SXin Li template<typename DstXprType, typename XprType>
301*bf2c3715SXin Li struct Assignment<DstXprType, Inverse<XprType>, internal::assign_op<typename DstXprType::Scalar,typename XprType::Scalar>, Dense2Dense>
302*bf2c3715SXin Li {
303*bf2c3715SXin Li   typedef Inverse<XprType> SrcXprType;
304*bf2c3715SXin Li   EIGEN_DEVICE_FUNC
305*bf2c3715SXin Li   static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<typename DstXprType::Scalar,typename XprType::Scalar> &)
306*bf2c3715SXin Li   {
307*bf2c3715SXin Li     Index dstRows = src.rows();
308*bf2c3715SXin Li     Index dstCols = src.cols();
309*bf2c3715SXin Li     if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
310*bf2c3715SXin Li       dst.resize(dstRows, dstCols);
311*bf2c3715SXin Li 
312*bf2c3715SXin Li     const int Size = EIGEN_PLAIN_ENUM_MIN(XprType::ColsAtCompileTime,DstXprType::ColsAtCompileTime);
313*bf2c3715SXin Li     EIGEN_ONLY_USED_FOR_DEBUG(Size);
314*bf2c3715SXin Li     eigen_assert(( (Size<=1) || (Size>4) || (extract_data(src.nestedExpression())!=extract_data(dst)))
315*bf2c3715SXin Li               && "Aliasing problem detected in inverse(), you need to do inverse().eval() here.");
316*bf2c3715SXin Li 
317*bf2c3715SXin Li     typedef typename internal::nested_eval<XprType,XprType::ColsAtCompileTime>::type  ActualXprType;
318*bf2c3715SXin Li     typedef typename internal::remove_all<ActualXprType>::type                        ActualXprTypeCleanded;
319*bf2c3715SXin Li 
320*bf2c3715SXin Li     ActualXprType actual_xpr(src.nestedExpression());
321*bf2c3715SXin Li 
322*bf2c3715SXin Li     compute_inverse<ActualXprTypeCleanded, DstXprType>::run(actual_xpr, dst);
323*bf2c3715SXin Li   }
324*bf2c3715SXin Li };
325*bf2c3715SXin Li 
326*bf2c3715SXin Li 
327*bf2c3715SXin Li } // end namespace internal
328*bf2c3715SXin Li 
329*bf2c3715SXin Li /** \lu_module
330*bf2c3715SXin Li   *
331*bf2c3715SXin Li   * \returns the matrix inverse of this matrix.
332*bf2c3715SXin Li   *
333*bf2c3715SXin Li   * For small fixed sizes up to 4x4, this method uses cofactors.
334*bf2c3715SXin Li   * In the general case, this method uses class PartialPivLU.
335*bf2c3715SXin Li   *
336*bf2c3715SXin Li   * \note This matrix must be invertible, otherwise the result is undefined. If you need an
337*bf2c3715SXin Li   * invertibility check, do the following:
338*bf2c3715SXin Li   * \li for fixed sizes up to 4x4, use computeInverseAndDetWithCheck().
339*bf2c3715SXin Li   * \li for the general case, use class FullPivLU.
340*bf2c3715SXin Li   *
341*bf2c3715SXin Li   * Example: \include MatrixBase_inverse.cpp
342*bf2c3715SXin Li   * Output: \verbinclude MatrixBase_inverse.out
343*bf2c3715SXin Li   *
344*bf2c3715SXin Li   * \sa computeInverseAndDetWithCheck()
345*bf2c3715SXin Li   */
346*bf2c3715SXin Li template<typename Derived>
347*bf2c3715SXin Li EIGEN_DEVICE_FUNC
348*bf2c3715SXin Li inline const Inverse<Derived> MatrixBase<Derived>::inverse() const
349*bf2c3715SXin Li {
350*bf2c3715SXin Li   EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsInteger,THIS_FUNCTION_IS_NOT_FOR_INTEGER_NUMERIC_TYPES)
351*bf2c3715SXin Li   eigen_assert(rows() == cols());
352*bf2c3715SXin Li   return Inverse<Derived>(derived());
353*bf2c3715SXin Li }
354*bf2c3715SXin Li 
355*bf2c3715SXin Li /** \lu_module
356*bf2c3715SXin Li   *
357*bf2c3715SXin Li   * Computation of matrix inverse and determinant, with invertibility check.
358*bf2c3715SXin Li   *
359*bf2c3715SXin Li   * This is only for fixed-size square matrices of size up to 4x4.
360*bf2c3715SXin Li   *
361*bf2c3715SXin Li   * Notice that it will trigger a copy of input matrix when trying to do the inverse in place.
362*bf2c3715SXin Li   *
363*bf2c3715SXin Li   * \param inverse Reference to the matrix in which to store the inverse.
364*bf2c3715SXin Li   * \param determinant Reference to the variable in which to store the determinant.
365*bf2c3715SXin Li   * \param invertible Reference to the bool variable in which to store whether the matrix is invertible.
366*bf2c3715SXin Li   * \param absDeterminantThreshold Optional parameter controlling the invertibility check.
367*bf2c3715SXin Li   *                                The matrix will be declared invertible if the absolute value of its
368*bf2c3715SXin Li   *                                determinant is greater than this threshold.
369*bf2c3715SXin Li   *
370*bf2c3715SXin Li   * Example: \include MatrixBase_computeInverseAndDetWithCheck.cpp
371*bf2c3715SXin Li   * Output: \verbinclude MatrixBase_computeInverseAndDetWithCheck.out
372*bf2c3715SXin Li   *
373*bf2c3715SXin Li   * \sa inverse(), computeInverseWithCheck()
374*bf2c3715SXin Li   */
375*bf2c3715SXin Li template<typename Derived>
376*bf2c3715SXin Li template<typename ResultType>
377*bf2c3715SXin Li inline void MatrixBase<Derived>::computeInverseAndDetWithCheck(
378*bf2c3715SXin Li     ResultType& inverse,
379*bf2c3715SXin Li     typename ResultType::Scalar& determinant,
380*bf2c3715SXin Li     bool& invertible,
381*bf2c3715SXin Li     const RealScalar& absDeterminantThreshold
382*bf2c3715SXin Li   ) const
383*bf2c3715SXin Li {
384*bf2c3715SXin Li   // i'd love to put some static assertions there, but SFINAE means that they have no effect...
385*bf2c3715SXin Li   eigen_assert(rows() == cols());
386*bf2c3715SXin Li   // for 2x2, it's worth giving a chance to avoid evaluating.
387*bf2c3715SXin Li   // for larger sizes, evaluating has negligible cost and limits code size.
388*bf2c3715SXin Li   typedef typename internal::conditional<
389*bf2c3715SXin Li     RowsAtCompileTime == 2,
390*bf2c3715SXin Li     typename internal::remove_all<typename internal::nested_eval<Derived, 2>::type>::type,
391*bf2c3715SXin Li     PlainObject
392*bf2c3715SXin Li   >::type MatrixType;
393*bf2c3715SXin Li   internal::compute_inverse_and_det_with_check<MatrixType, ResultType>::run
394*bf2c3715SXin Li     (derived(), absDeterminantThreshold, inverse, determinant, invertible);
395*bf2c3715SXin Li }
396*bf2c3715SXin Li 
397*bf2c3715SXin Li /** \lu_module
398*bf2c3715SXin Li   *
399*bf2c3715SXin Li   * Computation of matrix inverse, with invertibility check.
400*bf2c3715SXin Li   *
401*bf2c3715SXin Li   * This is only for fixed-size square matrices of size up to 4x4.
402*bf2c3715SXin Li   *
403*bf2c3715SXin Li   * Notice that it will trigger a copy of input matrix when trying to do the inverse in place.
404*bf2c3715SXin Li   *
405*bf2c3715SXin Li   * \param inverse Reference to the matrix in which to store the inverse.
406*bf2c3715SXin Li   * \param invertible Reference to the bool variable in which to store whether the matrix is invertible.
407*bf2c3715SXin Li   * \param absDeterminantThreshold Optional parameter controlling the invertibility check.
408*bf2c3715SXin Li   *                                The matrix will be declared invertible if the absolute value of its
409*bf2c3715SXin Li   *                                determinant is greater than this threshold.
410*bf2c3715SXin Li   *
411*bf2c3715SXin Li   * Example: \include MatrixBase_computeInverseWithCheck.cpp
412*bf2c3715SXin Li   * Output: \verbinclude MatrixBase_computeInverseWithCheck.out
413*bf2c3715SXin Li   *
414*bf2c3715SXin Li   * \sa inverse(), computeInverseAndDetWithCheck()
415*bf2c3715SXin Li   */
416*bf2c3715SXin Li template<typename Derived>
417*bf2c3715SXin Li template<typename ResultType>
418*bf2c3715SXin Li inline void MatrixBase<Derived>::computeInverseWithCheck(
419*bf2c3715SXin Li     ResultType& inverse,
420*bf2c3715SXin Li     bool& invertible,
421*bf2c3715SXin Li     const RealScalar& absDeterminantThreshold
422*bf2c3715SXin Li   ) const
423*bf2c3715SXin Li {
424*bf2c3715SXin Li   Scalar determinant;
425*bf2c3715SXin Li   // i'd love to put some static assertions there, but SFINAE means that they have no effect...
426*bf2c3715SXin Li   eigen_assert(rows() == cols());
427*bf2c3715SXin Li   computeInverseAndDetWithCheck(inverse,determinant,invertible,absDeterminantThreshold);
428*bf2c3715SXin Li }
429*bf2c3715SXin Li 
430*bf2c3715SXin Li } // end namespace Eigen
431*bf2c3715SXin Li 
432*bf2c3715SXin Li #endif // EIGEN_INVERSE_IMPL_H
433