initial commit
This commit is contained in:
		
							
								
								
									
										321
									
								
								lib/glm/gtc/ulp.inl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										321
									
								
								lib/glm/gtc/ulp.inl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,321 @@ | ||||
| /// @ref gtc_ulp | ||||
| /// @file glm/gtc/ulp.inl | ||||
| /// | ||||
| /// 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. | ||||
|  | ||||
| #include "../detail/type_int.hpp" | ||||
| #include <cmath> | ||||
| #include <cfloat> | ||||
| #include <limits> | ||||
|  | ||||
| #if(GLM_COMPILER & GLM_COMPILER_VC) | ||||
| #	pragma warning(push) | ||||
| #	pragma warning(disable : 4127) | ||||
| #endif | ||||
|  | ||||
| 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) | ||||
| #	pragma warning(pop) | ||||
| #endif | ||||
|  | ||||
| namespace glm | ||||
| { | ||||
| 	template <> | ||||
| 	GLM_FUNC_QUALIFIER float next_float(float const & x) | ||||
| 	{ | ||||
| #		if GLM_HAS_CXX11_STL | ||||
| 			return std::nextafter(x, std::numeric_limits<float>::max()); | ||||
| #		elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) | ||||
| 			return detail::nextafterf(x, FLT_MAX); | ||||
| #		elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) | ||||
| 			return __builtin_nextafterf(x, FLT_MAX); | ||||
| #		else | ||||
| 			return nextafterf(x, FLT_MAX); | ||||
| #		endif | ||||
| 	} | ||||
|  | ||||
| 	template <> | ||||
| 	GLM_FUNC_QUALIFIER double next_float(double const & x) | ||||
| 	{ | ||||
| #		if GLM_HAS_CXX11_STL | ||||
| 			return std::nextafter(x, std::numeric_limits<double>::max()); | ||||
| #		elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) | ||||
| 			return detail::nextafter(x, std::numeric_limits<double>::max()); | ||||
| #		elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) | ||||
| 			return __builtin_nextafter(x, FLT_MAX); | ||||
| #		else | ||||
| 			return nextafter(x, DBL_MAX); | ||||
| #		endif | ||||
| 	} | ||||
|  | ||||
| 	template<typename T, precision P, template<typename, precision> class vecType> | ||||
| 	GLM_FUNC_QUALIFIER vecType<T, P> next_float(vecType<T, P> const & x) | ||||
| 	{ | ||||
| 		vecType<T, P> Result(uninitialize); | ||||
| 		for(length_t i = 0, n = Result.length(); i < n; ++i) | ||||
| 			Result[i] = next_float(x[i]); | ||||
| 		return Result; | ||||
| 	} | ||||
|  | ||||
| 	GLM_FUNC_QUALIFIER float prev_float(float const & x) | ||||
| 	{ | ||||
| #		if GLM_HAS_CXX11_STL | ||||
| 			return std::nextafter(x, std::numeric_limits<float>::min()); | ||||
| #		elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) | ||||
| 			return detail::nextafterf(x, FLT_MIN); | ||||
| #		elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) | ||||
| 			return __builtin_nextafterf(x, FLT_MIN); | ||||
| #		else | ||||
| 			return nextafterf(x, FLT_MIN); | ||||
| #		endif | ||||
| 	} | ||||
|  | ||||
| 	GLM_FUNC_QUALIFIER double prev_float(double const & x) | ||||
| 	{ | ||||
| #		if GLM_HAS_CXX11_STL | ||||
| 			return std::nextafter(x, std::numeric_limits<double>::min()); | ||||
| #		elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) | ||||
| 			return _nextafter(x, DBL_MIN); | ||||
| #		elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) | ||||
| 			return __builtin_nextafter(x, DBL_MIN); | ||||
| #		else | ||||
| 			return nextafter(x, DBL_MIN); | ||||
| #		endif | ||||
| 	} | ||||
|  | ||||
| 	template<typename T, precision P, template<typename, precision> class vecType> | ||||
| 	GLM_FUNC_QUALIFIER vecType<T, P> prev_float(vecType<T, P> const & x) | ||||
| 	{ | ||||
| 		vecType<T, P> Result(uninitialize); | ||||
| 		for(length_t i = 0, n = Result.length(); i < n; ++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(uint i = 0; i < ulps; ++i) | ||||
| 			temp = next_float(temp); | ||||
| 		return temp; | ||||
| 	} | ||||
|  | ||||
| 	template<typename T, precision P, template<typename, precision> class vecType> | ||||
| 	GLM_FUNC_QUALIFIER vecType<T, P> next_float(vecType<T, P> const & x, vecType<uint, P> const & ulps) | ||||
| 	{ | ||||
| 		vecType<T, P> Result(uninitialize); | ||||
| 		for(length_t i = 0, n = Result.length(); i < n; ++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(uint i = 0; i < ulps; ++i) | ||||
| 			temp = prev_float(temp); | ||||
| 		return temp; | ||||
| 	} | ||||
|  | ||||
| 	template<typename T, precision P, template<typename, precision> class vecType> | ||||
| 	GLM_FUNC_QUALIFIER vecType<T, P> prev_float(vecType<T, P> const & x, vecType<uint, P> const & ulps) | ||||
| 	{ | ||||
| 		vecType<T, P> Result(uninitialize); | ||||
| 		for(length_t i = 0, n = Result.length(); i < n; ++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) | ||||
| 	{ | ||||
| 		uint 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, precision P, template<typename, precision> class vecType> | ||||
| 	GLM_FUNC_QUALIFIER vecType<uint, P> float_distance(vecType<T, P> const & x, vecType<T, P> const & y) | ||||
| 	{ | ||||
| 		vecType<uint, P> Result(uninitialize); | ||||
| 		for(length_t i = 0, n = Result.length(); i < n; ++i) | ||||
| 			Result[i] = float_distance(x[i], y[i]); | ||||
| 		return Result; | ||||
| 	} | ||||
| }//namespace glm | ||||
		Reference in New Issue
	
	Block a user
	 izenynn
					izenynn