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