From c07e9b265213a847670c24a094de1735d1147186 Mon Sep 17 00:00:00 2001 From: Stephane Del Pino <stephane.delpino44@gmail.com> Date: Mon, 5 Oct 2020 18:39:33 +0200 Subject: [PATCH] Fix TinyMatrix determinant for N>3 The case of zero determinant was not treated correctly when dealing with N*N matrices with N>4 For these matrices, a Gauss-pivot is used but it was incorrect in the singular case --- src/algebra/TinyMatrix.hpp | 31 ++++++++++++++++++++----------- tests/test_TinyMatrix.cpp | 3 +++ 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/algebra/TinyMatrix.hpp b/src/algebra/TinyMatrix.hpp index 3ef5e1807..a4499baa4 100644 --- a/src/algebra/TinyMatrix.hpp +++ b/src/algebra/TinyMatrix.hpp @@ -50,14 +50,16 @@ class TinyMatrix } PUGS_INLINE - constexpr friend TinyMatrix operator*(const T& t, const TinyMatrix& A) + constexpr friend TinyMatrix + operator*(const T& t, const TinyMatrix& A) { TinyMatrix B = A; return B *= t; } PUGS_INLINE - constexpr friend TinyMatrix operator*(const T& t, TinyMatrix&& A) + constexpr friend TinyMatrix + operator*(const T& t, TinyMatrix&& A) { return std::move(A *= t); } @@ -73,7 +75,8 @@ class TinyMatrix } PUGS_INLINE - constexpr TinyMatrix operator*(const TinyMatrix& B) const + constexpr TinyMatrix + operator*(const TinyMatrix& B) const { const TinyMatrix& A = *this; TinyMatrix AB; @@ -90,7 +93,8 @@ class TinyMatrix } PUGS_INLINE - constexpr TinyVector<N, T> operator*(const TinyVector<N, T>& x) const + constexpr TinyVector<N, T> + operator*(const TinyVector<N, T>& x) const { const TinyMatrix& A = *this; TinyVector<N, T> Ax; @@ -342,14 +346,19 @@ det(const TinyMatrix<N, T>& A) determinent *= -1; } } - const size_t I = index[i]; - const T inv_Mii = 1. / M(I, i); - for (size_t k = i + 1; k < N; ++k) { - const size_t K = index[k]; - const T factor = M(K, i) * inv_Mii; - for (size_t l = i + 1; l < N; ++l) { - M(K, l) -= factor * M(I, l); + const size_t I = index[i]; + const T Mii = M(I, i); + if (Mii != 0) { + const T inv_Mii = 1. / M(I, i); + for (size_t k = i + 1; k < N; ++k) { + const size_t K = index[k]; + const T factor = M(K, i) * inv_Mii; + for (size_t l = i + 1; l < N; ++l) { + M(K, l) -= factor * M(I, l); + } } + } else { + return 0; } } diff --git a/tests/test_TinyMatrix.cpp b/tests/test_TinyMatrix.cpp index e0d7ef39d..0d3510dc3 100644 --- a/tests/test_TinyMatrix.cpp +++ b/tests/test_TinyMatrix.cpp @@ -161,9 +161,12 @@ TEST_CASE("TinyMatrix", "[algebra]") { REQUIRE(det(TinyMatrix<1, int>(6)) == 6); REQUIRE(det(TinyMatrix<2, int>(3, 1, -3, 6)) == 21); + REQUIRE(det(TinyMatrix<3, int>(1, 1, 1, 1, 2, 1, 2, 1, 3)) == 1); REQUIRE(det(B) == -1444); REQUIRE(det(TinyMatrix<4, double>(1, 2.3, 7, -6.2, 3, 4, 9, 1, 4.1, 5, 2, -3, 2, 27, 3, 17.5)) == Approx(6661.455).epsilon(1E-14)); + + REQUIRE(det(TinyMatrix<4, double>(1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 2, 0, 0, 2, 2)) == 0); } SECTION("checking for inverse calculations") -- GitLab