From 787a60956f1980f8dce9e28ea47a4651073cf42c Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Tue, 22 Feb 2011 01:35:55 +0000 Subject: [PATCH 01/19] Added files for GLM_GTX_ulp extension --- glm/ext.hpp | 1 + glm/gtx/ulp.hpp | 50 +++++++++++++++++++++++++++++++++++++++++++++++++ glm/gtx/ulp.inl | 0 3 files changed, 51 insertions(+) create mode 100644 glm/gtx/ulp.hpp create mode 100644 glm/gtx/ulp.inl diff --git a/glm/ext.hpp b/glm/ext.hpp index e28d4fdb..e337d9af 100644 --- a/glm/ext.hpp +++ b/glm/ext.hpp @@ -73,6 +73,7 @@ #include "./gtx/string_cast.hpp" #include "./gtx/transform.hpp" #include "./gtx/transform2.hpp" +#include "./gtx/ulp.hpp" #include "./gtx/unsigned_int.hpp" #include "./gtx/vec1.hpp" #include "./gtx/vector_access.hpp" diff --git a/glm/gtx/ulp.hpp b/glm/gtx/ulp.hpp new file mode 100644 index 00000000..b15f08cf --- /dev/null +++ b/glm/gtx/ulp.hpp @@ -0,0 +1,50 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////// +// OpenGL Mathematics Copyright (c) 2005 - 2011 G-Truc Creation (www.g-truc.net) +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Created : 2011-02-21 +// Updated : 2009-02-21 +// Licence : This source is under MIT License +// File : glm/gtx/ulp.hpp +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Dependency: +// - GLM core +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef glm_gtx_ulp +#define glm_gtx_ulp + +// Dependency: +#include "../glm.hpp" + +#if(defined(GLM_MESSAGES) && !defined(glm_ext)) +# pragma message("GLM: GLM_GTX_ulp extension included") +#endif + +namespace glm +{ + namespace gtx{ + //! GLM_GTX_ulp extension: Precision calculation functions + namespace spline + { + /// \addtogroup gtx_ulp + ///@{ + + //! Return the number of ULP between 2 variables. + //! From GLM_GTX_ulp extension. + template + genIType ulp( + genType const & a, + genType const & b); + + ///@} + + }//namespace ulp + }//namespace gtx +}//namespace glm + +#include "spline.inl" + +namespace glm{using namespace gtx::spline;} + +#endif//glm_gtx_spline + diff --git a/glm/gtx/ulp.inl b/glm/gtx/ulp.inl new file mode 100644 index 00000000..e69de29b From 0990ac4583587860af7b874b7834884ae0aa0250 Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Sun, 6 Mar 2011 13:39:19 +0000 Subject: [PATCH 02/19] Added ULP base function --- glm/gtx/ulp.hpp | 2 +- glm/gtx/ulp.inl | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/glm/gtx/ulp.hpp b/glm/gtx/ulp.hpp index b15f08cf..18ce2f53 100644 --- a/glm/gtx/ulp.hpp +++ b/glm/gtx/ulp.hpp @@ -42,7 +42,7 @@ namespace glm }//namespace gtx }//namespace glm -#include "spline.inl" +#include "ulp.inl" namespace glm{using namespace gtx::spline;} diff --git a/glm/gtx/ulp.inl b/glm/gtx/ulp.inl index e69de29b..253f5b4e 100644 --- a/glm/gtx/ulp.inl +++ b/glm/gtx/ulp.inl @@ -0,0 +1,43 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////// +// OpenGL Mathematics Copyright (c) 2005 - 2011 G-Truc Creation (www.g-truc.net) +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Created : 2011-03-07 +// Updated : 2011-03-07 +// Licence : This source is under MIT License +// File : glm/gtx/ulp.inl +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#include + +namespace glm{ +namespace gtx{ +namespace ulp +{ + inline std::size_t ulp + ( + double const & a, + double const & b + ) + { + std::size_t Count = 0; + double Temp = a; + while((Temp = nextafterf(Temp, b)) != b) + ++Count; + return Count; + } + + inline std::size_t ulp + ( + float const & a, + float const & b + ) + { + std::size_t Count = 0; + float Temp = a; + while((Temp = nextafterf(Temp, b)) != b) + ++Count; + return Count; + } +}//namespace ulp +}//namespace gtx +}//namespace glm From 84fef7d9887fef303afe7eb05063fc2b3f7a7714 Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Mon, 7 Mar 2011 09:56:48 +0000 Subject: [PATCH 03/19] updated ULP extension --- glm/gtx/ulp.inl | 62 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/glm/gtx/ulp.inl b/glm/gtx/ulp.inl index 253f5b4e..931c33c4 100644 --- a/glm/gtx/ulp.inl +++ b/glm/gtx/ulp.inl @@ -15,13 +15,14 @@ namespace ulp { inline std::size_t ulp ( - double const & a, - double const & b + half const & a, + half const & b ) { std::size_t Count = 0; - double Temp = a; - while((Temp = nextafterf(Temp, b)) != b) + float TempA = a; + float TempB = b; + while((TempA = nextafterf(TempA, TempB)) != TempB) ++Count; return Count; } @@ -38,6 +39,59 @@ namespace ulp ++Count; return Count; } + + inline std::size_t ulp + ( + double const & a, + double const & b + ) + { + std::size_t Count = 0; + double Temp = a; + while((Temp = nextafter(Temp, b)) != b) + ++Count; + return Count; + } + + template + inline detail::xvec2 ulp + ( + detail::xvec2 const & a, + detail::xvec2 const & b + ) + { + return detail::xvec2( + ulp(a[0], b[0]), + ulp(a[1], b[1])); + } + + template + inline detail::xvec3 ulp + ( + detail::xvec3 const & a, + detail::xvec3 const & b + ) + { + return detail::xvec2( + ulp(a[0], b[0]), + ulp(a[1], b[1]), + ulp(a[2], b[2])); + } + + template + inline detail::xvec4 ulp + ( + detail::xvec4 const & a, + detail::xvec4 const & b + ) + { + return detail::xvec2( + ulp(a[0], b[0]), + ulp(a[1], b[1]), + ulp(a[2], b[2]), + ulp(a[3], b[3])); + } + }//namespace ulp }//namespace gtx }//namespace glm From 2ca5985b0ecbf65afebc3b6b0852b4a5a20b02de Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Tue, 26 Apr 2011 12:08:30 +0100 Subject: [PATCH 04/19] Added ULP test file --- glm/gtx/ulp.inl | 30 +++++++++++++++--------------- test/gtx/CMakeLists.txt | 1 + test/gtx/gtx-ulp.cpp | 0 3 files changed, 16 insertions(+), 15 deletions(-) create mode 100644 test/gtx/gtx-ulp.cpp diff --git a/glm/gtx/ulp.inl b/glm/gtx/ulp.inl index 931c33c4..f5cb0d8d 100644 --- a/glm/gtx/ulp.inl +++ b/glm/gtx/ulp.inl @@ -53,39 +53,39 @@ namespace ulp return Count; } - template - inline detail::xvec2 ulp + template + inline detail::xvec2 ulp ( - detail::xvec2 const & a, - detail::xvec2 const & b + detail::xvec2 const & a, + detail::xvec2 const & b ) { - return detail::xvec2( + return detail::xvec2( ulp(a[0], b[0]), ulp(a[1], b[1])); } - template - inline detail::xvec3 ulp + template + inline detail::xvec3 ulp ( - detail::xvec3 const & a, - detail::xvec3 const & b + detail::xvec3 const & a, + detail::xvec3 const & b ) { - return detail::xvec2( + return detail::xvec3( ulp(a[0], b[0]), ulp(a[1], b[1]), ulp(a[2], b[2])); } - template - inline detail::xvec4 ulp + template + inline detail::xvec4 ulp ( - detail::xvec4 const & a, - detail::xvec4 const & b + detail::xvec4 const & a, + detail::xvec4 const & b ) { - return detail::xvec2( + return detail::xvec4( ulp(a[0], b[0]), ulp(a[1], b[1]), ulp(a[2], b[2]), diff --git a/test/gtx/CMakeLists.txt b/test/gtx/CMakeLists.txt index a10131e5..218e333a 100644 --- a/test/gtx/CMakeLists.txt +++ b/test/gtx/CMakeLists.txt @@ -1,3 +1,4 @@ glmCreateTestGTC(gtx-bit) glmCreateTestGTC(gtx-simd-vec4) glmCreateTestGTC(gtx-simd-mat4) +glmCreateTestGTC(gtx-ulp) diff --git a/test/gtx/gtx-ulp.cpp b/test/gtx/gtx-ulp.cpp new file mode 100644 index 00000000..e69de29b From 8e4dcece16e7f04d5de27253f813cf7145d2456c Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Tue, 26 Apr 2011 12:29:56 +0100 Subject: [PATCH 05/19] Fixed vector based ULP functions --- glm/gtx/ulp.inl | 42 +++++++++++++++++++++++++++--------------- test/gtx/gtx-ulp.cpp | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 15 deletions(-) diff --git a/glm/gtx/ulp.inl b/glm/gtx/ulp.inl index f5cb0d8d..bd2e3430 100644 --- a/glm/gtx/ulp.inl +++ b/glm/gtx/ulp.inl @@ -54,42 +54,54 @@ namespace ulp } template - inline detail::xvec2 ulp + inline std::size_t ulp ( detail::xvec2 const & a, detail::xvec2 const & b ) { - return detail::xvec2( - ulp(a[0], b[0]), - ulp(a[1], b[1])); + std::size_t ulps[] = + { + ulp(a[0], b[0]), + ulp(a[1], b[1]) + }; + + return glm::max(ulps[0], ulps[1])s; } template - inline detail::xvec3 ulp + inline std::size_t ulp ( detail::xvec3 const & a, detail::xvec3 const & b ) { - return detail::xvec3( - ulp(a[0], b[0]), - ulp(a[1], b[1]), - ulp(a[2], b[2])); + std::size_t ulps[] = + { + ulp(a[0], b[0]), + ulp(a[1], b[1]), + ulp(a[2], b[2]) + }; + + return glm::max(glm::max(ulps[0], ulps[1]), ulps[2]); } template - inline detail::xvec4 ulp + inline std::size_t ulp ( detail::xvec4 const & a, detail::xvec4 const & b ) { - return detail::xvec4( - ulp(a[0], b[0]), - ulp(a[1], b[1]), - ulp(a[2], b[2]), - ulp(a[3], b[3])); + std::size_t ulps[] = + { + ulp(a[0], b[0]), + ulp(a[1], b[1]), + ulp(a[2], b[2]), + ulp(a[3], b[3]) + }; + + return glm::max(glm::max(ulps[0], ulps[1]), glm::max(ulps[2], ulps[3])); } }//namespace ulp diff --git a/test/gtx/gtx-ulp.cpp b/test/gtx/gtx-ulp.cpp index e69de29b..ee1bd3e9 100644 --- a/test/gtx/gtx-ulp.cpp +++ b/test/gtx/gtx-ulp.cpp @@ -0,0 +1,32 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////// +// OpenGL Mathematics Copyright (c) 2005 - 2011 G-Truc Creation (www.g-truc.net) +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Created : 2011-04-26 +// Updated : 2011-04-26 +// Licence : This source is under MIT licence +// File : test/gtx/ulp.cpp +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include + +int test_ulp_float() +{ + std::size_t A = ulp(0.01, 0.02); + std::size_t B = ulp(glm::vec2(0.01), glm::vec2(0.02)); + std::size_t C = ulp(glm::vec3(0.01), glm::vec3(0.02)); + std::size_t D = ulp(glm::vec4(0.01), glm::vec4(0.02)); + std::cout << "glm::ulp test: " << A << std::endl; + std::cout << "glm::ulp test: " << B << std::endl; + std::cout << "glm::ulp test: " << C << std::endl; + std::cout << "glm::ulp test: " << D << std::endl; + return 0; +} + +int main() +{ + test_ulp_float(); +} + + From 1dd95326054797d56b0ac8e2a31ea4cb1201fa73 Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Tue, 26 Apr 2011 12:42:01 +0100 Subject: [PATCH 06/19] Fixed ULP declaration --- glm/gtx/ulp.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glm/gtx/ulp.hpp b/glm/gtx/ulp.hpp index 18ce2f53..fce68d73 100644 --- a/glm/gtx/ulp.hpp +++ b/glm/gtx/ulp.hpp @@ -32,7 +32,7 @@ namespace glm //! Return the number of ULP between 2 variables. //! From GLM_GTX_ulp extension. template - genIType ulp( + std::size_t ulp( genType const & a, genType const & b); From 69c764eca9b0dc51b8f1ac72fd984d9acba23364 Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Tue, 26 Apr 2011 14:24:45 +0100 Subject: [PATCH 07/19] Fixed build --- glm/gtx/ulp.hpp | 6 +++--- glm/gtx/ulp.inl | 24 ++++++++++++------------ test/gtx/gtx-ulp.cpp | 8 ++++---- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/glm/gtx/ulp.hpp b/glm/gtx/ulp.hpp index fce68d73..d93c1990 100644 --- a/glm/gtx/ulp.hpp +++ b/glm/gtx/ulp.hpp @@ -24,7 +24,7 @@ namespace glm { namespace gtx{ //! GLM_GTX_ulp extension: Precision calculation functions - namespace spline + namespace ulp { /// \addtogroup gtx_ulp ///@{ @@ -44,7 +44,7 @@ namespace glm #include "ulp.inl" -namespace glm{using namespace gtx::spline;} +namespace glm{using namespace gtx::ulp;} -#endif//glm_gtx_spline +#endif//glm_gtx_ulp diff --git a/glm/gtx/ulp.inl b/glm/gtx/ulp.inl index bd2e3430..b223e543 100644 --- a/glm/gtx/ulp.inl +++ b/glm/gtx/ulp.inl @@ -2,7 +2,7 @@ // OpenGL Mathematics Copyright (c) 2005 - 2011 G-Truc Creation (www.g-truc.net) /////////////////////////////////////////////////////////////////////////////////////////////////// // Created : 2011-03-07 -// Updated : 2011-03-07 +// Updated : 2011-04-26 // Licence : This source is under MIT License // File : glm/gtx/ulp.inl /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -15,13 +15,13 @@ namespace ulp { inline std::size_t ulp ( - half const & a, - half const & b + detail::thalf const & a, + detail::thalf const & b ) { std::size_t Count = 0; - float TempA = a; - float TempB = b; + float TempA(a); + float TempB(b); while((TempA = nextafterf(TempA, TempB)) != TempB) ++Count; return Count; @@ -56,8 +56,8 @@ namespace ulp template inline std::size_t ulp ( - detail::xvec2 const & a, - detail::xvec2 const & b + detail::tvec2 const & a, + detail::tvec2 const & b ) { std::size_t ulps[] = @@ -66,14 +66,14 @@ namespace ulp ulp(a[1], b[1]) }; - return glm::max(ulps[0], ulps[1])s; + return glm::max(ulps[0], ulps[1]); } template inline std::size_t ulp ( - detail::xvec3 const & a, - detail::xvec3 const & b + detail::tvec3 const & a, + detail::tvec3 const & b ) { std::size_t ulps[] = @@ -89,8 +89,8 @@ namespace ulp template inline std::size_t ulp ( - detail::xvec4 const & a, - detail::xvec4 const & b + detail::tvec4 const & a, + detail::tvec4 const & b ) { std::size_t ulps[] = diff --git a/test/gtx/gtx-ulp.cpp b/test/gtx/gtx-ulp.cpp index ee1bd3e9..753f5729 100644 --- a/test/gtx/gtx-ulp.cpp +++ b/test/gtx/gtx-ulp.cpp @@ -13,10 +13,10 @@ int test_ulp_float() { - std::size_t A = ulp(0.01, 0.02); - std::size_t B = ulp(glm::vec2(0.01), glm::vec2(0.02)); - std::size_t C = ulp(glm::vec3(0.01), glm::vec3(0.02)); - std::size_t D = ulp(glm::vec4(0.01), glm::vec4(0.02)); + std::size_t A = glm::ulp(0.01, 0.02); + std::size_t B = glm::ulp(glm::vec2(0.01), glm::vec2(0.02)); + std::size_t C = glm::ulp(glm::vec3(0.01), glm::vec3(0.02)); + std::size_t D = glm::ulp(glm::vec4(0.01), glm::vec4(0.02)); std::cout << "glm::ulp test: " << A << std::endl; std::cout << "glm::ulp test: " << B << std::endl; std::cout << "glm::ulp test: " << C << std::endl; From eb95923402d5d7a60312e1dfe73c8c5c0ba24972 Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Tue, 26 Apr 2011 14:46:30 +0100 Subject: [PATCH 08/19] Developement test --- glm/gtx/ulp.inl | 7 +++++++ test/gtx/gtx-ulp.cpp | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/glm/gtx/ulp.inl b/glm/gtx/ulp.inl index b223e543..0e1346e9 100644 --- a/glm/gtx/ulp.inl +++ b/glm/gtx/ulp.inl @@ -8,6 +8,7 @@ /////////////////////////////////////////////////////////////////////////////////////////////////// #include +#include namespace glm{ namespace gtx{ @@ -36,7 +37,10 @@ namespace ulp std::size_t Count = 0; float Temp = a; while((Temp = nextafterf(Temp, b)) != b) + { + std::cout << Temp << " " << b << std::endl; ++Count; + } return Count; } @@ -49,7 +53,10 @@ namespace ulp std::size_t Count = 0; double Temp = a; while((Temp = nextafter(Temp, b)) != b) + { + std::cout << Temp << " " << b << std::endl; ++Count; + } return Count; } diff --git a/test/gtx/gtx-ulp.cpp b/test/gtx/gtx-ulp.cpp index 753f5729..5c8ed883 100644 --- a/test/gtx/gtx-ulp.cpp +++ b/test/gtx/gtx-ulp.cpp @@ -13,6 +13,9 @@ int test_ulp_float() { + double Temp = nextafter(0.02, 0.01); + std::cout << Temp << " 0.01, 0.02" << std::endl; + std::size_t A = glm::ulp(0.01, 0.02); std::size_t B = glm::ulp(glm::vec2(0.01), glm::vec2(0.02)); std::size_t C = glm::ulp(glm::vec3(0.01), glm::vec3(0.02)); @@ -26,6 +29,7 @@ int test_ulp_float() int main() { + std::cout << "Test 76" << std::endl; test_ulp_float(); } From a432aec5153ba8e4cd5d909caf9c881024761b5d Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Tue, 3 May 2011 00:20:09 +0100 Subject: [PATCH 09/19] Visual C++ Version... --- glm/gtx/ulp.inl | 6 +++--- test/gtx/gtx-ulp.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/glm/gtx/ulp.inl b/glm/gtx/ulp.inl index 0e1346e9..4768b5ff 100644 --- a/glm/gtx/ulp.inl +++ b/glm/gtx/ulp.inl @@ -23,7 +23,7 @@ namespace ulp std::size_t Count = 0; float TempA(a); float TempB(b); - while((TempA = nextafterf(TempA, TempB)) != TempB) + while((TempA = _nextafterf(TempA, TempB)) != TempB) ++Count; return Count; } @@ -36,7 +36,7 @@ namespace ulp { std::size_t Count = 0; float Temp = a; - while((Temp = nextafterf(Temp, b)) != b) + while((Temp = _nextafterf(Temp, b)) != b) { std::cout << Temp << " " << b << std::endl; ++Count; @@ -52,7 +52,7 @@ namespace ulp { std::size_t Count = 0; double Temp = a; - while((Temp = nextafter(Temp, b)) != b) + while((Temp = _nextafter(Temp, b)) != b) { std::cout << Temp << " " << b << std::endl; ++Count; diff --git a/test/gtx/gtx-ulp.cpp b/test/gtx/gtx-ulp.cpp index 5c8ed883..5dbdb01c 100644 --- a/test/gtx/gtx-ulp.cpp +++ b/test/gtx/gtx-ulp.cpp @@ -13,8 +13,8 @@ int test_ulp_float() { - double Temp = nextafter(0.02, 0.01); - std::cout << Temp << " 0.01, 0.02" << std::endl; + double Temp = _nextafter(0.01, 0.011); + std::cout << Temp << " 0.01, 0.011" << std::endl; std::size_t A = glm::ulp(0.01, 0.02); std::size_t B = glm::ulp(glm::vec2(0.01), glm::vec2(0.02)); From 7a1cc47897a40a63b501fcce0f1749fc4e191102 Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Wed, 4 May 2011 00:54:35 +0100 Subject: [PATCH 10/19] Added development tests --- test/gtx/gtx-ulp.cpp | 72 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 2 deletions(-) diff --git a/test/gtx/gtx-ulp.cpp b/test/gtx/gtx-ulp.cpp index 5dbdb01c..48fe148b 100644 --- a/test/gtx/gtx-ulp.cpp +++ b/test/gtx/gtx-ulp.cpp @@ -10,11 +10,79 @@ #include #include #include +#include + +namespace +{ + template + T next(T const & x); + +#if(GLM_COMPILER & GLM_COMPILER_VC) +# include + GLM_FUNC_QUALIFIER float next(float const & x) + { + return _nextafterf(x, std::numeric_limits::max()); + } + + GLM_FUNC_QUALIFIER double next(double const & x) + { + return _nextafter(x, std::numeric_limits::max()); + } +#else +# include + GLM_FUNC_QUALIFIER float next(float const & x) + { + return nextafterf(x, std::numeric_limits::max()); + } + + GLM_FUNC_QUALIFIER double next(double const & x) + { + return nextafter(x, std::numeric_limits::max()); + } +#endif + + template + GLM_FUNC_QUALIFIER T next(T const & x, std::size_t const & Steps) + { + T temp = x; + for(std::size_t i = 0; i < Steps; ++i) + temp = next(temp); + return temp; + } + + template + GLM_FUNC_QUALIFIER std::size_t ulp_distance(T const & x, T const & y) + { + std::size_t ulp = 0; + T temp = x; + + while(temp != y) + { + ++ulp; + temp = next(temp); + } + + return ulp; + } +}//namespace int test_ulp_float() { - double Temp = _nextafter(0.01, 0.011); - std::cout << Temp << " 0.01, 0.011" << std::endl; + std::cout.precision(std::numeric_limits::digits10 + 1); + + float W = 1.0f; + float X = next(W); + bool TestX = W != X; + std::cout << " 1.0f, Next: " << ulp_distance(W, X)<< std::endl; + std::cout << " 1.0f, Nextt(1000): " << next(W, 1000)<< std::endl; + //std::cout << " 0.01, 0.011: " << ulp_distance(0.00000000001f, 0.000000000011f) << std::endl; + //std::cout << " 0.01, 0.011: " << ulp_distance(0.00000000001, 0.000000000011) << std::endl; + + double Y = 1.0; + double Z = next(Y); + bool TestZ = Y != Z; + std::cout << Z << " 0.01, 0.011" << std::endl; + std::cout << " 1.0, Next(1000000): " << next(Y, 1000000)<< std::endl; std::size_t A = glm::ulp(0.01, 0.02); std::size_t B = glm::ulp(glm::vec2(0.01), glm::vec2(0.02)); From 58d2d282f2c8f81cce09365c6654393e160a9dc2 Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Wed, 4 May 2011 10:21:25 +0100 Subject: [PATCH 11/19] Updated naming conventions --- glm/gtx/ulp.inl | 6 +-- test/gtx/gtx-ulp.cpp | 106 +++++++++++++++++++++++++++++-------------- 2 files changed, 75 insertions(+), 37 deletions(-) diff --git a/glm/gtx/ulp.inl b/glm/gtx/ulp.inl index 4768b5ff..b99e8c49 100644 --- a/glm/gtx/ulp.inl +++ b/glm/gtx/ulp.inl @@ -23,7 +23,7 @@ namespace ulp std::size_t Count = 0; float TempA(a); float TempB(b); - while((TempA = _nextafterf(TempA, TempB)) != TempB) + //while((TempA = _nextafterf(TempA, TempB)) != TempB) ++Count; return Count; } @@ -36,7 +36,7 @@ namespace ulp { std::size_t Count = 0; float Temp = a; - while((Temp = _nextafterf(Temp, b)) != b) + //while((Temp = _nextafterf(Temp, b)) != b) { std::cout << Temp << " " << b << std::endl; ++Count; @@ -52,7 +52,7 @@ namespace ulp { std::size_t Count = 0; double Temp = a; - while((Temp = _nextafter(Temp, b)) != b) + //while((Temp = _nextafter(Temp, b)) != b) { std::cout << Temp << " " << b << std::endl; ++Count; diff --git a/test/gtx/gtx-ulp.cpp b/test/gtx/gtx-ulp.cpp index 48fe148b..54512d5c 100644 --- a/test/gtx/gtx-ulp.cpp +++ b/test/gtx/gtx-ulp.cpp @@ -15,53 +15,82 @@ namespace { template - T next(T const & x); + T next_float(T const & x); #if(GLM_COMPILER & GLM_COMPILER_VC) # include - GLM_FUNC_QUALIFIER float next(float const & x) +# define GLM_NEXT_AFTER _nextafterf +#else +# include +# define GLM_NEXT_AFTER nextafterf +#endif + + GLM_FUNC_QUALIFIER float next_float(float const & x) { - return _nextafterf(x, std::numeric_limits::max()); + return GLM_NEXT_AFTER(x, std::numeric_limits::max()); } - GLM_FUNC_QUALIFIER double next(double const & x) + GLM_FUNC_QUALIFIER double next_float(double const & x) { - return _nextafter(x, std::numeric_limits::max()); + return GLM_NEXT_AFTER(x, std::numeric_limits::max()); } -#else -# include - GLM_FUNC_QUALIFIER float next(float const & x) + + GLM_FUNC_QUALIFIER float prev_float(float const & x) { - return nextafterf(x, std::numeric_limits::max()); + return GLM_NEXT_AFTER(x, std::numeric_limits::min()); } - - GLM_FUNC_QUALIFIER double next(double const & x) + + GLM_FUNC_QUALIFIER double prev_float(double const & x) { - return nextafter(x, std::numeric_limits::max()); + return GLM_NEXT_AFTER(x, std::numeric_limits::min()); } -#endif template - GLM_FUNC_QUALIFIER T next(T const & x, std::size_t const & Steps) + GLM_FUNC_QUALIFIER T next_float(T const & x, std::size_t const & ulps) { T temp = x; - for(std::size_t i = 0; i < Steps; ++i) - temp = next(temp); + for(std::size_t i = 0; i < ulps; ++i) + temp = next_float(temp); return temp; } template - GLM_FUNC_QUALIFIER std::size_t ulp_distance(T const & x, T const & y) + GLM_FUNC_QUALIFIER T prev_float(T const & x, std::size_t const & ulps) { - std::size_t ulp = 0; T temp = x; - - while(temp != y) - { - ++ulp; - temp = next(temp); - } - + for(std::size_t i = 0; i < ulps; ++i) + temp = prev_float(temp); + return temp; + } + + template + GLM_FUNC_QUALIFIER std::size_t float_distance(T const & x, T const & y) + { + std::size_t ulp = 0; + + if(x < y) + { + T temp = x; + while(temp != y && ulp < std::numeric_limits::max()) + { + ++ulp; + temp = next_float(temp); + } + } + else if(y < x) + { + T temp = y; + while(temp != x && ulp < std::numeric_limits::max()) + { + ++ulp; + temp = next_float(temp); + } + } + else // == + { + + } + return ulp; } }//namespace @@ -71,18 +100,27 @@ int test_ulp_float() std::cout.precision(std::numeric_limits::digits10 + 1); float W = 1.0f; - float X = next(W); + float X = next_float(W); + + double Y = 1.0; + double Z = next_float(Y); + bool TestX = W != X; - std::cout << " 1.0f, Next: " << ulp_distance(W, X)<< std::endl; - std::cout << " 1.0f, Nextt(1000): " << next(W, 1000)<< std::endl; - //std::cout << " 0.01, 0.011: " << ulp_distance(0.00000000001f, 0.000000000011f) << std::endl; - //std::cout << " 0.01, 0.011: " << ulp_distance(0.00000000001, 0.000000000011) << std::endl; + bool TestZ = Y != Z; + + std::cout << "1.0f, Next: " << float_distance(W, X)<< std::endl; + std::cout << "1.0f, Next(1000): " << float_distance(W, next_float(W, 1000)) << std::endl; + + std::cout << "1.0f, Next: " << float_distance(X, W)<< std::endl; + std::cout << "1.0f, Next(1000): " << float_distance(next_float(W, 1000), W) << std::endl; + + std::cout << "1.0, Next: " << float_distance(Y, Z) << std::endl; + std::cout << "1.0, Next(1000): " << float_distance(next_float(Y, 1000), Y) << std::endl; + + - double Y = 1.0; - double Z = next(Y); - bool TestZ = Y != Z; std::cout << Z << " 0.01, 0.011" << std::endl; - std::cout << " 1.0, Next(1000000): " << next(Y, 1000000)<< std::endl; + std::cout << " 1.0, Next(1000000): " << next_float(Y, 1000000)<< std::endl; std::size_t A = glm::ulp(0.01, 0.02); std::size_t B = glm::ulp(glm::vec2(0.01), glm::vec2(0.02)); From cb455f49ce08b412c323fec41829047aa6e228dc Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Wed, 4 May 2011 10:32:44 +0100 Subject: [PATCH 12/19] Added GTX_ulp implementation of scalar functions (TODO: vector ones) --- glm/gtx/ulp.inl | 96 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 94 insertions(+), 2 deletions(-) diff --git a/glm/gtx/ulp.inl b/glm/gtx/ulp.inl index b99e8c49..dbd85a35 100644 --- a/glm/gtx/ulp.inl +++ b/glm/gtx/ulp.inl @@ -7,13 +7,105 @@ // File : glm/gtx/ulp.inl /////////////////////////////////////////////////////////////////////////////////////////////////// -#include -#include +#if(GLM_COMPILER & GLM_COMPILER_VC) +# include +# define GLM_NEXT_AFTER _nextafterf +#else +# include +# define GLM_NEXT_AFTER nextafterf +#endif namespace glm{ namespace gtx{ namespace ulp { + GLM_FUNC_QUALIFIER float next_float(float const & x) + { + return GLM_NEXT_AFTER(x, std::numeric_limits::max()); + } + + GLM_FUNC_QUALIFIER double next_float(double const & x) + { + return GLM_NEXT_AFTER(x, std::numeric_limits::max()); + } + + template class vecType> + GLM_FUNC_QUALIFIER vecType next_float(vecType const & x) + { + vecType Result; + for(std::size_t i = 0; i < Result.length(); ++i) + Result[i] = next_float(x[i]); + return Result; + } + + GLM_FUNC_QUALIFIER float prev_float(float const & x) + { + return GLM_NEXT_AFTER(x, std::numeric_limits::min()); + } + + GLM_FUNC_QUALIFIER double prev_float(double const & x) + { + return GLM_NEXT_AFTER(x, std::numeric_limits::min()); + } + + template class vecType> + GLM_FUNC_QUALIFIER vecType prev_float(vecType const & x) + { + vecType Result; + for(std::size_t i = 0; i < Result.length(); ++i) + Result[i] = prev_float(x[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER T next_float(T const & x, std::size_t const & ulps) + { + T temp = x; + for(std::size_t i = 0; i < ulps; ++i) + temp = next_float(temp); + return temp; + } + + template + GLM_FUNC_QUALIFIER T prev_float(T const & x, std::size_t const & ulps) + { + T temp = x; + for(std::size_t i = 0; i < ulps; ++i) + temp = prev_float(temp); + return temp; + } + + template + GLM_FUNC_QUALIFIER std::size_t float_distance(T const & x, T const & y) + { + std::size_t ulp = 0; + + if(x < y) + { + T temp = x; + while(temp != y && ulp < std::numeric_limits::max()) + { + ++ulp; + temp = next_float(temp); + } + } + else if(y < x) + { + T temp = y; + while(temp != x && ulp < std::numeric_limits::max()) + { + ++ulp; + temp = next_float(temp); + } + } + else // == + { + + } + + return ulp; + } + inline std::size_t ulp ( detail::thalf const & a, From 17c964be6eb01fba643330bd49e9e96180c2bbf2 Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Wed, 4 May 2011 20:18:05 +0100 Subject: [PATCH 13/19] Added vector implementation --- glm/gtx/ulp.inl | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/glm/gtx/ulp.inl b/glm/gtx/ulp.inl index dbd85a35..3f8cbedb 100644 --- a/glm/gtx/ulp.inl +++ b/glm/gtx/ulp.inl @@ -58,7 +58,7 @@ namespace ulp } template - GLM_FUNC_QUALIFIER T next_float(T const & x, std::size_t const & ulps) + GLM_FUNC_QUALIFIER T next_float(T const & x, uint const & ulps) { T temp = x; for(std::size_t i = 0; i < ulps; ++i) @@ -66,8 +66,17 @@ namespace ulp return temp; } + template class vecType> + GLM_FUNC_QUALIFIER vecType next_float(vecType const & x, vecType const & ulps) + { + vecType Result; + for(std::size_t i = 0; i < Result.length(); ++i) + Result[i] = next_float(x[i], ulps[i]); + return Result; + } + template - GLM_FUNC_QUALIFIER T prev_float(T const & x, std::size_t const & ulps) + GLM_FUNC_QUALIFIER T prev_float(T const & x, uint const & ulps) { T temp = x; for(std::size_t i = 0; i < ulps; ++i) @@ -75,8 +84,17 @@ namespace ulp return temp; } + template class vecType> + GLM_FUNC_QUALIFIER vecType prev_float(vecType const & x, vecType const & ulps) + { + vecType Result; + for(std::size_t i = 0; i < Result.length(); ++i) + Result[i] = prev_float(x[i], ulps[i]); + return Result; + } + template - GLM_FUNC_QUALIFIER std::size_t float_distance(T const & x, T const & y) + GLM_FUNC_QUALIFIER uint float_distance(T const & x, T const & y) { std::size_t ulp = 0; @@ -106,6 +124,15 @@ namespace ulp return ulp; } + template class vecType> + GLM_FUNC_QUALIFIER vecType float_distance(vecType const & x, vecType const & y) + { + vecType Result; + for(std::size_t i = 0; i < Result.length(); ++i) + Result[i] = float_distance(x[i], y[i]); + return Result; + } +/* inline std::size_t ulp ( detail::thalf const & a, @@ -202,7 +229,7 @@ namespace ulp return glm::max(glm::max(ulps[0], ulps[1]), glm::max(ulps[2], ulps[3])); } - +*/ }//namespace ulp }//namespace gtx }//namespace glm From b6857ae15fe3d711afe1138e12835baf57c18ece Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Wed, 4 May 2011 20:58:30 +0100 Subject: [PATCH 14/19] Added ULP functions declarations --- glm/gtx/ulp.hpp | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/glm/gtx/ulp.hpp b/glm/gtx/ulp.hpp index d93c1990..81f588db 100644 --- a/glm/gtx/ulp.hpp +++ b/glm/gtx/ulp.hpp @@ -29,13 +29,36 @@ namespace glm /// \addtogroup gtx_ulp ///@{ - //! Return the number of ULP between 2 variables. + //! Return the next ULP value(s) after the input value(s). //! From GLM_GTX_ulp extension. - template - std::size_t ulp( - genType const & a, - genType const & b); + template + genType next_float(genType const & x); + + //! Return the previous ULP value(s) before the input value(s). + //! From GLM_GTX_ulp extension. + template + genType prev_float(genType const & x); + //! Return the value(s) ULP distance after the input value(s). + //! From GLM_GTX_ulp extension. + template + genType next_float(genType const & x, uint const & Distance); + + //! Return the value(s) ULP distance before the input value(s). + //! From GLM_GTX_ulp extension. + template + genType prev_float(genType const & x, uint const & Distance); + + //! Return the distance in the number of ULP between 2 scalars. + //! From GLM_GTX_ulp extension. + template + uint float_distance(T const & x, T const & y); + + //! Return the distance in the number of ULP between 2 vectors. + //! From GLM_GTX_ulp extension. + template class vecType> + vecType float_distance(vecType const & x, vecType const & y); + ///@} }//namespace ulp From 06d0b33f7ba50c742e2cf5293520ab5865cc6025 Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Thu, 5 May 2011 13:36:07 +0100 Subject: [PATCH 15/19] Fixed build --- glm/gtx/ulp.inl | 23 ++++++--- test/gtx/gtx-ulp.cpp | 119 +++++++------------------------------------ 2 files changed, 33 insertions(+), 109 deletions(-) diff --git a/glm/gtx/ulp.inl b/glm/gtx/ulp.inl index 3f8cbedb..e86c44ce 100644 --- a/glm/gtx/ulp.inl +++ b/glm/gtx/ulp.inl @@ -7,12 +7,19 @@ // File : glm/gtx/ulp.inl /////////////////////////////////////////////////////////////////////////////////////////////////// +#include +#include + #if(GLM_COMPILER & GLM_COMPILER_VC) -# include -# define GLM_NEXT_AFTER _nextafterf +# if(GLM_MODEL == GLM_MODEL_32) +# define GLM_NEXT_AFTER_FLT(x, toward) (float)_nextafter(x, float(toward)) +# else +# define GLM_NEXT_AFTER_FLT(x, toward) _nextafterf(x, toward) +# endif +# define GLM_NEXT_AFTER_DBL(x, toward) _nextafter(x, toward) #else -# include -# define GLM_NEXT_AFTER nextafterf +# define GLM_NEXT_AFTER_FLT(x, toward) nextafterf(x, toward) +# define GLM_NEXT_AFTER_DBL(x, toward) nextafter(x, toward) #endif namespace glm{ @@ -21,12 +28,12 @@ namespace ulp { GLM_FUNC_QUALIFIER float next_float(float const & x) { - return GLM_NEXT_AFTER(x, std::numeric_limits::max()); + return GLM_NEXT_AFTER_FLT(x, std::numeric_limits::max()); } GLM_FUNC_QUALIFIER double next_float(double const & x) { - return GLM_NEXT_AFTER(x, std::numeric_limits::max()); + return GLM_NEXT_AFTER_DBL(x, std::numeric_limits::max()); } template class vecType> @@ -40,12 +47,12 @@ namespace ulp GLM_FUNC_QUALIFIER float prev_float(float const & x) { - return GLM_NEXT_AFTER(x, std::numeric_limits::min()); + return GLM_NEXT_AFTER_FLT(x, std::numeric_limits::min()); } GLM_FUNC_QUALIFIER double prev_float(double const & x) { - return GLM_NEXT_AFTER(x, std::numeric_limits::min()); + return GLM_NEXT_AFTER_DBL(x, std::numeric_limits::min()); } template class vecType> diff --git a/test/gtx/gtx-ulp.cpp b/test/gtx/gtx-ulp.cpp index 54512d5c..348a09ce 100644 --- a/test/gtx/gtx-ulp.cpp +++ b/test/gtx/gtx-ulp.cpp @@ -12,124 +12,41 @@ #include #include -namespace -{ - template - T next_float(T const & x); - -#if(GLM_COMPILER & GLM_COMPILER_VC) -# include -# define GLM_NEXT_AFTER _nextafterf -#else -# include -# define GLM_NEXT_AFTER nextafterf -#endif - - GLM_FUNC_QUALIFIER float next_float(float const & x) - { - return GLM_NEXT_AFTER(x, std::numeric_limits::max()); - } - - GLM_FUNC_QUALIFIER double next_float(double const & x) - { - return GLM_NEXT_AFTER(x, std::numeric_limits::max()); - } - - GLM_FUNC_QUALIFIER float prev_float(float const & x) - { - return GLM_NEXT_AFTER(x, std::numeric_limits::min()); - } - - GLM_FUNC_QUALIFIER double prev_float(double const & x) - { - return GLM_NEXT_AFTER(x, std::numeric_limits::min()); - } - - template - GLM_FUNC_QUALIFIER T next_float(T const & x, std::size_t const & ulps) - { - T temp = x; - for(std::size_t i = 0; i < ulps; ++i) - temp = next_float(temp); - return temp; - } - - template - GLM_FUNC_QUALIFIER T prev_float(T const & x, std::size_t const & ulps) - { - T temp = x; - for(std::size_t i = 0; i < ulps; ++i) - temp = prev_float(temp); - return temp; - } - - template - GLM_FUNC_QUALIFIER std::size_t float_distance(T const & x, T const & y) - { - std::size_t ulp = 0; - - if(x < y) - { - T temp = x; - while(temp != y && ulp < std::numeric_limits::max()) - { - ++ulp; - temp = next_float(temp); - } - } - else if(y < x) - { - T temp = y; - while(temp != x && ulp < std::numeric_limits::max()) - { - ++ulp; - temp = next_float(temp); - } - } - else // == - { - - } - - return ulp; - } -}//namespace - int test_ulp_float() { std::cout.precision(std::numeric_limits::digits10 + 1); float W = 1.0f; - float X = next_float(W); + float X = glm::next_float(W); double Y = 1.0; - double Z = next_float(Y); + double Z = glm::next_float(Y); bool TestX = W != X; bool TestZ = Y != Z; - std::cout << "1.0f, Next: " << float_distance(W, X)<< std::endl; - std::cout << "1.0f, Next(1000): " << float_distance(W, next_float(W, 1000)) << std::endl; + std::cout << "1.0f, Next: " << glm::float_distance(W, X)<< std::endl; + std::cout << "1.0f, Next(1000): " << glm::float_distance(W, glm::next_float(W, 1000)) << std::endl; - std::cout << "1.0f, Next: " << float_distance(X, W)<< std::endl; - std::cout << "1.0f, Next(1000): " << float_distance(next_float(W, 1000), W) << std::endl; + std::cout << "1.0f, Next: " << glm::float_distance(X, W)<< std::endl; + std::cout << "1.0f, Next(1000): " << glm::float_distance(glm::next_float(W, 1000), W) << std::endl; - std::cout << "1.0, Next: " << float_distance(Y, Z) << std::endl; - std::cout << "1.0, Next(1000): " << float_distance(next_float(Y, 1000), Y) << std::endl; + std::cout << "1.0, Next: " << glm::float_distance(Y, Z) << std::endl; + std::cout << "1.0, Next(1000): " << glm::float_distance(glm::next_float(Y, 1000), Y) << std::endl; std::cout << Z << " 0.01, 0.011" << std::endl; - std::cout << " 1.0, Next(1000000): " << next_float(Y, 1000000)<< std::endl; - - std::size_t A = glm::ulp(0.01, 0.02); - std::size_t B = glm::ulp(glm::vec2(0.01), glm::vec2(0.02)); - std::size_t C = glm::ulp(glm::vec3(0.01), glm::vec3(0.02)); - std::size_t D = glm::ulp(glm::vec4(0.01), glm::vec4(0.02)); - std::cout << "glm::ulp test: " << A << std::endl; - std::cout << "glm::ulp test: " << B << std::endl; - std::cout << "glm::ulp test: " << C << std::endl; - std::cout << "glm::ulp test: " << D << std::endl; + std::cout << " 1.0, Next(1000000): " << glm::next_float(Y, 1000000)<< std::endl; + + //std::size_t A = glm::ulp(0.01, 0.02); + //std::size_t B = glm::ulp(glm::vec2(0.01), glm::vec2(0.02)); + //std::size_t C = glm::ulp(glm::vec3(0.01), glm::vec3(0.02)); + //std::size_t D = glm::ulp(glm::vec4(0.01), glm::vec4(0.02)); + //std::cout << "glm::ulp test: " << A << std::endl; + //std::cout << "glm::ulp test: " << B << std::endl; + //std::cout << "glm::ulp test: " << C << std::endl; + //std::cout << "glm::ulp test: " << D << std::endl; return 0; } From 16a9250842e47f34391f8dfb9e48438256aa6eb8 Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Fri, 6 May 2011 11:16:10 +0100 Subject: [PATCH 16/19] Added nextafter implementation --- glm/gtx/ulp.inl | 138 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) diff --git a/glm/gtx/ulp.inl b/glm/gtx/ulp.inl index e86c44ce..b60db3e4 100644 --- a/glm/gtx/ulp.inl +++ b/glm/gtx/ulp.inl @@ -10,6 +10,144 @@ #include #include +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* +#define EXTRACT_WORDS(ix0,ix1,d) \ +do { \ + ieee_double_shape_type ew_u; \ + ew_u.value = (d); \ + (ix0) = ew_u.parts.msw; \ + (ix1) = ew_u.parts.lsw; \ +} while (0) + +#define GET_FLOAT_WORD(i,d) \ +do { \ + ieee_float_shape_type gf_u; \ + gf_u.value = (d); \ + (i) = gf_u.word; \ +} while (0) + +#define SET_FLOAT_WORD(d,i) \ +do { \ + ieee_float_shape_type sf_u; \ + sf_u.word = (i); \ + (d) = sf_u.value; \ +} while (0) + +#define INSERT_WORDS(d,ix0,ix1) \ +do { \ + ieee_double_shape_type iw_u; \ + iw_u.parts.msw = (ix0); \ + iw_u.parts.lsw = (ix1); \ + (d) = iw_u.value; \ +} while (0) + +float nextafterf(float x, float y) +{ + volatile float t; + int32_t hx,hy,ix,iy; + + GET_FLOAT_WORD(hx,x); + GET_FLOAT_WORD(hy,y); + ix = hx&0x7fffffff; // |x| + iy = hy&0x7fffffff; // |y| + + if((ix>0x7f800000) || // x is nan + (iy>0x7f800000)) // y is nan + return x+y; + if(x==y) return y; // x=y, return y + if(ix==0) { // x == 0 + SET_FLOAT_WORD(x,(hy&0x80000000)|1);// return +-minsubnormal + t = x*x; + if(t==x) return t; else return x; // raise underflow flag + } + if(hx>=0) { // x > 0 + if(hx>hy) { // x > y, x -= ulp + hx -= 1; + } else { // x < y, x += ulp + hx += 1; + } + } else { // x < 0 + if(hy>=0||hx>hy){ // x < y, x -= ulp + hx -= 1; + } else { // x > y, x += ulp + hx += 1; + } + } + hy = hx&0x7f800000; + if(hy>=0x7f800000) return x+x; // overflow + if(hy<0x00800000) { // underflow + t = x*x; + if(t!=x) { // raise underflow flag + SET_FLOAT_WORD(y,hx); + return y; + } + } + SET_FLOAT_WORD(x,hx); + return x; +} +*/ +/* +double nextafter(double x, double y) +{ + volatile double t; + int32_t hx,hy,ix,iy; + u_int32_t lx,ly; + + EXTRACT_WORDS(hx,lx,x); + EXTRACT_WORDS(hy,ly,y); + ix = hx&0x7fffffff; // |x| + iy = hy&0x7fffffff; // |y| + + if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || // x is nan + ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0)) // y is nan + return x+y; + if(x==y) return y; // x=y, return y + if((ix|lx)==0) { // x == 0 + INSERT_WORDS(x,hy&0x80000000,1); // return +-minsubnormal + t = x*x; + if(t==x) return t; else return x; // raise underflow flag + } + if(hx>=0) { // x > 0 + if(hx>hy||((hx==hy)&&(lx>ly))) { // x > y, x -= ulp + if(lx==0) hx -= 1; + lx -= 1; + } else { // x < y, x += ulp + lx += 1; + if(lx==0) hx += 1; + } + } else { // x < 0 + if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){// x < y, x -= ulp + if(lx==0) hx -= 1; + lx -= 1; + } else { // x > y, x += ulp + lx += 1; + if(lx==0) hx += 1; + } + } + hy = hx&0x7ff00000; + if(hy>=0x7ff00000) return x+x; // overflow + if(hy<0x00100000) { // underflow + t = x*x; + if(t!=x) { // raise underflow flag + INSERT_WORDS(y,hx,lx); + return y; + } + } + INSERT_WORDS(x,hx,lx); + return x; +} +*/ + #if(GLM_COMPILER & GLM_COMPILER_VC) # if(GLM_MODEL == GLM_MODEL_32) # define GLM_NEXT_AFTER_FLT(x, toward) (float)_nextafter(x, float(toward)) From 3d7d4dc9c2f0ce1146d10b77067943950924f1fe Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Fri, 6 May 2011 12:12:22 +0100 Subject: [PATCH 17/19] Fixed glm::detail::nextafter implementation --- glm/gtx/ulp.inl | 213 ++++++++++++++++++++++++------------------------ 1 file changed, 108 insertions(+), 105 deletions(-) diff --git a/glm/gtx/ulp.inl b/glm/gtx/ulp.inl index b60db3e4..6cc19219 100644 --- a/glm/gtx/ulp.inl +++ b/glm/gtx/ulp.inl @@ -20,8 +20,8 @@ * is preserved. * ==================================================== */ -/* -#define EXTRACT_WORDS(ix0,ix1,d) \ + +#define GLM_EXTRACT_WORDS(ix0,ix1,d) \ do { \ ieee_double_shape_type ew_u; \ ew_u.value = (d); \ @@ -29,21 +29,21 @@ do { \ (ix1) = ew_u.parts.lsw; \ } while (0) -#define GET_FLOAT_WORD(i,d) \ +#define GLM_GET_FLOAT_WORD(i,d) \ do { \ ieee_float_shape_type gf_u; \ gf_u.value = (d); \ (i) = gf_u.word; \ } while (0) -#define SET_FLOAT_WORD(d,i) \ +#define GLM_SET_FLOAT_WORD(d,i) \ do { \ ieee_float_shape_type sf_u; \ sf_u.word = (i); \ (d) = sf_u.value; \ } while (0) -#define INSERT_WORDS(d,ix0,ix1) \ +#define GLM_INSERT_WORDS(d,ix0,ix1) \ do { \ ieee_double_shape_type iw_u; \ iw_u.parts.msw = (ix0); \ @@ -51,113 +51,116 @@ do { \ (d) = iw_u.value; \ } while (0) -float nextafterf(float x, float y) -{ - volatile float t; - int32_t hx,hy,ix,iy; - - GET_FLOAT_WORD(hx,x); - GET_FLOAT_WORD(hy,y); - ix = hx&0x7fffffff; // |x| - iy = hy&0x7fffffff; // |y| - - if((ix>0x7f800000) || // x is nan - (iy>0x7f800000)) // y is nan - return x+y; - if(x==y) return y; // x=y, return y - if(ix==0) { // x == 0 - SET_FLOAT_WORD(x,(hy&0x80000000)|1);// return +-minsubnormal - t = x*x; - if(t==x) return t; else return x; // raise underflow flag - } - if(hx>=0) { // x > 0 - if(hx>hy) { // x > y, x -= ulp - hx -= 1; - } else { // x < y, x += ulp - hx += 1; - } - } else { // x < 0 - if(hy>=0||hx>hy){ // x < y, x -= ulp - hx -= 1; - } else { // x > y, x += ulp - hx += 1; - } - } - hy = hx&0x7f800000; - if(hy>=0x7f800000) return x+x; // overflow - if(hy<0x00800000) { // underflow - t = x*x; - if(t!=x) { // raise underflow flag - SET_FLOAT_WORD(y,hx); - return y; - } - } - SET_FLOAT_WORD(x,hx); - return x; -} -*/ -/* -double nextafter(double x, double y) +namespace glm{ +namespace detail { - volatile double t; - int32_t hx,hy,ix,iy; - u_int32_t lx,ly; - - EXTRACT_WORDS(hx,lx,x); - EXTRACT_WORDS(hy,ly,y); - ix = hx&0x7fffffff; // |x| - iy = hy&0x7fffffff; // |y| - - if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || // x is nan - ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0)) // y is nan - return x+y; - if(x==y) return y; // x=y, return y - if((ix|lx)==0) { // x == 0 - INSERT_WORDS(x,hy&0x80000000,1); // return +-minsubnormal - t = x*x; - if(t==x) return t; else return x; // raise underflow flag - } - if(hx>=0) { // x > 0 - if(hx>hy||((hx==hy)&&(lx>ly))) { // x > y, x -= ulp - if(lx==0) hx -= 1; - lx -= 1; - } else { // x < y, x += ulp - lx += 1; - if(lx==0) hx += 1; - } - } else { // x < 0 - if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){// x < y, x -= ulp - if(lx==0) hx -= 1; - lx -= 1; - } else { // x > y, x += ulp - lx += 1; - if(lx==0) hx += 1; - } - } - hy = hx&0x7ff00000; - if(hy>=0x7ff00000) return x+x; // overflow - if(hy<0x00100000) { // underflow - t = x*x; - if(t!=x) { // raise underflow flag - INSERT_WORDS(y,hx,lx); - return y; - } - } - INSERT_WORDS(x,hx,lx); - return x; -} -*/ + GLM_FUNC_QUALIFIER float nextafterf(float x, float y) + { + volatile float t; + glm::int32 hx, hy, ix, iy; + + GLM_GET_FLOAT_WORD(hx,x); + GLM_GET_FLOAT_WORD(hy,y); + ix = hx&0x7fffffff; // |x| + iy = hy&0x7fffffff; // |y| + + if((ix>0x7f800000) || // x is nan + (iy>0x7f800000)) // y is nan + return x+y; + if(x==y) return y; // x=y, return y + if(ix==0) { // x == 0 + GLM_SET_FLOAT_WORD(x,(hy&0x80000000)|1);// return +-minsubnormal + t = x*x; + if(t==x) return t; else return x; // raise underflow flag + } + if(hx>=0) { // x > 0 + if(hx>hy) { // x > y, x -= ulp + hx -= 1; + } else { // x < y, x += ulp + hx += 1; + } + } else { // x < 0 + if(hy>=0||hx>hy){ // x < y, x -= ulp + hx -= 1; + } else { // x > y, x += ulp + hx += 1; + } + } + hy = hx&0x7f800000; + if(hy>=0x7f800000) return x+x; // overflow + if(hy<0x00800000) { // underflow + t = x*x; + if(t!=x) { // raise underflow flag + GLM_SET_FLOAT_WORD(y,hx); + return y; + } + } + GLM_SET_FLOAT_WORD(x,hx); + return x; + } + + GLM_FUNC_QUALIFIER double nextafter(double x, double y) + { + volatile double t; + glm::int32 hx, hy, ix, iy; + glm::uint32 lx, ly; + + GLM_EXTRACT_WORDS(hx, lx, x); + GLM_EXTRACT_WORDS(hy, ly, y); + ix = hx & 0x7fffffff; // |x| + iy = hy & 0x7fffffff; // |y| + + if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || // x is nan + ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0)) // y is nan + return x+y; + if(x==y) return y; // x=y, return y + if((ix|lx)==0) { // x == 0 + GLM_INSERT_WORDS(x, hy & 0x80000000, 1); // return +-minsubnormal + t = x*x; + if(t==x) return t; else return x; // raise underflow flag + } + if(hx>=0) { // x > 0 + if(hx>hy||((hx==hy)&&(lx>ly))) { // x > y, x -= ulp + if(lx==0) hx -= 1; + lx -= 1; + } else { // x < y, x += ulp + lx += 1; + if(lx==0) hx += 1; + } + } else { // x < 0 + if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){// x < y, x -= ulp + if(lx==0) hx -= 1; + lx -= 1; + } else { // x > y, x += ulp + lx += 1; + if(lx==0) hx += 1; + } + } + hy = hx&0x7ff00000; + if(hy>=0x7ff00000) return x+x; // overflow + if(hy<0x00100000) { // underflow + t = x*x; + if(t!=x) { // raise underflow flag + GLM_INSERT_WORDS(y,hx,lx); + return y; + } + } + GLM_INSERT_WORDS(x,hx,lx); + return x; + } +}//namespace detail +}//namespace glm #if(GLM_COMPILER & GLM_COMPILER_VC) # if(GLM_MODEL == GLM_MODEL_32) -# define GLM_NEXT_AFTER_FLT(x, toward) (float)_nextafter(x, float(toward)) +# define GLM_NEXT_AFTER_FLT(x, toward) glm::detail::nextafter((x), (toward)) # else -# define GLM_NEXT_AFTER_FLT(x, toward) _nextafterf(x, toward) +# define GLM_NEXT_AFTER_FLT(x, toward) _nextafterf((x), (toward)) # endif -# define GLM_NEXT_AFTER_DBL(x, toward) _nextafter(x, toward) +# define GLM_NEXT_AFTER_DBL(x, toward) _nextafter((x), (toward)) #else -# define GLM_NEXT_AFTER_FLT(x, toward) nextafterf(x, toward) -# define GLM_NEXT_AFTER_DBL(x, toward) nextafter(x, toward) +# define GLM_NEXT_AFTER_FLT(x, toward) nextafterf((x), (toward)) +# define GLM_NEXT_AFTER_DBL(x, toward) nextafter((x), (toward)) #endif namespace glm{ From 9fd02f9177c5535f3644c3e0e48472c976f83df5 Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Fri, 6 May 2011 12:22:51 +0100 Subject: [PATCH 18/19] Fixed Visual C++ 32 case --- glm/gtx/ulp.inl | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/glm/gtx/ulp.inl b/glm/gtx/ulp.inl index 6cc19219..872b858d 100644 --- a/glm/gtx/ulp.inl +++ b/glm/gtx/ulp.inl @@ -21,6 +21,23 @@ * ==================================================== */ +typedef union +{ + float value; + /* FIXME: Assumes 32 bit int. */ + unsigned int word; +} ieee_float_shape_type; + +typedef union +{ + double value; + struct + { + glm::detail::int32 lsw; + glm::detail::int32 msw; + } parts; +} ieee_double_shape_type; + #define GLM_EXTRACT_WORDS(ix0,ix1,d) \ do { \ ieee_double_shape_type ew_u; \ @@ -57,7 +74,7 @@ namespace detail GLM_FUNC_QUALIFIER float nextafterf(float x, float y) { volatile float t; - glm::int32 hx, hy, ix, iy; + glm::detail::int32 hx, hy, ix, iy; GLM_GET_FLOAT_WORD(hx,x); GLM_GET_FLOAT_WORD(hy,y); @@ -102,8 +119,8 @@ namespace detail GLM_FUNC_QUALIFIER double nextafter(double x, double y) { volatile double t; - glm::int32 hx, hy, ix, iy; - glm::uint32 lx, ly; + glm::detail::int32 hx, hy, ix, iy; + glm::detail::uint32 lx, ly; GLM_EXTRACT_WORDS(hx, lx, x); GLM_EXTRACT_WORDS(hy, ly, y); @@ -153,7 +170,7 @@ namespace detail #if(GLM_COMPILER & GLM_COMPILER_VC) # if(GLM_MODEL == GLM_MODEL_32) -# define GLM_NEXT_AFTER_FLT(x, toward) glm::detail::nextafter((x), (toward)) +# define GLM_NEXT_AFTER_FLT(x, toward) glm::detail::nextafterf((x), (toward)) # else # define GLM_NEXT_AFTER_FLT(x, toward) _nextafterf((x), (toward)) # endif From 13ca4eabcc76cfe91ce584e4c16390b72a14e648 Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Fri, 6 May 2011 12:56:47 +0100 Subject: [PATCH 19/19] Added ULP tests --- test/gtx/gtx-ulp.cpp | 122 ++++++++++++++++++++++++++++++------------- 1 file changed, 85 insertions(+), 37 deletions(-) diff --git a/test/gtx/gtx-ulp.cpp b/test/gtx/gtx-ulp.cpp index 348a09ce..2de895d5 100644 --- a/test/gtx/gtx-ulp.cpp +++ b/test/gtx/gtx-ulp.cpp @@ -12,48 +12,96 @@ #include #include -int test_ulp_float() +int test_ulp_float_dist() { - std::cout.precision(std::numeric_limits::digits10 + 1); - - float W = 1.0f; - float X = glm::next_float(W); - - double Y = 1.0; - double Z = glm::next_float(Y); - - bool TestX = W != X; - bool TestZ = Y != Z; - - std::cout << "1.0f, Next: " << glm::float_distance(W, X)<< std::endl; - std::cout << "1.0f, Next(1000): " << glm::float_distance(W, glm::next_float(W, 1000)) << std::endl; - - std::cout << "1.0f, Next: " << glm::float_distance(X, W)<< std::endl; - std::cout << "1.0f, Next(1000): " << glm::float_distance(glm::next_float(W, 1000), W) << std::endl; - - std::cout << "1.0, Next: " << glm::float_distance(Y, Z) << std::endl; - std::cout << "1.0, Next(1000): " << glm::float_distance(glm::next_float(Y, 1000), Y) << std::endl; - - - - std::cout << Z << " 0.01, 0.011" << std::endl; - std::cout << " 1.0, Next(1000000): " << glm::next_float(Y, 1000000)<< std::endl; - - //std::size_t A = glm::ulp(0.01, 0.02); - //std::size_t B = glm::ulp(glm::vec2(0.01), glm::vec2(0.02)); - //std::size_t C = glm::ulp(glm::vec3(0.01), glm::vec3(0.02)); - //std::size_t D = glm::ulp(glm::vec4(0.01), glm::vec4(0.02)); - //std::cout << "glm::ulp test: " << A << std::endl; - //std::cout << "glm::ulp test: " << B << std::endl; - //std::cout << "glm::ulp test: " << C << std::endl; - //std::cout << "glm::ulp test: " << D << std::endl; - return 0; + int Error = 0; + + float A = 1.0f; + + float B = glm::next_float(A); + Error += A != B ? 0 : 1; + float C = glm::prev_float(B); + Error += A == C ? 0 : 1; + + int D = glm::float_distance(A, B); + Error += D == 1 ? 0 : 1; + int E = glm::float_distance(A, C); + Error += E == 0 ? 0 : 1; + + return Error; +} + +int test_ulp_float_step() +{ + int Error = 0; + + float A = 1.0f; + + for(int i = 10; i < 1000; i *= 10) + { + float B = glm::next_float(A, i); + Error += A != B ? 0 : 1; + float C = glm::prev_float(B, i); + Error += A == C ? 0 : 1; + + int D = glm::float_distance(A, B); + Error += D == i ? 0 : 1; + int E = glm::float_distance(A, C); + Error += E == 0 ? 0 : 1; + } + + return Error; +} + +int test_ulp_double_dist() +{ + int Error = 0; + + double A = 1.0; + + double B = glm::next_float(A); + Error += A != B ? 0 : 1; + double C = glm::prev_float(B); + Error += A == C ? 0 : 1; + + int D = glm::float_distance(A, B); + Error += D == 1 ? 0 : 1; + int E = glm::float_distance(A, C); + Error += E == 0 ? 0 : 1; + + return Error; +} + +int test_ulp_double_step() +{ + int Error = 0; + + double A = 1.0; + + for(int i = 10; i < 1000; i *= 10) + { + double B = glm::next_float(A, i); + Error += A != B ? 0 : 1; + double C = glm::prev_float(B, i); + Error += A == C ? 0 : 1; + + int D = glm::float_distance(A, B); + Error += D == i ? 0 : 1; + int E = glm::float_distance(A, C); + Error += E == 0 ? 0 : 1; + } + + return Error; } int main() { - std::cout << "Test 76" << std::endl; - test_ulp_float(); + 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; }