blob: cc5644401999ea1a55c615267e0b138fe6b4e583 [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
53 * RISC OS 4 StrongARM Norcroft C
54 * Solaris 2.5.1 x86 gcc
55 * Solaris 2.5.1 Sparc gcc
56 * Solaris 2.6 Sparc WorkShop 4.2
57 * Solaris 8 Sparc Forte C 6
58 * Tru64 4.0D Alpha gcc
59 * Tru64 5.1 Alpha gcc
60 * WinNT x86 MSVC 5.0 & 6.0
61 *
62 ************************************************************************/
63
64static const char rcsid[] = "@(#)$Id$";
65
66
67/*************************************************************************
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
80#include <assert.h>
81
Bjorn Reese0b2ae432001-08-31 16:31:57 +000082#ifdef __STDC__
83# define CONST const
84# define VOLATILE volatile
85#else
86# define CONST
87# define VOLATILE
Bjorn Reese45029602001-08-21 09:23:53 +000088#endif
89
90/*************************************************************************
91 * Definitions
92 */
93
94/* We must enable IEEE floating-point on Alpha */
95#if defined(__alpha) && !defined(_IEEE_FP)
96# if defined(TRIO_COMPILER_DECC)
97# error "Must be compiled with option -ieee"
98# elif defined(TRIO_COMPILER_GCC) && (defined(__osf__) || defined(__linux__))
99# error "Must be compiled with option -mieee"
100# endif
101#endif /* __alpha && ! _IEEE_FP */
102
103/*
104 * In ANSI/IEEE 754-1985 64-bits double format numbers have the
105 * following properties (amoungst others)
106 *
107 * o FLT_RADIX == 2: binary encoding
108 * o DBL_MAX_EXP == 1024: 11 bits exponent, where one bit is used
109 * to indicate special numbers (e.g. NaN and Infinity), so the
110 * maximum exponent is 10 bits wide (2^10 == 1024).
111 * o DBL_MANT_DIG == 53: The mantissa is 52 bits wide, but because
112 * numbers are normalized the initial binary 1 is represented
113 * implictly (the so-called "hidden bit"), which leaves us with
114 * the ability to represent 53 bits wide mantissa.
115 */
116#if (FLT_RADIX == 2) && (DBL_MAX_EXP == 1024) && (DBL_MANT_DIG == 53)
117# define USE_IEEE_754
118#endif
119
120
121/*************************************************************************
122 * Data
123 */
124
125#if defined(USE_IEEE_754)
126
127/*
128 * Endian-agnostic indexing macro.
129 *
130 * The value of internalEndianMagic, when converted into a 64-bit
131 * integer, becomes 0x0001020304050607 (we could have used a 64-bit
132 * integer value instead of a double, but not all platforms supports
133 * that type). The value is automatically encoded with the correct
134 * endianess by the compiler, which means that we can support any
135 * kind of endianess. The individual bytes are then used as an index
136 * for the IEEE 754 bit-patterns and masks.
137 */
138#define TRIO_DOUBLE_INDEX(x) (((unsigned char *)&internalEndianMagic)[(x)])
139
Bjorn Reese0b2ae432001-08-31 16:31:57 +0000140static CONST double internalEndianMagic = 1.4015997730788920e-309;
Bjorn Reese45029602001-08-21 09:23:53 +0000141
142/* Mask for the exponent */
Bjorn Reese0b2ae432001-08-31 16:31:57 +0000143static CONST unsigned char ieee_754_exponent_mask[] = {
Bjorn Reese45029602001-08-21 09:23:53 +0000144 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
145};
146
147/* Mask for the mantissa */
Bjorn Reese0b2ae432001-08-31 16:31:57 +0000148static CONST unsigned char ieee_754_mantissa_mask[] = {
Bjorn Reese45029602001-08-21 09:23:53 +0000149 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
150};
151
152/* Bit-pattern for infinity */
Bjorn Reese0b2ae432001-08-31 16:31:57 +0000153static CONST unsigned char ieee_754_infinity_array[] = {
Bjorn Reese45029602001-08-21 09:23:53 +0000154 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
155};
156
157/* Bit-pattern for quiet NaN */
Bjorn Reese0b2ae432001-08-31 16:31:57 +0000158static CONST unsigned char ieee_754_qnan_array[] = {
Bjorn Reese45029602001-08-21 09:23:53 +0000159 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
160};
161
162
163/*************************************************************************
164 * trio_make_double
165 */
166static double
Bjorn Reese0b2ae432001-08-31 16:31:57 +0000167trio_make_double(CONST unsigned char *values)
Bjorn Reese45029602001-08-21 09:23:53 +0000168{
Bjorn Reese0b2ae432001-08-31 16:31:57 +0000169 VOLATILE double result;
Bjorn Reese45029602001-08-21 09:23:53 +0000170 int i;
171
172 for (i = 0; i < (int)sizeof(double); i++) {
Bjorn Reese0b2ae432001-08-31 16:31:57 +0000173 ((VOLATILE unsigned char *)&result)[TRIO_DOUBLE_INDEX(i)] = values[i];
Bjorn Reese45029602001-08-21 09:23:53 +0000174 }
175 return result;
176}
177
178/*************************************************************************
179 * trio_examine_double
180 */
181static int
182trio_is_special_quantity(double number,
183 int *has_mantissa)
184{
185 unsigned int i;
186 unsigned char current;
187 int is_special_quantity = (1 == 1);
188
189 *has_mantissa = 0;
190
191 for (i = 0; i < (unsigned int)sizeof(double); i++) {
192 current = ((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)];
193 is_special_quantity
194 &= ((current & ieee_754_exponent_mask[i]) == ieee_754_exponent_mask[i]);
195 *has_mantissa |= (current & ieee_754_mantissa_mask[i]);
196 }
197 return is_special_quantity;
198}
199
200#endif /* USE_IEEE_754 */
201
202
203/*************************************************************************
204 * trio_pinf
205 */
Daniel Veillardcda96922001-08-21 10:56:31 +0000206TRIO_PUBLIC double
Bjorn Reese45029602001-08-21 09:23:53 +0000207trio_pinf(void)
208{
209 /* Cache the result */
210 static double result = 0.0;
211
212 if (result == 0.0) {
213
214#if defined(INFINITY) && defined(__STDC_IEC_559__)
215 result = (double)INFINITY;
216
217#elif defined(USE_IEEE_754)
218 result = trio_make_double(ieee_754_infinity_array);
219
220#else
221 /*
222 * If HUGE_VAL is different from DBL_MAX, then HUGE_VAL is used
223 * as infinity. Otherwise we have to resort to an overflow
224 * operation to generate infinity.
225 */
226# if defined(TRIO_PLATFORM_UNIX)
227 void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
228# endif
229
230 result = HUGE_VAL;
231 if (HUGE_VAL == DBL_MAX) {
232 /* Force overflow */
233 result += HUGE_VAL;
234 }
235
236# if defined(TRIO_PLATFORM_UNIX)
237 signal(SIGFPE, signal_handler);
238# endif
239
240#endif
241 }
242 return result;
243}
244
245/*************************************************************************
246 * trio_ninf
247 */
Daniel Veillardcda96922001-08-21 10:56:31 +0000248TRIO_PUBLIC double
Bjorn Reese45029602001-08-21 09:23:53 +0000249trio_ninf(void)
250{
251 static double result = 0.0;
252
253 if (result == 0.0) {
254 /*
255 * Negative infinity is calculated by negating positive infinity,
256 * which can be done because it is legal to do calculations on
257 * infinity (for example, 1 / infinity == 0).
258 */
259 result = -trio_pinf();
260 }
261 return result;
262}
263
264/*************************************************************************
265 * trio_nan
266 */
Daniel Veillardcda96922001-08-21 10:56:31 +0000267TRIO_PUBLIC double
Bjorn Reese45029602001-08-21 09:23:53 +0000268trio_nan(void)
269{
270 /* Cache the result */
271 static double result = 0.0;
272
273 if (result == 0.0) {
274
275#if defined(TRIO_COMPILER_SUPPORTS_C99)
276 result = nan(NULL);
277
278#elif defined(NAN) && defined(__STDC_IEC_559__)
279 result = (double)NAN;
280
281#elif defined(USE_IEEE_754)
282 result = trio_make_double(ieee_754_qnan_array);
283
284#else
285 /*
286 * There are several ways to generate NaN. The one used here is
287 * to divide infinity by infinity. I would have preferred to add
288 * negative infinity to positive infinity, but that yields wrong
289 * result (infinity) on FreeBSD.
290 *
291 * This may fail if the hardware does not support NaN, or if
292 * the Invalid Operation floating-point exception is unmasked.
293 */
294# if defined(TRIO_PLATFORM_UNIX)
295 void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
296# endif
297
298 result = trio_pinf() / trio_pinf();
299
300# if defined(TRIO_PLATFORM_UNIX)
301 signal(SIGFPE, signal_handler);
302# endif
303
304#endif
305 }
306 return result;
307}
308
309/*************************************************************************
310 * trio_isnan
311 */
Daniel Veillardcda96922001-08-21 10:56:31 +0000312TRIO_PUBLIC int
Bjorn Reese0b2ae432001-08-31 16:31:57 +0000313trio_isnan(VOLATILE double number)
Bjorn Reese45029602001-08-21 09:23:53 +0000314{
315#if defined(isnan) || defined(TRIO_COMPILER_SUPPORTS_UNIX95)
316 /*
317 * C99 defines isnan() as a macro. UNIX95 defines isnan() as a
318 * function. This function was already present in XPG4, but this
319 * is a bit tricky to detect with compiler defines, so we choose
320 * the conservative approach and only use it for UNIX95.
321 */
322 return isnan(number);
323
324#elif defined(TRIO_COMPILER_MSVC)
325 /*
326 * MSC has an _isnan() function
327 */
328 return _isnan(number);
329
330#elif defined(USE_IEEE_754)
331 /*
332 * Examine IEEE 754 bit-pattern. A NaN must have a special exponent
333 * pattern, and a non-empty mantissa.
334 */
335 int has_mantissa;
336 int is_special_quantity;
337
338 is_special_quantity = trio_is_special_quantity(number, &has_mantissa);
339
340 return (is_special_quantity && has_mantissa);
341
342#else
343 /*
344 * Fallback solution
345 */
346 int status;
347 double integral, fraction;
348
349# if defined(TRIO_PLATFORM_UNIX)
350 void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
351# endif
352
353 status = (/*
354 * NaN is the only number which does not compare to itself
355 */
356 (number != number) ||
357 /*
358 * Fallback solution if NaN compares to NaN
359 */
360 ((number != 0.0) &&
361 (fraction = modf(number, &integral),
362 integral == fraction)));
363
364# if defined(TRIO_PLATFORM_UNIX)
365 signal(SIGFPE, signal_handler);
366# endif
367
368 return status;
369
370#endif
371}
372
373/*************************************************************************
374 * trio_isinf
375 */
Daniel Veillardcda96922001-08-21 10:56:31 +0000376TRIO_PUBLIC int
Bjorn Reese0b2ae432001-08-31 16:31:57 +0000377trio_isinf(VOLATILE double number)
Bjorn Reese45029602001-08-21 09:23:53 +0000378{
379#if defined(TRIO_COMPILER_DECC)
380 /*
381 * DECC has an isinf() macro, but it works differently than that
382 * of C99, so we use the fp_class() function instead.
383 */
384 return ((fp_class(number) == FP_POS_INF)
385 ? 1
386 : ((fp_class(number) == FP_NEG_INF) ? -1 : 0));
387
388#elif defined(isinf)
389 /*
390 * C99 defines isinf() as a macro.
391 */
392 return isinf(number);
393
394#elif defined(TRIO_COMPILER_MSVC)
395 /*
396 * MSVC has an _fpclass() function that can be used to detect infinity.
397 */
398 return ((_fpclass(number) == _FPCLASS_PINF)
399 ? 1
400 : ((_fpclass(number) == _FPCLASS_NINF) ? -1 : 0));
401
402#elif defined(USE_IEEE_754)
403 /*
404 * Examine IEEE 754 bit-pattern. Infinity must have a special exponent
405 * pattern, and an empty mantissa.
406 */
407 int has_mantissa;
408 int is_special_quantity;
409
410 is_special_quantity = trio_is_special_quantity(number, &has_mantissa);
411
412 return (is_special_quantity && !has_mantissa)
413 ? ((number < 0.0) ? -1 : 1)
414 : 0;
415
416#else
417 /*
418 * Fallback solution.
419 */
420 int status;
421
422# if defined(TRIO_PLATFORM_UNIX)
423 void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
424# endif
425
426 double infinity = trio_pinf();
427
428 status = ((number == infinity)
429 ? 1
430 : ((number == -infinity) ? -1 : 0));
431
432# if defined(TRIO_PLATFORM_UNIX)
433 signal(SIGFPE, signal_handler);
434# endif
435
436 return status;
437
438#endif
439}
440
441/*************************************************************************
442 */
443#if defined(STANDALONE)
444# include <stdio.h>
445
446int main(void)
447{
448 double my_nan;
449 double my_pinf;
450 double my_ninf;
451# if defined(TRIO_PLATFORM_UNIX)
452 void (*signal_handler)(int);
453# endif
454
455 my_nan = trio_nan();
456 my_pinf = trio_pinf();
457 my_ninf = trio_ninf();
458
459 printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
460 my_nan,
461 ((unsigned char *)&my_nan)[0],
462 ((unsigned char *)&my_nan)[1],
463 ((unsigned char *)&my_nan)[2],
464 ((unsigned char *)&my_nan)[3],
465 ((unsigned char *)&my_nan)[4],
466 ((unsigned char *)&my_nan)[5],
467 ((unsigned char *)&my_nan)[6],
468 ((unsigned char *)&my_nan)[7],
469 trio_isnan(my_nan), trio_isinf(my_nan));
470 printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
471 my_pinf,
472 ((unsigned char *)&my_pinf)[0],
473 ((unsigned char *)&my_pinf)[1],
474 ((unsigned char *)&my_pinf)[2],
475 ((unsigned char *)&my_pinf)[3],
476 ((unsigned char *)&my_pinf)[4],
477 ((unsigned char *)&my_pinf)[5],
478 ((unsigned char *)&my_pinf)[6],
479 ((unsigned char *)&my_pinf)[7],
480 trio_isnan(my_pinf), trio_isinf(my_pinf));
481 printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
482 my_ninf,
483 ((unsigned char *)&my_ninf)[0],
484 ((unsigned char *)&my_ninf)[1],
485 ((unsigned char *)&my_ninf)[2],
486 ((unsigned char *)&my_ninf)[3],
487 ((unsigned char *)&my_ninf)[4],
488 ((unsigned char *)&my_ninf)[5],
489 ((unsigned char *)&my_ninf)[6],
490 ((unsigned char *)&my_ninf)[7],
491 trio_isnan(my_ninf), trio_isinf(my_ninf));
492
493# if defined(TRIO_PLATFORM_UNIX)
494 signal_handler = signal(SIGFPE, SIG_IGN);
495# endif
496
497 my_pinf = DBL_MAX + DBL_MAX;
498 my_ninf = -my_pinf;
499 my_nan = my_pinf / my_pinf;
500
501# if defined(TRIO_PLATFORM_UNIX)
502 signal(SIGFPE, signal_handler);
503# endif
504
505 printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
506 my_nan,
507 ((unsigned char *)&my_nan)[0],
508 ((unsigned char *)&my_nan)[1],
509 ((unsigned char *)&my_nan)[2],
510 ((unsigned char *)&my_nan)[3],
511 ((unsigned char *)&my_nan)[4],
512 ((unsigned char *)&my_nan)[5],
513 ((unsigned char *)&my_nan)[6],
514 ((unsigned char *)&my_nan)[7],
515 trio_isnan(my_nan), trio_isinf(my_nan));
516 printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
517 my_pinf,
518 ((unsigned char *)&my_pinf)[0],
519 ((unsigned char *)&my_pinf)[1],
520 ((unsigned char *)&my_pinf)[2],
521 ((unsigned char *)&my_pinf)[3],
522 ((unsigned char *)&my_pinf)[4],
523 ((unsigned char *)&my_pinf)[5],
524 ((unsigned char *)&my_pinf)[6],
525 ((unsigned char *)&my_pinf)[7],
526 trio_isnan(my_pinf), trio_isinf(my_pinf));
527 printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
528 my_ninf,
529 ((unsigned char *)&my_ninf)[0],
530 ((unsigned char *)&my_ninf)[1],
531 ((unsigned char *)&my_ninf)[2],
532 ((unsigned char *)&my_ninf)[3],
533 ((unsigned char *)&my_ninf)[4],
534 ((unsigned char *)&my_ninf)[5],
535 ((unsigned char *)&my_ninf)[6],
536 ((unsigned char *)&my_ninf)[7],
537 trio_isnan(my_ninf), trio_isinf(my_ninf));
538
539 return 0;
540}
541#endif