diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 13566b8..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/labo01/CMakeLists.txt b/labo01/CMakeLists.txt index 21ca42b..e206da3 100644 --- a/labo01/CMakeLists.txt +++ b/labo01/CMakeLists.txt @@ -5,6 +5,7 @@ project(labo01) # Setup language requirements set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") # Add .cpp and .h files set(HEADERS DenseStorage.h MatrixBase.h Matrix.h Math3D.h Vector.h Operators.h) diff --git a/labo01/DenseStorage.h b/labo01/DenseStorage.h index 4c2ec97..c0394b6 100644 --- a/labo01/DenseStorage.h +++ b/labo01/DenseStorage.h @@ -129,8 +129,7 @@ namespace gti320 { /** * Constructeur avec taille spécifiée */ - explicit DenseStorage(int _size) : m_data(nullptr), m_size(_size) { - m_data = new _Scalar[_size]; + explicit DenseStorage(int _size) : m_data(new _Scalar[_size]), m_size(_size) { setZero(); } @@ -138,17 +137,20 @@ namespace gti320 { * Constructeur de copie */ DenseStorage(const DenseStorage &other) - : m_data(nullptr), m_size(other.m_size) { - m_data = new _Scalar[m_size]; - memcpy(m_data, other.m_data, m_size); + : m_data(new _Scalar[m_size]), m_size(other.m_size) { + memcpy(m_data, other.m_data, m_size * sizeof(_Scalar)); } /** * Opérateur de copie */ DenseStorage &operator=(const DenseStorage &other) { - m_data = other.m_data; + if (m_size != other.size()) { + resize(other.size()); + } + m_size = other.m_size; + memcpy(m_data, other.m_data, m_size * sizeof(_Scalar)); return *this; } @@ -173,18 +175,19 @@ namespace gti320 { */ void resize(int _size) { auto *data = new _Scalar[_size]; -// memcpy(data, m_data, m_size); // ??? delete[] m_data; m_data = data; m_size = _size; + + setZero(); } /** * Met tous les éléments à zéro. */ void setZero() { - memset(m_data, 0, m_size); + memset(m_data, 0, m_size * sizeof(_Scalar)); } /** diff --git a/labo01/Matrix.h b/labo01/Matrix.h index 2a580f2..b878a97 100644 --- a/labo01/Matrix.h +++ b/labo01/Matrix.h @@ -11,6 +11,7 @@ * */ +#include #include "MatrixBase.h" namespace gti320 { @@ -59,13 +60,15 @@ namespace gti320 { */ template Matrix &operator=(const SubMatrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage> &submatrix) { - if (_RowsAtCompile != _OtherRows || _ColsAtCompile != _OtherCols) { - this->resize(_OtherRows, _OtherCols); + if (this->rows() != submatrix->rows() || this->cols() != submatrix->cols()) { + this->resize(submatrix->rows(), submatrix->cols()); } - // TODO copier les données de la sous-matrice. - // Note : si les dimensions ne correspondent pas, la matrice doit être redimensionnée. - // Vous pouvez présumer qu'il s'agit d'un stockage par colonnes. + for (int i = 0; i < this->rows(); i++) { + for (int j = 0; j < this->cols(); j++) { + this(i, j) = submatrix(i, j); + } + } return *this; } @@ -73,18 +76,16 @@ namespace gti320 { * Accesseur à une entrée de la matrice (lecture seule) */ _Scalar operator()(int i, int j) const { - // TODO implementer - return (double) (i + j); + int index = i * this->cols() + j; + return this->m_storage.data()[index]; } /** * Accesseur à une entrée de la matrice (lecture ou écriture) */ _Scalar &operator()(int i, int j) { - // TODO implementer - // Indice : l'implémentation est identique à celle de la fonction précédente. - _Scalar x = (double) (i + j); - return x; + int index = i * this->cols() + j; + return this->m_storage.data()[index]; } /** @@ -107,17 +108,25 @@ namespace gti320 { */ template Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage> transpose() const { - // TODO calcule et retourne la transposée de la matrice. - - return Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage>(); // pas bon, à changer + auto transposed = Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage>(this->cols(), this->rows()); + for (int i = 0; i < this->rows(); i++) { + for (int j = 0; j < this->cols(); j++) { + transposed(j, i) = (*this)(i, j); + } + } + return transposed; } /** * Affecte l'identité à la matrice */ inline void setIdentity() { - // TODO affecter la valeur 0.0 partour, sauf sur la diagonale principale où c'est 1.0.. - // Votre implémentation devrait aussi fonctionner pour des matrices qui ne sont pas carrées. + this->m_storage.setZero(); + int smallest = std::min(this->rows(), this->cols()); + + for (int i = 0; i < smallest; i++) { + (*this)(i, i) = 1; + } } }; @@ -157,11 +166,15 @@ namespace gti320 { */ template Matrix &operator=(const SubMatrix<_OtherScalar, OtherRows, _OtherCols, _OtherStorage> &submatrix) { + if (this->rows() != submatrix->rows() || this->cols() != submatrix->cols()) { + this->resize(submatrix->rows(), submatrix->cols()); + } - - // TODO copier les données de la sous-matrice. - // Note : si les dimensions ne correspondent pas, la matrice doit être redimensionnée. - // Vous pouvez présumer qu'il s'agit d'un stockage par lignes. + for (int j = 0; j < this->cols(); j++) { + for (int i = 0; i < this->rows(); i++) { + this(i, j) = submatrix(i, j); + } + } return *this; } @@ -169,17 +182,16 @@ namespace gti320 { * Accesseur à une entrée de la matrice (lecture seule) */ _Scalar operator()(int i, int j) const { - // TODO implementer - return 0.0; + int index = j * this->rows() + i; + return this->m_storage.data()[index]; } /** * Accesseur à une entrée de la matrice (lecture ou écriture) */ _Scalar &operator()(int i, int j) { - // TODO implementer - _Scalar x = 0.0; - return x; + int index = j * this->rows() + i; + return this->m_storage.data()[index]; } /** @@ -200,19 +212,28 @@ namespace gti320 { /** * Retourne la transposée de la matrice */ - Matrix<_Scalar, _ColsAtCompile, _RowsAtCompile, ColumnStorage> transpose() const { - // TODO calcule et retourne la transposée de la matrice. - // Optimisez cette fonction en tenant compte du type de stockage utilisé. + Matrix<_Scalar, _RowsAtCompile, _ColsAtCompile, ColumnStorage> transpose() const { + auto t = Matrix<_Scalar, _RowsAtCompile, _ColsAtCompile, ColumnStorage>(this->cols(), this->rows()); - return Matrix<_Scalar, _ColsAtCompile, _RowsAtCompile, ColumnStorage>(); + for (int i = 0; i < this->rows(); i++) { + for (int j = 0; j < this->cols(); j++) { + t(j, i) = (*this)(i, j); + } + } + + return t; } /** * Affecte l'identité à la matrice */ inline void setIdentity() { - // TODO affecter la valeur 0.0 partour, sauf sur la diagonale principale où c'est 1.0.. - // Votre implémentation devrait aussi fonctionner pour des matrices qui ne sont pas carrées. + this->m_storage.setZero(); + + int small_size = std::min(this->rows(), this->cols()); + for (int i = 0; i < small_size; i++) { + (*this)(i, i) = 1; + } } }; @@ -284,9 +305,15 @@ namespace gti320 { */ template SubMatrix &operator=(const Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage> &matrix) { - // TODO Cpopie les valeurs de la matrice dans la sous-matrice. - // Note les dimensions de la matrice doivent correspondre à celle de - // la sous-matrice. + assert(this->rows() == matrix.rows()); + assert(this->cols() == matrix.cols()); + + for (int i = 0; i < this->rows(); i++) { + for (int j = 0; j < this->cols(); j++) { + (*this)(i, j) = matrix(i, j); + } + } + return *this; } @@ -297,16 +324,15 @@ namespace gti320 { * sous-matrice */ _Scalar operator()(int i, int j) const { - assert(i > 0); - assert(i <= m_rows); - assert(j > 0); - assert(j <= m_cols); + assert(i >= 0); + assert(i <= this->rows()); + assert(j >= 0); + assert(j <= this->cols()); int full_i = this->m_i + i; int full_j = this->m_j + j; - int storage_index = full_i * this->m_matrix.rows() + full_j; - return this->m_matrix.data()[storage_index]; + return this->m_matrix(full_i, full_j); } /** @@ -316,9 +342,14 @@ namespace gti320 { * sous-matrice */ _Scalar &operator()(int i, int j) { - // TODO implémenter - _Scalar x = 0.0; - return x; + assert(i >= 0); + assert(i <= this->rows()); + assert(j >= 0); + assert(j <= this->cols()); + + int full_i = this->m_i + i; + int full_j = this->m_j + j; + return this->m_matrix(full_i, full_j); } /** @@ -326,8 +357,15 @@ namespace gti320 { */ template Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage> transpose() const { - // TODO implémenter - return Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage>(); + auto t = Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage>(this->rows(), this->cols()); + + for (int i = 0; i < this->rows(); i++) { + for (int j = 0; j < this->cols(); j++) { + t(j, i) = (*this)(i, j); + } + } + + return t; } inline int rows() const { return m_rows; } diff --git a/labo01/Vector.h b/labo01/Vector.h index 441a5ba..8676e3d 100644 --- a/labo01/Vector.h +++ b/labo01/Vector.h @@ -50,7 +50,6 @@ namespace gti320 { * Opérateur de copie */ Vector &operator=(const Vector &other) { - // TODO implémenter this->m_storage = other.m_storage; return *this; } @@ -59,7 +58,7 @@ namespace gti320 { * Accesseur à une entrée du vecteur (lecture seule) */ _Scalar operator()(int i) const { - return this->data()[i]; + return this->m_storage.data()[i]; } /** @@ -84,7 +83,7 @@ namespace gti320 { _Scalar product = 0; for (int i = 0; i < this->size(); i++) { - product += this->data()[i] * other.data()[i]; + product += (*this)(i) * other(i); } return product; @@ -97,7 +96,7 @@ namespace gti320 { _Scalar norm = 0; for (int i = 0; i < this->size(); i++) { - norm += std::pow(this->data()[i], 2); + norm += std::pow((*this)(i), 2); } return std::sqrt(norm); diff --git a/labo01/main.cpp b/labo01/main.cpp index 92fb279..efea96c 100644 --- a/labo01/main.cpp +++ b/labo01/main.cpp @@ -507,8 +507,96 @@ TEST(TestLabo1, PerformanceLargeMatrixMatrix) TEST(TestLabo1, Supplementaires) { - // TODO remplacez le code avec vos propres tests ici - EXPECT_TRUE(false); + // === Stockage === + // Test 1: Set zero + DenseStorage S1(10); + S1.setZero(); + for (int i = 0; i < S1.size(); i++) { + EXPECT_EQ(S1.data()[i], 0); + } + + // Test 2: Resize dynamique + int size = 16; + S1.resize(size); + EXPECT_EQ(S1.size(), size); + + // Test 3: Resize statique + DenseStorage S2; + S2.resize(size); + EXPECT_EQ(S2.size(), 10); + + // Test 4: Copie + DenseStorage S3(20); + S3.data()[5] = 123; + S3.data()[7] = 321; + S1 = S3; + EXPECT_EQ(S1.size(), S3.size()); + EXPECT_EQ(S1.data()[5], S3.data()[5]); + EXPECT_EQ(S1.data()[7], S3.data()[7]); + + // === Matrices === + // Test 5: Identité + Matrix MC(4, 6); + MC.setIdentity(); + for (int i = 0; i < MC.rows(); i++) { + for (int j = 0; j < MC.cols(); j++) { + int expected = 0; + if (i == j) { + expected = 1; + } + + EXPECT_EQ(MC(i, j), expected); + } + } + + // Test 6: Création d'une sous-matrice + MC(1, 1) = 1; + MC(1, 2) = 2; + MC(1, 3) = 3; + MC(2, 1) = 4; + MC(2, 2) = 5; + MC(2, 3) = 6; + MC(3, 1) = 7; + MC(3, 2) = 8; + MC(3, 3) = 9; + SubMatrix s = MC.block(1, 1, 3, 3); + for (int i = 0; i < s.rows(); i++) { + for (int j = 0; j < s.cols(); j++) { + EXPECT_EQ(s(i, j), MC(i + 1, j + 1)); + } + } + + // Test 7: Transposée d'une sous-matrice + const Matrix t = s.transpose(); + for (int i = 0; i < t.rows(); i++) { + for (int j = 0; j < t.cols(); j++) { + EXPECT_EQ(t(j, i), s(i, j)); + } + } + + // Test 8: Stockage par colonne + MC(0, 0) = 4; + MC(1, 0) = 5; + MC(0, 1) = 6; + EXPECT_EQ(MC.data()[0], MC(0, 0)); + EXPECT_EQ(MC.data()[1], MC(0, 1)); + + // Test 9: Stockage par rangée + Matrix MS(4, 6); + MS(0, 0) = 4; + MS(1, 0) = 5; + MS(0, 1) = 6; + EXPECT_EQ(MS.data()[0], MS(0, 0)); + EXPECT_EQ(MS.data()[1], MS(1, 0)); + + // === Vecteurs === + // Test 10: Copie + Vector V1(10); + Vector V2(16); + V2(12) = 543; + V1 = V2; + EXPECT_EQ(V1.size(), V2.size()); + EXPECT_EQ(V1(12), V2(12)); } int main(int argc, char** argv)