diff --git a/.clang-format b/.clang-format index c4fdf5b..33de25e 100644 --- a/.clang-format +++ b/.clang-format @@ -14,7 +14,7 @@ AccessModifierOffset: -4 DerivePointerAlignment: false PointerAlignment: Left # Use 100 columns -ColumnLimit: 100 +ColumnLimit: 120 AlignConsecutiveStyle: Consecutive AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: Never @@ -29,4 +29,5 @@ NamespaceIndentation: All IndentAccessModifiers: false ReferenceAlignment: Right BreakConstructorInitializers: AfterColon +AlignArrayOfStructures: Right ... diff --git a/raytracing/src/color.cpp b/raytracing/src/color.cpp index 9327f4a..37aff07 100644 --- a/raytracing/src/color.cpp +++ b/raytracing/src/color.cpp @@ -74,6 +74,11 @@ bool Color::operator==(const Color &a_color) const const Color &Color::operator=(const Color &a_color) { + if (this == &a_color) + { + return *this; + } + m_red = a_color.m_red; m_green = a_color.m_green; m_blue = a_color.m_blue; diff --git a/raytracing/src/matrix.cpp b/raytracing/src/matrix.cpp index 87d9b71..5e513bf 100644 --- a/raytracing/src/matrix.cpp +++ b/raytracing/src/matrix.cpp @@ -38,18 +38,98 @@ using namespace Raytracer; /* ------------------------------------------------------------------------- */ -Matrix::Matrix(void) +Matrix::Matrix(void) : m_rows(0), m_cols(0) { + m_data = std::vector>(m_rows, std::vector(m_cols)); } /* ------------------------------------------------------------------------- */ -Matrix::Matrix(const Matrix &a_copy) +Matrix::Matrix(uint8_t a_rows, uint8_t a_cols) : m_rows(a_rows), m_cols(a_cols) { + m_data = std::vector>(m_rows, std::vector(m_cols)); } /* ------------------------------------------------------------------------- */ -Matrix::Matrix(uint8_t a_nb_row, uint8_t a_nb_col) +Matrix::Matrix(const std::initializer_list> &a_values) : + m_rows(a_values.size()), m_cols(a_values.size()) { + m_data = std::vector>(m_rows, std::vector(m_cols)); + if (!validate_dimensions(a_values)) + { + fprintf(stderr, "Error: All rows must have the same number of columns.\n"); + std::exit(EXIT_FAILURE); + } + std::size_t i = 0; + for (const auto &the_row : a_values) + { + std::copy(the_row.begin(), the_row.end(), m_data[i++].begin()); + } +} + +/* ------------------------------------------------------------------------- */ + +uint8_t Matrix::rows(void) +{ + return m_rows; +} + +/* ------------------------------------------------------------------------- */ + +uint8_t Matrix::cols(void) +{ + return m_cols; +} + +/* ------------------------------------------------------------------------- */ + +std::vector &Matrix::operator[](uint8_t an_index) +{ + return m_data[an_index]; +} + +/* ------------------------------------------------------------------------- */ + +const std::vector &Matrix::operator[](uint8_t an_index) const +{ + return m_data[an_index]; +} + +/* ------------------------------------------------------------------------- */ + +bool Matrix::operator==(const Matrix &a_matrix) const +{ + for (auto the_it1 = m_data.cbegin(), the_it2 = a_matrix.m_data.cbegin(); the_it1 != m_data.cend(); + ++the_it1, ++the_it2) + { + for (auto the_elem1 = the_it1->cbegin(), the_elem2 = the_it2->cbegin(); the_elem1 != the_it1->cend(); + ++the_elem1, ++the_elem2) + { + if (!double_equal(*the_elem1, *the_elem2)) + return false; + } + } + return true; +} + +/* ------------------------------------------------------------------------- */ + +bool Matrix::operator!=(const Matrix &a_matrix) const +{ + return !(*this == a_matrix); +} + +/* ------------------------------------------------------------------------- */ + +bool Matrix::validate_dimensions(const std::initializer_list> &a_values) const +{ + for (const auto &the_row : a_values) + { + if (the_row.size() != m_cols) + { + return false; + } + } + return true; } diff --git a/raytracing/src/matrix.h b/raytracing/src/matrix.h index 78428d0..32caa36 100644 --- a/raytracing/src/matrix.h +++ b/raytracing/src/matrix.h @@ -29,6 +29,8 @@ /* ------------------------------------------------------------------------- */ #include +#include +#include /* ------------------------------------------------------------------------- */ @@ -38,10 +40,25 @@ namespace Raytracer { public: Matrix(void); - Matrix(const Matrix &a_copy); - Matrix(uint8_t a_nb_row, uint8_t a_nb_col); + Matrix(uint8_t a_rows, uint8_t a_cols); + Matrix(const std::initializer_list> &a_values); + + uint8_t rows(void); + uint8_t cols(void); + + std::vector &operator[](uint8_t an_index); + const std::vector &operator[](uint8_t an_index) const; + + bool operator==(const Matrix &a_matrix) const; + bool operator!=(const Matrix &a_matrix) const; private: + bool validate_dimensions(const std::initializer_list> &a_values) const; + + private: + std::vector> m_data; + uint8_t m_rows; + uint8_t m_cols; }; }; // namespace Raytracer diff --git a/raytracing/src/tuple.cpp b/raytracing/src/tuple.cpp index 6639f39..02f1ccc 100644 --- a/raytracing/src/tuple.cpp +++ b/raytracing/src/tuple.cpp @@ -75,6 +75,11 @@ bool Tuple::operator==(const Tuple &an_other) const const Tuple &Tuple::operator=(const Tuple &an_other) { + if (this == &an_other) + { + return *this; + } + m_x = an_other.m_x; m_y = an_other.m_y; m_z = an_other.m_z; diff --git a/tests/02_1_colors.cpp b/tests/02_1_colors.cpp index 3d5d2df..97ff31f 100644 --- a/tests/02_1_colors.cpp +++ b/tests/02_1_colors.cpp @@ -1,5 +1,5 @@ /*! - * 02_colors.cpp + * 02_1_colors.cpp * * Copyright (c) 2015-2024, NADAL Jean-Baptiste. All rights reserved. * diff --git a/tests/02_2_canvas.cpp b/tests/02_2_canvas.cpp index 768e221..57e0cd0 100644 --- a/tests/02_2_canvas.cpp +++ b/tests/02_2_canvas.cpp @@ -1,5 +1,5 @@ /*! - * 03_canvas.cpp + * 02_2_canvas.cpp * * Copyright (c) 2015-2024, NADAL Jean-Baptiste. All rights reserved. * diff --git a/tests/03_matrix.cpp b/tests/03_matrix.cpp index e69de29..c607e98 100644 --- a/tests/03_matrix.cpp +++ b/tests/03_matrix.cpp @@ -0,0 +1,131 @@ +/*! + * 03_matrix.cpp + * + * Copyright (c) 2015-2024, NADAL Jean-Baptiste. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * @Author: NADAL Jean-Baptiste + * @Date: 01/02/2024 + * + */ + +/*---------------------------------------------------------------------------*/ + +#include + +#include "matrix.h" + +using namespace Raytracer; + +/* ------------------------------------------------------------------------- */ + +TEST_CASE("[Matrix] Constructing and inspecting a 4x4 matrix", "[Matrix]") +{ + Matrix m = { + { 1, 2, 3, 4}, + { 5.5, 6.5, 7.5, 8.5}, + { 9, 10, 11, 12}, + {13.5, 14.5, 15.5, 16.5} + }; + + REQUIRE(m.rows() == 4); + REQUIRE(m.cols() == 4); + + REQUIRE(m[0][0] == 1); + REQUIRE(m[0][3] == 4); + REQUIRE(m[1][0] == 5.5); + REQUIRE(m[1][2] == 7.5); + REQUIRE(m[2][2] == 11); + REQUIRE(m[3][0] == 13.5); + REQUIRE(m[3][2] == 15.5); +} + +/* ------------------------------------------------------------------------- */ + +TEST_CASE("[Matrix] A 2x2 matrix ought to be representable", "[Matrix]") +{ + Matrix m = { + {-3, 5}, + { 1, -2} + }; + + REQUIRE(m.rows() == 2); + REQUIRE(m.cols() == 2); + + REQUIRE(m[0][0] == -3); + REQUIRE(m[0][1] == 5); + REQUIRE(m[1][0] == 1); + REQUIRE(m[1][1] == -2); +} + +/* ------------------------------------------------------------------------- */ + +TEST_CASE("[Matrix] A 3x3 matrix ought to be representable", "[Matrix]") +{ + Matrix m = { + {-3, 5, 0}, + { 1, -2, -7}, + { 0, 1, 1} + }; + + REQUIRE(m.rows() == 3); + REQUIRE(m.cols() == 3); + + REQUIRE(m[0][0] == -3); + REQUIRE(m[1][1] == -2); + REQUIRE(m[2][2] == 1); +} + +/* ------------------------------------------------------------------------- */ + +TEST_CASE("[Matrix] Matrix equality with identical matrices", "[Matrix]") +{ + Matrix a = { + {1, 2, 3, 4}, + {5, 6, 7, 8}, + {9, 8, 7, 6}, + {5, 4, 3, 2} + }; + Matrix b = { + {1, 2, 3, 4}, + {5, 6, 7, 8}, + {9, 8, 7, 6}, + {5, 4, 3, 2} + }; + + REQUIRE(a == b); +} + +/* ------------------------------------------------------------------------- */ + +TEST_CASE("[Matrix] Matrix equality with different matrices", "[Matrix]") +{ + Matrix a = { + {1, 2, 3, 4}, + {5, 6, 7, 8}, + {9, 8, 7, 6}, + {5, 4, 3, 2} + }; + Matrix b = { + {2, 3, 4, 5}, + {6, 7, 8, 9}, + {8, 7, 6, 5}, + {4, 3, 2, 1} + }; + + REQUIRE(a != b); +}