1 /* $Id: float.h,v 1.5 2009/08/29 21:19:43 fredette Exp $ */
2
3 /* tme/generic/float.h - public header file for floating-point emulation */
4
5 /*
6 * Copyright (c) 2004 Matt Fredette
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Matt Fredette.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 #ifndef _TME_GENERIC_FLOAT_H
37 #define _TME_GENERIC_FLOAT_H
38
39 #include <tme/common.h>
40 _TME_RCSID("$Id: float.h,v 1.5 2009/08/29 21:19:43 fredette Exp $");
41
42 /* includes: */
43 #include <tme/threads.h>
44 #include <setjmp.h>
45 #include <math.h>
46 #ifdef _TME_HAVE_IEEEFP_H
47 #include <ieeefp.h>
48 #endif /* _TME_HAVE_IEEEFP_H */
49 #ifdef _TME_HAVE_FLOAT_H
50 #include <float.h>
51 #endif /* _TME_HAVE_FLOAT_H */
52 #ifdef _TME_HAVE_LIMITS_H
53 #include <limits.h>
54 #endif /* _TME_HAVE_LIMITS_H */
55
56 /* macros: */
57
58 /* floating-point formats. even though these are individual bits, we
59 can't use TME_BIT() because these are used in preprocessor ifs: */
60 #define TME_FLOAT_FORMAT_NULL (0)
61 #ifndef TME_FLOAT_FORMAT_FLOAT
62 #define TME_FLOAT_FORMAT_FLOAT (1)
63 #endif /* !TME_FLOAT_FORMAT_FLOAT */
64 #ifndef TME_FLOAT_FORMAT_DOUBLE
65 #define TME_FLOAT_FORMAT_DOUBLE (2)
66 #endif /* !TME_FLOAT_FORMAT_FLOAT */
67 #ifdef _TME_HAVE_LONG_DOUBLE
68 #ifndef TME_FLOAT_FORMAT_LONG_DOUBLE
69 #define TME_FLOAT_FORMAT_LONG_DOUBLE (4)
70 #endif /* !TME_FLOAT_FORMAT_LONG_DOUBLE */
71 #endif /* _TME_HAVE_LONG_DOUBLE */
72 #define TME_FLOAT_FORMAT_IEEE754_SINGLE (8)
73 #define TME_FLOAT_FORMAT_IEEE754_DOUBLE (16)
74 #define TME_FLOAT_FORMAT_IEEE754_EXTENDED80_I387 (32)
75 #define TME_FLOAT_FORMAT_IEEE754_EXTENDED80_M68881 (64)
76 #define TME_FLOAT_FORMAT_IEEE754_QUAD (128)
77
78 /* if the long double type is available, this expands to the code
79 fragment in x, else it expands to nothing: */
80 #ifdef _TME_HAVE_LONG_DOUBLE
81 #define TME_FLOAT_IF_LONG_DOUBLE(x) x
82 #else /* !_TME_HAVE_LONG_DOUBLE */
83 #define TME_FLOAT_IF_LONG_DOUBLE(x) /* */
84 #endif /* !_TME_HAVE_LONG_DOUBLE */
85
86 /* a mask of all builtin floating-point formats: */
87 #define TME_FLOAT_FORMATS_BUILTIN (TME_FLOAT_FORMAT_FLOAT \
88 | TME_FLOAT_FORMAT_DOUBLE \
89 TME_FLOAT_IF_LONG_DOUBLE(| TME_FLOAT_FORMAT_LONG_DOUBLE))
90
91 /* floating-point rounding modes: */
92 #ifdef _TME_HAVE_FPSETROUND
93 #define TME_FLOAT_ROUND_NULL (0xdeadbeef)
94 #define TME_FLOAT_ROUND_NEAREST_EVEN (FP_RN)
95 #define TME_FLOAT_ROUND_DOWN (FP_RM)
96 #define TME_FLOAT_ROUND_UP (FP_RP)
97 #define TME_FLOAT_ROUND_TO_ZERO (FP_RZ)
98 #else /* !_TME_HAVE_FPSETROUND */
99 #define TME_FLOAT_ROUND_NULL (0)
100 #define TME_FLOAT_ROUND_NEAREST_EVEN (1)
101 #define TME_FLOAT_ROUND_DOWN (2)
102 #define TME_FLOAT_ROUND_UP (3)
103 #define TME_FLOAT_ROUND_TO_ZERO (4)
104 #endif /* !_TME_HAVE_FPSETROUND */
105
106 /* floating-point exceptions: */
107 #define TME_FLOAT_EXCEPTION_GENERIC TME_BIT(0)
108 #define TME_FLOAT_EXCEPTION_INVALID TME_BIT(1)
109 #define TME_FLOAT_EXCEPTION_DIVBYZERO TME_BIT(2)
110 #define TME_FLOAT_EXCEPTION_OVERFLOW TME_BIT(3)
111 #define TME_FLOAT_EXCEPTION_UNDERFLOW TME_BIT(4)
112 #define TME_FLOAT_EXCEPTION_INEXACT TME_BIT(5)
113 #define TME_FLOAT_EXCEPTION_OVERFLOW_INT TME_BIT(6)
114 #define TME_FLOAT_EXCEPTION_DENORMAL TME_BIT(7)
115
116 /* types: */
117
118 /* each of these types describes a floating point format supported on
119 hosts. each of these types may also be used in code that emulates
120 the a floating point format, but each type's first purpose is to
121 overlap exactly with one or more of the host's builtin C types that
122 uses the format.
123
124 for example, if the host has a builtin C type that uses the i387
125 style of the IEEE 754 80-bit extended precision format, struct
126 tme_float_ieee754_extended80 matches that style, not the m68k
127 style. if no builtin C type uses any style of the IEEE 754 80-bit
128 extended precision format, struct tme_float_ieee754_extended80
129 matches a random style.
130
131 member values in these structures are always in host byte and word
132 order.
133
134 we also allow for these parts of the header file to be multiply
135 included, so that these types can be incorporated into emulation
136 code under different names: */
137
138 /* tme_uint32_t is used for the IEEE 754 single precision format. */
139
140 /* union tme_value64 is used for the IEEE 754 double precision format. */
141
142 #undef _TME_GENERIC_FLOAT_H
143 #endif /* !_TME_GENERIC_FLOAT_H */
144
145 #ifndef TME_FLOAT_FORMAT_IEEE754_EXTENDED80
146
147 /* making the IEEE 754 80-bit extended precision float structure
148 overlap with a native type is complicated, since there are four
149 possible representations: i387-style (where the 16 bits of sign and
150 exponent are adjacent to the significand) and m68881-style (where
151 there is a 16-bit gap between the significand and the 16 bits of
152 sign and exponent), plus big- and little-endian variants of each: */
153
154 /* decide where the 16-bit sign-exponent word and any 16-bit padding
155 words are in relation to the significand: */
156 #if ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_EXTENDED80_M68881) != 0)
157 #define TME_FLOAT_FORMAT_IEEE754_EXTENDED80 TME_FLOAT_FORMAT_IEEE754_EXTENDED80_M68881
158 #define _tme_float_ieee754_extended80_word_1 tme_float_ieee754_extended80_sexp
159 #define _tme_float_ieee754_extended80_word_0 tme_float_ieee754_extended80_pad
160 #else /* ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_EXTENDED80_M68881) == 0) */
161 #define TME_FLOAT_FORMAT_IEEE754_EXTENDED80 TME_FLOAT_FORMAT_IEEE754_EXTENDED80_I387
162 #define _tme_float_ieee754_extended80_word_0 tme_float_ieee754_extended80_sexp
163 #endif /* ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_EXTENDED80_M68881) == 0) */
164
165 /* the IEEE 754 80-bit extended precision format: */
166 struct tme_float_ieee754_extended80 {
167
168 /* if this is a big-endian host: */
169 #ifdef _TME_WORDS_BIGENDIAN
170
171 /* up to four 16-bit words preceding the significand: */
172 #ifdef _tme_float_ieee754_extended80_word_3
173 tme_uint16_t _tme_float_ieee754_extended80_word_3;
174 #endif /* _tme_float_ieee754_extended80_word_3 */
175 #ifdef _tme_float_ieee754_extended80_word_2
176 tme_uint16_t _tme_float_ieee754_extended80_word_2;
177 #endif /* _tme_float_ieee754_extended80_word_2 */
178 #ifdef _tme_float_ieee754_extended80_word_1
179 tme_uint16_t _tme_float_ieee754_extended80_word_1;
180 #endif /* _tme_float_ieee754_extended80_word_1 */
181 tme_uint16_t _tme_float_ieee754_extended80_word_0;
182
183 #endif /* _TME_WORDS_BIGENDIAN */
184
185 /* the significand: */
186 #ifndef tme_float_ieee754_extended80
187 union tme_value64 tme_float_ieee754_extended80_significand;
188 #else /* !tme_float_ieee754_extended80 */
189 tme_uint64_t tme_float_ieee754_extended80_significand;
190 #endif /* !tme_float_ieee754_extended80 */
191
192 /* if this is a little-endian host: */
193 #ifndef _TME_WORDS_BIGENDIAN
194
195 /* up to four 16-bit words following the significand: */
196 tme_uint16_t _tme_float_ieee754_extended80_word_0;
197 #ifdef _tme_float_ieee754_extended80_word_1
198 tme_uint16_t _tme_float_ieee754_extended80_word_1;
199 #endif /* _tme_float_ieee754_extended80_word_1 */
200 #ifdef _tme_float_ieee754_extended80_word_2
201 tme_uint16_t _tme_float_ieee754_extended80_word_2;
202 #endif /* _tme_float_ieee754_extended80_word_2 */
203 #ifdef _tme_float_ieee754_extended80_word_3
204 tme_uint16_t _tme_float_ieee754_extended80_word_3;
205 #endif /* _tme_float_ieee754_extended80_word_3 */
206
207 #endif /* !_TME_WORDS_BIGENDIAN */
208 #undef _tme_float_ieee754_extended80_word_0
209 #undef _tme_float_ieee754_extended80_word_1
210 #undef _tme_float_ieee754_extended80_word_2
211 #undef _tme_float_ieee754_extended80_word_3
212 };
213
214 #endif /* TME_FLOAT_FORMAT_IEEE754_EXTENDED80 */
215
216 #ifndef _TME_GENERIC_FLOAT_H
217 #define _TME_GENERIC_FLOAT_H
218
219 /* the IEEE 754 quad precision format: */
220 struct tme_float_ieee754_quad {
221 #ifdef _TME_WORDS_BIGENDIAN
222 union tme_value64 tme_float_ieee754_quad_hi;
223 union tme_value64 tme_float_ieee754_quad_lo;
224 #else /* !_TME_WORDS_BIGENDIAN */
225 union tme_value64 tme_float_ieee754_quad_lo;
226 union tme_value64 tme_float_ieee754_quad_hi;
227 #endif /* !_TME_WORDS_BIGENDIAN */
228 };
229
230 /* the generic float: */
231 struct tme_float {
232
233 /* the format of this float: */
234 unsigned int tme_float_format;
235
236 /* the value of this float: */
237 union {
238
239 /* the builtin formats: */
240 float _tme_float_union_float;
241 double _tme_float_union_double;
242 #ifdef _TME_HAVE_LONG_DOUBLE
243 long double _tme_float_union_long_double;
244 #endif /* _TME_HAVE_LONG_DOUBLE */
245
246 /* the IEEE 754 formats: */
247 tme_uint32_t _tme_float_union_ieee754_single;
248 union tme_value64 _tme_float_union_ieee754_double;
249 struct tme_float_ieee754_extended80 _tme_float_union_ieee754_extended80;
250 struct tme_float_ieee754_quad _tme_float_union_ieee754_quad;
251 } _tme_float_union;
252
253 /* the public member names: */
254 #define tme_float_value_float _tme_float_union._tme_float_union_float
255 #define tme_float_value_double _tme_float_union._tme_float_union_double
256 #ifdef _TME_HAVE_LONG_DOUBLE
257 #define tme_float_value_long_double _tme_float_union._tme_float_union_long_double
258 #endif /* _TME_HAVE_LONG_DOUBLE */
259 #define tme_float_value_ieee754_single _tme_float_union._tme_float_union_ieee754_single
260 #define tme_float_value_ieee754_double _tme_float_union._tme_float_union_ieee754_double
261 #define tme_float_value_ieee754_extended80 _tme_float_union._tme_float_union_ieee754_extended80
262 #define tme_float_value_ieee754_quad _tme_float_union._tme_float_union_ieee754_quad
263 };
264
265 /* prototypes: */
266
267 /* this enters native floating-point operation: */
268 void tme_float_enter _TME_P((int, void (*)(int, void *), void *));
269
270 /* this returns the current native floating-point exceptions: */
271 int tme_float_exceptions _TME_P((void));
272
273 /* this leaves native floating-point operation: */
274 int tme_float_leave _TME_P((void));
275
276 /* this asserts that the float is in one of the expected formats: */
277 #ifndef NDEBUG
278 static _tme_inline int
tme_float_assert_formats(_tme_const struct tme_float * x,unsigned int formats)279 tme_float_assert_formats(_tme_const struct tme_float *x, unsigned int formats)
280 {
281 assert (x->tme_float_format & formats);
282 return (TRUE);
283 }
284 #else /* NDEBUG */
285 #define tme_float_assert_formats(x, formats) (TRUE)
286 #endif /* NDEBUG */
287
288 /* this evaluates to nonzero if the float is in a certain format, if
289 the float is known to be one of the given formats: */
290 #define tme_float_is_format(x, formats, format) \
291 (((formats) == (format)) || (((formats) & (format)) && ((x)->tme_float_format & (format))))
292
293 /* this sets a float to a given builtin value: */
294 #define tme_float_value_builtin_set(x, format, y) \
295 do { \
296 if ((format) == TME_FLOAT_FORMAT_FLOAT) { \
297 (x)->tme_float_value_float = (y); \
298 } \
299 TME_FLOAT_IF_LONG_DOUBLE(else if ((format) == TME_FLOAT_FORMAT_LONG_DOUBLE) { \
300 (x)->tme_float_value_long_double = (y); \
301 }) \
302 else { \
303 assert((format) == TME_FLOAT_FORMAT_DOUBLE); \
304 (x)->tme_float_value_double = (y); \
305 } \
306 (x)->tme_float_format = (format); \
307 } while (/* CONSTCOND */ 0)
308
309 /* these return the exponents of values in the IEEE 754 formats: */
310 #define tme_float_value_ieee754_exponent_single(x) \
311 TME_FIELD_MASK_EXTRACTU((x)->tme_float_value_ieee754_single, 0x7f800000)
312 #define tme_float_value_ieee754_exponent_double(x) \
313 TME_FIELD_MASK_EXTRACTU((x)->tme_float_value_ieee754_double.tme_value64_uint32_hi, 0x7ff00000)
314 #define tme_float_value_ieee754_exponent_extended80(x) \
315 TME_FIELD_MASK_EXTRACTU((x)->tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_sexp, 0x7fff)
316 #define tme_float_value_ieee754_exponent_quad(x) \
317 TME_FIELD_MASK_EXTRACTU((x)->tme_float_value_ieee754_quad.tme_float_ieee754_quad_hi.tme_value64_uint32_hi, 0x7fff0000)
318
319 /* these return a bitwise-or of the fraction bits in values in the
320 IEEE 754 formats (and, for the IEEE 754 80-bit extended precision
321 format, a bitwise-or of the entire significand, including the
322 explicit integer bit): */
323 #define tme_float_value_ieee754_fracor_single(x) \
324 ((x)->tme_float_value_ieee754_single & 0x007fffff)
325 #define tme_float_value_ieee754_fracor_double(x) \
326 (((x)->tme_float_value_ieee754_double.tme_value64_uint32_hi & 0x000fffff) | (x)->tme_float_value_ieee754_double.tme_value64_uint32_lo)
327 #define tme_float_value_ieee754_fracor_extended80(x) \
328 (((x)->tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_hi << 1) | (x)->tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_lo)
329 #define tme_float_value_ieee754_sigor_extended80(x) \
330 ((x)->tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_hi | (x)->tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_lo)
331 #define tme_float_value_ieee754_fracor_quad(x) \
332 (((x)->tme_float_value_ieee754_quad.tme_float_ieee754_quad_hi.tme_value64_uint32_hi & 0x0000ffff) \
333 | (x)->tme_float_value_ieee754_quad.tme_float_ieee754_quad_hi.tme_value64_uint32_lo \
334 | (x)->tme_float_value_ieee754_quad.tme_float_ieee754_quad_lo.tme_value64_uint32_hi \
335 | (x)->tme_float_value_ieee754_quad.tme_float_ieee754_quad_lo.tme_value64_uint32_lo)
336
337 /* this evaluates to nonzero if the float is a NaN: */
338 #define tme_float_is_nan(x, formats) \
339 (tme_float_assert_formats(x, formats) \
340 && (tme_float_is_format(x, formats, TME_FLOAT_FORMAT_IEEE754_SINGLE) \
341 ? (tme_float_value_ieee754_exponent_single(x) == 0xff \
342 && tme_float_value_ieee754_fracor_single(x) != 0) \
343 : tme_float_is_format(x, formats, TME_FLOAT_FORMAT_IEEE754_DOUBLE) \
344 ? (tme_float_value_ieee754_exponent_double(x) == 0x7ff \
345 && tme_float_value_ieee754_fracor_double(x) != 0) \
346 : tme_float_is_format(x, formats, TME_FLOAT_FORMAT_IEEE754_EXTENDED80) \
347 ? (tme_float_value_ieee754_exponent_extended80(x) == 0x7fff \
348 && tme_float_value_ieee754_fracor_extended80(x) != 0) \
349 : tme_float_is_format(x, formats, TME_FLOAT_FORMAT_IEEE754_QUAD) \
350 ? (tme_float_value_ieee754_exponent_quad(x) == 0x7fff \
351 && tme_float_value_ieee754_fracor_quad(x) != 0) \
352 : tme_float_is_format(x, formats, TME_FLOAT_FORMAT_FLOAT) \
353 ? isnanf((x)->tme_float_value_float) \
354 : tme_float_is_format(x, formats, TME_FLOAT_FORMAT_DOUBLE) \
355 ? isnan((x)->tme_float_value_double) \
356 : TME_FLOAT_IF_LONG_DOUBLE(isnan((x)->tme_float_value_long_double) ||) FALSE))
357
358 /* this evaluates to nonzero if the float is an infinity: */
359 #define tme_float_is_inf(x, formats) \
360 (tme_float_assert_formats(x, formats) \
361 && (tme_float_is_format(x, formats, TME_FLOAT_FORMAT_IEEE754_SINGLE) \
362 ? (tme_float_value_ieee754_exponent_single(x) == 0xff \
363 && tme_float_value_ieee754_fracor_single(x) == 0) \
364 : tme_float_is_format(x, formats, TME_FLOAT_FORMAT_IEEE754_DOUBLE) \
365 ? (tme_float_value_ieee754_exponent_double(x) == 0x7ff \
366 && tme_float_value_ieee754_fracor_double(x) == 0) \
367 : tme_float_is_format(x, formats, TME_FLOAT_FORMAT_IEEE754_EXTENDED80) \
368 ? (tme_float_value_ieee754_exponent_extended80(x) == 0x7fff \
369 && tme_float_value_ieee754_fracor_extended80(x) == 0) \
370 : tme_float_is_format(x, formats, TME_FLOAT_FORMAT_IEEE754_QUAD) \
371 ? (tme_float_value_ieee754_exponent_quad(x) == 0x7fff \
372 && tme_float_value_ieee754_fracor_quad(x) == 0) \
373 : tme_float_is_format(x, formats, TME_FLOAT_FORMAT_FLOAT) \
374 ? isinff((x)->tme_float_value_float) \
375 : tme_float_is_format(x, formats, TME_FLOAT_FORMAT_DOUBLE) \
376 ? isinf((x)->tme_float_value_double) \
377 : TME_FLOAT_IF_LONG_DOUBLE(isinf((x)->tme_float_value_long_double) ||) FALSE))
378
379 /* this evaluates to nonzero if the float is a zero: */
380 #define tme_float_is_zero(x, formats) \
381 (tme_float_assert_formats(x, formats) \
382 && (tme_float_is_format(x, formats, TME_FLOAT_FORMAT_IEEE754_SINGLE) \
383 ? (tme_float_value_ieee754_exponent_single(x) == 0 \
384 && tme_float_value_ieee754_fracor_single(x) == 0) \
385 : tme_float_is_format(x, formats, TME_FLOAT_FORMAT_IEEE754_DOUBLE) \
386 ? (tme_float_value_ieee754_exponent_double(x) == 0 \
387 && tme_float_value_ieee754_fracor_double(x) == 0) \
388 : tme_float_is_format(x, formats, TME_FLOAT_FORMAT_IEEE754_EXTENDED80) \
389 ? (tme_float_value_ieee754_exponent_extended80(x) == 0 \
390 && tme_float_value_ieee754_sigor_extended80(x) == 0) \
391 : tme_float_is_format(x, formats, TME_FLOAT_FORMAT_IEEE754_QUAD) \
392 ? (tme_float_value_ieee754_exponent_quad(x) == 0 \
393 && tme_float_value_ieee754_fracor_quad(x) == 0) \
394 : tme_float_is_format(x, formats, TME_FLOAT_FORMAT_FLOAT) \
395 ? ((x)->tme_float_value_float == 0) \
396 : tme_float_is_format(x, formats, TME_FLOAT_FORMAT_DOUBLE) \
397 ? ((x)->tme_float_value_double == 0) \
398 : TME_FLOAT_IF_LONG_DOUBLE(((x)->tme_float_value_long_double == 0) ||) FALSE))
399
400 /* this evaluates to nonzero if the float is negative: */
401 #define tme_float_is_negative(x, formats) \
402 (tme_float_assert_formats(x, formats) \
403 && (tme_float_is_format(x, formats, TME_FLOAT_FORMAT_IEEE754_SINGLE) \
404 ? (((x)->tme_float_value_ieee754_single & 0x80000000) != 0) \
405 : tme_float_is_format(x, formats, TME_FLOAT_FORMAT_IEEE754_DOUBLE) \
406 ? (((x)->tme_float_value_ieee754_double.tme_value64_uint32_hi & 0x80000000) != 0) \
407 : tme_float_is_format(x, formats, TME_FLOAT_FORMAT_IEEE754_EXTENDED80) \
408 ? (((x)->tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_sexp & 0x8000) != 0) \
409 : tme_float_is_format(x, formats, TME_FLOAT_FORMAT_IEEE754_QUAD) \
410 ? (((x)->tme_float_value_ieee754_quad.tme_float_ieee754_quad_hi.tme_value64_uint32_hi & 0x80000000) != 0) \
411 : tme_float_is_format(x, formats, TME_FLOAT_FORMAT_FLOAT) \
412 ? ((x)->tme_float_value_float < 0) \
413 : tme_float_is_format(x, formats, TME_FLOAT_FORMAT_DOUBLE) \
414 ? ((x)->tme_float_value_double < 0) \
415 : TME_FLOAT_IF_LONG_DOUBLE(((x)->tme_float_value_long_double < 0) ||) FALSE))
416
417 /* if possible, this returns a positive or negative infinity
418 float, otherwise, this returns the float value
419 closest to that infinity: */
420 float tme_float_infinity_float _TME_P((int));
421
422 /* if possible, this returns a negative zero float.
423 otherwise, this returns the negative float value closest
424 to zero: */
425 float tme_float_negative_zero_float _TME_P((void));
426
427 /* this returns the radix 2 mantissa and exponent of an in-range float.
428 the mantissa is either zero, or in the range [1,2): */
429 float tme_float_radix2_mantissa_exponent_float _TME_P((float, tme_int32_t *));
430
431 /* this scales a value by adding n to its exponent: */
432 float tme_float_radix2_scale_float _TME_P((float, tme_int32_t));
433
434 /* this returns the radix 10 mantissa and exponent of an in-range float.
435 the mantissa is either zero, or in the range [1,10): */
436 float tme_float_radix10_mantissa_exponent_float _TME_P((float, tme_int32_t *));
437
438 /* this scales a value by adding n to its exponent: */
439 float tme_float_radix10_scale_float _TME_P((float, tme_int32_t));
440
441 /* if possible, this returns a positive or negative infinity
442 double, otherwise, this returns the double value
443 closest to that infinity: */
444 double tme_float_infinity_double _TME_P((int));
445
446 /* if possible, this returns a negative zero double.
447 otherwise, this returns the negative double value closest
448 to zero: */
449 double tme_float_negative_zero_double _TME_P((void));
450
451 /* this returns the radix 2 mantissa and exponent of an in-range double.
452 the mantissa is either zero, or in the range [1,2): */
453 double tme_float_radix2_mantissa_exponent_double _TME_P((double, tme_int32_t *));
454
455 /* this scales a value by adding n to its exponent: */
456 double tme_float_radix2_scale_double _TME_P((double, tme_int32_t));
457
458 /* this returns the radix 10 mantissa and exponent of an in-range double.
459 the mantissa is either zero, or in the range [1,10): */
460 double tme_float_radix10_mantissa_exponent_double _TME_P((double, tme_int32_t *));
461
462 /* this scales a value by adding n to its exponent: */
463 double tme_float_radix10_scale_double _TME_P((double, tme_int32_t));
464
465 #ifdef _TME_HAVE_LONG_DOUBLE
466
467 /* if possible, this returns a positive or negative infinity
468 long double, otherwise, this returns the long double value
469 closest to that infinity: */
470 long double tme_float_infinity_long_double _TME_P((int));
471
472 /* if possible, this returns a negative zero long double.
473 otherwise, this returns the negative long double value closest
474 to zero: */
475 long double tme_float_negative_zero_long_double _TME_P((void));
476
477 /* this returns the radix 2 mantissa and exponent of an in-range long double.
478 the mantissa is either zero, or in the range [1,2): */
479 long double tme_float_radix2_mantissa_exponent_long_double _TME_P((long double, tme_int32_t *));
480
481 /* this scales a value by adding n to its exponent: */
482 long double tme_float_radix2_scale_long_double _TME_P((long double, tme_int32_t));
483
484 /* this returns the radix 10 mantissa and exponent of an in-range long double.
485 the mantissa is either zero, or in the range [1,10): */
486 long double tme_float_radix10_mantissa_exponent_long_double _TME_P((long double, tme_int32_t *));
487
488 /* this scales a value by adding n to its exponent: */
489 long double tme_float_radix10_scale_long_double _TME_P((long double, tme_int32_t));
490
491 #endif /* _TME_HAVE_LONG_DOUBLE */
492
493 /* prototypes for missing standard functions: */
494 #ifndef _TME_HAVE_ISINFF
495 int isinff _TME_P((float));
496 #endif /* !_TME_HAVE_ISINFF */
497
498 #endif /* _TME_GENERIC_FLOAT_H */
499