Added a template pack initializer

This commit is contained in:
Quinn Henthorne
2024-12-13 16:37:40 -05:00
parent fb16c6f61b
commit 53f3766658
3 changed files with 60 additions and 57 deletions

View File

@@ -2,10 +2,45 @@
// will evaluate to true
#include "Matrix.hpp"
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <type_traits>
template <uint8_t rows, uint8_t columns>
Matrix<rows, columns>::Matrix(float value) {
this->Fill(value);
}
template <uint8_t rows, uint8_t columns>
Matrix<rows, columns>::Matrix(const std::array<float, rows * columns> &array) {
this->setMatrixToArray(array);
}
template <uint8_t rows, uint8_t columns>
template <typename... Args>
Matrix<rows, columns>::Matrix(Args... args) {
constexpr uint16_t arraySize{static_cast<uint16_t>(rows) *
static_cast<uint16_t>(columns)};
std::initializer_list<float> initList{static_cast<float>(args)...};
std::array<float, arraySize> data{};
// choose whichever buffer size is smaller for the copy length
uint32_t minSize =
std::min(arraySize, static_cast<uint16_t>(initList.size()));
memcpy(data.begin(), initList.begin(), minSize * sizeof(float));
this->setMatrixToArray(data);
}
template <uint8_t rows, uint8_t columns>
Matrix<rows, columns>::Matrix(const Matrix<rows, columns> &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 <uint8_t rows, uint8_t columns>
void Matrix<rows, columns>::setMatrixToArray(
const std::array<float, rows * columns> &array) {
@@ -23,42 +58,6 @@ void Matrix<rows, columns>::setMatrixToArray(
}
}
template <uint8_t rows, uint8_t columns>
Matrix<rows, columns>::Matrix(float value) {
this->Fill(value);
}
template <uint8_t rows, uint8_t columns>
Matrix<rows, columns>::Matrix(const std::array<float, rows * columns> &array) {
this->setMatrixToArray(array);
}
// template <uint8_t rows, uint8_t columns>
// template <typename... Args>
// Matrix<rows, columns>::Matrix(Args&&... args){
// // Initialize a std::array with the arguments
// if(typeid(args) == typeid(std::array<float, 4>)){
// this->setMatrixToArray(args);
// }
// else{
// std::array<float, rows*columns> values = {static_cast<float>(args)...};
// // now store the array in our internal matrix
// this->setMatrixToArray(values);
// }
// }
template <uint8_t rows, uint8_t columns>
Matrix<rows, columns>::Matrix(const Matrix<rows, columns> &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 <uint8_t rows, uint8_t columns>
Matrix<rows, columns> &
Matrix<rows, columns>::Add(const Matrix<rows, columns> &other,

View File

@@ -30,12 +30,11 @@ public:
* @brief Initialize a matrix as a copy of another matrix
*/
Matrix(const Matrix<rows, columns> &other);
// TODO: Figure out how to do this
/**
* @brief Initialize a matrix directly with any number of arguments
*/
// template <typename... Args>
// Matrix(Args&&... args);
template <typename... Args> Matrix(Args... args);
/**
* @brief Set all elements in this to value
*/

View File

@@ -11,9 +11,8 @@
#include <iostream>
TEST_CASE("Elementary Matrix Operations", "Matrix") {
std::array<float, 4> arr1{1, 2, 3, 4};
std::array<float, 4> 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<float, 9> 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<float, 9> 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<float, 9> 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<float, 9> 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<float, 6> 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<float, 2> 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<float, 16> 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") {