1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// OpenGL Mathematics Copyright (c) 2005 - 2012 G-Truc Creation (www.g-truc.net)
3
///////////////////////////////////////////////////////////////////////////////////////////////////
4
// Created : 2011-03-07
5
// Updated : 2011-04-26
6
// Licence : This source is under MIT License
7
// File : glm/gtx/ulp.inl
8
///////////////////////////////////////////////////////////////////////////////////////////////////
14
* ====================================================
15
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
17
* Developed at SunPro, a Sun Microsystems, Inc. business.
18
* Permission to use, copy, modify, and distribute this
19
* software is freely granted, provided that this notice
21
* ====================================================
25
#pragma warning(disable : 4127)
30
/* FIXME: Assumes 32 bit int. */
32
} ieee_float_shape_type;
39
glm::detail::int32 lsw;
40
glm::detail::int32 msw;
42
} ieee_double_shape_type;
44
#define GLM_EXTRACT_WORDS(ix0,ix1,d) \
46
ieee_double_shape_type ew_u; \
48
(ix0) = ew_u.parts.msw; \
49
(ix1) = ew_u.parts.lsw; \
52
#define GLM_GET_FLOAT_WORD(i,d) \
54
ieee_float_shape_type gf_u; \
59
#define GLM_SET_FLOAT_WORD(d,i) \
61
ieee_float_shape_type sf_u; \
66
#define GLM_INSERT_WORDS(d,ix0,ix1) \
68
ieee_double_shape_type iw_u; \
69
iw_u.parts.msw = (ix0); \
70
iw_u.parts.lsw = (ix1); \
77
GLM_FUNC_QUALIFIER float nextafterf(float x, float y)
80
glm::detail::int32 hx, hy, ix, iy;
82
GLM_GET_FLOAT_WORD(hx, x);
83
GLM_GET_FLOAT_WORD(hy, y);
84
ix = hx&0x7fffffff; // |x|
85
iy = hy&0x7fffffff; // |y|
87
if((ix>0x7f800000) || // x is nan
88
(iy>0x7f800000)) // y is nan
90
if(x==y) return y; // x=y, return y
92
GLM_SET_FLOAT_WORD(x,(hy&0x80000000)|1);// return +-minsubnormal
94
if(t==x) return t; else return x; // raise underflow flag
97
if(hx>hy) { // x > y, x -= ulp
99
} else { // x < y, x += ulp
103
if(hy>=0||hx>hy){ // x < y, x -= ulp
105
} else { // x > y, x += ulp
110
if(hy>=0x7f800000) return x+x; // overflow
111
if(hy<0x00800000) { // underflow
113
if(t!=x) { // raise underflow flag
114
GLM_SET_FLOAT_WORD(y,hx);
118
GLM_SET_FLOAT_WORD(x,hx);
122
GLM_FUNC_QUALIFIER double nextafter(double x, double y)
125
glm::detail::int32 hx, hy, ix, iy;
126
glm::detail::uint32 lx, ly;
128
GLM_EXTRACT_WORDS(hx, lx, x);
129
GLM_EXTRACT_WORDS(hy, ly, y);
130
ix = hx & 0x7fffffff; // |x|
131
iy = hy & 0x7fffffff; // |y|
133
if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || // x is nan
134
((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0)) // y is nan
136
if(x==y) return y; // x=y, return y
137
if((ix|lx)==0) { // x == 0
138
GLM_INSERT_WORDS(x, hy & 0x80000000, 1); // return +-minsubnormal
140
if(t==x) return t; else return x; // raise underflow flag
143
if(hx>hy||((hx==hy)&&(lx>ly))) { // x > y, x -= ulp
146
} else { // x < y, x += ulp
151
if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){// x < y, x -= ulp
154
} else { // x > y, x += ulp
160
if(hy>=0x7ff00000) return x+x; // overflow
161
if(hy<0x00100000) { // underflow
163
if(t!=x) { // raise underflow flag
164
GLM_INSERT_WORDS(y,hx,lx);
168
GLM_INSERT_WORDS(x,hx,lx);
176
#if(GLM_COMPILER & GLM_COMPILER_VC || GLM_COMPILER & GLM_COMPILER_INTEL)
177
# define GLM_NEXT_AFTER_FLT(x, toward) glm::detail::nextafterf((x), (toward))
178
# define GLM_NEXT_AFTER_DBL(x, toward) _nextafter((x), (toward))
180
# define GLM_NEXT_AFTER_FLT(x, toward) nextafterf((x), (toward))
181
# define GLM_NEXT_AFTER_DBL(x, toward) nextafter((x), (toward))
186
GLM_FUNC_QUALIFIER float next_float(float const & x)
188
return GLM_NEXT_AFTER_FLT(x, std::numeric_limits<float>::max());
191
GLM_FUNC_QUALIFIER double next_float(double const & x)
193
return GLM_NEXT_AFTER_DBL(x, std::numeric_limits<double>::max());
196
template<typename T, template<typename> class vecType>
197
GLM_FUNC_QUALIFIER vecType<T> next_float(vecType<T> const & x)
200
for(std::size_t i = 0; i < Result.length(); ++i)
201
Result[i] = next_float(x[i]);
205
GLM_FUNC_QUALIFIER float prev_float(float const & x)
207
return GLM_NEXT_AFTER_FLT(x, std::numeric_limits<float>::min());
210
GLM_FUNC_QUALIFIER double prev_float(double const & x)
212
return GLM_NEXT_AFTER_DBL(x, std::numeric_limits<double>::min());
215
template<typename T, template<typename> class vecType>
216
GLM_FUNC_QUALIFIER vecType<T> prev_float(vecType<T> const & x)
219
for(std::size_t i = 0; i < Result.length(); ++i)
220
Result[i] = prev_float(x[i]);
224
template <typename T>
225
GLM_FUNC_QUALIFIER T next_float(T const & x, uint const & ulps)
228
for(std::size_t i = 0; i < ulps; ++i)
229
temp = next_float(temp);
233
template<typename T, template<typename> class vecType>
234
GLM_FUNC_QUALIFIER vecType<T> next_float(vecType<T> const & x, vecType<uint> const & ulps)
237
for(std::size_t i = 0; i < Result.length(); ++i)
238
Result[i] = next_float(x[i], ulps[i]);
242
template <typename T>
243
GLM_FUNC_QUALIFIER T prev_float(T const & x, uint const & ulps)
246
for(std::size_t i = 0; i < ulps; ++i)
247
temp = prev_float(temp);
251
template<typename T, template<typename> class vecType>
252
GLM_FUNC_QUALIFIER vecType<T> prev_float(vecType<T> const & x, vecType<uint> const & ulps)
255
for(std::size_t i = 0; i < Result.length(); ++i)
256
Result[i] = prev_float(x[i], ulps[i]);
260
template <typename T>
261
GLM_FUNC_QUALIFIER uint float_distance(T const & x, T const & y)
268
while(temp != y && ulp < std::numeric_limits<std::size_t>::max())
271
temp = next_float(temp);
277
while(temp != x && ulp < std::numeric_limits<std::size_t>::max())
280
temp = next_float(temp);
291
template<typename T, template<typename> class vecType>
292
GLM_FUNC_QUALIFIER vecType<uint> float_distance(vecType<T> const & x, vecType<T> const & y)
294
vecType<uint> Result;
295
for(std::size_t i = 0; i < Result.length(); ++i)
296
Result[i] = float_distance(x[i], y[i]);