From 61540a5204e12c937eef5a26e0f0530c60325d51 Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Wed, 15 Aug 2018 20:07:12 +0200 Subject: [PATCH] Added missing fmin and fmax overloads --- glm/ext/quaternion_relational.hpp | 1 - glm/ext/quaternion_relational.inl | 4 +- glm/ext/vector_common.hpp | 43 ++++-- glm/ext/vector_common.inl | 28 +++- test/ext/ext_scalar_common.cpp | 1 - test/ext/ext_vector_common.cpp | 218 ++++++++++++++++++++++++++++++ 6 files changed, 276 insertions(+), 19 deletions(-) diff --git a/glm/ext/quaternion_relational.hpp b/glm/ext/quaternion_relational.hpp index 7bd8e610..c7d4e331 100644 --- a/glm/ext/quaternion_relational.hpp +++ b/glm/ext/quaternion_relational.hpp @@ -11,7 +11,6 @@ #pragma once // Dependency: -#include "./quaternion_geometric.hpp" #include "../vector_relational.hpp" #if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) diff --git a/glm/ext/quaternion_relational.inl b/glm/ext/quaternion_relational.inl index 44fa5226..b1713e95 100644 --- a/glm/ext/quaternion_relational.inl +++ b/glm/ext/quaternion_relational.inl @@ -5,7 +5,7 @@ namespace glm { vec<4, bool, Q> Result; for(length_t i = 0; i < x.length(); ++i) - Result[i] = detail::compute_equal::is_iec559>::call(x[i], y[i]); + Result[i] = x[i] == y[i]; return Result; } @@ -21,7 +21,7 @@ namespace glm { vec<4, bool, Q> Result; for(length_t i = 0; i < x.length(); ++i) - Result[i] = !detail::compute_equal::is_iec559>::call(x[i], y[i]); + Result[i] = x[i] != y[i]; return Result; } diff --git a/glm/ext/vector_common.hpp b/glm/ext/vector_common.hpp index bfcd4779..0c7d5631 100644 --- a/glm/ext/vector_common.hpp +++ b/glm/ext/vector_common.hpp @@ -13,7 +13,8 @@ #pragma once // Dependency: -#include "../glm.hpp" +#include "../ext/scalar_common.hpp" +#include "../common.hpp" #if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) # pragma message("GLM: GLM_EXT_vector_common extension included") @@ -86,16 +87,27 @@ namespace glm template GLM_FUNC_DECL vec fmin(vec const& x, vec const& y); - /// Returns y if x < y; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned. + /// Returns y if y < x; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned. /// /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector /// @tparam T Floating-point scalar types /// @tparam Q Value from qualifier enum /// /// @see ext_vector_common - /// @see std::fmax documentation + /// @see std::fmin documentation template - GLM_FUNC_DECL vec fmax(vec const& x, T y); + GLM_FUNC_DECL vec fmin(vec const& a, vec const& b, vec const& c); + + /// Returns y if y < x; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_common + /// @see std::fmin documentation + template + GLM_FUNC_DECL vec fmin(vec const& a, vec const& b, vec const& c, vec const& d); /// Returns y if x < y; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned. /// @@ -106,27 +118,40 @@ namespace glm /// @see ext_vector_common /// @see std::fmax documentation template - GLM_FUNC_DECL vec fmax(vec const& x, vec const& y); + GLM_FUNC_DECL vec fmax(vec const& a, T b); - /// Returns min(max(x, minVal), maxVal) for each component in x. If one of the two arguments is NaN, the value of the other argument is returned. + /// Returns y if x < y; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned. /// /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector /// @tparam T Floating-point scalar types /// @tparam Q Value from qualifier enum /// /// @see ext_vector_common + /// @see std::fmax documentation template - GLM_FUNC_DECL vec fclamp(vec const& x, T minVal, T maxVal); + GLM_FUNC_DECL vec fmax(vec const& a, vec const& b); - /// Returns min(max(x, minVal), maxVal) for each component in x. If one of the two arguments is NaN, the value of the other argument is returned. + /// Returns y if x < y; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned. /// /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector /// @tparam T Floating-point scalar types /// @tparam Q Value from qualifier enum /// /// @see ext_vector_common + /// @see std::fmax documentation template - GLM_FUNC_DECL vec fclamp(vec const& x, vec const& minVal, vec const& maxVal); + GLM_FUNC_DECL vec fmax(vec const& a, vec const& b, vec const& c); + + /// Returns y if x < y; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_common + /// @see std::fmax documentation + template + GLM_FUNC_DECL vec fmax(vec const& a, vec const& b, vec const& c, vec const& d); /// @} }//namespace glm diff --git a/glm/ext/vector_common.inl b/glm/ext/vector_common.inl index 882805d5..43ae6d84 100644 --- a/glm/ext/vector_common.inl +++ b/glm/ext/vector_common.inl @@ -1,3 +1,5 @@ +#include "../detail/_vectorize.hpp" + namespace glm { template @@ -42,6 +44,20 @@ namespace glm return detail::functor2::call(fmin, a, b); } + template + GLM_FUNC_QUALIFIER vec fmin(vec const& a, vec const& b, vec const& c) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmin' only accept floating-point inputs"); + return fmin(fmin(a, b), c); + } + + template + GLM_FUNC_QUALIFIER vec fmin(vec const& a, vec const& b, vec const& c, vec const& d) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmin' only accept floating-point inputs"); + return fmin(fmin(a, b), fmin(c, d)); + } + template GLM_FUNC_QUALIFIER vec fmax(vec const& a, T b) { @@ -57,16 +73,16 @@ namespace glm } template - GLM_FUNC_QUALIFIER vec fclamp(vec const& x, T minVal, T maxVal) + GLM_FUNC_QUALIFIER vec fmax(vec const& a, vec const& b, vec const& c) { - GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fclamp' only accept floating-point inputs"); - return fmin(fmax(x, vec(minVal)), vec(maxVal)); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmax' only accept floating-point inputs"); + return fmax(fmax(a, b), c); } template - GLM_FUNC_QUALIFIER vec fclamp(vec const& x, vec const& minVal, vec const& maxVal) + GLM_FUNC_QUALIFIER vec fmax(vec const& a, vec const& b, vec const& c, vec const& d) { - GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fclamp' only accept floating-point inputs"); - return fmin(fmax(x, minVal), maxVal); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmax' only accept floating-point inputs"); + return fmax(fmax(a, b), fmax(c, d)); } }//namespace glm diff --git a/test/ext/ext_scalar_common.cpp b/test/ext/ext_scalar_common.cpp index 6731cffd..1c35b5a6 100644 --- a/test/ext/ext_scalar_common.cpp +++ b/test/ext/ext_scalar_common.cpp @@ -2,7 +2,6 @@ #include #include #include -#include template static int test_min() diff --git a/test/ext/ext_vector_common.cpp b/test/ext/ext_vector_common.cpp index 3d09ae70..566f247b 100644 --- a/test/ext/ext_vector_common.cpp +++ b/test/ext/ext_vector_common.cpp @@ -1,4 +1,13 @@ #include +#include +#include +#include +#include +#include +#include +#include +#include + #include #include #include @@ -15,10 +24,219 @@ #include #include #include +#include +#include +#include +#include + +template +static int test_min() +{ + typedef typename vecType::value_type T; + + int Error = 0; + + vecType const N(static_cast(0)); + vecType const B(static_cast(1)); + Error += glm::all(glm::equal(glm::min(N, B), N, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::min(B, N), N, glm::epsilon())) ? 0 : 1; + + vecType const C(static_cast(2)); + Error += glm::all(glm::equal(glm::min(N, B, C), N, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::min(B, N, C), N, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::min(C, N, B), N, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::min(C, B, N), N, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::min(B, C, N), N, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::min(N, C, B), N, glm::epsilon())) ? 0 : 1; + + vecType const D(static_cast(3)); + Error += glm::all(glm::equal(glm::min(D, N, B, C), N, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::min(B, D, N, C), N, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::min(C, N, D, B), N, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::min(C, B, D, N), N, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::min(B, C, N, D), N, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::min(N, C, B, D), N, glm::epsilon())) ? 0 : 1; + + return Error; +} + +template +static int test_min_nan() +{ + typedef typename vecType::value_type T; + + int Error = 0; + + vecType const A(static_cast(0)); + vecType const B(static_cast(1)); + vecType const N(A / A); + Error += glm::all(glm::isnan(glm::min(N, B))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::min(B, N))) ? 0 : 1; + + vecType const C(static_cast(2)); + Error += glm::all(glm::isnan(glm::min(N, B, C))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::min(B, N, C))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::min(C, N, B))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::min(C, B, N))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::min(B, C, N))) ? 0 : 1; + Error += glm::all(glm::isnan(glm::min(N, C, B))) ? 0 : 1; + + vecType const D(static_cast(3)); + Error += !glm::all(glm::isnan(glm::min(D, N, B, C))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::min(B, D, N, C))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::min(C, N, D, B))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::min(C, B, D, N))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::min(B, C, N, D))) ? 0 : 1; + Error += glm::all(glm::isnan(glm::min(N, C, B, D))) ? 0 : 1; + + return Error; +} + +template +static int test_max() +{ + typedef typename vecType::value_type T; + + int Error = 0; + + vecType const N(static_cast(0)); + vecType const B(static_cast(1)); + Error += glm::all(glm::equal(glm::max(N, B), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::max(B, N), B, glm::epsilon())) ? 0 : 1; + + vecType const C(static_cast(2)); + Error += glm::all(glm::equal(glm::max(N, B, C), C, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::max(B, N, C), C, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::max(C, N, B), C, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::max(C, B, N), C, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::max(B, C, N), C, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::max(N, C, B), C, glm::epsilon())) ? 0 : 1; + + vecType const D(static_cast(3)); + Error += glm::all(glm::equal(glm::max(D, N, B, C), D, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::max(B, D, N, C), D, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::max(C, N, D, B), D, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::max(C, B, D, N), D, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::max(B, C, N, D), D, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::max(N, C, B, D), D, glm::epsilon())) ? 0 : 1; + + return Error; +} + +template +static int test_max_nan() +{ + typedef typename vecType::value_type T; + + int Error = 0; + + vecType const A(static_cast(0)); + vecType const B(static_cast(1)); + vecType const N(A / A); + + Error += glm::all(glm::isnan(glm::max(N, B))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::max(B, N))) ? 0 : 1; + + vecType const C(static_cast(2)); + Error += glm::all(glm::isnan(glm::max(N, B, C))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::max(B, N, C))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::max(C, N, B))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::max(C, B, N))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::max(B, C, N))) ? 0 : 1; + Error += glm::all(glm::isnan(glm::max(N, C, B))) ? 0 : 1; + + vecType const D(static_cast(3)); + Error += !glm::all(glm::isnan(glm::max(D, N, B, C))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::max(B, D, N, C))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::max(C, N, D, B))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::max(C, B, D, N))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::max(B, C, N, D))) ? 0 : 1; + Error += glm::all(glm::isnan(glm::max(N, C, B, D))) ? 0 : 1; + + return Error; +} + +template +static int test_fmin() +{ + typedef typename vecType::value_type T; + + int Error = 0; + + vecType const A(static_cast(0)); + vecType const B(static_cast(1)); + Error += glm::all(glm::equal(glm::fmin(A / A, B), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmin(B, A / A), B, glm::epsilon())) ? 0 : 1; + + vecType const C(static_cast(2)); + Error += glm::all(glm::equal(glm::fmin(A / A, B, C), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmin(B, A / A, C), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmin(C, A / A, B), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmin(C, B, A / A), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmin(B, C, A / A), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmin(A / A, C, B), B, glm::epsilon())) ? 0 : 1; + + vecType const D(static_cast(3)); + Error += glm::all(glm::equal(glm::fmin(D, A / A, B, C), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmin(B, D, A / A, C), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmin(C, A / A, D, B), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmin(C, B, D, A / A), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmin(B, C, A / A, D), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmin(A / A, C, B, D), B, glm::epsilon())) ? 0 : 1; + + return Error; +} + +template +static int test_fmax() +{ + typedef typename vecType::value_type T; + + int Error = 0; + + vecType const A(static_cast(0)); + vecType const B(static_cast(1)); + Error += glm::all(glm::equal(glm::fmax(A / A, B), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmax(B, A / A), B, glm::epsilon())) ? 0 : 1; + + vecType const C(static_cast(2)); + Error += glm::all(glm::equal(glm::fmax(A / A, B, C), C, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmax(B, A / A, C), C, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmax(C, A / A, B), C, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmax(C, B, A / A), C, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmax(B, C, A / A), C, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmax(A / A, C, B), C, glm::epsilon())) ? 0 : 1; + + vecType const D(static_cast(3)); + Error += glm::all(glm::equal(glm::fmax(D, A / A, B, C), D, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmax(B, D, A / A, C), D, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmax(C, A / A, D, B), D, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmax(C, B, D, A / A), D, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmax(B, C, A / A, D), D, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmax(A / A, C, B, D), D, glm::epsilon())) ? 0 : 1; + + return Error; +} int main() { int Error = 0; + Error += test_min(); + Error += test_min(); + Error += test_min_nan(); + Error += test_min_nan(); + + Error += test_max(); + Error += test_max(); + Error += test_max_nan(); + Error += test_max_nan(); + + Error += test_fmin(); + Error += test_fmin(); + + Error += test_fmax(); + Error += test_fmax(); + return Error; }