File indexing completed on 2025-04-19 09:06:21
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef EIGEN_INVERSE_IMPL_H
0012 #define EIGEN_INVERSE_IMPL_H
0013
0014 namespace RivetEigen {
0015
0016 namespace internal {
0017
0018
0019
0020
0021
0022 template<typename MatrixType, typename ResultType, int Size = MatrixType::RowsAtCompileTime>
0023 struct compute_inverse
0024 {
0025 EIGEN_DEVICE_FUNC
0026 static inline void run(const MatrixType& matrix, ResultType& result)
0027 {
0028 result = matrix.partialPivLu().inverse();
0029 }
0030 };
0031
0032 template<typename MatrixType, typename ResultType, int Size = MatrixType::RowsAtCompileTime>
0033 struct compute_inverse_and_det_with_check { };
0034
0035
0036
0037
0038
0039 template<typename MatrixType, typename ResultType>
0040 struct compute_inverse<MatrixType, ResultType, 1>
0041 {
0042 EIGEN_DEVICE_FUNC
0043 static inline void run(const MatrixType& matrix, ResultType& result)
0044 {
0045 typedef typename MatrixType::Scalar Scalar;
0046 internal::evaluator<MatrixType> matrixEval(matrix);
0047 result.coeffRef(0,0) = Scalar(1) / matrixEval.coeff(0,0);
0048 }
0049 };
0050
0051 template<typename MatrixType, typename ResultType>
0052 struct compute_inverse_and_det_with_check<MatrixType, ResultType, 1>
0053 {
0054 EIGEN_DEVICE_FUNC
0055 static inline void run(
0056 const MatrixType& matrix,
0057 const typename MatrixType::RealScalar& absDeterminantThreshold,
0058 ResultType& result,
0059 typename ResultType::Scalar& determinant,
0060 bool& invertible
0061 )
0062 {
0063 using std::abs;
0064 determinant = matrix.coeff(0,0);
0065 invertible = abs(determinant) > absDeterminantThreshold;
0066 if(invertible) result.coeffRef(0,0) = typename ResultType::Scalar(1) / determinant;
0067 }
0068 };
0069
0070
0071
0072
0073
0074 template<typename MatrixType, typename ResultType>
0075 EIGEN_DEVICE_FUNC
0076 inline void compute_inverse_size2_helper(
0077 const MatrixType& matrix, const typename ResultType::Scalar& invdet,
0078 ResultType& result)
0079 {
0080 typename ResultType::Scalar temp = matrix.coeff(0,0);
0081 result.coeffRef(0,0) = matrix.coeff(1,1) * invdet;
0082 result.coeffRef(1,0) = -matrix.coeff(1,0) * invdet;
0083 result.coeffRef(0,1) = -matrix.coeff(0,1) * invdet;
0084 result.coeffRef(1,1) = temp * invdet;
0085 }
0086
0087 template<typename MatrixType, typename ResultType>
0088 struct compute_inverse<MatrixType, ResultType, 2>
0089 {
0090 EIGEN_DEVICE_FUNC
0091 static inline void run(const MatrixType& matrix, ResultType& result)
0092 {
0093 typedef typename ResultType::Scalar Scalar;
0094 const Scalar invdet = typename MatrixType::Scalar(1) / matrix.determinant();
0095 compute_inverse_size2_helper(matrix, invdet, result);
0096 }
0097 };
0098
0099 template<typename MatrixType, typename ResultType>
0100 struct compute_inverse_and_det_with_check<MatrixType, ResultType, 2>
0101 {
0102 EIGEN_DEVICE_FUNC
0103 static inline void run(
0104 const MatrixType& matrix,
0105 const typename MatrixType::RealScalar& absDeterminantThreshold,
0106 ResultType& inverse,
0107 typename ResultType::Scalar& determinant,
0108 bool& invertible
0109 )
0110 {
0111 using std::abs;
0112 typedef typename ResultType::Scalar Scalar;
0113 determinant = matrix.determinant();
0114 invertible = abs(determinant) > absDeterminantThreshold;
0115 if(!invertible) return;
0116 const Scalar invdet = Scalar(1) / determinant;
0117 compute_inverse_size2_helper(matrix, invdet, inverse);
0118 }
0119 };
0120
0121
0122
0123
0124
0125 template<typename MatrixType, int i, int j>
0126 EIGEN_DEVICE_FUNC
0127 inline typename MatrixType::Scalar cofactor_3x3(const MatrixType& m)
0128 {
0129 enum {
0130 i1 = (i+1) % 3,
0131 i2 = (i+2) % 3,
0132 j1 = (j+1) % 3,
0133 j2 = (j+2) % 3
0134 };
0135 return m.coeff(i1, j1) * m.coeff(i2, j2)
0136 - m.coeff(i1, j2) * m.coeff(i2, j1);
0137 }
0138
0139 template<typename MatrixType, typename ResultType>
0140 EIGEN_DEVICE_FUNC
0141 inline void compute_inverse_size3_helper(
0142 const MatrixType& matrix,
0143 const typename ResultType::Scalar& invdet,
0144 const Matrix<typename ResultType::Scalar,3,1>& cofactors_col0,
0145 ResultType& result)
0146 {
0147
0148 typedef typename ResultType::Scalar Scalar;
0149 const Scalar c01 = cofactor_3x3<MatrixType,0,1>(matrix) * invdet;
0150 const Scalar c11 = cofactor_3x3<MatrixType,1,1>(matrix) * invdet;
0151 const Scalar c02 = cofactor_3x3<MatrixType,0,2>(matrix) * invdet;
0152 result.coeffRef(1,2) = cofactor_3x3<MatrixType,2,1>(matrix) * invdet;
0153 result.coeffRef(2,1) = cofactor_3x3<MatrixType,1,2>(matrix) * invdet;
0154 result.coeffRef(2,2) = cofactor_3x3<MatrixType,2,2>(matrix) * invdet;
0155 result.coeffRef(1,0) = c01;
0156 result.coeffRef(1,1) = c11;
0157 result.coeffRef(2,0) = c02;
0158 result.row(0) = cofactors_col0 * invdet;
0159 }
0160
0161 template<typename MatrixType, typename ResultType>
0162 struct compute_inverse<MatrixType, ResultType, 3>
0163 {
0164 EIGEN_DEVICE_FUNC
0165 static inline void run(const MatrixType& matrix, ResultType& result)
0166 {
0167 typedef typename ResultType::Scalar Scalar;
0168 Matrix<typename MatrixType::Scalar,3,1> cofactors_col0;
0169 cofactors_col0.coeffRef(0) = cofactor_3x3<MatrixType,0,0>(matrix);
0170 cofactors_col0.coeffRef(1) = cofactor_3x3<MatrixType,1,0>(matrix);
0171 cofactors_col0.coeffRef(2) = cofactor_3x3<MatrixType,2,0>(matrix);
0172 const Scalar det = (cofactors_col0.cwiseProduct(matrix.col(0))).sum();
0173 const Scalar invdet = Scalar(1) / det;
0174 compute_inverse_size3_helper(matrix, invdet, cofactors_col0, result);
0175 }
0176 };
0177
0178 template<typename MatrixType, typename ResultType>
0179 struct compute_inverse_and_det_with_check<MatrixType, ResultType, 3>
0180 {
0181 EIGEN_DEVICE_FUNC
0182 static inline void run(
0183 const MatrixType& matrix,
0184 const typename MatrixType::RealScalar& absDeterminantThreshold,
0185 ResultType& inverse,
0186 typename ResultType::Scalar& determinant,
0187 bool& invertible
0188 )
0189 {
0190 typedef typename ResultType::Scalar Scalar;
0191 Matrix<Scalar,3,1> cofactors_col0;
0192 cofactors_col0.coeffRef(0) = cofactor_3x3<MatrixType,0,0>(matrix);
0193 cofactors_col0.coeffRef(1) = cofactor_3x3<MatrixType,1,0>(matrix);
0194 cofactors_col0.coeffRef(2) = cofactor_3x3<MatrixType,2,0>(matrix);
0195 determinant = (cofactors_col0.cwiseProduct(matrix.col(0))).sum();
0196 invertible = RivetEigen::numext::abs(determinant) > absDeterminantThreshold;
0197 if(!invertible) return;
0198 const Scalar invdet = Scalar(1) / determinant;
0199 compute_inverse_size3_helper(matrix, invdet, cofactors_col0, inverse);
0200 }
0201 };
0202
0203
0204
0205
0206
0207 template<typename Derived>
0208 EIGEN_DEVICE_FUNC
0209 inline const typename Derived::Scalar general_det3_helper
0210 (const MatrixBase<Derived>& matrix, int i1, int i2, int i3, int j1, int j2, int j3)
0211 {
0212 return matrix.coeff(i1,j1)
0213 * (matrix.coeff(i2,j2) * matrix.coeff(i3,j3) - matrix.coeff(i2,j3) * matrix.coeff(i3,j2));
0214 }
0215
0216 template<typename MatrixType, int i, int j>
0217 EIGEN_DEVICE_FUNC
0218 inline typename MatrixType::Scalar cofactor_4x4(const MatrixType& matrix)
0219 {
0220 enum {
0221 i1 = (i+1) % 4,
0222 i2 = (i+2) % 4,
0223 i3 = (i+3) % 4,
0224 j1 = (j+1) % 4,
0225 j2 = (j+2) % 4,
0226 j3 = (j+3) % 4
0227 };
0228 return general_det3_helper(matrix, i1, i2, i3, j1, j2, j3)
0229 + general_det3_helper(matrix, i2, i3, i1, j1, j2, j3)
0230 + general_det3_helper(matrix, i3, i1, i2, j1, j2, j3);
0231 }
0232
0233 template<int Arch, typename Scalar, typename MatrixType, typename ResultType>
0234 struct compute_inverse_size4
0235 {
0236 EIGEN_DEVICE_FUNC
0237 static void run(const MatrixType& matrix, ResultType& result)
0238 {
0239 result.coeffRef(0,0) = cofactor_4x4<MatrixType,0,0>(matrix);
0240 result.coeffRef(1,0) = -cofactor_4x4<MatrixType,0,1>(matrix);
0241 result.coeffRef(2,0) = cofactor_4x4<MatrixType,0,2>(matrix);
0242 result.coeffRef(3,0) = -cofactor_4x4<MatrixType,0,3>(matrix);
0243 result.coeffRef(0,2) = cofactor_4x4<MatrixType,2,0>(matrix);
0244 result.coeffRef(1,2) = -cofactor_4x4<MatrixType,2,1>(matrix);
0245 result.coeffRef(2,2) = cofactor_4x4<MatrixType,2,2>(matrix);
0246 result.coeffRef(3,2) = -cofactor_4x4<MatrixType,2,3>(matrix);
0247 result.coeffRef(0,1) = -cofactor_4x4<MatrixType,1,0>(matrix);
0248 result.coeffRef(1,1) = cofactor_4x4<MatrixType,1,1>(matrix);
0249 result.coeffRef(2,1) = -cofactor_4x4<MatrixType,1,2>(matrix);
0250 result.coeffRef(3,1) = cofactor_4x4<MatrixType,1,3>(matrix);
0251 result.coeffRef(0,3) = -cofactor_4x4<MatrixType,3,0>(matrix);
0252 result.coeffRef(1,3) = cofactor_4x4<MatrixType,3,1>(matrix);
0253 result.coeffRef(2,3) = -cofactor_4x4<MatrixType,3,2>(matrix);
0254 result.coeffRef(3,3) = cofactor_4x4<MatrixType,3,3>(matrix);
0255 result /= (matrix.col(0).cwiseProduct(result.row(0).transpose())).sum();
0256 }
0257 };
0258
0259 template<typename MatrixType, typename ResultType>
0260 struct compute_inverse<MatrixType, ResultType, 4>
0261 : compute_inverse_size4<Architecture::Target, typename MatrixType::Scalar,
0262 MatrixType, ResultType>
0263 {
0264 };
0265
0266 template<typename MatrixType, typename ResultType>
0267 struct compute_inverse_and_det_with_check<MatrixType, ResultType, 4>
0268 {
0269 EIGEN_DEVICE_FUNC
0270 static inline void run(
0271 const MatrixType& matrix,
0272 const typename MatrixType::RealScalar& absDeterminantThreshold,
0273 ResultType& inverse,
0274 typename ResultType::Scalar& determinant,
0275 bool& invertible
0276 )
0277 {
0278 using std::abs;
0279 determinant = matrix.determinant();
0280 invertible = abs(determinant) > absDeterminantThreshold;
0281 if(invertible && extract_data(matrix) != extract_data(inverse)) {
0282 compute_inverse<MatrixType, ResultType>::run(matrix, inverse);
0283 }
0284 else if(invertible) {
0285 MatrixType matrix_t = matrix;
0286 compute_inverse<MatrixType, ResultType>::run(matrix_t, inverse);
0287 }
0288 }
0289 };
0290
0291
0292
0293
0294
0295 }
0296
0297 namespace internal {
0298
0299
0300 template<typename DstXprType, typename XprType>
0301 struct Assignment<DstXprType, Inverse<XprType>, internal::assign_op<typename DstXprType::Scalar,typename XprType::Scalar>, Dense2Dense>
0302 {
0303 typedef Inverse<XprType> SrcXprType;
0304 EIGEN_DEVICE_FUNC
0305 static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<typename DstXprType::Scalar,typename XprType::Scalar> &)
0306 {
0307 Index dstRows = src.rows();
0308 Index dstCols = src.cols();
0309 if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
0310 dst.resize(dstRows, dstCols);
0311
0312 const int Size = EIGEN_PLAIN_ENUM_MIN(XprType::ColsAtCompileTime,DstXprType::ColsAtCompileTime);
0313 EIGEN_ONLY_USED_FOR_DEBUG(Size);
0314 eigen_assert(( (Size<=1) || (Size>4) || (extract_data(src.nestedExpression())!=extract_data(dst)))
0315 && "Aliasing problem detected in inverse(), you need to do inverse().eval() here.");
0316
0317 typedef typename internal::nested_eval<XprType,XprType::ColsAtCompileTime>::type ActualXprType;
0318 typedef typename internal::remove_all<ActualXprType>::type ActualXprTypeCleanded;
0319
0320 ActualXprType actual_xpr(src.nestedExpression());
0321
0322 compute_inverse<ActualXprTypeCleanded, DstXprType>::run(actual_xpr, dst);
0323 }
0324 };
0325
0326
0327 }
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346 template<typename Derived>
0347 EIGEN_DEVICE_FUNC
0348 inline const Inverse<Derived> MatrixBase<Derived>::inverse() const
0349 {
0350 EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsInteger,THIS_FUNCTION_IS_NOT_FOR_INTEGER_NUMERIC_TYPES)
0351 eigen_assert(rows() == cols());
0352 return Inverse<Derived>(derived());
0353 }
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375 template<typename Derived>
0376 template<typename ResultType>
0377 inline void MatrixBase<Derived>::computeInverseAndDetWithCheck(
0378 ResultType& inverse,
0379 typename ResultType::Scalar& determinant,
0380 bool& invertible,
0381 const RealScalar& absDeterminantThreshold
0382 ) const
0383 {
0384
0385 eigen_assert(rows() == cols());
0386
0387
0388 typedef typename internal::conditional<
0389 RowsAtCompileTime == 2,
0390 typename internal::remove_all<typename internal::nested_eval<Derived, 2>::type>::type,
0391 PlainObject
0392 >::type MatrixType;
0393 internal::compute_inverse_and_det_with_check<MatrixType, ResultType>::run
0394 (derived(), absDeterminantThreshold, inverse, determinant, invertible);
0395 }
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416 template<typename Derived>
0417 template<typename ResultType>
0418 inline void MatrixBase<Derived>::computeInverseWithCheck(
0419 ResultType& inverse,
0420 bool& invertible,
0421 const RealScalar& absDeterminantThreshold
0422 ) const
0423 {
0424 Scalar determinant;
0425
0426 eigen_assert(rows() == cols());
0427 computeInverseAndDetWithCheck(inverse,determinant,invertible,absDeterminantThreshold);
0428 }
0429
0430 }
0431
0432 #endif