Browse Source

Merge branch '0.9.2' of ssh://ogl-math.git.sourceforge.net/gitroot/ogl-math/ogl-math into 0.9.2

Christophe Riccio 14 years ago
parent
commit
49da4b3863

+ 4 - 8
glm/core/_detail.hpp

@@ -18,19 +18,15 @@ namespace detail
 {
 {
 	class thalf;
 	class thalf;
 
 
-#if(GLM_COMPILER & GLM_COMPILER_VC)
+#if(__STDC_VERSION__ >= 199901L) // C99 detected, 64 bit types available
+	typedef int64_t								sint64;
+	typedef uint64_t							uint64;
+#elif(GLM_COMPILER & GLM_COMPILER_VC)
 	typedef signed __int64						sint64;
 	typedef signed __int64						sint64;
 	typedef unsigned __int64					uint64;
 	typedef unsigned __int64					uint64;
 #elif(GLM_COMPILER & GLM_COMPILER_GCC)
 #elif(GLM_COMPILER & GLM_COMPILER_GCC)
 	__extension__ typedef signed long long		sint64;
 	__extension__ typedef signed long long		sint64;
 	__extension__ typedef unsigned long long	uint64;
 	__extension__ typedef unsigned long long	uint64;
-//#	if GLM_MODEL == GLM_MODEL_64
-//		typedef signed long							highp_int_t;
-//		typedef unsigned long						highp_uint_t;
-//#   elif GLM_MODEL == GLM_MODEL_32
-//		__extension__ typedef signed long long		highp_int_t;
-//		__extension__ typedef unsigned long long	highp_uint_t;
-//#	endif//GLM_MODEL
 #elif(GLM_COMPILER & GLM_COMPILER_BC)
 #elif(GLM_COMPILER & GLM_COMPILER_BC)
 	typedef Int64								sint64;
 	typedef Int64								sint64;
 	typedef Uint64								uint64;
 	typedef Uint64								uint64;

+ 2 - 0
glm/ext.hpp

@@ -48,6 +48,7 @@
 #include "./gtx/intersect.hpp"
 #include "./gtx/intersect.hpp"
 #include "./gtx/log_base.hpp"
 #include "./gtx/log_base.hpp"
 #include "./gtx/matrix_cross_product.hpp"
 #include "./gtx/matrix_cross_product.hpp"
+#include "./gtx/matrix_interpolation.hpp"
 #include "./gtx/matrix_major_storage.hpp"
 #include "./gtx/matrix_major_storage.hpp"
 #include "./gtx/matrix_operation.hpp"
 #include "./gtx/matrix_operation.hpp"
 #include "./gtx/matrix_query.hpp"
 #include "./gtx/matrix_query.hpp"
@@ -73,6 +74,7 @@
 #include "./gtx/string_cast.hpp"
 #include "./gtx/string_cast.hpp"
 #include "./gtx/transform.hpp"
 #include "./gtx/transform.hpp"
 #include "./gtx/transform2.hpp"
 #include "./gtx/transform2.hpp"
+#include "./gtx/ulp.hpp"
 #include "./gtx/unsigned_int.hpp"
 #include "./gtx/unsigned_int.hpp"
 #include "./gtx/vec1.hpp"
 #include "./gtx/vec1.hpp"
 #include "./gtx/vector_access.hpp"
 #include "./gtx/vector_access.hpp"

+ 73 - 0
glm/gtx/matrix_interpolation.hpp

@@ -0,0 +1,73 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// OpenGL Mathematics Copyright (c) 2005 - 2011 G-Truc Creation (www.g-truc.net)
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Created : 2011-03-05
+// Updated : 2011-03-05
+// Licence : This source is under MIT License
+// File    : glm/gtx/matrix_interpolation.hpp
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Dependency:
+// - GLM core
+// - GLM_GTX_matric_interpolation
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// This extension has been written by Ghenadii Ursachi ([email protected])
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifndef glm_gtx_matrix_interpolation
+#define glm_gtx_matrix_interpolation
+
+// Dependency:
+//#include "../glm.hpp"
+
+#if(defined(GLM_MESSAGES) && !defined(glm_ext))
+#	pragma message("GLM: GLM_GTX_matrix_interpolation extension included")
+#endif
+
+namespace glm
+{
+	namespace test{
+		void main_gtx_transform();
+	}//namespace test
+
+	namespace gtx{
+	//! GLM_GTX_matrix_interpolation extension: Add transformation matrices
+	namespace matrix_interpolation
+	{
+		/// \addtogroup gtx_matrix_interpolation
+		///@{
+
+		//! Get the axis and angle of the rotation from a matrix.
+        //! From GLM_GTX_matrix_interpolation extension.
+		template <typename T>
+        void axisAngle(
+            detail::tmat4x4<T> const & mat,
+            detail::tvec3<T> & axis,
+            T & angle);
+
+        //! Build a matrix from axis and angle.
+        //! From GLM_GTX_matrix_interpolation extension.
+		template <typename T>
+        detail::tmat4x4<T> axisAngleMatrix(
+            detail::tvec3<T> const & axis,
+            T const angle);
+
+		//! Build a interpolation of 4 * 4 matrixes.
+        //! From GLM_GTX_matrix_interpolation extension.
+        //! Warning! works only with rotation and/or translation matrixes, scale will generate unexpected results.
+		template <typename T>
+        detail::tmat4x4<T> interpolate(
+            detail::tmat4x4<T> const & m1,
+            detail::tmat4x4<T> const & m2,
+            T const delta);
+
+		///@}
+
+	}//namespace matrix_interpolation
+	}//namespace gtx
+}//namespace glm
+
+#include "matrix_interpolation.inl"
+
+namespace glm{using namespace gtx::matrix_interpolation;}
+
+#endif//glm_gtx_transform

+ 117 - 0
glm/gtx/matrix_interpolation.inl

@@ -0,0 +1,117 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// OpenGL Mathematics Copyright (c) 2005 - 2011 G-Truc Creation (www.g-truc.net)
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Created : 2011-03-05
+// Updated : 2011-03-05
+// Licence : This source is under MIT License
+// File    : glm/gtx/matrix_interpolation.inl
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+namespace glm{
+namespace gtx{
+namespace matrix_interpolation
+{
+    template <typename T>
+    GLM_FUNC_QUALIFIER void axisAngle(
+        detail::tmat4x4<T> const & mat,
+        detail::tvec3<T> & axis,
+        T & angle)
+    {
+        T epsilon = (T)0.01;
+        T epsilon2 = (T)0.1;
+
+        if ((fabs(mat[1][0] - mat[0][1]) < epsilon) && (fabs(mat[2][0] - mat[0][2]) < epsilon) && (fabs(mat[2][1] - mat[1][2]) < epsilon)) {
+            if ((fabs(mat[1][0] + mat[0][1]) < epsilon2) && (fabs(mat[2][0] + mat[0][2]) < epsilon2) && (fabs(mat[2][1] + mat[1][2]) < epsilon2) && (fabs(mat[0][0] + mat[1][1] + mat[2][2] - (T)3.0) < epsilon2)) {
+                angle = (T)0.0;
+                axis.x = (T)1.0;
+                axis.y = (T)0.0;
+                axis.z = (T)0.0;
+                return;
+            }
+            angle = M_1_PI;
+            T xx = (mat[0][0] + (T)1.0) / (T)2.0;
+            T yy = (mat[1][1] + (T)1.0) / (T)2.0;
+            T zz = (mat[2][2] + (T)1.0) / (T)2.0;
+            T xy = (mat[1][0] + mat[0][1]) / (T)4.0;
+            T xz = (mat[2][0] + mat[0][2]) / (T)4.0;
+            T yz = (mat[2][1] + mat[1][2]) / (T)4.0;
+            if ((xx > yy) && (xx > zz)) {
+                if (xx < epsilon) {
+                    axis.x = (T)0.0;
+                    axis.y = (T)0.7071;
+                    axis.z = (T)0.7071;
+                } else {
+                    axis.x = sqrt(xx);
+                    axis.y = xy / axis.x;
+                    axis.z = xz / axis.x;
+                }
+            } else if (yy > zz) {
+                if (yy < epsilon) {
+                    axis.x = (T)0.7071;
+                    axis.y = (T)0.0;
+                    axis.z = (T)0.7071;
+                } else {
+                    axis.y = sqrt(yy);
+                    axis.x = xy / axis.y;
+                    axis.z = yz / axis.y;
+                }
+            } else {
+                if (zz < epsilon) {
+                    axis.x = (T)0.7071;
+                    axis.y = (T)0.7071;
+                    axis.z = (T)0.0;
+                } else {
+                    axis.z = sqrt(zz);
+                    axis.x = xz / axis.z;
+                    axis.y = yz / axis.z;
+                }
+            }
+            return;
+        }
+        T s = sqrt((mat[2][1] - mat[1][2]) * (mat[2][1] - mat[1][2]) + (mat[2][0] - mat[0][2]) * (mat[2][0] - mat[0][2]) + (mat[1][0] - mat[0][1]) * (mat[1][0] - mat[0][1]));
+        if (glm::abs(s) < T(0.001))
+            s = (T)1.0;
+        angle = acos((mat[0][0] + mat[1][1] + mat[2][2] - (T)1.0) / (T)2.0);
+        axis.x = (mat[1][2] - mat[2][1]) / s;
+        axis.y = (mat[2][0] - mat[0][2]) / s;
+        axis.z = (mat[0][1] - mat[1][0]) / s;
+    }
+
+    template <typename T>
+    GLM_FUNC_QUALIFIER detail::tmat4x4<T> axisAngleMatrix(
+		detail::tvec3<T> const & axis,
+		T const angle)
+    {
+        T c = cos(angle);
+        T s = sin(angle);
+        T t = T(1) - c;
+        detail::tvec3<T> n = normalize(axis);
+
+        return detail::tmat4x4<T>(
+            t * n.x * n.x + c,          t * n.x * n.y + n.z * s,    t * n.x * n.z - n.y * s,    T(0),
+            t * n.x * n.y - n.z * s,    t * n.y * n.y + c,          t * n.y * n.z + n.x * s,    T(0),
+            t * n.x * n.z + n.y * s,    t * n.y * n.z - n.x * s,    t * n.z * n.z + c,          T(0),
+            T(0),                        T(0),                        T(0),                     T(1)
+        );
+    }
+
+    template <typename T>
+    GLM_FUNC_QUALIFIER detail::tmat4x4<T> interpolate(
+		detail::tmat4x4<T> const & m1,
+		detail::tmat4x4<T> const & m2,
+		T const delta)
+    {
+		detail::tmat4x4<T> dltRotation = m2 * transpose(m1);
+		detail::tvec3<T> dltAxis;
+		T dltAngle;
+		axisAngle(dltRotation, dltAxis, dltAngle);
+		detail::tmat4x4<T> out = axisAngleMatrix(dltAxis, dltAngle * delta) * rotationMatrix(m1);
+		out[3][0] = m1[3][0] + delta * (m2[3][0] - m1[3][0]);
+		out[3][1] = m1[3][1] + delta * (m2[3][1] - m1[3][1]);
+		out[3][2] = m1[3][2] + delta * (m2[3][2] - m1[3][2]);
+		return out;
+    }
+
+}//namespace transform
+}//namespace gtx
+}//namespace glm

+ 73 - 0
glm/gtx/ulp.hpp

@@ -0,0 +1,73 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// 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 ulp
+	{
+		/// \addtogroup gtx_ulp
+		///@{
+
+		//! Return the next ULP value(s) after the input value(s).
+		//! From GLM_GTX_ulp extension.
+        template <typename genType>
+        genType next_float(genType const & x);
+        
+		//! Return the previous ULP value(s) before the input value(s).
+		//! From GLM_GTX_ulp extension.
+        template <typename genType>
+        genType prev_float(genType const & x);
+
+		//! Return the value(s) ULP distance after the input value(s).
+		//! From GLM_GTX_ulp extension.
+        template <typename genType>
+        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 <typename genType>
+        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 <typename T>
+        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<typename T, template<typename> class vecType>
+        vecType<uint> float_distance(vecType<T> const & x, vecType<T> const & y);
+        
+		///@}
+
+	}//namespace ulp
+	}//namespace gtx
+}//namespace glm
+
+#include "ulp.inl"
+
+namespace glm{using namespace gtx::ulp;}
+
+#endif//glm_gtx_ulp
+

+ 400 - 0
glm/gtx/ulp.inl

@@ -0,0 +1,400 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// OpenGL Mathematics Copyright (c) 2005 - 2011 G-Truc Creation (www.g-truc.net)
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Created : 2011-03-07
+// Updated : 2011-04-26
+// Licence : This source is under MIT License
+// File    : glm/gtx/ulp.inl
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+#include <cmath>
+#include <cfloat>
+
+/*
+ * ====================================================
+ * 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.
+ * ====================================================
+ */
+
+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;                                  \
+  ew_u.value = (d);                                             \
+  (ix0) = ew_u.parts.msw;                                       \
+  (ix1) = ew_u.parts.lsw;                                       \
+} while (0)
+
+#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 GLM_SET_FLOAT_WORD(d,i)                                     \
+do {                                                            \
+  ieee_float_shape_type sf_u;                                   \
+  sf_u.word = (i);                                              \
+  (d) = sf_u.value;                                             \
+} while (0)
+
+#define GLM_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)
+
+namespace glm{
+namespace detail
+{
+	GLM_FUNC_QUALIFIER float nextafterf(float x, float y)
+	{
+		volatile float t;
+		glm::detail::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::detail::int32 hx, hy, ix, iy;
+		glm::detail::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) glm::detail::nextafterf((x), (toward))
+#	else
+#		define GLM_NEXT_AFTER_FLT(x, toward) _nextafterf((x), (toward))
+#	endif
+#   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))
+#endif
+
+namespace glm{
+namespace gtx{
+namespace ulp
+{
+    GLM_FUNC_QUALIFIER float next_float(float const & x)
+    {
+        return GLM_NEXT_AFTER_FLT(x, std::numeric_limits<float>::max());
+    }
+
+    GLM_FUNC_QUALIFIER double next_float(double const & x)
+    {
+        return GLM_NEXT_AFTER_DBL(x, std::numeric_limits<double>::max());
+    }
+
+    template<typename T, template<typename> class vecType>
+    GLM_FUNC_QUALIFIER vecType<T> next_float(vecType<T> const & x)
+    {
+        vecType<T> 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_FLT(x, std::numeric_limits<float>::min());
+    }
+
+    GLM_FUNC_QUALIFIER double prev_float(double const & x)
+    {
+        return GLM_NEXT_AFTER_DBL(x, std::numeric_limits<double>::min());
+    }
+
+    template<typename T, template<typename> class vecType>
+    GLM_FUNC_QUALIFIER vecType<T> prev_float(vecType<T> const & x)
+    {
+        vecType<T> Result;
+        for(std::size_t i = 0; i < Result.length(); ++i)
+            Result[i] = prev_float(x[i]);
+        return Result;
+    }
+
+    template <typename T>
+    GLM_FUNC_QUALIFIER T next_float(T const & x, uint const & ulps)
+    {
+        T temp = x;
+        for(std::size_t i = 0; i < ulps; ++i)
+            temp = next_float(temp);
+        return temp;
+    }
+
+    template<typename T, template<typename> class vecType>
+    GLM_FUNC_QUALIFIER vecType<T> next_float(vecType<T> const & x, vecType<uint> const & ulps)
+    {
+        vecType<T> Result;
+        for(std::size_t i = 0; i < Result.length(); ++i)
+            Result[i] = next_float(x[i], ulps[i]);
+        return Result;
+    }
+
+    template <typename T>
+    GLM_FUNC_QUALIFIER T prev_float(T const & x, uint const & ulps)
+    {
+        T temp = x;
+        for(std::size_t i = 0; i < ulps; ++i)
+            temp = prev_float(temp);
+        return temp;
+    }
+
+    template<typename T, template<typename> class vecType>
+    GLM_FUNC_QUALIFIER vecType<T> prev_float(vecType<T> const & x, vecType<uint> const & ulps)
+    {
+        vecType<T> Result;
+        for(std::size_t i = 0; i < Result.length(); ++i)
+            Result[i] = prev_float(x[i], ulps[i]);
+        return Result;
+    }
+
+    template <typename T>
+    GLM_FUNC_QUALIFIER uint 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<std::size_t>::max())
+            {
+                ++ulp;
+                temp = next_float(temp);
+            }
+        }
+        else if(y < x)
+        {
+            T temp = y;
+            while(temp != x && ulp < std::numeric_limits<std::size_t>::max())
+            {
+                ++ulp;
+                temp = next_float(temp);
+            }
+        }
+        else // ==
+        {
+
+        }
+
+        return ulp;
+    }
+
+    template<typename T, template<typename> class vecType>
+    GLM_FUNC_QUALIFIER vecType<uint> float_distance(vecType<T> const & x, vecType<T> const & y)
+    {
+        vecType<uint> 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,
+		detail::thalf const & b
+	)
+	{
+		std::size_t Count = 0;
+		float TempA(a);
+		float TempB(b);
+		//while((TempA = _nextafterf(TempA, TempB)) != TempB)
+			++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)
+        {
+            std::cout << Temp << " " << b << std::endl;
+			++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)
+        {
+            std::cout << Temp << " " << b << std::endl;
+			++Count;
+        }
+		return Count;
+	}
+
+	template <typename T>
+	inline std::size_t ulp
+	(
+		detail::tvec2<T> const & a,
+		detail::tvec2<T> const & b
+	)
+	{
+        std::size_t ulps[] = 
+        {
+            ulp(a[0], b[0]),
+            ulp(a[1], b[1])
+        };
+
+        return glm::max(ulps[0], ulps[1]);
+	}
+
+	template <typename T>
+	inline std::size_t ulp
+	(
+		detail::tvec3<T> const & a,
+		detail::tvec3<T> const & b
+	)
+	{
+        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 <typename T>
+	inline std::size_t ulp
+	(
+		detail::tvec4<T> const & a,
+		detail::tvec4<T> const & b
+	)
+	{
+        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
+}//namespace gtx
+}//namespace glm

+ 1 - 0
test/gtx/CMakeLists.txt

@@ -1,3 +1,4 @@
 glmCreateTestGTC(gtx-bit)
 glmCreateTestGTC(gtx-bit)
 glmCreateTestGTC(gtx-simd-vec4)
 glmCreateTestGTC(gtx-simd-vec4)
 glmCreateTestGTC(gtx-simd-mat4)
 glmCreateTestGTC(gtx-simd-mat4)
+glmCreateTestGTC(gtx-ulp)

+ 107 - 0
test/gtx/gtx-ulp.cpp

@@ -0,0 +1,107 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// 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 <glm/glm.hpp>
+#include <glm/gtx/ulp.hpp>
+#include <iostream>
+#include <limits>
+
+int test_ulp_float_dist()
+{
+	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()
+{
+	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;
+}
+
+