diff --git a/README.md b/README.md index 43cfac7..2b00337 100644 --- a/README.md +++ b/README.md @@ -1388,97 +1388,184 @@ constexpr bool not_equal_to(T x, T y) noexcept; #### Vector ```cpp -template < typename T, size_t Size > -constexpr bool any(const vec& xs); +template < typename T, std::size_t Size + , typename U = decltype(any(std::declval())) > +constexpr U any(const vec& xs); -template < typename T, size_t Size > -constexpr bool all(const vec& xs); +template < typename T, std::size_t Size + , typename U = decltype(all(std::declval())) > +constexpr U all(const vec& xs); -template < typename T, size_t Size > -constexpr vec approx(const vec& xs, const vec& ys); +template < typename T, std::size_t Size + , typename U = decltype(approx( + std::declval(), + std::declval())) > +constexpr vec approx(const vec& xs, const vec& ys); -template < typename T, size_t Size > -constexpr vec approx(const vec& xs, const vec& ys, T epsilon); +template < typename T, std::size_t Size + , typename U = decltype(approx( + std::declval(), + std::declval(), + std::declval())) > +constexpr vec approx(const vec& xs, const vec& ys, T epsilon); -template < typename T, size_t Size > -constexpr vec less(const vec& xs, const vec& ys); +template < typename T, std::size_t Size + , typename U = decltype(less( + std::declval(), + std::declval())) > +constexpr vec less(const vec& xs, const vec& ys); -template < typename T, size_t Size > -constexpr vec less_equal(const vec& xs, const vec& ys); +template < typename T, std::size_t Size + , typename U = decltype(less_equal( + std::declval(), + std::declval())) > +constexpr vec less_equal(const vec& xs, const vec& ys); -template < typename T, size_t Size > -constexpr vec greater(const vec& xs, const vec& ys); +template < typename T, std::size_t Size + , typename U = decltype(greater( + std::declval(), + std::declval())) > +constexpr vec greater(const vec& xs, const vec& ys); -template < typename T, size_t Size > -constexpr vec greater_equal(const vec& xs, const vec& ys); +template < typename T, std::size_t Size + , typename U = decltype(greater_equal( + std::declval(), + std::declval())) > +constexpr vec greater_equal(const vec& xs, const vec& ys); -template < typename T, size_t Size > -constexpr vec equal_to(const vec& xs, const vec& ys); +template < typename T, std::size_t Size + , typename U = decltype(equal_to( + std::declval(), + std::declval())) > +constexpr vec equal_to(const vec& xs, const vec& ys); -template < typename T, size_t Size > -constexpr vec not_equal_to(const vec& xs, const vec& ys); +template < typename T, std::size_t Size + , typename U = decltype(not_equal_to( + std::declval(), + std::declval())) > +constexpr vec not_equal_to(const vec& xs, const vec& ys); ``` #### Matrix ```cpp -template < typename T, size_t Size > -constexpr bool any(const mat& xs); +template < typename T, std::size_t Size + , typename U = decltype(any(std::declval>())) > +constexpr U any(const mat& xs); -template < typename T, size_t Size > -constexpr bool all(const mat& xs); +template < typename T, std::size_t Size + , typename U = decltype(all(std::declval>())) > +constexpr U all(const mat& xs); -template < typename T, size_t Size > -constexpr mat approx(const mat& xs, const mat& ys); +template < typename T, std::size_t Size + , typename U = typename decltype(approx( + std::declval>(), + std::declval>()))::component_type > +constexpr mat approx(const mat& xs, const mat& ys); -template < typename T, size_t Size > -constexpr mat approx(const mat& xs, const mat& ys, T epsilon); +template < typename T, std::size_t Size + , typename U = typename decltype(approx( + std::declval>(), + std::declval>(), + std::declval()))::component_type > +constexpr mat approx(const mat& xs, const mat& ys, T epsilon); -template < typename T, size_t Size > -constexpr mat less(const mat& xs, const mat& ys); +template < typename T, std::size_t Size + , typename U = typename decltype(less( + std::declval>(), + std::declval>()))::component_type > +constexpr mat less(const mat& xs, const mat& ys); -template < typename T, size_t Size > -constexpr mat less_equal(const mat& xs, const mat& ys); +template < typename T, std::size_t Size + , typename U = typename decltype(less_equal( + std::declval>(), + std::declval>()))::component_type > +constexpr mat less_equal(const mat& xs, const mat& ys); -template < typename T, size_t Size > -constexpr mat greater(const mat& xs, const mat& ys); +template < typename T, std::size_t Size + , typename U = typename decltype(greater( + std::declval>(), + std::declval>()))::component_type > +constexpr mat greater(const mat& xs, const mat& ys); -template < typename T, size_t Size > -constexpr mat greater_equal(const mat& xs, const mat& ys); +template < typename T, std::size_t Size + , typename U = typename decltype(greater_equal( + std::declval>(), + std::declval>()))::component_type > +constexpr mat greater_equal(const mat& xs, const mat& ys); -template < typename T, size_t Size > -constexpr mat equal_to(const mat& xs, const mat& ys); +template < typename T, std::size_t Size + , typename U = typename decltype(equal_to( + std::declval>(), + std::declval>()))::component_type > +constexpr mat equal_to(const mat& xs, const mat& ys); -template < typename T, size_t Size > -constexpr mat not_equal_to(const mat& xs, const mat& ys); +template < typename T, std::size_t Size + , typename U = typename decltype(not_equal_to( + std::declval>(), + std::declval>()))::component_type > +constexpr mat not_equal_to(const mat& xs, const mat& ys); ``` #### Quaternion ```cpp -template < typename T > -constexpr vec approx(const qua& xs, const qua& ys); +template < typename T + , typename U = decltype(any(std::declval>())) > +constexpr U any(const qua& xs); -template < typename T > -constexpr vec approx(const qua& xs, const qua& ys, T epsilon); +template < typename T + , typename U = decltype(all(std::declval>())) > +constexpr U all(const qua& xs); -template < typename T > -constexpr vec less(const qua& xs, const qua& ys); +template < typename T + , typename U = typename decltype(approx( + std::declval>(), + std::declval>()))::component_type > +constexpr vec approx(const qua& xs, const qua& ys); -template < typename T > -constexpr vec less_equal(const qua& xs, const qua& ys); +template < typename T + , typename U = typename decltype(approx( + std::declval>(), + std::declval>(), + std::declval()))::component_type > +constexpr vec approx(const qua& xs, const qua& ys, T epsilon); -template < typename T > -constexpr vec greater(const qua& xs, const qua& ys); +template < typename T + , typename U = typename decltype(less( + std::declval>(), + std::declval>()))::component_type > +constexpr vec less(const qua& xs, const qua& ys); -template < typename T > -constexpr vec greater_equal(const qua& xs, const qua& ys); +template < typename T + , typename U = typename decltype(less_equal( + std::declval>(), + std::declval>()))::component_type > +constexpr vec less_equal(const qua& xs, const qua& ys); -template < typename T > -constexpr vec equal_to(const qua& xs, const qua& ys); +template < typename T + , typename U = typename decltype(greater( + std::declval>(), + std::declval>()))::component_type > +constexpr vec greater(const qua& xs, const qua& ys); -template < typename T > -constexpr vec not_equal_to(const qua& xs, const qua& ys); +template < typename T + , typename U = typename decltype(greater_equal( + std::declval>(), + std::declval>()))::component_type > +constexpr vec greater_equal(const qua& xs, const qua& ys); + +template < typename T + , typename U = typename decltype(equal_to( + std::declval>(), + std::declval>()))::component_type > +constexpr vec equal_to(const qua& xs, const qua& ys); + +template < typename T + , typename U = typename decltype(not_equal_to( + std::declval>(), + std::declval>()))::component_type > +constexpr vec not_equal_to(const qua& xs, const qua& ys); ``` ### Matrix Functions diff --git a/headers/vmath.hpp/vmath_mat_fun.hpp b/headers/vmath.hpp/vmath_mat_fun.hpp index 704f850..2f0e053 100644 --- a/headers/vmath.hpp/vmath_mat_fun.hpp +++ b/headers/vmath.hpp/vmath_mat_fun.hpp @@ -501,53 +501,80 @@ namespace vmath_hpp namespace vmath_hpp { - template < typename T, std::size_t Size > - [[nodiscard]] constexpr bool any(const mat& xs) { - return fold_join([](bool acc, const vec& x){ return acc || any(x); }, false, xs); + template < typename T, std::size_t Size + , typename U = decltype(any(std::declval>())) > + [[nodiscard]] constexpr U any(const mat& xs) { + return fold_join([](U acc, const vec& x){ return acc || any(x); }, U{false}, xs); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr bool all(const mat& xs) { - return fold_join([](bool acc, const vec& x){ return acc && all(x); }, true, xs); + template < typename T, std::size_t Size + , typename U = decltype(all(std::declval>())) > + [[nodiscard]] constexpr U all(const mat& xs) { + return fold_join([](U acc, const vec& x){ return acc && all(x); }, U{true}, xs); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat approx(const mat& xs, const mat& ys) { + template < typename T, std::size_t Size + , typename U = typename decltype(approx( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr mat approx(const mat& xs, const mat& ys) { return map_join([](const vec& x, const vec& y){ return approx(x, y); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat approx(const mat& xs, const mat& ys, T epsilon) { + template < typename T, std::size_t Size + , typename U = typename decltype(approx( + std::declval>(), + std::declval>(), + std::declval()))::component_type > + [[nodiscard]] constexpr mat approx(const mat& xs, const mat& ys, T epsilon) { return map_join([epsilon](const vec& x, const vec& y){ return approx(x, y, epsilon); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat less(const mat& xs, const mat& ys) { + template < typename T, std::size_t Size + , typename U = typename decltype(less( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr mat less(const mat& xs, const mat& ys) { return map_join([](const vec& x, const vec& y){ return less(x, y); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat less_equal(const mat& xs, const mat& ys) { + template < typename T, std::size_t Size + , typename U = typename decltype(less_equal( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr mat less_equal(const mat& xs, const mat& ys) { return map_join([](const vec& x, const vec& y){ return less_equal(x, y); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat greater(const mat& xs, const mat& ys) { + template < typename T, std::size_t Size + , typename U = typename decltype(greater( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr mat greater(const mat& xs, const mat& ys) { return map_join([](const vec& x, const vec& y){ return greater(x, y); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat greater_equal(const mat& xs, const mat& ys) { + template < typename T, std::size_t Size + , typename U = typename decltype(greater_equal( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr mat greater_equal(const mat& xs, const mat& ys) { return map_join([](const vec& x, const vec& y){ return greater_equal(x, y); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat equal_to(const mat& xs, const mat& ys) { + template < typename T, std::size_t Size + , typename U = typename decltype(equal_to( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr mat equal_to(const mat& xs, const mat& ys) { return map_join([](const vec& x, const vec& y){ return equal_to(x, y); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat not_equal_to(const mat& xs, const mat& ys) { + template < typename T, std::size_t Size + , typename U = typename decltype(not_equal_to( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr mat not_equal_to(const mat& xs, const mat& ys) { return map_join([](const vec& x, const vec& y){ return not_equal_to(x, y); }, xs, ys); } } diff --git a/headers/vmath.hpp/vmath_qua_fun.hpp b/headers/vmath.hpp/vmath_qua_fun.hpp index 3c5d574..ea7b755 100644 --- a/headers/vmath.hpp/vmath_qua_fun.hpp +++ b/headers/vmath.hpp/vmath_qua_fun.hpp @@ -169,7 +169,7 @@ namespace vmath_hpp template < typename T > [[nodiscard]] qua nlerp(const qua& unit_xs, const qua& unit_ys, T a) { - const T xs_scale = T(1) - a; + const T xs_scale = T{1} - a; const T ys_scale = a * sign(dot(unit_xs, unit_ys)); return normalize(lerp(unit_xs, unit_ys, xs_scale, ys_scale)); } @@ -183,15 +183,15 @@ namespace vmath_hpp const T raw_cos_theta_sign = sign(raw_cos_theta); // half degree linear threshold: cos((pi / 180) * 0.25) - if ( const T cos_theta = raw_cos_theta * raw_cos_theta_sign; cos_theta < T(0.99999) ) { + if ( const T cos_theta = raw_cos_theta * raw_cos_theta_sign; cos_theta < T{0.99999} ) { const T theta = acos(cos_theta); - const T rsin_theta = rsqrt(T(1) - sqr(cos_theta)); - const T xs_scale = sin((T(1) - a) * theta) * rsin_theta; + const T rsin_theta = rsqrt(T{1} - sqr(cos_theta)); + const T xs_scale = sin((T{1} - a) * theta) * rsin_theta; const T ys_scale = sin(a * theta) * raw_cos_theta_sign * rsin_theta; return lerp(unit_xs, unit_ys, xs_scale, ys_scale); } else { // use linear interpolation for small angles - const T xs_scale = T(1) - a; + const T xs_scale = T{1} - a; const T ys_scale = a * raw_cos_theta_sign; return normalize(lerp(unit_xs, unit_ys, xs_scale, ys_scale)); } @@ -222,7 +222,7 @@ namespace vmath_hpp template < typename T > [[nodiscard]] T distance(const qua& xs, const qua& ys) { const qua zs = xs * conjugate(ys); - return T(2) * atan2(length(zs.v), abs(zs.s)); + return T{2} * atan2(length(zs.v), abs(zs.s)); } template < typename T > @@ -237,43 +237,80 @@ namespace vmath_hpp namespace vmath_hpp { - template < typename T > - [[nodiscard]] constexpr vec approx(const qua& xs, const qua& ys) { + template < typename T + , typename U = decltype(any(std::declval>())) > + [[nodiscard]] constexpr U any(const qua& xs) { + return any(vec{xs}); + } + + template < typename T + , typename U = decltype(all(std::declval>())) > + [[nodiscard]] constexpr U all(const qua& xs) { + return all(vec{xs}); + } + + template < typename T + , typename U = typename decltype(approx( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr vec approx(const qua& xs, const qua& ys) { return approx(vec{xs}, vec{ys}); } - template < typename T > - [[nodiscard]] constexpr vec approx(const qua& xs, const qua& ys, T epsilon) { + template < typename T + , typename U = typename decltype(approx( + std::declval>(), + std::declval>(), + std::declval()))::component_type > + [[nodiscard]] constexpr vec approx(const qua& xs, const qua& ys, T epsilon) { return approx(vec{xs}, vec{ys}, epsilon); } - template < typename T > - [[nodiscard]] constexpr vec less(const qua& xs, const qua& ys) { + template < typename T + , typename U = typename decltype(less( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr vec less(const qua& xs, const qua& ys) { return less(vec{xs}, vec{ys}); } - template < typename T > - [[nodiscard]] constexpr vec less_equal(const qua& xs, const qua& ys) { + template < typename T + , typename U = typename decltype(less_equal( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr vec less_equal(const qua& xs, const qua& ys) { return less_equal(vec{xs}, vec{ys}); } - template < typename T > - [[nodiscard]] constexpr vec greater(const qua& xs, const qua& ys) { + template < typename T + , typename U = typename decltype(greater( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr vec greater(const qua& xs, const qua& ys) { return greater(vec{xs}, vec{ys}); } - template < typename T > - [[nodiscard]] constexpr vec greater_equal(const qua& xs, const qua& ys) { + template < typename T + , typename U = typename decltype(greater_equal( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr vec greater_equal(const qua& xs, const qua& ys) { return greater_equal(vec{xs}, vec{ys}); } - template < typename T > - [[nodiscard]] constexpr vec equal_to(const qua& xs, const qua& ys) { + template < typename T + , typename U = typename decltype(equal_to( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr vec equal_to(const qua& xs, const qua& ys) { return equal_to(vec{xs}, vec{ys}); } - template < typename T > - [[nodiscard]] constexpr vec not_equal_to(const qua& xs, const qua& ys) { + template < typename T + , typename U = typename decltype(not_equal_to( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr vec not_equal_to(const qua& xs, const qua& ys) { return not_equal_to(vec{xs}, vec{ys}); } } diff --git a/headers/vmath.hpp/vmath_vec_fun.hpp b/headers/vmath.hpp/vmath_vec_fun.hpp index 017f940..44817a0 100644 --- a/headers/vmath.hpp/vmath_vec_fun.hpp +++ b/headers/vmath.hpp/vmath_vec_fun.hpp @@ -821,7 +821,7 @@ namespace vmath_hpp [[nodiscard]] constexpr T dot(const vec& xs, const vec& ys) { return fold_join([](T acc, T x, T y){ return acc + (x * y); - }, T(0), xs, ys); + }, T{0}, xs, ys); } template < typename T, std::size_t Size > @@ -869,53 +869,80 @@ namespace vmath_hpp namespace vmath_hpp { - template < typename T, std::size_t Size > - [[nodiscard]] constexpr bool any(const vec& xs) { - return fold_join([](bool acc, T x){ return acc || any(x); }, false, xs); + template < typename T, std::size_t Size + , typename U = decltype(any(std::declval())) > + [[nodiscard]] constexpr U any(const vec& xs) { + return fold_join([](U acc, T x){ return acc || any(x); }, U{false}, xs); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr bool all(const vec& xs) { - return fold_join([](bool acc, T x){ return acc && all(x); }, true, xs); + template < typename T, std::size_t Size + , typename U = decltype(all(std::declval())) > + [[nodiscard]] constexpr U all(const vec& xs) { + return fold_join([](U acc, T x){ return acc && all(x); }, U{true}, xs); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec approx(const vec& xs, const vec& ys) { + template < typename T, std::size_t Size + , typename U = decltype(approx( + std::declval(), + std::declval())) > + [[nodiscard]] constexpr vec approx(const vec& xs, const vec& ys) { return map_join([](T x, T y){ return approx(x, y); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec approx(const vec& xs, const vec& ys, T epsilon) { + template < typename T, std::size_t Size + , typename U = decltype(approx( + std::declval(), + std::declval(), + std::declval())) > + [[nodiscard]] constexpr vec approx(const vec& xs, const vec& ys, T epsilon) { return map_join([epsilon](T x, T y){ return approx(x, y, epsilon); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec less(const vec& xs, const vec& ys) { + template < typename T, std::size_t Size + , typename U = decltype(less( + std::declval(), + std::declval())) > + [[nodiscard]] constexpr vec less(const vec& xs, const vec& ys) { return map_join([](T x, T y){ return less(x, y); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec less_equal(const vec& xs, const vec& ys) { + template < typename T, std::size_t Size + , typename U = decltype(less_equal( + std::declval(), + std::declval())) > + [[nodiscard]] constexpr vec less_equal(const vec& xs, const vec& ys) { return map_join([](T x, T y){ return less_equal(x, y); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec greater(const vec& xs, const vec& ys) { + template < typename T, std::size_t Size + , typename U = decltype(greater( + std::declval(), + std::declval())) > + [[nodiscard]] constexpr vec greater(const vec& xs, const vec& ys) { return map_join([](T x, T y){ return greater(x, y); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec greater_equal(const vec& xs, const vec& ys) { + template < typename T, std::size_t Size + , typename U = decltype(greater_equal( + std::declval(), + std::declval())) > + [[nodiscard]] constexpr vec greater_equal(const vec& xs, const vec& ys) { return map_join([](T x, T y){ return greater_equal(x, y); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec equal_to(const vec& xs, const vec& ys) { + template < typename T, std::size_t Size + , typename U = decltype(equal_to( + std::declval(), + std::declval())) > + [[nodiscard]] constexpr vec equal_to(const vec& xs, const vec& ys) { return map_join([](T x, T y){ return equal_to(x, y); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec not_equal_to(const vec& xs, const vec& ys) { + template < typename T, std::size_t Size + , typename U = decltype(not_equal_to( + std::declval(), + std::declval())) > + [[nodiscard]] constexpr vec not_equal_to(const vec& xs, const vec& ys) { return map_join([](T x, T y){ return not_equal_to(x, y); }, xs, ys); } } diff --git a/untests/vmath_qua_fun_tests.cpp b/untests/vmath_qua_fun_tests.cpp index 9b6df77..0c71cc3 100644 --- a/untests/vmath_qua_fun_tests.cpp +++ b/untests/vmath_qua_fun_tests.cpp @@ -150,6 +150,19 @@ TEST_CASE("vmath/qua_fun") { } SUBCASE("Relational Functions") { + STATIC_CHECK(any(qua(1,0,0,0))); + STATIC_CHECK(any(qua(0,1,0,0))); + STATIC_CHECK(any(qua(0,0,1,0))); + STATIC_CHECK(any(qua(0,0,0,1))); + STATIC_CHECK(any(qua(1,1,1,1))); + STATIC_CHECK_FALSE(any(qua(0,0,0,0))); + + STATIC_CHECK_FALSE(all(qua(1,0,0,0))); + STATIC_CHECK_FALSE(all(qua(0,1,0,0))); + STATIC_CHECK_FALSE(all(qua(0,0,1,0))); + STATIC_CHECK(all(qua(1,1,1,1))); + STATIC_CHECK_FALSE(all(qua(0,0,0,0))); + STATIC_CHECK(approx(qua(1,1,1,1), qua(0,1,2,3)) == bool4(false, true, false, false)); STATIC_CHECK(approx(qua(1,1,1,1), qua(0,1,2,3), 0) == bool4(false, true, false, false)); STATIC_CHECK(approx(qua(1,1,1,1), qua(0,1,2,3), 1) == bool4(true, true, true, false));