From 5133695c6f0ced5967b2fd33b479f35386fccb85 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Sat, 16 Jan 2021 22:46:52 +0300 Subject: [PATCH] Add matrix tests --- libs/geom/tests/matrix.cpp | 190 ++++++++++++++++++++++++ tools/test/include/psemek/test/test.hpp | 11 ++ 2 files changed, 201 insertions(+) create mode 100644 libs/geom/tests/matrix.cpp diff --git a/libs/geom/tests/matrix.cpp b/libs/geom/tests/matrix.cpp new file mode 100644 index 00000000..5f46a572 --- /dev/null +++ b/libs/geom/tests/matrix.cpp @@ -0,0 +1,190 @@ +#include + +#include +#include + +using namespace psemek::geom; + +test_case(geom_matrix_empty) +{ + matrix m00; + matrix m10; + matrix m01; + + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + + expect_equal(m00.columns, 0); + expect_equal(m00.rows, 0); + expect_equal(m10.columns, 0); + expect_equal(m10.rows, 1); + expect_equal(m01.columns, 1); + expect_equal(m01.rows, 0); + + expect_throw(m00[0][0], detail::empty_array_exception); + expect_throw(m10[0][0], detail::empty_array_exception); + expect_throw(m01[0][0], detail::empty_array_exception); +} + +test_case(geom_matrix_init) +{ + matrix m; + m[0][0] = 1; + m[0][1] = 2; + m[1][0] = 3; + m[1][1] = 4; + + expect_equal(m[0][0], 1); + expect_equal(m[0][1], 2); + expect_equal(m[1][0], 3); + expect_equal(m[1][1], 4); +} + +test_case(geom_matrix_by__rows) +{ + matrix m; + m[0][0] = 1; + m[0][1] = 2; + m[1][0] = 3; + m[1][1] = 4; + + expect_equal(m, (by_rows(vector{1, 2}, vector{3, 4}))); +} + +test_case(geom_matrix_by__columns) +{ + matrix m; + m[0][0] = 1; + m[0][1] = 2; + m[1][0] = 3; + m[1][1] = 4; + + expect_equal(m, (by_columns(vector{1, 3}, vector{2, 4}))); +} + +test_case(geom_matrix_zero) +{ + auto m = matrix::zero(); + + for (std::size_t i = 0; i < m.rows; ++i) + { + for (std::size_t j = 0; j < m.rows; ++j) + { + expect_equal(m[i][j], 0.f); + } + } +} + +test_case(geom_matrix_identity) +{ + auto m = matrix::identity(); + + for (std::size_t i = 0; i < m.rows; ++i) + { + for (std::size_t j = 0; j < m.rows; ++j) + { + expect_equal(m[i][j], (i == j ? 1.f : 0.f)); + } + } +} + +test_case(geom_matrix_scalar) +{ + auto m = matrix::scalar(3.f); + + for (std::size_t i = 0; i < m.rows; ++i) + { + for (std::size_t j = 0; j < m.rows; ++j) + { + expect_equal(m[i][j], (i == j ? 3.f : 0.f)); + } + } +} + +test_case(geom_matrix_arithmetic) +{ + vector v{1.f, 2.f}; + + matrix m1, m2; + + m1[0][0] = 1.f; + m1[0][1] = 2.f; + m1[1][0] = 3.f; + m1[1][1] = 4.f; + + m2[0][0] = 5.f; + m2[0][1] = 6.f; + m2[1][0] = 7.f; + m2[1][1] = 8.f; + + expect_equal(m1 * v, (vector{5.f, 11.f})); + expect_equal(m2 * v, (vector{17.f, 23.f})); + + expect_equal(-m1, (by_rows(vector{-1.f, -2.f}, vector{-3.f, -4.f}))); + expect_equal(5.f * m1, (by_rows(vector{5.f, 10.f}, vector{15.f, 20.f}))); + expect_equal(m1 * 5.f, (by_rows(vector{5.f, 10.f}, vector{15.f, 20.f}))); + expect_equal(m1 + m2, (by_rows(vector{6.f, 8.f}, vector{10.f, 12.f}))); + expect_equal(m1 - m2, (by_rows(vector{-4.f, -4.f}, vector{-4.f, -4.f}))); + expect_equal(m1 * m2, (by_rows(vector{19.f, 22.f}, vector{43.f, 50.f}))); + expect_equal(m2 * m1, (by_rows(vector{23.f, 34.f}, vector{31.f, 46.f}))); + + expect_equal(transpose(m1), (by_rows(vector{1.f, 3.f}, vector{2.f, 4.f}))); + expect_equal(transpose(transpose(m1)), m1); +} + +test_case(geom_matrix_trace) +{ + matrix m; + + m[0][0] = 1.f; + m[0][1] = 2.f; + m[1][0] = 3.f; + m[1][1] = 4.f; + + expect_close(trace(m), 5.f, 1e-6); +} + +test_case(geom_matrix_det) +{ + matrix m; + + m[0][0] = 1.f; + m[0][1] = 2.f; + m[1][0] = 3.f; + m[1][1] = 4.f; + + expect_close(det(m), -2.f, 1e-6); +} + +test_case(geom_matrix_solve) +{ + matrix m; + + m[0][0] = 1.f; + m[0][1] = 2.f; + m[1][0] = 3.f; + m[1][1] = 4.f; + + vector v{1.f, 2.f}; + + auto s = solve(m, v); + + expect(s); + expect_small(length(*s - vector{0.f, 0.5f}), 1e-6); +} + +test_case(geom_matrix_inverse) +{ + matrix m; + + m[0][0] = 1.f; + m[0][1] = 2.f; + m[1][0] = 3.f; + m[1][1] = 4.f; + + auto i = inverse(m); + + expect(i); + expect_small(frobenius_norm(*i - by_rows(vector{-2.f, 1.f}, vector{1.5f, -0.5f})), 1e-6); +} diff --git a/tools/test/include/psemek/test/test.hpp b/tools/test/include/psemek/test/test.hpp index 12acc1ee..9d3aa963 100644 --- a/tools/test/include/psemek/test/test.hpp +++ b/tools/test/include/psemek/test/test.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -66,6 +67,16 @@ namespace psemek::test } +template +Stream & operator << (Stream & s, std::optional const & o) +{ + if (o) + s << *o; + else + s << "(empty)"; + return s; +} + #define test_case(name) \ void name ## _test_case (::psemek::test::context &); \ static const auto name ## _test_case_registrator = []{ ::psemek::test::add_test_case(#name, &(name ## _test_case)); return 0; }(); \