diff --git a/glm/gtc/ulp.hpp b/glm/gtc/ulp.hpp index ad1e174d..11665a2c 100644 --- a/glm/gtc/ulp.hpp +++ b/glm/gtc/ulp.hpp @@ -17,6 +17,7 @@ // Dependencies #include "../gtc/constants.hpp" #include "../ext/vector_relational.hpp" +#include "../ext/scalar_int_sized.hpp" #if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) # pragma message("GLM: GLM_GTC_ulp extension included") @@ -40,22 +41,32 @@ namespace glm /// Return the value(s) ULP distance after the input value(s). /// @see gtc_ulp template - GLM_FUNC_DECL genType next_float(genType const& x, uint const& Distance); + GLM_FUNC_DECL genType next_float(genType const& x, int DistanceULPs); /// Return the value(s) ULP distance before the input value(s). /// @see gtc_ulp template - GLM_FUNC_DECL genType prev_float(genType const& x, uint const& Distance); + GLM_FUNC_DECL genType prev_float(genType const& x, int DistanceULPs); - /// Return the distance in the number of ULP between 2 scalars. + /// Return the distance in the number of ULP between 2 single-precision floating-point scalars. /// @see gtc_ulp template - GLM_FUNC_DECL uint float_distance(T const& x, T const& y); + GLM_FUNC_DECL int float_distance(float x, float y); - /// Return the distance in the number of ULP between 2 vectors. + /// Return the distance in the number of ULP between 2 double-precision floating-point scalars. /// @see gtc_ulp - template - GLM_FUNC_DECL vec<2, uint, Q> float_distance(vec<2, T, Q> const& x, vec<2, T, Q> const& y); + template + GLM_FUNC_DECL int64 float_distance(double x, double y); + + /// Return the distance in the number of ULP between single-precision floating-point 2 vectors. + /// @see gtc_ulp + template + GLM_FUNC_DECL vec float_distance(vec const& x, vec const& y); + + /// Return the distance in the number of ULP between double-precision floating-point 2 vectors. + /// @see gtc_ulp + template + GLM_FUNC_DECL vec float_distance(vec const& x, vec const& y); /// @} }// namespace glm diff --git a/glm/gtc/ulp.inl b/glm/gtc/ulp.inl index 6cff9b06..2251407e 100644 --- a/glm/gtc/ulp.inl +++ b/glm/gtc/ulp.inl @@ -11,6 +11,7 @@ #include #include #include +#include "../detail/type_float.hpp" #if(GLM_COMPILER & GLM_COMPILER_VC) # pragma warning(push) @@ -260,16 +261,16 @@ namespace glm } template - GLM_FUNC_QUALIFIER T next_float(T const& x, uint const& ulps) + GLM_FUNC_QUALIFIER T next_float(T const& x, int ulps) { T temp = x; - for(uint i = 0; i < ulps; ++i) + for(int i = 0; i < ulps; ++i) temp = next_float(temp); return temp; } template - GLM_FUNC_QUALIFIER vec next_float(vec const& x, vec const& ulps) + GLM_FUNC_QUALIFIER vec next_float(vec const& x, vec const& ulps) { vec Result; for(length_t i = 0, n = Result.length(); i < n; ++i) @@ -278,16 +279,18 @@ namespace glm } template - GLM_FUNC_QUALIFIER T prev_float(T const& x, uint const& ulps) + GLM_FUNC_QUALIFIER T prev_float(T const& x, int ulps) { + assert(ulps >= 0); + T temp = x; - for(uint i = 0; i < ulps; ++i) + for(int i = 0; i < ulps; ++i) temp = prev_float(temp); return temp; } template - GLM_FUNC_QUALIFIER vec prev_float(vec const& x, vec const& ulps) + GLM_FUNC_QUALIFIER vec prev_float(vec const& x, vec const& ulps) { vec Result; for(length_t i = 0, n = Result.length(); i < n; ++i) @@ -295,41 +298,35 @@ namespace glm return Result; } - template - GLM_FUNC_QUALIFIER uint float_distance(T const& x, T const& y) + GLM_FUNC_QUALIFIER int float_distance(float x, float y) { - uint ulp = 0; + detail::float_t const a(x); + detail::float_t const b(y); - if(x < y) - { - T temp = x; - while(glm::epsilonNotEqual(temp, y, glm::epsilon()))// && ulp < std::numeric_limits::max()) - { - ++ulp; - temp = next_float(temp); - } - } - else if(y < x) - { - T temp = y; - while(glm::epsilonNotEqual(temp, x, glm::epsilon()))// && ulp < std::numeric_limits::max()) - { - ++ulp; - temp = next_float(temp); - } - } - else // == - { - - } - - return ulp; + return abs(a.i - b.i); } - template - GLM_FUNC_QUALIFIER vec float_distance(vec const& x, vec const& y) + GLM_FUNC_QUALIFIER int64 float_distance(double x, double y) { - vec Result; + detail::float_t const a(x); + detail::float_t const b(y); + + return abs(a.i - b.i); + } + + template + GLM_FUNC_QUALIFIER vec float_distance(vec const& x, vec const& y) + { + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = float_distance(x[i], y[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec float_distance(vec const& x, vec const& y) + { + vec Result; for(length_t i = 0, n = Result.length(); i < n; ++i) Result[i] = float_distance(x[i], y[i]); return Result; diff --git a/test/gtc/gtc_ulp.cpp b/test/gtc/gtc_ulp.cpp index 58ef5ce1..d5074a3d 100644 --- a/test/gtc/gtc_ulp.cpp +++ b/test/gtc/gtc_ulp.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include int test_ulp_float_dist() @@ -9,9 +9,9 @@ int test_ulp_float_dist() float A = 1.0f; float B = glm::next_float(A); - Error += !glm::epsilonEqual(A, B, glm::epsilon()) ? 0 : 1; + Error += glm::notEqual(A, B, 0) ? 0 : 1; float C = glm::prev_float(B); - Error += glm::epsilonEqual(A, C, glm::epsilon()) ? 0 : 1; + Error += glm::equal(A, C, 0) ? 0 : 1; int D = glm::float_distance(A, B); Error += D == 1 ? 0 : 1; @@ -30,9 +30,9 @@ int test_ulp_float_step() for(int i = 10; i < 1000; i *= 10) { float B = glm::next_float(A, i); - Error += !glm::epsilonEqual(A, B, glm::epsilon()) ? 0 : 1; + Error += glm::notEqual(A, B, 0) ? 0 : 1; float C = glm::prev_float(B, i); - Error += glm::epsilonEqual(A, C, glm::epsilon()) ? 0 : 1; + Error += glm::equal(A, C, 0) ? 0 : 1; int D = glm::float_distance(A, B); Error += D == i ? 0 : 1; @@ -50,13 +50,13 @@ int test_ulp_double_dist() double A = 1.0; double B = glm::next_float(A); - Error += !glm::epsilonEqual(A, B, glm::epsilon()) ? 0 : 1; + Error += glm::notEqual(A, B, 0) ? 0 : 1; double C = glm::prev_float(B); - Error += glm::epsilonEqual(A, C, glm::epsilon()) ? 0 : 1; + Error += glm::equal(A, C, 0) ? 0 : 1; - int D = glm::float_distance(A, B); + glm::int64 const D = glm::float_distance(A, B); Error += D == 1 ? 0 : 1; - int E = glm::float_distance(A, C); + glm::int64 const E = glm::float_distance(A, C); Error += E == 0 ? 0 : 1; return Error; @@ -71,13 +71,13 @@ int test_ulp_double_step() for(int i = 10; i < 1000; i *= 10) { double B = glm::next_float(A, i); - Error += !glm::epsilonEqual(A, B, glm::epsilon()) ? 0 : 1; + Error += glm::notEqual(A, B, 0) ? 0 : 1; double C = glm::prev_float(B, i); - Error += glm::epsilonEqual(A, C, glm::epsilon()) ? 0 : 1; + Error += glm::equal(A, C, 0) ? 0 : 1; - int D = glm::float_distance(A, B); + glm::int64 const D = glm::float_distance(A, B); Error += D == i ? 0 : 1; - int E = glm::float_distance(A, C); + glm::int64 const E = glm::float_distance(A, C); Error += E == 0 ? 0 : 1; } @@ -87,10 +87,12 @@ int test_ulp_double_step() int main() { int Error = 0; + Error += test_ulp_float_dist(); Error += test_ulp_float_step(); Error += test_ulp_double_dist(); Error += test_ulp_double_step(); + return Error; }