Primitives of dynamic dimension, part 1: make vector, point & matrix dimensions retrievable via non-static functions

This commit is contained in:
Nikita Lisitsa 2021-01-16 23:26:20 +03:00
parent 5133695c6f
commit 9995f38ab0
8 changed files with 59 additions and 40 deletions

View file

@ -482,9 +482,9 @@ void controller::randomize(RNG && rng, float amplitude)
auto visit_m = [&rng, &d, amplitude](auto & m)
{
for (std::size_t i = 0; i < m.rows; ++i)
for (std::size_t i = 0; i < m.rows(); ++i)
{
for (std::size_t j = 0; j < m.columns; ++j)
for (std::size_t j = 0; j < m.columns(); ++j)
{
m[i][j] = d(rng) * amplitude;
}
@ -493,7 +493,7 @@ void controller::randomize(RNG && rng, float amplitude)
auto visit_v = [&rng, &d, amplitude](auto & v)
{
for (std::size_t i = 0; i < v.dimension; ++i)
for (std::size_t i = 0; i < v.dimension(); ++i)
{
v[i] = d(rng) * amplitude;
}
@ -535,9 +535,9 @@ void controller::mutate(RNG && rng, float amplitude)
auto visit_m = [&rng, &d, amplitude](auto & m)
{
for (std::size_t i = 0; i < m.rows; ++i)
for (std::size_t i = 0; i < m.rows(); ++i)
{
for (std::size_t j = 0; j < m.columns; ++j)
for (std::size_t j = 0; j < m.columns(); ++j)
{
m[i][j] += d(rng) * amplitude;
}
@ -546,7 +546,7 @@ void controller::mutate(RNG && rng, float amplitude)
auto visit_v = [&rng, &d, amplitude](auto & v)
{
for (std::size_t i = 0; i < v.dimension; ++i)
for (std::size_t i = 0; i < v.dimension(); ++i)
{
v[i] += d(rng) * amplitude;
}
@ -1098,7 +1098,7 @@ float animation_2d_app::eval_score(controller const & c, random::generator rng)
physics.advance(dt, sel, [&c, &energy, dt](system const & physics){
std::vector<float> torque(physics.joints.size(), 0.f);
auto ctrl = c.apply(physics);
for (std::size_t i = 0; i < ctrl.dimension; ++i)
for (std::size_t i = 0; i < ctrl.dimension(); ++i)
torque[i] = ctrl[i];
energy += geom::length(ctrl) * dt;
return torque;
@ -1441,7 +1441,7 @@ void animation_2d_app::do_test()
physics.advance(frame_clock.restart().count(), sel, [this](system const & physics){
std::vector<float> torque(physics.joints.size());
auto ctrl = population[test_id].apply(physics);
for (std::size_t i = 0; i < ctrl.dimension; ++i)
for (std::size_t i = 0; i < ctrl.dimension(); ++i)
torque[i] = ctrl[i];
return torque;
});

View file

@ -12,13 +12,22 @@ namespace psemek::geom
template <typename T, std::size_t R, std::size_t C>
struct matrix
{
static constexpr std::size_t rows = R;
static constexpr std::size_t columns = C;
using scalar_type = T;
static constexpr std::size_t static_rows = R;
static constexpr std::size_t static_columns = C;
detail::array<T, R * C>::type coords;
std::size_t rows() const
{
return R;
}
std::size_t columns() const
{
return C;
}
auto operator[](std::size_t i)
{
return coords + C * i;
@ -251,8 +260,8 @@ namespace psemek::geom
vector<T, N> m[] = {v, rows...};
matrix<T, sizeof...(Rows) + 1, N> result;
for (std::size_t i = 0; i < result.rows; ++i)
for (std::size_t j = 0; j < result.columns; ++j)
for (std::size_t i = 0; i < result.rows(); ++i)
for (std::size_t j = 0; j < result.columns(); ++j)
result[i][j] = m[i][j];
return result;
}
@ -263,8 +272,8 @@ namespace psemek::geom
vector<T, N> m[] = {v, columns...};
matrix<T, N, sizeof...(Columns) + 1> result;
for (std::size_t i = 0; i < result.rows; ++i)
for (std::size_t j = 0; j < result.columns; ++j)
for (std::size_t i = 0; i < result.rows(); ++i)
for (std::size_t j = 0; j < result.columns(); ++j)
result[i][j] = m[j][i];
return result;
}

View file

@ -9,9 +9,8 @@ namespace psemek::geom
template <typename T, std::size_t N>
struct point
{
static constexpr std::size_t dimension = N;
using scalar_type = T;
static constexpr std::size_t static_dimension = N;
detail::array<T, N>::type coords;
@ -30,6 +29,11 @@ namespace psemek::geom
static_assert(sizeof...(Args) == N);
}
std::size_t dimension() const
{
return N;
}
T & operator[](std::size_t i)
{
return coords[i];

View file

@ -14,9 +14,8 @@ namespace psemek::geom
template <typename T, std::size_t N>
struct vector
{
static constexpr std::size_t dimension = N;
using scalar_type = T;
static constexpr std::size_t static_dimension = N;
detail::array<T, N>::type coords;
@ -35,6 +34,11 @@ namespace psemek::geom
static_assert(sizeof...(Args) == N);
}
std::size_t dimension() const
{
return N;
}
T & operator[](std::size_t i)
{
return coords[i];

View file

@ -15,12 +15,12 @@ test_case(geom_matrix_empty)
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_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);
@ -35,6 +35,8 @@ test_case(geom_matrix_init)
m[1][0] = 3;
m[1][1] = 4;
expect_equal(m.columns(), 2);
expect_equal(m.rows(), 2);
expect_equal(m[0][0], 1);
expect_equal(m[0][1], 2);
expect_equal(m[1][0], 3);
@ -67,9 +69,9 @@ 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 i = 0; i < m.rows(); ++i)
{
for (std::size_t j = 0; j < m.rows; ++j)
for (std::size_t j = 0; j < m.columns(); ++j)
{
expect_equal(m[i][j], 0.f);
}
@ -80,9 +82,9 @@ 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 i = 0; i < m.rows(); ++i)
{
for (std::size_t j = 0; j < m.rows; ++j)
for (std::size_t j = 0; j < m.columns(); ++j)
{
expect_equal(m[i][j], (i == j ? 1.f : 0.f));
}
@ -93,9 +95,9 @@ 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 i = 0; i < m.rows(); ++i)
{
for (std::size_t j = 0; j < m.rows; ++j)
for (std::size_t j = 0; j < m.columns(); ++j)
{
expect_equal(m[i][j], (i == j ? 3.f : 0.f));
}

View file

@ -12,8 +12,8 @@ test_case(geom_point_empty)
static_assert(std::is_same_v<decltype(pi)::scalar_type, int>);
static_assert(std::is_same_v<decltype(pf)::scalar_type, float>);
expect_equal(pi.dimension, 0);
expect_equal(pf.dimension, 0);
expect_equal(pi.dimension(), 0);
expect_equal(pf.dimension(), 0);
expect_throw(pi[0], detail::empty_array_exception);
expect_throw(pf[0], detail::empty_array_exception);
}

View file

@ -13,8 +13,8 @@ test_case(geom_vector_empty)
static_assert(std::is_same_v<decltype(pi)::scalar_type, int>);
static_assert(std::is_same_v<decltype(pf)::scalar_type, float>);
expect_equal(pi.dimension, 0);
expect_equal(pf.dimension, 0);
expect_equal(pi.dimension(), 0);
expect_equal(pf.dimension(), 0);
expect_throw(pi[0], detail::empty_array_exception);
expect_throw(pf[0], detail::empty_array_exception);
}

View file

@ -330,9 +330,9 @@ namespace psemek::gfx
if constexpr (is_matrix<attr>::value)
{
using T = typename attr::scalar_type;
using traits = attrib_traits<geom::vector<T, attr::columns>>;
using traits = attrib_traits<geom::vector<T, attr::static_columns>>;
for (std::size_t row = 0; row < attr::rows; ++row)
for (std::size_t row = 0; row < attr::static_rows; ++row)
{
attrib_description attr;
attr.index = index + row;
@ -340,13 +340,13 @@ namespace psemek::gfx
attr.type = traits::type;
attr.normalized = traits::normalized;
attr.stride = stride;
attr.pointer = reinterpret_cast<char const *>(offset + row * attr::columns * sizeof(T));
attr.pointer = reinterpret_cast<char const *>(offset + row * attr::static_columns * sizeof(T));
attr.divisor = Instance ? 1 : 0;
result.attribs.push_back(attr);
}
make_attribs_description_impl<Instance, Attribs...>::make_impl(result, index + attr::rows, offset + attr_size<Attr1>(), stride);
make_attribs_description_impl<Instance, Attribs...>::make_impl(result, index + attr::static_rows, offset + attr_size<Attr1>(), stride);
}
else
{
@ -373,7 +373,7 @@ namespace psemek::gfx
if constexpr (is_matrix<attr>::value)
{
make_attribs_description_impl<Instance, Attribs...>::make_impl(result, index + attr::rows, offset, stride);
make_attribs_description_impl<Instance, Attribs...>::make_impl(result, index + attr::static_rows, offset, stride);
}
else
{