#if GTEST #include #include #include #include "Matrix.h" template bool isDefaultValue(const T& value) { // Use std::is_floating_point to determine if T is a floating type if constexpr (std::is_arithmetic::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>; using BaseTypes = ::testing::Types; template class Matrix2Tests : public ::testing::Test {}; TYPED_TEST_SUITE(Matrix2Tests, BaseTypes); TYPED_TEST(Matrix2Tests, Zero) { using Matrix2 = Matrix2Of; // 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; // 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 class Matrix1Test : public ::testing::Test { protected: }; TYPED_TEST_SUITE(Matrix1Test, BaseTypes); TYPED_TEST(Matrix2Tests, Init) { using Matrix2 = Matrix2Of; // 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; 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; 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