diff --git a/glm/detail/qualifier.hpp b/glm/detail/qualifier.hpp index 115817f1..be4ed3e8 100644 --- a/glm/detail/qualifier.hpp +++ b/glm/detail/qualifier.hpp @@ -206,5 +206,18 @@ namespace detail return genType(1); } }; + + // https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ + union float_t + { + GLM_CONSTEXPR float_t(float Num = 0.0f) : f(Num) {} + // Portable extraction of components. + GLM_CONSTEXPR bool negative() const { return i < 0; } + GLM_CONSTEXPR int mantissa() const { return i & ((1 << 23) - 1); } + GLM_CONSTEXPR int exponent() const { return (i >> 23) & 0xFF; } + + int const i; + float const f; + }; }//namespace detail }//namespace glm diff --git a/glm/ext/scalar_relational.inl b/glm/ext/scalar_relational.inl index 22e79906..089a2f5d 100644 --- a/glm/ext/scalar_relational.inl +++ b/glm/ext/scalar_relational.inl @@ -2,23 +2,8 @@ #include "../ext/scalar_int_sized.hpp" #include "../ext/scalar_uint_sized.hpp" -namespace glm{ -namespace detail +namespace glm { - // https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ - union float_t - { - GLM_CONSTEXPR float_t(float Num = 0.0f) : f(Num) {} - // Portable extraction of components. - GLM_CONSTEXPR bool negative() const { return i < 0; } - GLM_CONSTEXPR int32 mantissa() const { return i & ((1 << 23) - 1); } - GLM_CONSTEXPR int32 exponent() const { return (i >> 23) & 0xFF; } - - int32 const i; - float const f; - }; -}//namespace detail - template GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool equal(genType const& x, genType const& y, genType const& epsilon) { diff --git a/glm/ext/vector_relational.hpp b/glm/ext/vector_relational.hpp index a7f93d23..a556bdfa 100644 --- a/glm/ext/vector_relational.hpp +++ b/glm/ext/vector_relational.hpp @@ -62,6 +62,42 @@ namespace glm template GLM_FUNC_DECL GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y, vec const& epsilon); + /// Returns the component-wise comparison between two vectors in term of ULPs. + /// True if this expression is satisfied. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec equal(vec const& x, vec const& y, int ULPs); + + /// Returns the component-wise comparison between two vectors in term of ULPs. + /// True if this expression is satisfied. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec equal(vec const& x, vec const& y, vec const& ULPs); + + /// Returns the component-wise comparison between two vectors in term of ULPs. + /// True if this expression is not satisfied. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y, int ULPs); + + /// Returns the component-wise comparison between two vectors in term of ULPs. + /// True if this expression is not satisfied. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y, vec const& ULPs); + /// @} }//namespace glm diff --git a/glm/ext/vector_relational.inl b/glm/ext/vector_relational.inl index 812cce38..22d2d505 100644 --- a/glm/ext/vector_relational.inl +++ b/glm/ext/vector_relational.inl @@ -27,4 +27,46 @@ namespace glm { return greaterThan(abs(x - y), Epsilon); } + + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec equal(vec const& x, vec const& y, int MaxULPs) + { + return equal(x, y, vec(MaxULPs)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec equal(vec const& x, vec const& y, vec const& MaxULPs) + { + vec Result; + for(length_t i = 0; i < L; ++i) + { + detail::float_t const a(x[i]); + detail::float_t const b(y[i]); + + // Different signs means they do not match. + if(a.negative() != b.negative()) + { + // Check for equality to make sure +0==-0 + return a.mantissa() == b.mantissa() && a.exponent() == b.exponent(); + } + + // Find the difference in ULPs. + int const DiffULPs = abs(a.i - b.i); + Result[i] = DiffULPs <= MaxULPs; + } + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y, int MaxULPs) + { + return !equal(x, y, MaxULPs); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y, vec const& MaxULPs) + { + return !equal(x, y, MaxULPs); + } }//namespace glm