Clutter Engine 0.0.1
Loading...
Searching...
No Matches
scalar_ulp.inl
1
7
8#include "../detail/type_float.hpp"
10#include <cmath>
11#include <cfloat>
12
13#if(GLM_COMPILER & GLM_COMPILER_VC)
14# pragma warning(push)
15# pragma warning(disable : 4127)
16#endif
17
18typedef union
19{
20 float value;
21 /* FIXME: Assumes 32 bit int. */
22 unsigned int word;
24
25typedef union
26{
27 double value;
28 struct
29 {
30 int lsw;
31 int msw;
32 } parts;
34
35#define GLM_EXTRACT_WORDS(ix0,ix1,d) \
36 do { \
37 ieee_double_shape_type ew_u; \
38 ew_u.value = (d); \
39 (ix0) = ew_u.parts.msw; \
40 (ix1) = ew_u.parts.lsw; \
41 } while (0)
42
43#define GLM_GET_FLOAT_WORD(i,d) \
44 do { \
45 ieee_float_shape_type gf_u; \
46 gf_u.value = (d); \
47 (i) = gf_u.word; \
48 } while (0)
49
50#define GLM_SET_FLOAT_WORD(d,i) \
51 do { \
52 ieee_float_shape_type sf_u; \
53 sf_u.word = (i); \
54 (d) = sf_u.value; \
55 } while (0)
56
57#define GLM_INSERT_WORDS(d,ix0,ix1) \
58 do { \
59 ieee_double_shape_type iw_u; \
60 iw_u.parts.msw = (ix0); \
61 iw_u.parts.lsw = (ix1); \
62 (d) = iw_u.value; \
63 } while (0)
64
65namespace glm{
66namespace detail
67{
68 GLM_FUNC_QUALIFIER float nextafterf(float x, float y)
69 {
70 volatile float t;
71 int hx, hy, ix, iy;
72
73 GLM_GET_FLOAT_WORD(hx, x);
74 GLM_GET_FLOAT_WORD(hy, y);
75 ix = hx & 0x7fffffff; // |x|
76 iy = hy & 0x7fffffff; // |y|
77
78 if((ix > 0x7f800000) || // x is nan
79 (iy > 0x7f800000)) // y is nan
80 return x + y;
81 if(abs(y - x) <= epsilon<float>())
82 return y; // x=y, return y
83 if(ix == 0)
84 { // x == 0
85 GLM_SET_FLOAT_WORD(x, (hy & 0x80000000) | 1);// return +-minsubnormal
86 t = x * x;
87 if(abs(t - x) <= epsilon<float>())
88 return t;
89 else
90 return x; // raise underflow flag
91 }
92 if(hx >= 0)
93 { // x > 0
94 if(hx > hy) // x > y, x -= ulp
95 hx -= 1;
96 else // x < y, x += ulp
97 hx += 1;
98 }
99 else
100 { // x < 0
101 if(hy >= 0 || hx > hy) // x < y, x -= ulp
102 hx -= 1;
103 else // x > y, x += ulp
104 hx += 1;
105 }
106 hy = hx & 0x7f800000;
107 if(hy >= 0x7f800000)
108 return x + x; // overflow
109 if(hy < 0x00800000) // underflow
110 {
111 t = x * x;
112 if(abs(t - x) > epsilon<float>())
113 { // raise underflow flag
114 GLM_SET_FLOAT_WORD(y, hx);
115 return y;
116 }
117 }
118 GLM_SET_FLOAT_WORD(x, hx);
119 return x;
120 }
121
122 GLM_FUNC_QUALIFIER double nextafter(double x, double y)
123 {
124 volatile double t;
125 int hx, hy, ix, iy;
126 unsigned int lx, ly;
127
128 GLM_EXTRACT_WORDS(hx, lx, x);
129 GLM_EXTRACT_WORDS(hy, ly, y);
130 ix = hx & 0x7fffffff; // |x|
131 iy = hy & 0x7fffffff; // |y|
132
133 if(((ix >= 0x7ff00000) && ((ix - 0x7ff00000) | lx) != 0) || // x is nan
134 ((iy >= 0x7ff00000) && ((iy - 0x7ff00000) | ly) != 0)) // y is nan
135 return x + y;
136 if(abs(y - x) <= epsilon<double>())
137 return y; // x=y, return y
138 if((ix | lx) == 0)
139 { // x == 0
140 GLM_INSERT_WORDS(x, hy & 0x80000000, 1); // return +-minsubnormal
141 t = x * x;
142 if(abs(t - x) <= epsilon<double>())
143 return t;
144 else
145 return x; // raise underflow flag
146 }
147 if(hx >= 0) { // x > 0
148 if(hx > hy || ((hx == hy) && (lx > ly))) { // x > y, x -= ulp
149 if(lx == 0) hx -= 1;
150 lx -= 1;
151 }
152 else { // x < y, x += ulp
153 lx += 1;
154 if(lx == 0) hx += 1;
155 }
156 }
157 else { // x < 0
158 if(hy >= 0 || hx > hy || ((hx == hy) && (lx > ly))){// x < y, x -= ulp
159 if(lx == 0) hx -= 1;
160 lx -= 1;
161 }
162 else { // x > y, x += ulp
163 lx += 1;
164 if(lx == 0) hx += 1;
165 }
166 }
167 hy = hx & 0x7ff00000;
168 if(hy >= 0x7ff00000)
169 return x + x; // overflow
170 if(hy < 0x00100000)
171 { // underflow
172 t = x * x;
173 if(abs(t - x) > epsilon<double>())
174 { // raise underflow flag
175 GLM_INSERT_WORDS(y, hx, lx);
176 return y;
177 }
178 }
179 GLM_INSERT_WORDS(x, hx, lx);
180 return x;
181 }
182}//namespace detail
183}//namespace glm
184
185#if(GLM_COMPILER & GLM_COMPILER_VC)
186# pragma warning(pop)
187#endif
188
189namespace glm
190{
191 template<>
192 GLM_FUNC_QUALIFIER float nextFloat(float x)
193 {
194# if GLM_HAS_CXX11_STL
195 return std::nextafter(x, std::numeric_limits<float>::max());
196# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS)))
197 return detail::nextafterf(x, FLT_MAX);
198# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID)
199 return __builtin_nextafterf(x, FLT_MAX);
200# else
201 return nextafterf(x, FLT_MAX);
202# endif
203 }
204
205 template<>
206 GLM_FUNC_QUALIFIER double nextFloat(double x)
207 {
208# if GLM_HAS_CXX11_STL
209 return std::nextafter(x, std::numeric_limits<double>::max());
210# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS)))
211 return detail::nextafter(x, std::numeric_limits<double>::max());
212# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID)
213 return __builtin_nextafter(x, DBL_MAX);
214# else
215 return nextafter(x, DBL_MAX);
216# endif
217 }
218
219 template<typename T>
220 GLM_FUNC_QUALIFIER T nextFloat(T x, int ULPs)
221 {
222 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'next_float' only accept floating-point input");
223 assert(ULPs >= 0);
224
225 T temp = x;
226 for(int i = 0; i < ULPs; ++i)
227 temp = nextFloat(temp);
228 return temp;
229 }
230
231 GLM_FUNC_QUALIFIER float prevFloat(float x)
232 {
233# if GLM_HAS_CXX11_STL
234 return std::nextafter(x, std::numeric_limits<float>::min());
235# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS)))
236 return detail::nextafterf(x, FLT_MIN);
237# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID)
238 return __builtin_nextafterf(x, FLT_MIN);
239# else
240 return nextafterf(x, FLT_MIN);
241# endif
242 }
243
244 GLM_FUNC_QUALIFIER double prevFloat(double x)
245 {
246# if GLM_HAS_CXX11_STL
247 return std::nextafter(x, std::numeric_limits<double>::min());
248# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS)))
249 return _nextafter(x, DBL_MIN);
250# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID)
251 return __builtin_nextafter(x, DBL_MIN);
252# else
253 return nextafter(x, DBL_MIN);
254# endif
255 }
256
257 template<typename T>
258 GLM_FUNC_QUALIFIER T prevFloat(T x, int ULPs)
259 {
260 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'prev_float' only accept floating-point input");
261 assert(ULPs >= 0);
262
263 T temp = x;
264 for(int i = 0; i < ULPs; ++i)
265 temp = prevFloat(temp);
266 return temp;
267 }
268
269 GLM_FUNC_QUALIFIER int floatDistance(float x, float y)
270 {
271 detail::float_t<float> const a(x);
272 detail::float_t<float> const b(y);
273
274 return abs(a.i - b.i);
275 }
276
277 GLM_FUNC_QUALIFIER int64 floatDistance(double x, double y)
278 {
279 detail::float_t<double> const a(x);
280 detail::float_t<double> const b(y);
281
282 return abs(a.i - b.i);
283 }
284}//namespace glm
GLM_FUNC_DECL GLM_CONSTEXPR genType abs(genType x)
GLM_FUNC_DECL GLM_CONSTEXPR genType epsilon()
Return the epsilon constant for floating point types.
Definition scalar_constants.inl:6
detail::int64 int64
64 bit signed integer type.
Definition scalar_int_sized.hpp:67
detail namespace with internal helper functions
Definition json.h:249
Core features
Definition common.hpp:21
GLM_FUNC_DECL genType prevFloat(genType x)
GLM_FUNC_DECL genType nextFloat(genType x)
GLM_FUNC_DECL int floatDistance(float x, float y)
Definition scalar_ulp.inl:269
Definition type_float.hpp:15
Definition scalar_ulp.inl:26
Definition scalar_ulp.inl:19