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