From 1d45c1ae31fc13ceeaf50480603c808928d90e10 Mon Sep 17 00:00:00 2001 From: FyloZ Date: Wed, 14 Feb 2024 18:17:17 -0500 Subject: [PATCH] Finalisation --- labo01/Operators.h | 127 +++++++++++++++++++++++++++++++++------------ labo01/main.cpp | 82 ++++++++++++++++++++++------- 2 files changed, 158 insertions(+), 51 deletions(-) diff --git a/labo01/Operators.h b/labo01/Operators.h index 0075e2c..4454405 100644 --- a/labo01/Operators.h +++ b/labo01/Operators.h @@ -306,13 +306,102 @@ namespace gti320 { } } + template + bool is_identity(const Matrix<_Scalar, _Rows, _Cols> &m) { + for (int i = 0; i < m.rows(); i++) { + if (m(i, i) != 1) { + return false; + } + } + + return true; + } + + template + bool is_triangle(const Matrix<_Scalar, _Rows, _Cols> &m) { + int n = m.rows(); + + int lower, upper = 0; + int required_zero = 0; + for (int i = 1; i < n; i++) { + required_zero += i; + } + + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (i < j && m(i, j) == 0) { + upper++; + } + + if (j < i && m(i, j) == 0) { + lower++; + } + + if (lower == n || upper == n) { + return true; + } + } + } + + return false; + } + + // Calcul générique du déterminant + template + double det(const Matrix<_Scalar, _Rows, _Cols> &m) { + assert(m.rows() == m.cols()); + + // Cherche d'abord pour un algorithme plus simple + if (is_identity(m)) { + return 1; + } + if (is_triangle(m)) { + return det_tri(m); + } + + int n = m.rows(); + auto l = Matrix(); + auto u = Matrix(); + + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + // L + if (i < j) { + l(i, j) = 0; + } else if (j == i) { + l(i, j) = 1; + } else { + l(i, j) = m(i, j) / u(j, j); + for (int k = 0; k < j; k++) { + l(i, j) -= (u(k, j) * l(i, k)) / u(j, j); + } + } + + // U + if (j < i) { + u(i, j) = 0; + } else { + u(i, j) = m(i, j); + for (int k = 0; k < i; k++) { + u(i, j) -= l(i, k) * u(k, j); + } + } + } + } + + // Det(L) = 1, on peut l'ignorer + return det_tri(u); + } + + // Déterminant d'une matrice 1x1 template - _Scalar det(const Matrix<_Scalar, 1, 1> &m) { + double det(const Matrix<_Scalar, 1, 1> &m) { return m(0, 0); } + // Déterminant d'une matrice 2x2 template - _Scalar det(const Matrix<_Scalar, 2, 2> &m) { + double det(const Matrix<_Scalar, 2, 2> &m) { _Scalar a = m(0, 0); _Scalar b = m(0, 1); _Scalar c = m(1, 0); @@ -321,40 +410,12 @@ namespace gti320 { return (a * d) - (b * c); } + // Déterminant d'une matrice triangulaire template - double det(const Matrix<_Scalar, _Rows, _Cols> &m) { - assert(m.rows() == m.cols()); - - auto l = Matrix(); - auto u = Matrix(); - - for (int j = 0; j < m.cols(); j++) { - for (int i = 0; i < m.rows(); i++) { - u(i, j) = m(i, j); - l(i, j) = m(i, j); - - for (int k = 0; k < i; k++) { - u(i, j) -= l(i, k) * u(k, j); - } - - for (int k = 0; k < j; k++) { - l(i, j) -= l(i, k) * u(k, j); - } - - l(i, j) = 1 / u(j, j); - } - } - - print_matrix(l); - print_matrix(u); - return det_tri(l) * det_tri(u); - } - - template - _Scalar det_tri(const Matrix<_Scalar, _Rows, _Cols> &m) { + double det_tri(const Matrix<_Scalar, _Rows, _Cols> &m) { int n = std::min(m.rows(), m.cols()); - int det = 1; + double det = 1; for (int i = 0; i < n; i++) { det *= m(i, i); } diff --git a/labo01/main.cpp b/labo01/main.cpp index 61da7a4..6e7a6e0 100644 --- a/labo01/main.cpp +++ b/labo01/main.cpp @@ -125,8 +125,6 @@ TEST(TestLabo1, DynamicMatrixTests) { EXPECT_DOUBLE_EQ(RowMT(2, 3), 0.0); } - - /** * Test pour les vecteurs à taille dynamique */ @@ -557,6 +555,18 @@ TEST(TestLabo1, PerformanceLargeMatrixMatrix) { EXPECT_TRUE(optimal_t < 0.4 * naive_t); } +template +Matrix<_Scalar, _Rows, _Cols> build_test_matrix() { + Matrix<_Scalar, _Rows, _Cols> m; + int n = m.rows(); + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + m(i, j) = i * m.rows() + j + 1; + } + } + return m; +} + TEST(TestLabo1, Supplementaires) { // === Stockage === // Test 1: Set zero @@ -670,30 +680,66 @@ TEST(TestLabo1, Supplementaires) { EXPECT_EQ(V5(i), V4(i)); } - // === Déterminants === - Matrix MD1x1; - MD1x1(0, 0) = 1; - - Matrix MD2x2; - MD2x2(0, 0) = 1; MD2x2(0, 1) = 2; - MD2x2(1, 0) = 3; MD2x2(1, 1) = 4; - - Matrix MD3x3; - MD3x3(0, 0) = 1; MD3x3(0, 1) = 2; MD3x3(0, 2) = 3; - MD3x3(1, 0) = 4; MD3x3(1, 1) = 5; MD3x3(1, 2) = 6; - MD3x3(2, 0) = 7; MD3x3(2, 1) = 9; MD3x3(2, 2) = 0; + // === Déterminants ==== + auto MD1x1 = build_test_matrix(); + auto MD2x2 = build_test_matrix(); + auto MD3x3 = build_test_matrix(); // Test 13: 1x1 - int det1 = det(MD1x1); + double det1 = det(MD1x1); EXPECT_EQ(det1, MD1x1(0, 0)); // Test 14: 2x2 - int det2 = det(MD2x2); + double det2 = det(MD2x2); EXPECT_EQ(det2, -2); // Test 15: 3x3 - int det3 = det(MD3x3); - EXPECT_EQ(det3, 33); + MD3x3(2, 1) = 9; + MD3x3(2, 2) = 0; + double det3 = det(MD3x3); + EXPECT_NEAR(det3, 33, 0.1); + + // Test 16: Identité + Matrix MI; + MI.setIdentity(); + double detI = det(MI); + EXPECT_EQ(detI, 1); + + // Test 17: Triangle + MD3x3(0, 0) = 1; + MD3x3(0, 1) = 0; + MD3x3(0, 2) = 0; + MD3x3(1, 0) = 4; + MD3x3(1, 1) = 5; + MD3x3(1, 2) = 0; + MD3x3(2, 0) = 7; + MD3x3(2, 1) = 9; + MD3x3(2, 2) = 3; + double detT = det(MD3x3); + EXPECT_EQ(detT, 1 * 5 * 3); + + // Test 18: Triangle avec 0 + MD3x3(1, 1) = 0; + detT = det(MD3x3); + EXPECT_EQ(detT, 0); + + // Test 19: Matrix4d setIdentity + Matrix4d M4D; + M4D.setIdentity(); + for (int i = 0; i < M4D.rows(); i++) { + EXPECT_EQ(M4D(i, i), 1); + } + + // Test 20: build_test_matrix (Si ce test ne fonctionne pas, plusieurs autres tests seront aussi cassés) + auto BM = build_test_matrix(); + int n = 1; + for (int i = 0; i < BM.rows(); i++) { + for (int j = 0; j < BM.rows(); j++) { + EXPECT_EQ(BM(i, j), n); + + n++; + } + } } int main(int argc, char **argv) {