blob: 6f67c5bed6fa7e4466bdfee5f9d3cd5eb4b531e9 [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
Daniel Veillard21458c82002-03-27 16:12:22 +000096#define TRIO_TRUE (1 == 1)
97#define TRIO_FALSE (0 == 1)
98
Bjorn Reese45029602001-08-21 09:23:53 +000099/* We must enable IEEE floating-point on Alpha */
100#if defined(__alpha) && !defined(_IEEE_FP)
101# if defined(TRIO_COMPILER_DECC)
Bjorn Reese026d29f2002-01-19 15:40:18 +0000102# if defined(TRIO_PLATFORM_VMS)
103# error "Must be compiled with option /IEEE_MODE=UNDERFLOW_TO_ZERO/FLOAT=IEEE"
104# else
105# error "Must be compiled with option -ieee"
106# endif
Bjorn Reese45029602001-08-21 09:23:53 +0000107# elif defined(TRIO_COMPILER_GCC) && (defined(__osf__) || defined(__linux__))
108# error "Must be compiled with option -mieee"
109# endif
110#endif /* __alpha && ! _IEEE_FP */
111
112/*
113 * In ANSI/IEEE 754-1985 64-bits double format numbers have the
114 * following properties (amoungst others)
115 *
116 * o FLT_RADIX == 2: binary encoding
117 * o DBL_MAX_EXP == 1024: 11 bits exponent, where one bit is used
118 * to indicate special numbers (e.g. NaN and Infinity), so the
119 * maximum exponent is 10 bits wide (2^10 == 1024).
120 * o DBL_MANT_DIG == 53: The mantissa is 52 bits wide, but because
121 * numbers are normalized the initial binary 1 is represented
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000122 * implicitly (the so-called "hidden bit"), which leaves us with
Bjorn Reese45029602001-08-21 09:23:53 +0000123 * the ability to represent 53 bits wide mantissa.
124 */
125#if (FLT_RADIX == 2) && (DBL_MAX_EXP == 1024) && (DBL_MANT_DIG == 53)
126# define USE_IEEE_754
127#endif
128
129
130/*************************************************************************
131 * Data
132 */
133
134#if defined(USE_IEEE_754)
135
136/*
137 * Endian-agnostic indexing macro.
138 *
139 * The value of internalEndianMagic, when converted into a 64-bit
Bjorn Reese026d29f2002-01-19 15:40:18 +0000140 * integer, becomes 0x0706050403020100 (we could have used a 64-bit
Bjorn Reese45029602001-08-21 09:23:53 +0000141 * integer value instead of a double, but not all platforms supports
142 * that type). The value is automatically encoded with the correct
143 * endianess by the compiler, which means that we can support any
144 * kind of endianess. The individual bytes are then used as an index
145 * for the IEEE 754 bit-patterns and masks.
146 */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000147#define TRIO_DOUBLE_INDEX(x) (((unsigned char *)&internalEndianMagic)[7-(x)])
Bjorn Reese45029602001-08-21 09:23:53 +0000148
Bjorn Reese026d29f2002-01-19 15:40:18 +0000149static TRIO_CONST double internalEndianMagic = 7.949928895127363e-275;
Bjorn Reese45029602001-08-21 09:23:53 +0000150
151/* Mask for the exponent */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000152static TRIO_CONST unsigned char ieee_754_exponent_mask[] = {
Bjorn Reese45029602001-08-21 09:23:53 +0000153 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
154};
155
156/* Mask for the mantissa */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000157static TRIO_CONST unsigned char ieee_754_mantissa_mask[] = {
Bjorn Reese45029602001-08-21 09:23:53 +0000158 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
159};
160
Daniel Veillard21458c82002-03-27 16:12:22 +0000161/* Mask for the sign bit */
162static TRIO_CONST unsigned char ieee_754_sign_mask[] = {
163 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
164};
165
Daniel Veillard5fc1f082002-03-27 09:05:40 +0000166/* Bit-pattern for negative zero */
167static TRIO_CONST unsigned char ieee_754_negzero_array[] = {
168 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
169};
170
Bjorn Reese45029602001-08-21 09:23:53 +0000171/* Bit-pattern for infinity */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000172static TRIO_CONST unsigned char ieee_754_infinity_array[] = {
Bjorn Reese45029602001-08-21 09:23:53 +0000173 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
174};
175
176/* Bit-pattern for quiet NaN */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000177static TRIO_CONST unsigned char ieee_754_qnan_array[] = {
Bjorn Reese45029602001-08-21 09:23:53 +0000178 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
179};
180
181
182/*************************************************************************
Bjorn Reese026d29f2002-01-19 15:40:18 +0000183 * Functions
184 */
185
186/*
Bjorn Reese45029602001-08-21 09:23:53 +0000187 * trio_make_double
188 */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000189TRIO_PRIVATE double
190trio_make_double(TRIO_CONST unsigned char *values)
Bjorn Reese45029602001-08-21 09:23:53 +0000191{
Bjorn Reese026d29f2002-01-19 15:40:18 +0000192 TRIO_VOLATILE double result;
Bjorn Reese45029602001-08-21 09:23:53 +0000193 int i;
194
195 for (i = 0; i < (int)sizeof(double); i++) {
Bjorn Reese026d29f2002-01-19 15:40:18 +0000196 ((TRIO_VOLATILE unsigned char *)&result)[TRIO_DOUBLE_INDEX(i)] = values[i];
Bjorn Reese45029602001-08-21 09:23:53 +0000197 }
198 return result;
199}
200
Bjorn Reese026d29f2002-01-19 15:40:18 +0000201/*
Daniel Veillard21458c82002-03-27 16:12:22 +0000202 * trio_is_special_quantity
Bjorn Reese45029602001-08-21 09:23:53 +0000203 */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000204TRIO_PRIVATE int
Bjorn Reese45029602001-08-21 09:23:53 +0000205trio_is_special_quantity(double number,
206 int *has_mantissa)
207{
208 unsigned int i;
209 unsigned char current;
Daniel Veillard21458c82002-03-27 16:12:22 +0000210 int is_special_quantity = TRIO_TRUE;
Bjorn Reese45029602001-08-21 09:23:53 +0000211
212 *has_mantissa = 0;
213
214 for (i = 0; i < (unsigned int)sizeof(double); i++) {
215 current = ((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)];
216 is_special_quantity
217 &= ((current & ieee_754_exponent_mask[i]) == ieee_754_exponent_mask[i]);
218 *has_mantissa |= (current & ieee_754_mantissa_mask[i]);
219 }
220 return is_special_quantity;
221}
222
Daniel Veillard21458c82002-03-27 16:12:22 +0000223/*
224 * trio_is_negative
225 */
226TRIO_PRIVATE int
227trio_is_negative(double number)
Daniel Veillard5fc1f082002-03-27 09:05:40 +0000228{
229 unsigned int i;
Daniel Veillard21458c82002-03-27 16:12:22 +0000230 int is_negative = TRIO_FALSE;
Daniel Veillard5fc1f082002-03-27 09:05:40 +0000231
232 for (i = 0; i < (unsigned int)sizeof(double); i++) {
Daniel Veillard21458c82002-03-27 16:12:22 +0000233 is_negative |= (((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)]
234 & ieee_754_sign_mask[i]);
Daniel Veillard5fc1f082002-03-27 09:05:40 +0000235 }
Daniel Veillard21458c82002-03-27 16:12:22 +0000236 return is_negative;
Daniel Veillard5fc1f082002-03-27 09:05:40 +0000237}
238
Daniel Veillard5fc1f082002-03-27 09:05:40 +0000239TRIO_PUBLIC double
Daniel Veillard21458c82002-03-27 16:12:22 +0000240trio_nzero(void)
Daniel Veillard5fc1f082002-03-27 09:05:40 +0000241{
242 return trio_make_double(ieee_754_negzero_array);
243}
244
Bjorn Reese45029602001-08-21 09:23:53 +0000245#endif /* USE_IEEE_754 */
246
247
Bjorn Reese026d29f2002-01-19 15:40:18 +0000248/**
249 Generate positive infinity.
250
251 @return Floating-point representation of positive infinity.
252*/
Daniel Veillardcda96922001-08-21 10:56:31 +0000253TRIO_PUBLIC double
Bjorn Reese45029602001-08-21 09:23:53 +0000254trio_pinf(void)
255{
256 /* Cache the result */
257 static double result = 0.0;
258
259 if (result == 0.0) {
260
261#if defined(INFINITY) && defined(__STDC_IEC_559__)
262 result = (double)INFINITY;
263
264#elif defined(USE_IEEE_754)
265 result = trio_make_double(ieee_754_infinity_array);
266
267#else
268 /*
269 * If HUGE_VAL is different from DBL_MAX, then HUGE_VAL is used
270 * as infinity. Otherwise we have to resort to an overflow
271 * operation to generate infinity.
272 */
273# if defined(TRIO_PLATFORM_UNIX)
274 void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
275# endif
276
277 result = HUGE_VAL;
278 if (HUGE_VAL == DBL_MAX) {
279 /* Force overflow */
280 result += HUGE_VAL;
281 }
282
283# if defined(TRIO_PLATFORM_UNIX)
284 signal(SIGFPE, signal_handler);
285# endif
286
287#endif
288 }
289 return result;
290}
291
Bjorn Reese026d29f2002-01-19 15:40:18 +0000292/**
293 Generate negative infinity.
294
295 @return Floating-point value of negative infinity.
296*/
Daniel Veillardcda96922001-08-21 10:56:31 +0000297TRIO_PUBLIC double
Bjorn Reese45029602001-08-21 09:23:53 +0000298trio_ninf(void)
299{
300 static double result = 0.0;
301
302 if (result == 0.0) {
303 /*
304 * Negative infinity is calculated by negating positive infinity,
305 * which can be done because it is legal to do calculations on
306 * infinity (for example, 1 / infinity == 0).
307 */
308 result = -trio_pinf();
309 }
310 return result;
311}
312
Bjorn Reese026d29f2002-01-19 15:40:18 +0000313/**
314 Generate NaN.
315
316 @return Floating-point representation of NaN.
317*/
Daniel Veillardcda96922001-08-21 10:56:31 +0000318TRIO_PUBLIC double
Bjorn Reese45029602001-08-21 09:23:53 +0000319trio_nan(void)
320{
321 /* Cache the result */
322 static double result = 0.0;
323
324 if (result == 0.0) {
325
326#if defined(TRIO_COMPILER_SUPPORTS_C99)
Bjorn Reese54d02fb2002-04-19 15:16:01 +0000327 result = nan("");
Bjorn Reese45029602001-08-21 09:23:53 +0000328
329#elif defined(NAN) && defined(__STDC_IEC_559__)
330 result = (double)NAN;
331
332#elif defined(USE_IEEE_754)
333 result = trio_make_double(ieee_754_qnan_array);
334
335#else
336 /*
337 * There are several ways to generate NaN. The one used here is
338 * to divide infinity by infinity. I would have preferred to add
339 * negative infinity to positive infinity, but that yields wrong
340 * result (infinity) on FreeBSD.
341 *
342 * This may fail if the hardware does not support NaN, or if
343 * the Invalid Operation floating-point exception is unmasked.
344 */
345# if defined(TRIO_PLATFORM_UNIX)
346 void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
347# endif
348
349 result = trio_pinf() / trio_pinf();
350
351# if defined(TRIO_PLATFORM_UNIX)
352 signal(SIGFPE, signal_handler);
353# endif
354
355#endif
356 }
357 return result;
358}
359
Bjorn Reese026d29f2002-01-19 15:40:18 +0000360/**
361 Check for NaN.
362
363 @param number An arbitrary floating-point number.
364 @return Boolean value indicating whether or not the number is a NaN.
365*/
Daniel Veillardcda96922001-08-21 10:56:31 +0000366TRIO_PUBLIC int
Bjorn Reese026d29f2002-01-19 15:40:18 +0000367trio_isnan(TRIO_VOLATILE double number)
Bjorn Reese45029602001-08-21 09:23:53 +0000368{
369#if defined(isnan) || defined(TRIO_COMPILER_SUPPORTS_UNIX95)
370 /*
371 * C99 defines isnan() as a macro. UNIX95 defines isnan() as a
372 * function. This function was already present in XPG4, but this
373 * is a bit tricky to detect with compiler defines, so we choose
374 * the conservative approach and only use it for UNIX95.
375 */
376 return isnan(number);
377
378#elif defined(TRIO_COMPILER_MSVC)
379 /*
Daniel Veillard21458c82002-03-27 16:12:22 +0000380 * MSVC has an _isnan() function
Bjorn Reese45029602001-08-21 09:23:53 +0000381 */
382 return _isnan(number);
383
384#elif defined(USE_IEEE_754)
385 /*
386 * Examine IEEE 754 bit-pattern. A NaN must have a special exponent
387 * pattern, and a non-empty mantissa.
388 */
389 int has_mantissa;
390 int is_special_quantity;
391
392 is_special_quantity = trio_is_special_quantity(number, &has_mantissa);
393
394 return (is_special_quantity && has_mantissa);
395
396#else
397 /*
398 * Fallback solution
399 */
400 int status;
401 double integral, fraction;
402
403# if defined(TRIO_PLATFORM_UNIX)
404 void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
405# endif
406
407 status = (/*
408 * NaN is the only number which does not compare to itself
409 */
410 (number != number) ||
411 /*
412 * Fallback solution if NaN compares to NaN
413 */
414 ((number != 0.0) &&
415 (fraction = modf(number, &integral),
416 integral == fraction)));
417
418# if defined(TRIO_PLATFORM_UNIX)
419 signal(SIGFPE, signal_handler);
420# endif
421
422 return status;
423
424#endif
425}
426
Bjorn Reese026d29f2002-01-19 15:40:18 +0000427/**
428 Check for infinity.
429
430 @param number An arbitrary floating-point number.
431 @return 1 if positive infinity, -1 if negative infinity, 0 otherwise.
432*/
Daniel Veillardcda96922001-08-21 10:56:31 +0000433TRIO_PUBLIC int
Bjorn Reese026d29f2002-01-19 15:40:18 +0000434trio_isinf(TRIO_VOLATILE double number)
Bjorn Reese45029602001-08-21 09:23:53 +0000435{
436#if defined(TRIO_COMPILER_DECC)
437 /*
438 * DECC has an isinf() macro, but it works differently than that
439 * of C99, so we use the fp_class() function instead.
440 */
441 return ((fp_class(number) == FP_POS_INF)
442 ? 1
443 : ((fp_class(number) == FP_NEG_INF) ? -1 : 0));
444
445#elif defined(isinf)
446 /*
447 * C99 defines isinf() as a macro.
448 */
449 return isinf(number);
450
451#elif defined(TRIO_COMPILER_MSVC)
452 /*
453 * MSVC has an _fpclass() function that can be used to detect infinity.
454 */
455 return ((_fpclass(number) == _FPCLASS_PINF)
456 ? 1
457 : ((_fpclass(number) == _FPCLASS_NINF) ? -1 : 0));
458
459#elif defined(USE_IEEE_754)
460 /*
461 * Examine IEEE 754 bit-pattern. Infinity must have a special exponent
462 * pattern, and an empty mantissa.
463 */
464 int has_mantissa;
465 int is_special_quantity;
466
467 is_special_quantity = trio_is_special_quantity(number, &has_mantissa);
468
469 return (is_special_quantity && !has_mantissa)
470 ? ((number < 0.0) ? -1 : 1)
471 : 0;
472
473#else
474 /*
475 * Fallback solution.
476 */
477 int status;
478
479# if defined(TRIO_PLATFORM_UNIX)
480 void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
481# endif
482
483 double infinity = trio_pinf();
484
485 status = ((number == infinity)
486 ? 1
487 : ((number == -infinity) ? -1 : 0));
488
489# if defined(TRIO_PLATFORM_UNIX)
490 signal(SIGFPE, signal_handler);
491# endif
492
493 return status;
494
495#endif
496}
497
Daniel Veillard21458c82002-03-27 16:12:22 +0000498
499/**
500 Check for finity.
501
502 @param number An arbitrary floating-point number.
503 @return Boolean value indicating whether or not the number is a finite.
504*/
505TRIO_PUBLIC int
506trio_isfinite(TRIO_VOLATILE double number)
507{
508#if defined(isfinite)
509 /*
510 * C99 defines isfinite() as a macro.
511 */
512 return isfinite(number);
513
514#elif defined(TRIO_COMPILER_MSVC)
515 /*
516 * MSVC uses _finite().
517 */
518 return _finite(number);
519
520#elif defined(USE_IEEE_754)
521 /*
522 * Examine IEEE 754 bit-pattern. For finity we do not care about the
523 * mantissa.
524 */
525 int dummy;
526
527 return (! trio_is_special_quantity(number, &dummy));
528
529#else
530 /*
531 * Fallback solution.
532 */
533 return ((trio_isinf(number) == 0) && (trio_isnan(number) == 0));
534
535#endif
536}
537
538/*
539 * The sign of NaN is always false
540 */
541TRIO_PRIVATE int
542trio_fpclass(TRIO_VOLATILE double number,
543 int *is_negative)
544{
545#if defined(fpclassify) && defined(signbit)
546 /*
547 * C99 defines fpclassify() and signbit() as a macros
548 */
549 *is_negative = signbit(number);
550 switch (fpclassify(number)) {
551 case FP_NAN:
552 return TRIO_FP_NAN;
553 case FP_INFINITE:
554 return TRIO_FP_INFINITE;
555 case FP_SUBNORMAL:
556 return TRIO_FP_SUBNORMAL;
557 case FP_ZERO:
558 return TRIO_FP_ZERO;
559 default:
560 return TRIO_FP_NORMAL;
561 }
562
563#elif defined(TRIO_COMPILER_DECC)
564 /*
565 * DECC has an fp_class() function.
566 */
567 switch (fp_class(number)) {
568 case FP_QNAN:
569 case FP_SNAN:
570 *is_negative = TRIO_FALSE; /* NaN has no sign */
571 return TRIO_FP_NAN;
572 case FP_POS_INF:
573 *is_negative = TRIO_FALSE;
574 return TRIO_FP_INFINITE;
575 case FP_NEG_INF:
576 *is_negative = TRIO_TRUE;
577 return TRIO_FP_INFINITE;
578 case FP_POS_DENORM:
579 *is_negative = TRIO_FALSE;
580 return TRIO_FP_SUBNORMAL;
581 case FP_NEG_DENORM:
582 *is_negative = TRIO_TRUE;
583 return TRIO_FP_SUBNORMAL;
584 case FP_POS_ZERO:
585 *is_negative = TRIO_FALSE;
586 return TRIO_FP_ZERO;
587 case FP_NEG_ZERO:
588 *is_negative = TRIO_TRUE;
589 return TRIO_FP_ZERO;
590 case FP_POS_NORM:
591 *is_negative = TRIO_FALSE;
592 return TRIO_FP_NORMAL;
593 case FP_NEG_NORM:
594 *is_negative = TRIO_TRUE;
595 return TRIO_FP_NORMAL;
596 default:
597 /* Just in case... */
598 *is_negative = (number < 0.0);
599 return TRIO_FP_NORMAL;
600 }
601
602#elif defined(TRIO_COMPILER_MSVC)
603 /*
604 * MSVC has an _fpclass() function.
605 */
606 switch (_fpclass(number)) {
607 case _FPCLASS_QNAN:
608 case _FPCLASS_SNAN:
609 *is_negative = TRIO_FALSE;
610 return TRIO_FP_NAN;
611 case _FPCLASS_PINF:
612 *is_negative = TRIO_FALSE;
613 return TRIO_FP_INFINITE;
614 case _FPCLASS_NINF:
615 *is_negative = TRIO_TRUE;
616 return TRIO_FP_INFINITE;
617 case _FPCLASS_PD:
618 *is_negative = TRIO_FALSE;
619 return TRIO_FP_SUBNORMAL;
620 case _FPCLASS_ND:
621 *is_negative = TRIO_TRUE;
622 return TRIO_FP_SUBNORMAL;
623 case _FPCLASS_PZ:
624 *is_negative = TRIO_FALSE;
625 return TRIO_FP_ZERO;
626 case _FPCLASS_NZ:
627 *is_negative = TRIO_TRUE;
628 return TRIO_FP_ZERO;
629 case _FPCLASS_PN:
630 *is_negative = TRIO_FALSE;
631 return TRIO_FP_NORMAL;
632 case _FPCLASS_NN:
633 *is_negative = TRIO_TRUE;
634 return TRIO_FP_NORMAL;
635 default:
636 /* Just in case... */
637 *is_negative = (number < 0.0);
638 return TRIO_FP_NORMAL;
639 }
640
641#else
642 /*
643 * Fallback solution.
644 */
645 int rc;
646
647 if (number == 0.0) {
648 /*
649 * In IEEE 754 the sign of zero is ignored in comparisons, so we
650 * have to handle this as a special case by examining the sign bit
651 * directly.
652 */
653#if defined(USE_IEEE_754)
654 *is_negative = trio_is_negative(number);
655#else
656 *is_negative = TRIO_FALSE; /* FIXME */
657#endif
658 return TRIO_FP_ZERO;
659 }
660 if (trio_isnan(number)) {
661 *is_negative = TRIO_FALSE;
662 return TRIO_FP_NAN;
663 }
664 if ((rc = trio_isinf(number))) {
665 *is_negative = (rc == -1);
666 return TRIO_FP_INFINITE;
667 }
668 if ((number > 0.0) && (number < DBL_MIN)) {
669 *is_negative = TRIO_FALSE;
670 return TRIO_FP_SUBNORMAL;
671 }
672 if ((number < 0.0) && (number > -DBL_MIN)) {
673 *is_negative = TRIO_TRUE;
674 return TRIO_FP_SUBNORMAL;
675 }
676 *is_negative = (number < 0.0);
677 return TRIO_FP_NORMAL;
678
679#endif
680}
681
682/**
683 Examine the sign of a number.
684
685 @param number An arbitrary floating-point number.
686 @return Boolean value indicating whether or not the number has the
687 sign bit set (i.e. is negative).
688*/
689TRIO_PUBLIC int
690trio_signbit(TRIO_VOLATILE double number)
691{
692 int is_negative;
693
694 (void)trio_fpclass(number, &is_negative);
695 return is_negative;
696}
697
698/**
699 Examine the class of a number.
700
701 @param number An arbitrary floating-point number.
702 @return Enumerable value indicating the class of @p number
703*/
704TRIO_PUBLIC int
705trio_fpclassify(TRIO_VOLATILE double number)
706{
707 int dummy;
708
709 return trio_fpclass(number, &dummy);
710}
711
712
Bjorn Reese026d29f2002-01-19 15:40:18 +0000713/** @} SpecialQuantities */
714
Bjorn Reese45029602001-08-21 09:23:53 +0000715/*************************************************************************
Bjorn Reese026d29f2002-01-19 15:40:18 +0000716 * For test purposes.
717 *
718 * Add the following compiler option to include this test code.
719 *
720 * Unix : -DSTANDALONE
721 * VMS : /DEFINE=(STANDALONE)
Bjorn Reese45029602001-08-21 09:23:53 +0000722 */
723#if defined(STANDALONE)
724# include <stdio.h>
725
Daniel Veillard21458c82002-03-27 16:12:22 +0000726static const char *getClassification(int type)
727{
728 switch (type) {
729 case TRIO_FP_INFINITE:
730 return "FP_INFINITE";
731 case TRIO_FP_NAN:
732 return "FP_NAN";
733 case TRIO_FP_NORMAL:
734 return "FP_NORMAL";
735 case TRIO_FP_SUBNORMAL:
736 return "FP_SUBNORMAL";
737 case TRIO_FP_ZERO:
738 return "FP_ZERO";
739 default:
740 return "FP_UNKNOWN";
741 }
742}
743
744static void print_class(const char *prefix, double number)
745{
746 printf("%-6s: %s %-15s %g\n",
747 prefix,
748 trio_signbit(number) ? "-" : "+",
749 getClassification(trio_fpclassify(number)),
750 number);
751}
752
Bjorn Reese45029602001-08-21 09:23:53 +0000753int main(void)
754{
755 double my_nan;
756 double my_pinf;
757 double my_ninf;
758# if defined(TRIO_PLATFORM_UNIX)
759 void (*signal_handler)(int);
760# endif
761
762 my_nan = trio_nan();
763 my_pinf = trio_pinf();
764 my_ninf = trio_ninf();
765
Daniel Veillard21458c82002-03-27 16:12:22 +0000766 print_class("Nan", my_nan);
767 print_class("PInf", my_pinf);
768 print_class("NInf", my_ninf);
769 print_class("PZero", 0.0);
770 print_class("NZero", -0.0);
771 print_class("PNorm", 1.0);
772 print_class("NNorm", -1.0);
773 print_class("PSub", 1.01e-307 - 1.00e-307);
774 print_class("NSub", 1.00e-307 - 1.01e-307);
775
Bjorn Reese45029602001-08-21 09:23:53 +0000776 printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
777 my_nan,
778 ((unsigned char *)&my_nan)[0],
779 ((unsigned char *)&my_nan)[1],
780 ((unsigned char *)&my_nan)[2],
781 ((unsigned char *)&my_nan)[3],
782 ((unsigned char *)&my_nan)[4],
783 ((unsigned char *)&my_nan)[5],
784 ((unsigned char *)&my_nan)[6],
785 ((unsigned char *)&my_nan)[7],
786 trio_isnan(my_nan), trio_isinf(my_nan));
787 printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
788 my_pinf,
789 ((unsigned char *)&my_pinf)[0],
790 ((unsigned char *)&my_pinf)[1],
791 ((unsigned char *)&my_pinf)[2],
792 ((unsigned char *)&my_pinf)[3],
793 ((unsigned char *)&my_pinf)[4],
794 ((unsigned char *)&my_pinf)[5],
795 ((unsigned char *)&my_pinf)[6],
796 ((unsigned char *)&my_pinf)[7],
797 trio_isnan(my_pinf), trio_isinf(my_pinf));
798 printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
799 my_ninf,
800 ((unsigned char *)&my_ninf)[0],
801 ((unsigned char *)&my_ninf)[1],
802 ((unsigned char *)&my_ninf)[2],
803 ((unsigned char *)&my_ninf)[3],
804 ((unsigned char *)&my_ninf)[4],
805 ((unsigned char *)&my_ninf)[5],
806 ((unsigned char *)&my_ninf)[6],
807 ((unsigned char *)&my_ninf)[7],
808 trio_isnan(my_ninf), trio_isinf(my_ninf));
809
810# if defined(TRIO_PLATFORM_UNIX)
811 signal_handler = signal(SIGFPE, SIG_IGN);
812# endif
813
814 my_pinf = DBL_MAX + DBL_MAX;
815 my_ninf = -my_pinf;
816 my_nan = my_pinf / my_pinf;
817
818# if defined(TRIO_PLATFORM_UNIX)
819 signal(SIGFPE, signal_handler);
820# endif
821
822 printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
823 my_nan,
824 ((unsigned char *)&my_nan)[0],
825 ((unsigned char *)&my_nan)[1],
826 ((unsigned char *)&my_nan)[2],
827 ((unsigned char *)&my_nan)[3],
828 ((unsigned char *)&my_nan)[4],
829 ((unsigned char *)&my_nan)[5],
830 ((unsigned char *)&my_nan)[6],
831 ((unsigned char *)&my_nan)[7],
832 trio_isnan(my_nan), trio_isinf(my_nan));
833 printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
834 my_pinf,
835 ((unsigned char *)&my_pinf)[0],
836 ((unsigned char *)&my_pinf)[1],
837 ((unsigned char *)&my_pinf)[2],
838 ((unsigned char *)&my_pinf)[3],
839 ((unsigned char *)&my_pinf)[4],
840 ((unsigned char *)&my_pinf)[5],
841 ((unsigned char *)&my_pinf)[6],
842 ((unsigned char *)&my_pinf)[7],
843 trio_isnan(my_pinf), trio_isinf(my_pinf));
844 printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
845 my_ninf,
846 ((unsigned char *)&my_ninf)[0],
847 ((unsigned char *)&my_ninf)[1],
848 ((unsigned char *)&my_ninf)[2],
849 ((unsigned char *)&my_ninf)[3],
850 ((unsigned char *)&my_ninf)[4],
851 ((unsigned char *)&my_ninf)[5],
852 ((unsigned char *)&my_ninf)[6],
853 ((unsigned char *)&my_ninf)[7],
854 trio_isnan(my_ninf), trio_isinf(my_ninf));
855
856 return 0;
857}
858#endif