/** Generate NaN. @return Floating-point representation of NaN. */ TRIO_PUBLIC double trio_nan(void) { /* Cache the result */ static double result = 0.0; if (result == 0.0) { #if defined(TRIO_COMPILER_SUPPORTS_C99) result = nan(NULL); #elif defined(NAN) && defined(__STDC_IEC_559__) result = (double)NAN; #elif defined(USE_IEEE_754) result = trio_make_double(ieee_754_qnan_array); #else /* * There are several ways to generate NaN. The one used here is * to divide infinity by infinity. I would have preferred to add * negative infinity to positive infinity, but that yields wrong * result (infinity) on FreeBSD. * * This may fail if the hardware does not support NaN, or if * the Invalid Operation floating-point exception is unmasked. */ # if defined(TRIO_PLATFORM_UNIX) void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN); # endif result = trio_pinf() / trio_pinf(); # if defined(TRIO_PLATFORM_UNIX) signal(SIGFPE, signal_handler); # endif #endif } return result; }
/************************************************************************* * trio_ninf */ TRIO_PUBLIC double trio_ninf(void) { static double result = 0.0; if (result == 0.0) { /* * Negative infinity is calculated by negating positive infinity, * which can be done because it is legal to do calculations on * infinity (for example, 1 / infinity == 0). */ result = -trio_pinf(); } return result; }
int main(void) { double my_nan; double my_pinf; double my_ninf; # if defined(TRIO_PLATFORM_UNIX) void (*signal_handler)(int); # endif my_nan = trio_nan(); my_pinf = trio_pinf(); my_ninf = trio_ninf(); printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", my_nan, ((unsigned char *)&my_nan)[0], ((unsigned char *)&my_nan)[1], ((unsigned char *)&my_nan)[2], ((unsigned char *)&my_nan)[3], ((unsigned char *)&my_nan)[4], ((unsigned char *)&my_nan)[5], ((unsigned char *)&my_nan)[6], ((unsigned char *)&my_nan)[7], trio_isnan(my_nan), trio_isinf(my_nan)); printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", my_pinf, ((unsigned char *)&my_pinf)[0], ((unsigned char *)&my_pinf)[1], ((unsigned char *)&my_pinf)[2], ((unsigned char *)&my_pinf)[3], ((unsigned char *)&my_pinf)[4], ((unsigned char *)&my_pinf)[5], ((unsigned char *)&my_pinf)[6], ((unsigned char *)&my_pinf)[7], trio_isnan(my_pinf), trio_isinf(my_pinf)); printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", my_ninf, ((unsigned char *)&my_ninf)[0], ((unsigned char *)&my_ninf)[1], ((unsigned char *)&my_ninf)[2], ((unsigned char *)&my_ninf)[3], ((unsigned char *)&my_ninf)[4], ((unsigned char *)&my_ninf)[5], ((unsigned char *)&my_ninf)[6], ((unsigned char *)&my_ninf)[7], trio_isnan(my_ninf), trio_isinf(my_ninf)); # if defined(TRIO_PLATFORM_UNIX) signal_handler = signal(SIGFPE, SIG_IGN); # endif my_pinf = DBL_MAX + DBL_MAX; my_ninf = -my_pinf; my_nan = my_pinf / my_pinf; # if defined(TRIO_PLATFORM_UNIX) signal(SIGFPE, signal_handler); # endif printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", my_nan, ((unsigned char *)&my_nan)[0], ((unsigned char *)&my_nan)[1], ((unsigned char *)&my_nan)[2], ((unsigned char *)&my_nan)[3], ((unsigned char *)&my_nan)[4], ((unsigned char *)&my_nan)[5], ((unsigned char *)&my_nan)[6], ((unsigned char *)&my_nan)[7], trio_isnan(my_nan), trio_isinf(my_nan)); printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", my_pinf, ((unsigned char *)&my_pinf)[0], ((unsigned char *)&my_pinf)[1], ((unsigned char *)&my_pinf)[2], ((unsigned char *)&my_pinf)[3], ((unsigned char *)&my_pinf)[4], ((unsigned char *)&my_pinf)[5], ((unsigned char *)&my_pinf)[6], ((unsigned char *)&my_pinf)[7], trio_isnan(my_pinf), trio_isinf(my_pinf)); printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", my_ninf, ((unsigned char *)&my_ninf)[0], ((unsigned char *)&my_ninf)[1], ((unsigned char *)&my_ninf)[2], ((unsigned char *)&my_ninf)[3], ((unsigned char *)&my_ninf)[4], ((unsigned char *)&my_ninf)[5], ((unsigned char *)&my_ninf)[6], ((unsigned char *)&my_ninf)[7], trio_isnan(my_ninf), trio_isinf(my_ninf)); return 0; }
/************************************************************************* * trio_isinf */ TRIO_PUBLIC int trio_isinf(TRIO_VOLATILE double number) { #if defined(TRIO_COMPILER_DECC) /* * DECC has an isinf() macro, but it works differently than that * of C99, so we use the fp_class() function instead. */ return ((fp_class(number) == FP_POS_INF) ? 1 : ((fp_class(number) == FP_NEG_INF) ? -1 : 0)); #elif defined(isinf) /* * C99 defines isinf() as a macro. */ return isinf(number); #elif defined(TRIO_COMPILER_MSVC) /* * MSVC has an _fpclass() function that can be used to detect infinity. */ return ((_fpclass(number) == _FPCLASS_PINF) ? 1 : ((_fpclass(number) == _FPCLASS_NINF) ? -1 : 0)); #elif defined(USE_IEEE_754) /* * Examine IEEE 754 bit-pattern. Infinity must have a special exponent * pattern, and an empty mantissa. */ int has_mantissa; int is_special_quantity; is_special_quantity = trio_is_special_quantity(number, &has_mantissa); return (is_special_quantity && !has_mantissa) ? ((number < 0.0) ? -1 : 1) : 0; #else /* * Fallback solution. */ int status; # if defined(TRIO_PLATFORM_UNIX) void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN); # endif double infinity = trio_pinf(); status = ((number == infinity) ? 1 : ((number == -infinity) ? -1 : 0)); # if defined(TRIO_PLATFORM_UNIX) signal(SIGFPE, signal_handler); # endif return status; #endif }