Make a copy of input matrix when try to do the inverse in place, this fixes #2285.

(cherry picked from commit 4bcd42c271761dc5341f8e08ca7d357c3614cb01)
This commit is contained in:
Guoqiang QI 2021-07-08 17:05:26 +00:00 committed by Rasmus Munk Larsen
parent 7571704a43
commit 69ec4907da

View File

@ -77,10 +77,11 @@ inline void compute_inverse_size2_helper(
const MatrixType& matrix, const typename ResultType::Scalar& invdet,
ResultType& result)
{
typename ResultType::Scalar temp = matrix.coeff(0,0);
result.coeffRef(0,0) = matrix.coeff(1,1) * invdet;
result.coeffRef(1,0) = -matrix.coeff(1,0) * invdet;
result.coeffRef(0,1) = -matrix.coeff(0,1) * invdet;
result.coeffRef(1,1) = matrix.coeff(0,0) * invdet;
result.coeffRef(1,1) = temp * invdet;
}
template<typename MatrixType, typename ResultType>
@ -165,7 +166,12 @@ struct compute_inverse<MatrixType, ResultType, 3>
cofactors_col0.coeffRef(2) = cofactor_3x3<MatrixType,2,0>(matrix);
const Scalar det = (cofactors_col0.cwiseProduct(matrix.col(0))).sum();
const Scalar invdet = Scalar(1) / det;
compute_inverse_size3_helper(matrix, invdet, cofactors_col0, result);
if(extract_data(matrix) != extract_data(result)) {
compute_inverse_size3_helper(matrix, invdet, cofactors_col0, result);
} else {
MatrixType matrix_t = matrix;
compute_inverse_size3_helper(matrix_t, invdet, cofactors_col0, result);
}
}
};
@ -191,7 +197,12 @@ struct compute_inverse_and_det_with_check<MatrixType, ResultType, 3>
invertible = abs(determinant) > absDeterminantThreshold;
if(!invertible) return;
const Scalar invdet = Scalar(1) / determinant;
compute_inverse_size3_helper(matrix, invdet, cofactors_col0, inverse);
if(extract_data(matrix) != extract_data(inverse)) {
compute_inverse_size3_helper(matrix, invdet, cofactors_col0, inverse);
} else {
MatrixType matrix_t = matrix;
compute_inverse_size3_helper(matrix_t, invdet, cofactors_col0, inverse);
}
}
};
@ -273,7 +284,13 @@ struct compute_inverse_and_det_with_check<MatrixType, ResultType, 4>
using std::abs;
determinant = matrix.determinant();
invertible = abs(determinant) > absDeterminantThreshold;
if(invertible) compute_inverse<MatrixType, ResultType>::run(matrix, inverse);
if(invertible && extract_data(matrix) != extract_data(inverse)) {
compute_inverse<MatrixType, ResultType>::run(matrix, inverse);
}
else if(invertible) {
MatrixType matrix_t = matrix;
compute_inverse<MatrixType, ResultType>::run(matrix_t, inverse);
}
}
};
@ -347,6 +364,8 @@ inline const Inverse<Derived> MatrixBase<Derived>::inverse() const
*
* This is only for fixed-size square matrices of size up to 4x4.
*
* Notice that it will trigger a copy of input matrix when trying to do the inverse in place.
*
* \param inverse Reference to the matrix in which to store the inverse.
* \param determinant Reference to the variable in which to store the determinant.
* \param invertible Reference to the bool variable in which to store whether the matrix is invertible.
@ -387,6 +406,8 @@ inline void MatrixBase<Derived>::computeInverseAndDetWithCheck(
*
* This is only for fixed-size square matrices of size up to 4x4.
*
* Notice that it will trigger a copy of input matrix when trying to do the inverse in place.
*
* \param inverse Reference to the matrix in which to store the inverse.
* \param invertible Reference to the bool variable in which to store whether the matrix is invertible.
* \param absDeterminantThreshold Optional parameter controlling the invertibility check.