diff --git a/Matrix.cpp b/Matrix.cpp index c4e107c..d6864bc 100644 --- a/Matrix.cpp +++ b/Matrix.cpp @@ -2,10 +2,45 @@ // will evaluate to true #include "Matrix.hpp" +#include #include #include #include +template +Matrix::Matrix(float value) { + this->Fill(value); +} + +template +Matrix::Matrix(const std::array &array) { + this->setMatrixToArray(array); +} + +template +template +Matrix::Matrix(Args... args) { + constexpr uint16_t arraySize{static_cast(rows) * + static_cast(columns)}; + + std::initializer_list initList{static_cast(args)...}; + std::array data{}; + // choose whichever buffer size is smaller for the copy length + uint32_t minSize = + std::min(arraySize, static_cast(initList.size())); + memcpy(data.begin(), initList.begin(), minSize * sizeof(float)); + this->setMatrixToArray(data); +} + +template +Matrix::Matrix(const Matrix &other) { + for (uint8_t row_idx{0}; row_idx < rows; row_idx++) { + for (uint8_t column_idx{0}; column_idx < columns; column_idx++) { + this->matrix[row_idx][column_idx] = other.Get(row_idx, column_idx); + } + } +} + template void Matrix::setMatrixToArray( const std::array &array) { @@ -23,42 +58,6 @@ void Matrix::setMatrixToArray( } } -template -Matrix::Matrix(float value) { - this->Fill(value); -} - -template -Matrix::Matrix(const std::array &array) { - this->setMatrixToArray(array); -} - -// template -// template -// Matrix::Matrix(Args&&... args){ - -// // Initialize a std::array with the arguments -// if(typeid(args) == typeid(std::array)){ -// this->setMatrixToArray(args); -// } -// else{ -// std::array values = {static_cast(args)...}; - -// // now store the array in our internal matrix -// this->setMatrixToArray(values); -// } - -// } - -template -Matrix::Matrix(const Matrix &other) { - for (uint8_t row_idx{0}; row_idx < rows; row_idx++) { - for (uint8_t column_idx{0}; column_idx < columns; column_idx++) { - this->matrix[row_idx][column_idx] = other.Get(row_idx, column_idx); - } - } -} - template Matrix & Matrix::Add(const Matrix &other, diff --git a/Matrix.hpp b/Matrix.hpp index 54c9c1a..a2e9299 100644 --- a/Matrix.hpp +++ b/Matrix.hpp @@ -30,12 +30,11 @@ public: * @brief Initialize a matrix as a copy of another matrix */ Matrix(const Matrix &other); - // TODO: Figure out how to do this + /** * @brief Initialize a matrix directly with any number of arguments */ - // template - // Matrix(Args&&... args); + template Matrix(Args... args); /** * @brief Set all elements in this to value */ diff --git a/unit-tests/matrix-tests.cpp b/unit-tests/matrix-tests.cpp index f2ea173..09a3da9 100644 --- a/unit-tests/matrix-tests.cpp +++ b/unit-tests/matrix-tests.cpp @@ -11,9 +11,8 @@ #include TEST_CASE("Elementary Matrix Operations", "Matrix") { - std::array arr1{1, 2, 3, 4}; std::array arr2{5, 6, 7, 8}; - Matrix<2, 2> mat1{arr1}; + Matrix<2, 2> mat1{1, 2, 3, 4}; Matrix<2, 2> mat2{arr2}; Matrix<2, 2> mat3{}; @@ -29,7 +28,21 @@ TEST_CASE("Elementary Matrix Operations", "Matrix") { REQUIRE(mat3.Get(0, 1) == 0); REQUIRE(mat3.Get(1, 0) == 0); REQUIRE(mat3.Get(1, 1) == 0); - // TODO: what about a matrix of size 255x255? + + // template pack initialization + REQUIRE(mat2.Get(0, 0) == 5); + REQUIRE(mat2.Get(0, 1) == 6); + REQUIRE(mat2.Get(1, 0) == 7); + REQUIRE(mat2.Get(1, 1) == 8); + + // large matrix + Matrix<255, 255> mat6{}; + mat6.Fill(4); + for (uint8_t row{0}; row < 255; row++) { + for (uint8_t column{0}; column < 255; column++) { + REQUIRE(mat6.Get(row, column) == 4); + } + } } SECTION("Fill") { @@ -148,8 +161,7 @@ TEST_CASE("Elementary Matrix Operations", "Matrix") { REQUIRE(minorMat1.Get(0, 0) == 1); // minor matrix for 3x3 matrix - std::array arr4{1, 2, 3, 4, 5, 6, 7, 8, 9}; - Matrix<3, 3> mat4{arr4}; + Matrix<3, 3> mat4{1, 2, 3, 4, 5, 6, 7, 8, 9}; Matrix<2, 2> minorMat4{}; mat4.MinorMatrix(minorMat4, 0, 0); @@ -176,15 +188,13 @@ TEST_CASE("Elementary Matrix Operations", "Matrix") { REQUIRE_THAT(det1, Catch::Matchers::WithinRel(-2.0F, 1e-6f)); - std::array arr4{1, 2, 3, 4, 5, 6, 7, 8, 9}; - Matrix<3, 3> mat4{arr4}; + Matrix<3, 3> mat4{1, 2, 3, 4, 5, 6, 7, 8, 9}; float det4 = mat4.Det(); REQUIRE_THAT(det4, Catch::Matchers::WithinRel(0.0F, 1e-6f)); - std::array arr5{1, 0, 0, 0, 2, 0, 0, 0, 3}; - Matrix<3, 3> mat5{arr5}; + Matrix<3, 3> mat5{1, 0, 0, 0, 2, 0, 0, 0, 3}; float det5 = mat5.Det(); REQUIRE_THAT(det5, Catch::Matchers::WithinRel(6.0F, 1e-6f)); @@ -197,8 +207,7 @@ TEST_CASE("Elementary Matrix Operations", "Matrix") { REQUIRE_THAT(mat3.Get(1, 0), Catch::Matchers::WithinRel(2.0F, 1e-6f)); REQUIRE_THAT(mat3.Get(1, 1), Catch::Matchers::WithinRel(1.0F, 1e-6f)); - std::array arr4{1, 2, 3, 4, 5, 6, 7, 8, 9}; - Matrix<3, 3> mat4{arr4}; + Matrix<3, 3> mat4{1, 2, 3, 4, 5, 6, 7, 8, 9}; Matrix<3, 3> mat5{0}; mat4.MatrixOfMinors(mat5); REQUIRE_THAT(mat5.Get(0, 0), Catch::Matchers::WithinRel(-3.0F, 1e-6f)); @@ -230,8 +239,7 @@ TEST_CASE("Elementary Matrix Operations", "Matrix") { REQUIRE(mat3.Get(1, 1) == 4); // transpose a non-square matrix - std::array arr4{1, 2, 3, 4, 5, 6}; - Matrix<2, 3> mat4{arr4}; + Matrix<2, 3> mat4{1, 2, 3, 4, 5, 6}; Matrix<3, 2> mat5{}; mat4.Transpose(mat5); @@ -254,8 +262,7 @@ TEST_CASE("Elementary Matrix Operations", "Matrix") { REQUIRE(mat3.Get(1, 0) == 3 / sqrt_30); REQUIRE(mat3.Get(1, 1) == 4 / sqrt_30); - std::array arr4{-0.878877044, 2.92092276}; - Matrix<2, 1> mat4{arr4}; + Matrix<2, 1> mat4{-0.878877044, 2.92092276}; Matrix<2, 1> mat5{}; mat4.Normalize(mat5); @@ -304,9 +311,7 @@ TEST_CASE("Timing Tests", "Matrix") { Matrix<50, 50> mat3{}; // A smaller matrix to use for really badly optimized operations - std::array arr4{1, 2, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16}; - Matrix<4, 4> mat4{arr4}; + Matrix<4, 4> mat4{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; Matrix<4, 4> mat5{}; SECTION("Addition") {