| /* | |
| * ==================================================== | |
| * 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 <inttypes.h> | |
| #include <float.h> | |
| typedef unsigned int u_int32_t; | |
| typedef union | |
| { | |
| double value; | |
| struct | |
| { | |
| u_int32_t lsw; | |
| u_int32_t msw; | |
| } parts; | |
| } ieee_double_shape_type; | |
| typedef union { | |
| float value; | |
| u_int32_t word; | |
| } ieee_float_shape_type; | |
| /* Get two 32 bit ints from a double. */ | |
| #define 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) | |
| /* Get the most significant 32 bit int from a double. */ | |
| #define GET_HIGH_WORD(i,d) \ | |
| do { \ | |
| ieee_double_shape_type gh_u; \ | |
| gh_u.value = (d); \ | |
| (i) = gh_u.parts.msw; \ | |
| } while (0) | |
| /* Get the less significant 32 bit int from a double. */ | |
| #define GET_LOW_WORD(i,d) \ | |
| do { \ | |
| ieee_double_shape_type gl_u; \ | |
| gl_u.value = (d); \ | |
| (i) = gl_u.parts.lsw; \ | |
| } while (0) | |
| /* Set a double from two 32 bit ints. */ | |
| #define 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) | |
| /* Set the more significant 32 bits of a double from an int. */ | |
| #define SET_HIGH_WORD(d,v) \ | |
| do { \ | |
| ieee_double_shape_type sh_u; \ | |
| sh_u.value = (d); \ | |
| sh_u.parts.msw = (v); \ | |
| (d) = sh_u.value; \ | |
| } while (0) | |
| /* Set the less significant 32 bits of a double from an int. */ | |
| #define SET_LOW_WORD(d,v) \ | |
| do { \ | |
| ieee_double_shape_type sl_u; \ | |
| sl_u.value = (d); \ | |
| sl_u.parts.lsw = (v); \ | |
| (d) = sl_u.value; \ | |
| } while (0) | |
| #define GET_FLOAT_WORD(i,d) do \ | |
| { \ | |
| ieee_float_shape_type gf_u; \ | |
| gf_u.value = (d); \ | |
| (i) = gf_u.word; \ | |
| } while(0) | |
| #define SET_FLOAT_WORD(d,i) do \ | |
| { \ | |
| ieee_float_shape_type gf_u; \ | |
| gf_u.word = (i); \ | |
| (d) = gf_u.value; \ | |
| } while(0) | |
| #ifdef FLT_EVAL_METHOD | |
| /* | |
| * Attempt to get strict C99 semantics for assignment with non-C99 compilers. | |
| */ | |
| #if FLT_EVAL_METHOD == 0 || __GNUC__ == 0 | |
| #define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval)) | |
| #else | |
| #define STRICT_ASSIGN(type, lval, rval) do { \ | |
| volatile type __lval; \ | |
| \ | |
| if (sizeof(type) >= sizeof(long double)) \ | |
| (lval) = (rval); \ | |
| else { \ | |
| __lval = (rval); \ | |
| (lval) = __lval; \ | |
| } \ | |
| } while (0) | |
| #endif | |
| #endif /* FLT_EVAL_METHOD */ | |
| /* | |
| * Mix 0, 1 or 2 NaNs. First add 0 to each arg. This normally just turns | |
| * signaling NaNs into quiet NaNs by setting a quiet bit. We do this | |
| * because we want to never return a signaling NaN, and also because we | |
| * don't want the quiet bit to affect the result. Then mix the converted | |
| * args using the specified operation. | |
| * | |
| * When one arg is NaN, the result is typically that arg quieted. When both | |
| * args are NaNs, the result is typically the quietening of the arg whose | |
| * mantissa is largest after quietening. When neither arg is NaN, the | |
| * result may be NaN because it is indeterminate, or finite for subsequent | |
| * construction of a NaN as the indeterminate 0.0L/0.0L. | |
| * | |
| * Technical complications: the result in bits after rounding to the final | |
| * precision might depend on the runtime precision and/or on compiler | |
| * optimizations, especially when different register sets are used for | |
| * different precisions. Try to make the result not depend on at least the | |
| * runtime precision by always doing the main mixing step in long double | |
| * precision. Try to reduce dependencies on optimizations by adding the | |
| * the 0's in different precisions (unless everything is in long double | |
| * precision). | |
| */ | |
| #define nan_mix(x, y) (nan_mix_op((x), (y), +)) | |
| #define nan_mix_op(x, y, op) (((x) + 0.0L) op ((y) + 0)) |