Add matrix tests
This commit is contained in:
parent
bbd15c5942
commit
5133695c6f
2 changed files with 201 additions and 0 deletions
190
libs/geom/tests/matrix.cpp
Normal file
190
libs/geom/tests/matrix.cpp
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
#include <psemek/test/test.hpp>
|
||||
|
||||
#include <psemek/geom/matrix.hpp>
|
||||
#include <psemek/geom/gauss.hpp>
|
||||
|
||||
using namespace psemek::geom;
|
||||
|
||||
test_case(geom_matrix_empty)
|
||||
{
|
||||
matrix<int, 0, 0> m00;
|
||||
matrix<int, 1, 0> m10;
|
||||
matrix<int, 0, 1> m01;
|
||||
|
||||
static_assert(std::is_same_v<decltype(m00)::scalar_type, int>);
|
||||
static_assert(std::is_same_v<decltype(m10)::scalar_type, int>);
|
||||
static_assert(std::is_same_v<decltype(m01)::scalar_type, int>);
|
||||
|
||||
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<int, 2, 2> 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<int, 2, 2> 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<int, 2, 2> 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<float, 5, 5>::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<float, 5, 5>::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<float, 5, 5>::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<float, 2, 2> 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<float, 2, 2> 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<float, 2, 2> 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<float, 2, 2> 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<float, 2, 2> 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);
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
#include <exception>
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
|
||||
#include <psemek/util/to_string.hpp>
|
||||
|
||||
|
|
@ -66,6 +67,16 @@ namespace psemek::test
|
|||
|
||||
}
|
||||
|
||||
template <typename Stream, typename T>
|
||||
Stream & operator << (Stream & s, std::optional<T> 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; }(); \
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue