blob: 0f70f5a316689a1b8cedcdc199a9c0867598bb28 [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
148/* Mask for the exponent */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000149static TRIO_CONST unsigned char ieee_754_exponent_mask[] = {
Bjorn Reese45029602001-08-21 09:23:53 +0000150 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
151};
152
153/* Mask for the mantissa */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000154static TRIO_CONST unsigned char ieee_754_mantissa_mask[] = {
Bjorn Reese45029602001-08-21 09:23:53 +0000155 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
156};
157
158/* Bit-pattern for infinity */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000159static TRIO_CONST unsigned char ieee_754_infinity_array[] = {
Bjorn Reese45029602001-08-21 09:23:53 +0000160 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
161};
162
163/* Bit-pattern for quiet NaN */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000164static TRIO_CONST unsigned char ieee_754_qnan_array[] = {
Bjorn Reese45029602001-08-21 09:23:53 +0000165 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
166};
167
168
169/*************************************************************************
Bjorn Reese026d29f2002-01-19 15:40:18 +0000170 * Functions
171 */
172
173/*
Bjorn Reese45029602001-08-21 09:23:53 +0000174 * trio_make_double
175 */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000176TRIO_PRIVATE double
177trio_make_double(TRIO_CONST unsigned char *values)
Bjorn Reese45029602001-08-21 09:23:53 +0000178{
Bjorn Reese026d29f2002-01-19 15:40:18 +0000179 TRIO_VOLATILE double result;
Bjorn Reese45029602001-08-21 09:23:53 +0000180 int i;
181
182 for (i = 0; i < (int)sizeof(double); i++) {
Bjorn Reese026d29f2002-01-19 15:40:18 +0000183 ((TRIO_VOLATILE unsigned char *)&result)[TRIO_DOUBLE_INDEX(i)] = values[i];
Bjorn Reese45029602001-08-21 09:23:53 +0000184 }
185 return result;
186}
187
Bjorn Reese026d29f2002-01-19 15:40:18 +0000188/*
Bjorn Reese45029602001-08-21 09:23:53 +0000189 * trio_examine_double
190 */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000191TRIO_PRIVATE int
Bjorn Reese45029602001-08-21 09:23:53 +0000192trio_is_special_quantity(double number,
193 int *has_mantissa)
194{
195 unsigned int i;
196 unsigned char current;
197 int is_special_quantity = (1 == 1);
198
199 *has_mantissa = 0;
200
201 for (i = 0; i < (unsigned int)sizeof(double); i++) {
202 current = ((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)];
203 is_special_quantity
204 &= ((current & ieee_754_exponent_mask[i]) == ieee_754_exponent_mask[i]);
205 *has_mantissa |= (current & ieee_754_mantissa_mask[i]);
206 }
207 return is_special_quantity;
208}
209
210#endif /* USE_IEEE_754 */
211
212
Bjorn Reese026d29f2002-01-19 15:40:18 +0000213/**
214 Generate positive infinity.
215
216 @return Floating-point representation of positive infinity.
217*/
Daniel Veillardcda96922001-08-21 10:56:31 +0000218TRIO_PUBLIC double
Bjorn Reese45029602001-08-21 09:23:53 +0000219trio_pinf(void)
220{
221 /* Cache the result */
222 static double result = 0.0;
223
224 if (result == 0.0) {
225
226#if defined(INFINITY) && defined(__STDC_IEC_559__)
227 result = (double)INFINITY;
228
229#elif defined(USE_IEEE_754)
230 result = trio_make_double(ieee_754_infinity_array);
231
232#else
233 /*
234 * If HUGE_VAL is different from DBL_MAX, then HUGE_VAL is used
235 * as infinity. Otherwise we have to resort to an overflow
236 * operation to generate infinity.
237 */
238# if defined(TRIO_PLATFORM_UNIX)
239 void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
240# endif
241
242 result = HUGE_VAL;
243 if (HUGE_VAL == DBL_MAX) {
244 /* Force overflow */
245 result += HUGE_VAL;
246 }
247
248# if defined(TRIO_PLATFORM_UNIX)
249 signal(SIGFPE, signal_handler);
250# endif
251
252#endif
253 }
254 return result;
255}
256
Bjorn Reese026d29f2002-01-19 15:40:18 +0000257/**
258 Generate negative infinity.
259
260 @return Floating-point value of negative infinity.
261*/
Daniel Veillardcda96922001-08-21 10:56:31 +0000262TRIO_PUBLIC double
Bjorn Reese45029602001-08-21 09:23:53 +0000263trio_ninf(void)
264{
265 static double result = 0.0;
266
267 if (result == 0.0) {
268 /*
269 * Negative infinity is calculated by negating positive infinity,
270 * which can be done because it is legal to do calculations on
271 * infinity (for example, 1 / infinity == 0).
272 */
273 result = -trio_pinf();
274 }
275 return result;
276}
277
Bjorn Reese026d29f2002-01-19 15:40:18 +0000278/**
279 Generate NaN.
280
281 @return Floating-point representation of NaN.
282*/
Daniel Veillardcda96922001-08-21 10:56:31 +0000283TRIO_PUBLIC double
Bjorn Reese45029602001-08-21 09:23:53 +0000284trio_nan(void)
285{
286 /* Cache the result */
287 static double result = 0.0;
288
289 if (result == 0.0) {
290
291#if defined(TRIO_COMPILER_SUPPORTS_C99)
292 result = nan(NULL);
293
294#elif defined(NAN) && defined(__STDC_IEC_559__)
295 result = (double)NAN;
296
297#elif defined(USE_IEEE_754)
298 result = trio_make_double(ieee_754_qnan_array);
299
300#else
301 /*
302 * There are several ways to generate NaN. The one used here is
303 * to divide infinity by infinity. I would have preferred to add
304 * negative infinity to positive infinity, but that yields wrong
305 * result (infinity) on FreeBSD.
306 *
307 * This may fail if the hardware does not support NaN, or if
308 * the Invalid Operation floating-point exception is unmasked.
309 */
310# if defined(TRIO_PLATFORM_UNIX)
311 void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
312# endif
313
314 result = trio_pinf() / trio_pinf();
315
316# if defined(TRIO_PLATFORM_UNIX)
317 signal(SIGFPE, signal_handler);
318# endif
319
320#endif
321 }
322 return result;
323}
324
Bjorn Reese026d29f2002-01-19 15:40:18 +0000325/**
326 Check for NaN.
327
328 @param number An arbitrary floating-point number.
329 @return Boolean value indicating whether or not the number is a NaN.
330*/
Daniel Veillardcda96922001-08-21 10:56:31 +0000331TRIO_PUBLIC int
Bjorn Reese026d29f2002-01-19 15:40:18 +0000332trio_isnan(TRIO_VOLATILE double number)
Bjorn Reese45029602001-08-21 09:23:53 +0000333{
334#if defined(isnan) || defined(TRIO_COMPILER_SUPPORTS_UNIX95)
335 /*
336 * C99 defines isnan() as a macro. UNIX95 defines isnan() as a
337 * function. This function was already present in XPG4, but this
338 * is a bit tricky to detect with compiler defines, so we choose
339 * the conservative approach and only use it for UNIX95.
340 */
341 return isnan(number);
342
343#elif defined(TRIO_COMPILER_MSVC)
344 /*
345 * MSC has an _isnan() function
346 */
347 return _isnan(number);
348
349#elif defined(USE_IEEE_754)
350 /*
351 * Examine IEEE 754 bit-pattern. A NaN must have a special exponent
352 * pattern, and a non-empty mantissa.
353 */
354 int has_mantissa;
355 int is_special_quantity;
356
357 is_special_quantity = trio_is_special_quantity(number, &has_mantissa);
358
359 return (is_special_quantity && has_mantissa);
360
361#else
362 /*
363 * Fallback solution
364 */
365 int status;
366 double integral, fraction;
367
368# if defined(TRIO_PLATFORM_UNIX)
369 void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
370# endif
371
372 status = (/*
373 * NaN is the only number which does not compare to itself
374 */
375 (number != number) ||
376 /*
377 * Fallback solution if NaN compares to NaN
378 */
379 ((number != 0.0) &&
380 (fraction = modf(number, &integral),
381 integral == fraction)));
382
383# if defined(TRIO_PLATFORM_UNIX)
384 signal(SIGFPE, signal_handler);
385# endif
386
387 return status;
388
389#endif
390}
391
Bjorn Reese026d29f2002-01-19 15:40:18 +0000392/**
393 Check for infinity.
394
395 @param number An arbitrary floating-point number.
396 @return 1 if positive infinity, -1 if negative infinity, 0 otherwise.
397*/
Daniel Veillardcda96922001-08-21 10:56:31 +0000398TRIO_PUBLIC int
Bjorn Reese026d29f2002-01-19 15:40:18 +0000399trio_isinf(TRIO_VOLATILE double number)
Bjorn Reese45029602001-08-21 09:23:53 +0000400{
401#if defined(TRIO_COMPILER_DECC)
402 /*
403 * DECC has an isinf() macro, but it works differently than that
404 * of C99, so we use the fp_class() function instead.
405 */
406 return ((fp_class(number) == FP_POS_INF)
407 ? 1
408 : ((fp_class(number) == FP_NEG_INF) ? -1 : 0));
409
410#elif defined(isinf)
411 /*
412 * C99 defines isinf() as a macro.
413 */
414 return isinf(number);
415
416#elif defined(TRIO_COMPILER_MSVC)
417 /*
418 * MSVC has an _fpclass() function that can be used to detect infinity.
419 */
420 return ((_fpclass(number) == _FPCLASS_PINF)
421 ? 1
422 : ((_fpclass(number) == _FPCLASS_NINF) ? -1 : 0));
423
424#elif defined(USE_IEEE_754)
425 /*
426 * Examine IEEE 754 bit-pattern. Infinity must have a special exponent
427 * pattern, and an empty mantissa.
428 */
429 int has_mantissa;
430 int is_special_quantity;
431
432 is_special_quantity = trio_is_special_quantity(number, &has_mantissa);
433
434 return (is_special_quantity && !has_mantissa)
435 ? ((number < 0.0) ? -1 : 1)
436 : 0;
437
438#else
439 /*
440 * Fallback solution.
441 */
442 int status;
443
444# if defined(TRIO_PLATFORM_UNIX)
445 void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
446# endif
447
448 double infinity = trio_pinf();
449
450 status = ((number == infinity)
451 ? 1
452 : ((number == -infinity) ? -1 : 0));
453
454# if defined(TRIO_PLATFORM_UNIX)
455 signal(SIGFPE, signal_handler);
456# endif
457
458 return status;
459
460#endif
461}
462
Bjorn Reese026d29f2002-01-19 15:40:18 +0000463/** @} SpecialQuantities */
464
Bjorn Reese45029602001-08-21 09:23:53 +0000465/*************************************************************************
Bjorn Reese026d29f2002-01-19 15:40:18 +0000466 * For test purposes.
467 *
468 * Add the following compiler option to include this test code.
469 *
470 * Unix : -DSTANDALONE
471 * VMS : /DEFINE=(STANDALONE)
Bjorn Reese45029602001-08-21 09:23:53 +0000472 */
473#if defined(STANDALONE)
474# include <stdio.h>
475
476int main(void)
477{
478 double my_nan;
479 double my_pinf;
480 double my_ninf;
481# if defined(TRIO_PLATFORM_UNIX)
482 void (*signal_handler)(int);
483# endif
484
485 my_nan = trio_nan();
486 my_pinf = trio_pinf();
487 my_ninf = trio_ninf();
488
489 printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
490 my_nan,
491 ((unsigned char *)&my_nan)[0],
492 ((unsigned char *)&my_nan)[1],
493 ((unsigned char *)&my_nan)[2],
494 ((unsigned char *)&my_nan)[3],
495 ((unsigned char *)&my_nan)[4],
496 ((unsigned char *)&my_nan)[5],
497 ((unsigned char *)&my_nan)[6],
498 ((unsigned char *)&my_nan)[7],
499 trio_isnan(my_nan), trio_isinf(my_nan));
500 printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
501 my_pinf,
502 ((unsigned char *)&my_pinf)[0],
503 ((unsigned char *)&my_pinf)[1],
504 ((unsigned char *)&my_pinf)[2],
505 ((unsigned char *)&my_pinf)[3],
506 ((unsigned char *)&my_pinf)[4],
507 ((unsigned char *)&my_pinf)[5],
508 ((unsigned char *)&my_pinf)[6],
509 ((unsigned char *)&my_pinf)[7],
510 trio_isnan(my_pinf), trio_isinf(my_pinf));
511 printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
512 my_ninf,
513 ((unsigned char *)&my_ninf)[0],
514 ((unsigned char *)&my_ninf)[1],
515 ((unsigned char *)&my_ninf)[2],
516 ((unsigned char *)&my_ninf)[3],
517 ((unsigned char *)&my_ninf)[4],
518 ((unsigned char *)&my_ninf)[5],
519 ((unsigned char *)&my_ninf)[6],
520 ((unsigned char *)&my_ninf)[7],
521 trio_isnan(my_ninf), trio_isinf(my_ninf));
522
523# if defined(TRIO_PLATFORM_UNIX)
524 signal_handler = signal(SIGFPE, SIG_IGN);
525# endif
526
527 my_pinf = DBL_MAX + DBL_MAX;
528 my_ninf = -my_pinf;
529 my_nan = my_pinf / my_pinf;
530
531# if defined(TRIO_PLATFORM_UNIX)
532 signal(SIGFPE, signal_handler);
533# endif
534
535 printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
536 my_nan,
537 ((unsigned char *)&my_nan)[0],
538 ((unsigned char *)&my_nan)[1],
539 ((unsigned char *)&my_nan)[2],
540 ((unsigned char *)&my_nan)[3],
541 ((unsigned char *)&my_nan)[4],
542 ((unsigned char *)&my_nan)[5],
543 ((unsigned char *)&my_nan)[6],
544 ((unsigned char *)&my_nan)[7],
545 trio_isnan(my_nan), trio_isinf(my_nan));
546 printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
547 my_pinf,
548 ((unsigned char *)&my_pinf)[0],
549 ((unsigned char *)&my_pinf)[1],
550 ((unsigned char *)&my_pinf)[2],
551 ((unsigned char *)&my_pinf)[3],
552 ((unsigned char *)&my_pinf)[4],
553 ((unsigned char *)&my_pinf)[5],
554 ((unsigned char *)&my_pinf)[6],
555 ((unsigned char *)&my_pinf)[7],
556 trio_isnan(my_pinf), trio_isinf(my_pinf));
557 printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
558 my_ninf,
559 ((unsigned char *)&my_ninf)[0],
560 ((unsigned char *)&my_ninf)[1],
561 ((unsigned char *)&my_ninf)[2],
562 ((unsigned char *)&my_ninf)[3],
563 ((unsigned char *)&my_ninf)[4],
564 ((unsigned char *)&my_ninf)[5],
565 ((unsigned char *)&my_ninf)[6],
566 ((unsigned char *)&my_ninf)[7],
567 trio_isnan(my_ninf), trio_isinf(my_ninf));
568
569 return 0;
570}
571#endif