All checks were successful
Build and Run C++ Unit Tests / build-and-test (push) Successful in 2m1s
267 lines
7.2 KiB
C++
267 lines
7.2 KiB
C++
#if GTEST
|
|
#include <gtest/gtest.h>
|
|
#include <math.h>
|
|
#include <limits>
|
|
|
|
#include "Matrix.h"
|
|
|
|
template <typename T>
|
|
bool isDefaultValue(const T& value) {
|
|
// Use std::is_floating_point to determine if T is a floating type
|
|
if constexpr (std::is_arithmetic<T>::value) {
|
|
return value == T(); // Default constructed value for T (0 or 0.0)
|
|
}
|
|
// return false; // Improve this if you handle non-arithmetic types
|
|
}
|
|
|
|
// using MatrixTypes = ::testing::Types<Matrix2Of<float>, Matrix2Of<int>>;
|
|
using BaseTypes = ::testing::Types<float, int>;
|
|
|
|
template <typename T>
|
|
class Matrix2Tests : public ::testing::Test {};
|
|
TYPED_TEST_SUITE(Matrix2Tests, BaseTypes);
|
|
|
|
TYPED_TEST(Matrix2Tests, Zero) {
|
|
using Matrix2 = Matrix2Of<TypeParam>;
|
|
// Test case 1: 2x2 zero matrix
|
|
Matrix2 zeroMatrix = Matrix2::Zero(2, 2);
|
|
EXPECT_TRUE(zeroMatrix.RowCount() == 2);
|
|
EXPECT_TRUE(zeroMatrix.ColCount() == 2);
|
|
for (unsigned int rowIx = 0; rowIx < zeroMatrix.RowCount(); ++rowIx) {
|
|
for (unsigned int colIx = 0; colIx < zeroMatrix.ColCount(); ++colIx)
|
|
EXPECT_TRUE(isDefaultValue(zeroMatrix(rowIx, colIx)));
|
|
}
|
|
std::cout << "Test case 1 passed: 2x2 zero matrix\n";
|
|
|
|
// Test case 2: 3x3 zero matrix
|
|
zeroMatrix = Matrix2::Zero(3, 3);
|
|
EXPECT_TRUE(zeroMatrix.RowCount() == 3);
|
|
EXPECT_TRUE(zeroMatrix.ColCount() == 3);
|
|
for (unsigned int rowIx = 0; rowIx < zeroMatrix.RowCount(); ++rowIx) {
|
|
for (unsigned int colIx = 0; colIx < zeroMatrix.ColCount(); ++colIx)
|
|
EXPECT_TRUE(isDefaultValue(zeroMatrix(rowIx, colIx)));
|
|
}
|
|
std::cout << "Test case 2 passed: 3x3 zero matrix\n";
|
|
|
|
// Test case 3: 1x1 zero matrix
|
|
zeroMatrix = Matrix2::Zero(1, 1);
|
|
EXPECT_TRUE(zeroMatrix.RowCount() == 1);
|
|
EXPECT_TRUE(zeroMatrix.ColCount() == 1);
|
|
EXPECT_TRUE(isDefaultValue(zeroMatrix(0, 0)));
|
|
std::cout << "Test case 3 passed: 1x1 zero matrix\n";
|
|
|
|
// Test case 4: 0x0 matrix (edge case)
|
|
zeroMatrix = Matrix2::Zero(0, 0);
|
|
EXPECT_TRUE(zeroMatrix.RowCount() == 0);
|
|
EXPECT_TRUE(zeroMatrix.ColCount() == 0);
|
|
std::cout << "Test case 4 passed: 0x0 matrix\n";
|
|
}
|
|
|
|
TYPED_TEST(Matrix2Tests, Multiplication) {
|
|
using T = TypeParam;
|
|
using Matrix2 = Matrix2Of<TypeParam>;
|
|
|
|
// Test 1: Multiplying two 2x2 matrices
|
|
T dataA[] = {1, 2, 3, 4};
|
|
T dataB[] = {5, 6, 7, 8};
|
|
Matrix2 A(2, 2, dataA);
|
|
Matrix2 B(2, 2, dataB);
|
|
|
|
Matrix2 result = A * B;
|
|
|
|
float expectedData[] = {19, 22, 43, 50};
|
|
// for (int i = 0; i < 4; ++i)
|
|
for (unsigned int rowIx = 0; rowIx < 2; ++rowIx) {
|
|
for (unsigned int colIx = 0; colIx < 2; ++colIx) {
|
|
EXPECT_TRUE(result(rowIx, colIx) == expectedData[rowIx * 2 + colIx]);
|
|
}
|
|
}
|
|
// EXPECT_TRUE(result.data[i] == expectedData[i]);
|
|
std::cout << "Test 1 passed: 2x2 matrix multiplication.\n";
|
|
|
|
// Test 2: Multiplying a 3x2 matrix with a 2x3 matrix
|
|
T dataC[] = {1, 2, 3, 4, 5, 6};
|
|
T dataD[] = {7, 8, 9, 10, 11, 12};
|
|
Matrix2 C(3, 2, dataC);
|
|
Matrix2 D(2, 3, dataD);
|
|
|
|
Matrix2 result2 = C * D;
|
|
|
|
float expectedData2[] = {27, 30, 33, 61, 68, 75, 95, 106, 117};
|
|
for (unsigned int rowIx = 0; rowIx < 3; ++rowIx) {
|
|
for (unsigned int colIx = 0; colIx < 3; ++colIx) {
|
|
EXPECT_TRUE(result2(rowIx, colIx) == expectedData2[rowIx * 3 + colIx]);
|
|
}
|
|
}
|
|
// for (int i = 0; i < 9; ++i)
|
|
// EXPECT_TRUE(result2.data[i] == expectedData2[i]);
|
|
std::cout << "Test 2 passed: 3x2 * 2x3 matrix multiplication.\n";
|
|
|
|
// Test 3: Multiplying with a zero matrix
|
|
Matrix2 zeroMatrix = Matrix2::Zero(2, 2);
|
|
Matrix2 result3 = A * zeroMatrix;
|
|
|
|
for (unsigned int rowIx = 0; rowIx < 2; ++rowIx) {
|
|
for (unsigned int colIx = 0; colIx < 2; ++colIx) {
|
|
EXPECT_TRUE(result3(rowIx, colIx) == 0);
|
|
}
|
|
}
|
|
// for (int i = 0; i < 4; ++i)
|
|
// EXPECT_TRUE(result3.data[i] == 0);
|
|
std::cout << "Test 3 passed: Multiplication with zero matrix.\n";
|
|
|
|
// Test 4: Multiplying with an identity matrix
|
|
Matrix2 identityMatrix = Matrix2::Identity(2);
|
|
Matrix2 result4 = A * identityMatrix;
|
|
|
|
for (unsigned int rowIx = 0; rowIx < 2; ++rowIx) {
|
|
for (unsigned int colIx = 0; colIx < 2; ++colIx) {
|
|
EXPECT_TRUE(result4(rowIx, colIx) == A(rowIx, colIx));
|
|
}
|
|
}
|
|
// for (int i = 0; i < 4; ++i)
|
|
// EXPECT_TRUE(result4.data[i] == A.data[i]);
|
|
std::cout << "Test 4 passed: Multiplication with identity matrix.\n";
|
|
}
|
|
|
|
template <typename T>
|
|
class Matrix1Test : public ::testing::Test {
|
|
protected:
|
|
};
|
|
TYPED_TEST_SUITE(Matrix1Test, BaseTypes);
|
|
|
|
TYPED_TEST(Matrix2Tests, Init) {
|
|
using Matrix2 = Matrix2Of<TypeParam>;
|
|
// zero
|
|
Matrix2 m0 = Matrix2(0, 0);
|
|
|
|
// one
|
|
Matrix2 m1 = Matrix2(1, 1);
|
|
m1(0, 0) = 1;
|
|
|
|
// two
|
|
Matrix2 m2 = Matrix2(2, 2);
|
|
m2(0, 0) = 1;
|
|
m2(0, 1) = 2;
|
|
m2(1, 0) = 3;
|
|
m2(1, 1) = 4;
|
|
|
|
// negative
|
|
// Matrix1 m_1 = Matrix1(-1, -1);
|
|
// parameters are unsigned
|
|
}
|
|
|
|
TYPED_TEST(Matrix2Tests, Transpose) {
|
|
using Matrix2 = Matrix2Of<TypeParam>;
|
|
Matrix2 m = Matrix2(1, 1);
|
|
m(0, 0) = 1;
|
|
|
|
Matrix2 r = Matrix2(1, 1);
|
|
m = r.Transposed();
|
|
|
|
// 2 x 2
|
|
|
|
Matrix2 m22 = Matrix2(2, 2);
|
|
m22(0, 0) = 1;
|
|
m22(0, 1) = 2;
|
|
m22(1, 0) = 3;
|
|
m22(1, 1) = 4;
|
|
EXPECT_EQ(m22.RowCount(), 2);
|
|
EXPECT_EQ(m22.ColCount(), 2);
|
|
|
|
Matrix2 r22 = Matrix2(2, 2);
|
|
r22(0, 0) = 1;
|
|
r22(0, 1) = 2;
|
|
r22(1, 0) = 3;
|
|
r22(1, 1) = 4;
|
|
EXPECT_EQ(r22.RowCount(), 2);
|
|
EXPECT_EQ(r22.ColCount(), 2);
|
|
|
|
r22 = m22.Transposed();
|
|
EXPECT_EQ(r22.RowCount(), 2);
|
|
EXPECT_EQ(r22.ColCount(), 2);
|
|
EXPECT_EQ(r22(0, 0), 1);
|
|
EXPECT_EQ(r22(0, 1), 3);
|
|
EXPECT_EQ(r22(1, 0), 2);
|
|
EXPECT_EQ(r22(1, 1), 4);
|
|
|
|
// 1 x 2
|
|
Matrix2 m12 = Matrix2(1, 2);
|
|
m12(0, 0) = 1;
|
|
m12(0, 1) = 2;
|
|
EXPECT_EQ(m12.RowCount(), 1);
|
|
EXPECT_EQ(m12.ColCount(), 2);
|
|
|
|
// float data21[] = {0.0F, 0.0F};
|
|
Matrix2 r21 = Matrix2(2, 1);
|
|
r21(0, 0) = 0;
|
|
r21(1, 0) = 0;
|
|
EXPECT_EQ(r21.RowCount(), 2);
|
|
EXPECT_EQ(r21.ColCount(), 1);
|
|
|
|
// m12.Transpose(&r21);
|
|
r21 = m12.Transposed();
|
|
EXPECT_EQ(r21.RowCount(), 2);
|
|
EXPECT_EQ(r21.ColCount(), 1);
|
|
EXPECT_EQ(r21(0, 0), 1);
|
|
EXPECT_EQ(r21(1, 0), 2);
|
|
|
|
// changing dimensions, same size is okay
|
|
Matrix2 r12 = Matrix2::Zero(1, 2);
|
|
EXPECT_EQ(r12.RowCount(), 1);
|
|
EXPECT_EQ(r12.ColCount(), 2);
|
|
|
|
// m12.Transpose(&r12);
|
|
r12 = m12.Transposed();
|
|
EXPECT_EQ(r12.RowCount(), 2);
|
|
EXPECT_EQ(r12.ColCount(), 1);
|
|
EXPECT_EQ(r12(0, 0), 1);
|
|
EXPECT_EQ(r12(0, 1), 2);
|
|
}
|
|
|
|
TYPED_TEST(Matrix2Tests, Multiply) {
|
|
using Matrix2 = Matrix2Of<TypeParam>;
|
|
Matrix2 m12 = Matrix2(1, 2);
|
|
m12(0, 0) = 1;
|
|
m12(0, 1) = 2;
|
|
|
|
EXPECT_EQ(m12.RowCount(), 1);
|
|
EXPECT_EQ(m12.ColCount(), 2);
|
|
EXPECT_EQ(m12(0, 0), 1);
|
|
EXPECT_EQ(m12(0, 1), 2);
|
|
|
|
// float m21data[] = {3.0F, 4.0F};
|
|
Matrix2 m21 = Matrix2(2, 1); //, m21data);
|
|
m21(0, 0) = 3;
|
|
m21(1, 0) = 4;
|
|
|
|
EXPECT_EQ(m21.RowCount(), 2);
|
|
EXPECT_EQ(m21.ColCount(), 1);
|
|
EXPECT_EQ(m21(0, 0), 3);
|
|
EXPECT_EQ(m21(1, 0), 4);
|
|
|
|
// float r11data[] = {0.0F};
|
|
Matrix2 r11 = Matrix2::Zero(1, 1); //, r11data);
|
|
|
|
EXPECT_EQ(r11.RowCount(), 1);
|
|
EXPECT_EQ(r11.ColCount(), 1);
|
|
|
|
r11 = m12 * m21; // Matrix1::Multiply(&m12, &m21, &r11);
|
|
EXPECT_EQ(r11.RowCount(), 1);
|
|
EXPECT_EQ(r11.ColCount(), 1);
|
|
EXPECT_EQ(r11(0, 0), 11);
|
|
|
|
// float r22data[] = {0.0F, 0.0F, 0.0F, 0.0F};
|
|
Matrix2 r22 = Matrix2::Zero(2, 2); //, r22data);
|
|
|
|
// Matrix1::Multiply(&m21, &m12, &r22);
|
|
r22 = m21 * m12;
|
|
EXPECT_EQ(r22.RowCount(), 2);
|
|
EXPECT_EQ(r22.ColCount(), 2);
|
|
EXPECT_EQ(r22(0, 0), 3);
|
|
EXPECT_EQ(r22(0, 1), 6);
|
|
EXPECT_EQ(r22(1, 0), 4);
|
|
EXPECT_EQ(r22(1, 1), 8);
|
|
}
|
|
|
|
#endif |