blob: 59e63a9f0c56b15720e2157ed55aeac30f7595d2 [file] [log] [blame]
Bjorn Reese45029602001-08-21 09:23:53 +00001/*************************************************************************
2 *
3 * $Id$
4 *
5 * Copyright (C) 2001 Bjorn Reese <breese@users.sourceforge.net>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
12 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
13 * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
14 * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
15 *
16 ************************************************************************
17 *
18 * Functions to handle special quantities in floating-point numbers
19 * (that is, NaNs and infinity). They provide the capability to detect
20 * and fabricate special quantities.
21 *
22 * Although written to be as portable as possible, it can never be
23 * guaranteed to work on all platforms, as not all hardware supports
24 * special quantities.
25 *
26 * The approach used here (approximately) is to:
27 *
28 * 1. Use C99 functionality when available.
29 * 2. Use IEEE 754 bit-patterns if possible.
30 * 3. Use platform-specific techniques.
31 *
32 * This program has been tested on the following platforms (in
33 * alphabetic order)
34 *
35 * OS CPU Compiler
36 * -------------------------------------------------
37 * AIX 4.1.4 PowerPC gcc
38 * Darwin 1.3.7 PowerPC gcc
39 * FreeBSD 2.2 x86 gcc
40 * FreeBSD 3.3 x86 gcc
41 * FreeBSD 4.3 x86 gcc
42 * FreeBSD 4.3 Alpha gcc
43 * HP-UX 10.20 PA-RISC gcc
44 * HP-UX 10.20 PA-RISC HP C++
45 * IRIX 6.5 MIPS MIPSpro C
46 * Linux 2.2 x86 gcc
47 * Linux 2.2 Alpha gcc
48 * Linux 2.4 IA64 gcc
49 * Linux 2.4 StrongARM gcc
50 * NetBSD 1.4 x86 gcc
51 * NetBSD 1.4 StrongARM gcc
52 * NetBSD 1.5 Alpha gcc
Bjorn Reese026d29f2002-01-19 15:40:18 +000053 * OpenVMS 7.1 Alpha DEC C 6.0
Bjorn Reese45029602001-08-21 09:23:53 +000054 * RISC OS 4 StrongARM Norcroft C
55 * Solaris 2.5.1 x86 gcc
56 * Solaris 2.5.1 Sparc gcc
57 * Solaris 2.6 Sparc WorkShop 4.2
58 * Solaris 8 Sparc Forte C 6
59 * Tru64 4.0D Alpha gcc
60 * Tru64 5.1 Alpha gcc
61 * WinNT x86 MSVC 5.0 & 6.0
62 *
63 ************************************************************************/
64
65static const char rcsid[] = "@(#)$Id$";
66
Bjorn Reese45029602001-08-21 09:23:53 +000067/*************************************************************************
68 * Include files
69 */
70#include "triodef.h"
71#include "trionan.h"
72
73#include <math.h>
74#include <string.h>
75#include <limits.h>
76#include <float.h>
77#if defined(TRIO_PLATFORM_UNIX)
78# include <signal.h>
79#endif
Bjorn Reese026d29f2002-01-19 15:40:18 +000080#if defined(TRIO_COMPILER_DECC)
81# include <fp_class.h>
82#endif
Bjorn Reese45029602001-08-21 09:23:53 +000083#include <assert.h>
84
Bjorn Reese026d29f2002-01-19 15:40:18 +000085#if defined(TRIO_DOCUMENTATION)
86# include "doc/doc_nan.h"
Bjorn Reese45029602001-08-21 09:23:53 +000087#endif
Bjorn Reese026d29f2002-01-19 15:40:18 +000088/** @addtogroup SpecialQuantities
89 @{
90*/
Bjorn Reese45029602001-08-21 09:23:53 +000091
92/*************************************************************************
93 * Definitions
94 */
95
96/* We must enable IEEE floating-point on Alpha */
97#if defined(__alpha) && !defined(_IEEE_FP)
98# if defined(TRIO_COMPILER_DECC)
Bjorn Reese026d29f2002-01-19 15:40:18 +000099# if defined(TRIO_PLATFORM_VMS)
100# error "Must be compiled with option /IEEE_MODE=UNDERFLOW_TO_ZERO/FLOAT=IEEE"
101# else
102# error "Must be compiled with option -ieee"
103# endif
Bjorn Reese45029602001-08-21 09:23:53 +0000104# elif defined(TRIO_COMPILER_GCC) && (defined(__osf__) || defined(__linux__))
105# error "Must be compiled with option -mieee"
106# endif
107#endif /* __alpha && ! _IEEE_FP */
108
109/*
110 * In ANSI/IEEE 754-1985 64-bits double format numbers have the
111 * following properties (amoungst others)
112 *
113 * o FLT_RADIX == 2: binary encoding
114 * o DBL_MAX_EXP == 1024: 11 bits exponent, where one bit is used
115 * to indicate special numbers (e.g. NaN and Infinity), so the
116 * maximum exponent is 10 bits wide (2^10 == 1024).
117 * o DBL_MANT_DIG == 53: The mantissa is 52 bits wide, but because
118 * numbers are normalized the initial binary 1 is represented
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000119 * implicitly (the so-called "hidden bit"), which leaves us with
Bjorn Reese45029602001-08-21 09:23:53 +0000120 * the ability to represent 53 bits wide mantissa.
121 */
122#if (FLT_RADIX == 2) && (DBL_MAX_EXP == 1024) && (DBL_MANT_DIG == 53)
123# define USE_IEEE_754
124#endif
125
126
127/*************************************************************************
128 * Data
129 */
130
131#if defined(USE_IEEE_754)
132
133/*
134 * Endian-agnostic indexing macro.
135 *
136 * The value of internalEndianMagic, when converted into a 64-bit
Bjorn Reese026d29f2002-01-19 15:40:18 +0000137 * integer, becomes 0x0706050403020100 (we could have used a 64-bit
Bjorn Reese45029602001-08-21 09:23:53 +0000138 * integer value instead of a double, but not all platforms supports
139 * that type). The value is automatically encoded with the correct
140 * endianess by the compiler, which means that we can support any
141 * kind of endianess. The individual bytes are then used as an index
142 * for the IEEE 754 bit-patterns and masks.
143 */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000144#define TRIO_DOUBLE_INDEX(x) (((unsigned char *)&internalEndianMagic)[7-(x)])
Bjorn Reese45029602001-08-21 09:23:53 +0000145
Bjorn Reese026d29f2002-01-19 15:40:18 +0000146static TRIO_CONST double internalEndianMagic = 7.949928895127363e-275;
Bjorn Reese45029602001-08-21 09:23:53 +0000147
Daniel Veillard5fc1f082002-03-27 09:05:40 +0000148/* Mask for the sign */
149static TRIO_CONST unsigned char ieee_754_sign_mask[] = {
150 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
151};
152
Bjorn Reese45029602001-08-21 09:23:53 +0000153/* Mask for the exponent */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000154static TRIO_CONST unsigned char ieee_754_exponent_mask[] = {
Bjorn Reese45029602001-08-21 09:23:53 +0000155 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
156};
157
158/* Mask for the mantissa */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000159static TRIO_CONST unsigned char ieee_754_mantissa_mask[] = {
Bjorn Reese45029602001-08-21 09:23:53 +0000160 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
161};
162
Daniel Veillard5fc1f082002-03-27 09:05:40 +0000163/* Bit-pattern for negative zero */
164static TRIO_CONST unsigned char ieee_754_negzero_array[] = {
165 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
166};
167
Bjorn Reese45029602001-08-21 09:23:53 +0000168/* Bit-pattern for infinity */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000169static TRIO_CONST unsigned char ieee_754_infinity_array[] = {
Bjorn Reese45029602001-08-21 09:23:53 +0000170 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
171};
172
173/* Bit-pattern for quiet NaN */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000174static TRIO_CONST unsigned char ieee_754_qnan_array[] = {
Bjorn Reese45029602001-08-21 09:23:53 +0000175 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
176};
177
178
179/*************************************************************************
Bjorn Reese026d29f2002-01-19 15:40:18 +0000180 * Functions
181 */
182
183/*
Bjorn Reese45029602001-08-21 09:23:53 +0000184 * trio_make_double
185 */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000186TRIO_PRIVATE double
187trio_make_double(TRIO_CONST unsigned char *values)
Bjorn Reese45029602001-08-21 09:23:53 +0000188{
Bjorn Reese026d29f2002-01-19 15:40:18 +0000189 TRIO_VOLATILE double result;
Bjorn Reese45029602001-08-21 09:23:53 +0000190 int i;
191
192 for (i = 0; i < (int)sizeof(double); i++) {
Bjorn Reese026d29f2002-01-19 15:40:18 +0000193 ((TRIO_VOLATILE unsigned char *)&result)[TRIO_DOUBLE_INDEX(i)] = values[i];
Bjorn Reese45029602001-08-21 09:23:53 +0000194 }
195 return result;
196}
197
Bjorn Reese026d29f2002-01-19 15:40:18 +0000198/*
Bjorn Reese45029602001-08-21 09:23:53 +0000199 * trio_examine_double
200 */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000201TRIO_PRIVATE int
Bjorn Reese45029602001-08-21 09:23:53 +0000202trio_is_special_quantity(double number,
203 int *has_mantissa)
204{
205 unsigned int i;
206 unsigned char current;
207 int is_special_quantity = (1 == 1);
208
209 *has_mantissa = 0;
210
211 for (i = 0; i < (unsigned int)sizeof(double); i++) {
212 current = ((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)];
213 is_special_quantity
214 &= ((current & ieee_754_exponent_mask[i]) == ieee_754_exponent_mask[i]);
215 *has_mantissa |= (current & ieee_754_mantissa_mask[i]);
216 }
217 return is_special_quantity;
218}
219
Daniel Veillard5fc1f082002-03-27 09:05:40 +0000220/**
221 Get the sign value
222
223 @return 1 for negative, 0 for positive
224*/
225TRIO_PUBLIC int
226trio_get_sign(double number)
227{
228 unsigned int i;
229 unsigned char current;
230 int sign = (1 == 1);
231
232 for (i = 0; i < (unsigned int)sizeof(double); i++) {
233 current = ((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)];
234 sign
235 &= ((current & ieee_754_sign_mask[i]) == ieee_754_sign_mask[i]);
236 }
237 return sign;
238}
239
240/**
241 Generate negative zero
242
243 @return Floating-point representation of negative zero.
244*/
245TRIO_PUBLIC double
246trio_nzero(void)
247{
248 return trio_make_double(ieee_754_negzero_array);
249}
250
Bjorn Reese45029602001-08-21 09:23:53 +0000251#endif /* USE_IEEE_754 */
252
253
Bjorn Reese026d29f2002-01-19 15:40:18 +0000254/**
255 Generate positive infinity.
256
257 @return Floating-point representation of positive infinity.
258*/
Daniel Veillardcda96922001-08-21 10:56:31 +0000259TRIO_PUBLIC double
Bjorn Reese45029602001-08-21 09:23:53 +0000260trio_pinf(void)
261{
262 /* Cache the result */
263 static double result = 0.0;
264
265 if (result == 0.0) {
266
267#if defined(INFINITY) && defined(__STDC_IEC_559__)
268 result = (double)INFINITY;
269
270#elif defined(USE_IEEE_754)
271 result = trio_make_double(ieee_754_infinity_array);
272
273#else
274 /*
275 * If HUGE_VAL is different from DBL_MAX, then HUGE_VAL is used
276 * as infinity. Otherwise we have to resort to an overflow
277 * operation to generate infinity.
278 */
279# if defined(TRIO_PLATFORM_UNIX)
280 void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
281# endif
282
283 result = HUGE_VAL;
284 if (HUGE_VAL == DBL_MAX) {
285 /* Force overflow */
286 result += HUGE_VAL;
287 }
288
289# if defined(TRIO_PLATFORM_UNIX)
290 signal(SIGFPE, signal_handler);
291# endif
292
293#endif
294 }
295 return result;
296}
297
Bjorn Reese026d29f2002-01-19 15:40:18 +0000298/**
299 Generate negative infinity.
300
301 @return Floating-point value of negative infinity.
302*/
Daniel Veillardcda96922001-08-21 10:56:31 +0000303TRIO_PUBLIC double
Bjorn Reese45029602001-08-21 09:23:53 +0000304trio_ninf(void)
305{
306 static double result = 0.0;
307
308 if (result == 0.0) {
309 /*
310 * Negative infinity is calculated by negating positive infinity,
311 * which can be done because it is legal to do calculations on
312 * infinity (for example, 1 / infinity == 0).
313 */
314 result = -trio_pinf();
315 }
316 return result;
317}
318
Bjorn Reese026d29f2002-01-19 15:40:18 +0000319/**
320 Generate NaN.
321
322 @return Floating-point representation of NaN.
323*/
Daniel Veillardcda96922001-08-21 10:56:31 +0000324TRIO_PUBLIC double
Bjorn Reese45029602001-08-21 09:23:53 +0000325trio_nan(void)
326{
327 /* Cache the result */
328 static double result = 0.0;
329
330 if (result == 0.0) {
331
332#if defined(TRIO_COMPILER_SUPPORTS_C99)
333 result = nan(NULL);
334
335#elif defined(NAN) && defined(__STDC_IEC_559__)
336 result = (double)NAN;
337
338#elif defined(USE_IEEE_754)
339 result = trio_make_double(ieee_754_qnan_array);
340
341#else
342 /*
343 * There are several ways to generate NaN. The one used here is
344 * to divide infinity by infinity. I would have preferred to add
345 * negative infinity to positive infinity, but that yields wrong
346 * result (infinity) on FreeBSD.
347 *
348 * This may fail if the hardware does not support NaN, or if
349 * the Invalid Operation floating-point exception is unmasked.
350 */
351# if defined(TRIO_PLATFORM_UNIX)
352 void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
353# endif
354
355 result = trio_pinf() / trio_pinf();
356
357# if defined(TRIO_PLATFORM_UNIX)
358 signal(SIGFPE, signal_handler);
359# endif
360
361#endif
362 }
363 return result;
364}
365
Bjorn Reese026d29f2002-01-19 15:40:18 +0000366/**
367 Check for NaN.
368
369 @param number An arbitrary floating-point number.
370 @return Boolean value indicating whether or not the number is a NaN.
371*/
Daniel Veillardcda96922001-08-21 10:56:31 +0000372TRIO_PUBLIC int
Bjorn Reese026d29f2002-01-19 15:40:18 +0000373trio_isnan(TRIO_VOLATILE double number)
Bjorn Reese45029602001-08-21 09:23:53 +0000374{
375#if defined(isnan) || defined(TRIO_COMPILER_SUPPORTS_UNIX95)
376 /*
377 * C99 defines isnan() as a macro. UNIX95 defines isnan() as a
378 * function. This function was already present in XPG4, but this
379 * is a bit tricky to detect with compiler defines, so we choose
380 * the conservative approach and only use it for UNIX95.
381 */
382 return isnan(number);
383
384#elif defined(TRIO_COMPILER_MSVC)
385 /*
386 * MSC has an _isnan() function
387 */
388 return _isnan(number);
389
390#elif defined(USE_IEEE_754)
391 /*
392 * Examine IEEE 754 bit-pattern. A NaN must have a special exponent
393 * pattern, and a non-empty mantissa.
394 */
395 int has_mantissa;
396 int is_special_quantity;
397
398 is_special_quantity = trio_is_special_quantity(number, &has_mantissa);
399
400 return (is_special_quantity && has_mantissa);
401
402#else
403 /*
404 * Fallback solution
405 */
406 int status;
407 double integral, fraction;
408
409# if defined(TRIO_PLATFORM_UNIX)
410 void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
411# endif
412
413 status = (/*
414 * NaN is the only number which does not compare to itself
415 */
416 (number != number) ||
417 /*
418 * Fallback solution if NaN compares to NaN
419 */
420 ((number != 0.0) &&
421 (fraction = modf(number, &integral),
422 integral == fraction)));
423
424# if defined(TRIO_PLATFORM_UNIX)
425 signal(SIGFPE, signal_handler);
426# endif
427
428 return status;
429
430#endif
431}
432
Bjorn Reese026d29f2002-01-19 15:40:18 +0000433/**
434 Check for infinity.
435
436 @param number An arbitrary floating-point number.
437 @return 1 if positive infinity, -1 if negative infinity, 0 otherwise.
438*/
Daniel Veillardcda96922001-08-21 10:56:31 +0000439TRIO_PUBLIC int
Bjorn Reese026d29f2002-01-19 15:40:18 +0000440trio_isinf(TRIO_VOLATILE double number)
Bjorn Reese45029602001-08-21 09:23:53 +0000441{
442#if defined(TRIO_COMPILER_DECC)
443 /*
444 * DECC has an isinf() macro, but it works differently than that
445 * of C99, so we use the fp_class() function instead.
446 */
447 return ((fp_class(number) == FP_POS_INF)
448 ? 1
449 : ((fp_class(number) == FP_NEG_INF) ? -1 : 0));
450
451#elif defined(isinf)
452 /*
453 * C99 defines isinf() as a macro.
454 */
455 return isinf(number);
456
457#elif defined(TRIO_COMPILER_MSVC)
458 /*
459 * MSVC has an _fpclass() function that can be used to detect infinity.
460 */
461 return ((_fpclass(number) == _FPCLASS_PINF)
462 ? 1
463 : ((_fpclass(number) == _FPCLASS_NINF) ? -1 : 0));
464
465#elif defined(USE_IEEE_754)
466 /*
467 * Examine IEEE 754 bit-pattern. Infinity must have a special exponent
468 * pattern, and an empty mantissa.
469 */
470 int has_mantissa;
471 int is_special_quantity;
472
473 is_special_quantity = trio_is_special_quantity(number, &has_mantissa);
474
475 return (is_special_quantity && !has_mantissa)
476 ? ((number < 0.0) ? -1 : 1)
477 : 0;
478
479#else
480 /*
481 * Fallback solution.
482 */
483 int status;
484
485# if defined(TRIO_PLATFORM_UNIX)
486 void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
487# endif
488
489 double infinity = trio_pinf();
490
491 status = ((number == infinity)
492 ? 1
493 : ((number == -infinity) ? -1 : 0));
494
495# if defined(TRIO_PLATFORM_UNIX)
496 signal(SIGFPE, signal_handler);
497# endif
498
499 return status;
500
501#endif
502}
503
Bjorn Reese026d29f2002-01-19 15:40:18 +0000504/** @} SpecialQuantities */
505
Bjorn Reese45029602001-08-21 09:23:53 +0000506/*************************************************************************
Bjorn Reese026d29f2002-01-19 15:40:18 +0000507 * For test purposes.
508 *
509 * Add the following compiler option to include this test code.
510 *
511 * Unix : -DSTANDALONE
512 * VMS : /DEFINE=(STANDALONE)
Bjorn Reese45029602001-08-21 09:23:53 +0000513 */
514#if defined(STANDALONE)
515# include <stdio.h>
516
517int main(void)
518{
519 double my_nan;
520 double my_pinf;
521 double my_ninf;
522# if defined(TRIO_PLATFORM_UNIX)
523 void (*signal_handler)(int);
524# endif
525
526 my_nan = trio_nan();
527 my_pinf = trio_pinf();
528 my_ninf = trio_ninf();
529
530 printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
531 my_nan,
532 ((unsigned char *)&my_nan)[0],
533 ((unsigned char *)&my_nan)[1],
534 ((unsigned char *)&my_nan)[2],
535 ((unsigned char *)&my_nan)[3],
536 ((unsigned char *)&my_nan)[4],
537 ((unsigned char *)&my_nan)[5],
538 ((unsigned char *)&my_nan)[6],
539 ((unsigned char *)&my_nan)[7],
540 trio_isnan(my_nan), trio_isinf(my_nan));
541 printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
542 my_pinf,
543 ((unsigned char *)&my_pinf)[0],
544 ((unsigned char *)&my_pinf)[1],
545 ((unsigned char *)&my_pinf)[2],
546 ((unsigned char *)&my_pinf)[3],
547 ((unsigned char *)&my_pinf)[4],
548 ((unsigned char *)&my_pinf)[5],
549 ((unsigned char *)&my_pinf)[6],
550 ((unsigned char *)&my_pinf)[7],
551 trio_isnan(my_pinf), trio_isinf(my_pinf));
552 printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
553 my_ninf,
554 ((unsigned char *)&my_ninf)[0],
555 ((unsigned char *)&my_ninf)[1],
556 ((unsigned char *)&my_ninf)[2],
557 ((unsigned char *)&my_ninf)[3],
558 ((unsigned char *)&my_ninf)[4],
559 ((unsigned char *)&my_ninf)[5],
560 ((unsigned char *)&my_ninf)[6],
561 ((unsigned char *)&my_ninf)[7],
562 trio_isnan(my_ninf), trio_isinf(my_ninf));
563
564# if defined(TRIO_PLATFORM_UNIX)
565 signal_handler = signal(SIGFPE, SIG_IGN);
566# endif
567
568 my_pinf = DBL_MAX + DBL_MAX;
569 my_ninf = -my_pinf;
570 my_nan = my_pinf / my_pinf;
571
572# if defined(TRIO_PLATFORM_UNIX)
573 signal(SIGFPE, signal_handler);
574# endif
575
576 printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
577 my_nan,
578 ((unsigned char *)&my_nan)[0],
579 ((unsigned char *)&my_nan)[1],
580 ((unsigned char *)&my_nan)[2],
581 ((unsigned char *)&my_nan)[3],
582 ((unsigned char *)&my_nan)[4],
583 ((unsigned char *)&my_nan)[5],
584 ((unsigned char *)&my_nan)[6],
585 ((unsigned char *)&my_nan)[7],
586 trio_isnan(my_nan), trio_isinf(my_nan));
587 printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
588 my_pinf,
589 ((unsigned char *)&my_pinf)[0],
590 ((unsigned char *)&my_pinf)[1],
591 ((unsigned char *)&my_pinf)[2],
592 ((unsigned char *)&my_pinf)[3],
593 ((unsigned char *)&my_pinf)[4],
594 ((unsigned char *)&my_pinf)[5],
595 ((unsigned char *)&my_pinf)[6],
596 ((unsigned char *)&my_pinf)[7],
597 trio_isnan(my_pinf), trio_isinf(my_pinf));
598 printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
599 my_ninf,
600 ((unsigned char *)&my_ninf)[0],
601 ((unsigned char *)&my_ninf)[1],
602 ((unsigned char *)&my_ninf)[2],
603 ((unsigned char *)&my_ninf)[3],
604 ((unsigned char *)&my_ninf)[4],
605 ((unsigned char *)&my_ninf)[5],
606 ((unsigned char *)&my_ninf)[6],
607 ((unsigned char *)&my_ninf)[7],
608 trio_isnan(my_ninf), trio_isinf(my_ninf));
609
610 return 0;
611}
612#endif