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