diff --git a/headers/vmath.hpp/vmath_mat_ext.hpp b/headers/vmath.hpp/vmath_mat_ext.hpp index 11974e7..6639501 100644 --- a/headers/vmath.hpp/vmath_mat_ext.hpp +++ b/headers/vmath.hpp/vmath_mat_ext.hpp @@ -20,9 +20,49 @@ namespace vmath_hpp { + // cast_to + template < typename To, typename From, std::size_t Size > - constexpr mat cast_to(const mat& xs) { - return detail::map([](const vec& x){ return cast_to(x); }, xs); + constexpr mat cast_to(const mat& m) { + return detail::map([](const vec& v){ return cast_to(v); }, m); + } + + // row + + template < typename T, std::size_t Size > + constexpr vec row(const mat& m, std::size_t index) { + return m.rows[index]; + } + + template < typename T, std::size_t Size > + constexpr mat row(mat m, std::size_t index, const vec& v) { + m.rows[index] = v; + return m; + } + + // column + + namespace impl + { + template < typename T, std::size_t Size, std::size_t... Is > + constexpr vec column_impl(const mat& m, std::size_t index, std::index_sequence) { + return { m[Is][index]... }; + } + + template < typename T, std::size_t Size, std::size_t... Is > + constexpr mat column_impl(const mat& m, std::size_t index, const vec& v, std::index_sequence) { + return { component(m[Is], index, v[Is])... }; + } + } + + template < typename T, std::size_t Size > + constexpr vec column(const mat& m, std::size_t index) { + return impl::column_impl(m, index, std::make_index_sequence{}); + } + + template < typename T, std::size_t Size > + constexpr mat column(const mat& m, std::size_t index, const vec& v) { + return impl::column_impl(m, index, v, std::make_index_sequence{}); } } diff --git a/headers/vmath.hpp/vmath_vec_ext.hpp b/headers/vmath.hpp/vmath_vec_ext.hpp index 31095bc..84dd79d 100644 --- a/headers/vmath.hpp/vmath_vec_ext.hpp +++ b/headers/vmath.hpp/vmath_vec_ext.hpp @@ -16,8 +16,23 @@ namespace vmath_hpp { + // cast_to + template < typename To, typename From, std::size_t Size > - constexpr vec cast_to(const vec& xs) { - return detail::map([](From x){ return cast_to(x); }, xs); + constexpr vec cast_to(const vec& v) { + return detail::map([](From x){ return cast_to(x); }, v); + } + + // component + + template < typename T, std::size_t Size > + constexpr T component(const vec& v, std::size_t index) { + return v[index]; + } + + template < typename T, std::size_t Size > + constexpr vec component(vec v, std::size_t index, T x) { + v[index] = x; + return v; } } diff --git a/untests/vmath_mat_ext_tests.cpp b/untests/vmath_mat_ext_tests.cpp index 403ee2f..342ffd3 100644 --- a/untests/vmath_mat_ext_tests.cpp +++ b/untests/vmath_mat_ext_tests.cpp @@ -24,6 +24,22 @@ TEST_CASE("vmath/mat_ext") { STATIC_REQUIRE(std::is_same_v); } + SECTION("row") { + STATIC_REQUIRE(row(mat2i(1,2,3,4), 0) == vec2i(1,2)); + STATIC_REQUIRE(row(mat2i(1,2,3,4), 1) == vec2i(3,4)); + + STATIC_REQUIRE(row(mat2i(), 0, {1,2}) == mat2i(1,2,0,1)); + STATIC_REQUIRE(row(mat2i(), 1, {3,4}) == mat2i(1,0,3,4)); + } + + SECTION("column") { + STATIC_REQUIRE(column(mat2i(1,2,3,4), 0) == vec2i(1,3)); + STATIC_REQUIRE(column(mat2i(1,2,3,4), 1) == vec2i(2,4)); + + STATIC_REQUIRE(column(mat2i(), 0, {2,3}) == mat2i(2,0,3,1)); + STATIC_REQUIRE(column(mat2i(), 1, {3,4}) == mat2i(1,3,0,4)); + } + SECTION("identity") { STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * identity() == approx4(2.f,3.f,4.f,1.f)); STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * identity() == approx4(2.f,3.f,4.f,1.f)); diff --git a/untests/vmath_vec_ext_tests.cpp b/untests/vmath_vec_ext_tests.cpp index fa1f794..a013df2 100644 --- a/untests/vmath_vec_ext_tests.cpp +++ b/untests/vmath_vec_ext_tests.cpp @@ -23,4 +23,12 @@ TEST_CASE("vmath/vec_ext") { STATIC_REQUIRE(v == vec2i(1)); STATIC_REQUIRE(std::is_same_v); } + + SECTION("component") { + STATIC_REQUIRE(component(vec2i{1,2}, 0) == 1); + STATIC_REQUIRE(component(vec2i{1,2}, 1) == 2); + + STATIC_REQUIRE(component(vec2i{0,0}, 0, 1) == vec2i{1,0}); + STATIC_REQUIRE(component(vec2i{0,0}, 1, 2) == vec2i{0,2}); + } }