blob: 7e48b36e71d2a040765cfa0668beb274ce60d185 [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 *
Bjorn Reese45029602001-08-21 09:23:53 +000032 ************************************************************************/
33
Daniel Veillardb7c29c32002-09-25 22:44:43 +000034/*
35 * TODO:
36 * o Put all the magic into trio_fpclassify_and_signbit(), and use this from
37 * trio_isnan() etc.
38 */
Bjorn Reese45029602001-08-21 09:23:53 +000039
Bjorn Reese45029602001-08-21 09:23:53 +000040/*************************************************************************
41 * Include files
42 */
43#include "triodef.h"
44#include "trionan.h"
45
46#include <math.h>
47#include <string.h>
48#include <limits.h>
49#include <float.h>
50#if defined(TRIO_PLATFORM_UNIX)
51# include <signal.h>
52#endif
Bjorn Reese026d29f2002-01-19 15:40:18 +000053#if defined(TRIO_COMPILER_DECC)
54# include <fp_class.h>
55#endif
Bjorn Reese45029602001-08-21 09:23:53 +000056#include <assert.h>
57
Bjorn Reese026d29f2002-01-19 15:40:18 +000058#if defined(TRIO_DOCUMENTATION)
59# include "doc/doc_nan.h"
Bjorn Reese45029602001-08-21 09:23:53 +000060#endif
Bjorn Reese026d29f2002-01-19 15:40:18 +000061/** @addtogroup SpecialQuantities
62 @{
63*/
Bjorn Reese45029602001-08-21 09:23:53 +000064
65/*************************************************************************
66 * Definitions
67 */
68
Daniel Veillard21458c82002-03-27 16:12:22 +000069#define TRIO_TRUE (1 == 1)
70#define TRIO_FALSE (0 == 1)
71
Daniel Veillarda48ed3d2003-04-03 15:28:28 +000072/*
73 * We must enable IEEE floating-point on Alpha
74 */
Bjorn Reese45029602001-08-21 09:23:53 +000075#if defined(__alpha) && !defined(_IEEE_FP)
76# if defined(TRIO_COMPILER_DECC)
Bjorn Reese026d29f2002-01-19 15:40:18 +000077# if defined(TRIO_PLATFORM_VMS)
78# error "Must be compiled with option /IEEE_MODE=UNDERFLOW_TO_ZERO/FLOAT=IEEE"
79# else
Daniel Veillardb7c29c32002-09-25 22:44:43 +000080# if !defined(_CFE)
81# error "Must be compiled with option -ieee"
82# endif
Bjorn Reese026d29f2002-01-19 15:40:18 +000083# endif
Bjorn Reese45029602001-08-21 09:23:53 +000084# elif defined(TRIO_COMPILER_GCC) && (defined(__osf__) || defined(__linux__))
85# error "Must be compiled with option -mieee"
86# endif
87#endif /* __alpha && ! _IEEE_FP */
88
89/*
90 * In ANSI/IEEE 754-1985 64-bits double format numbers have the
91 * following properties (amoungst others)
92 *
93 * o FLT_RADIX == 2: binary encoding
94 * o DBL_MAX_EXP == 1024: 11 bits exponent, where one bit is used
95 * to indicate special numbers (e.g. NaN and Infinity), so the
96 * maximum exponent is 10 bits wide (2^10 == 1024).
97 * o DBL_MANT_DIG == 53: The mantissa is 52 bits wide, but because
98 * numbers are normalized the initial binary 1 is represented
Daniel Veillardcbaf3992001-12-31 16:16:02 +000099 * implicitly (the so-called "hidden bit"), which leaves us with
Bjorn Reese45029602001-08-21 09:23:53 +0000100 * the ability to represent 53 bits wide mantissa.
101 */
102#if (FLT_RADIX == 2) && (DBL_MAX_EXP == 1024) && (DBL_MANT_DIG == 53)
103# define USE_IEEE_754
104#endif
105
106
107/*************************************************************************
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000108 * Constants
Bjorn Reese45029602001-08-21 09:23:53 +0000109 */
110
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000111static TRIO_CONST char rcsid[] = "@(#)$Id$";
112
Bjorn Reese45029602001-08-21 09:23:53 +0000113#if defined(USE_IEEE_754)
114
115/*
116 * Endian-agnostic indexing macro.
117 *
118 * The value of internalEndianMagic, when converted into a 64-bit
Bjorn Reese026d29f2002-01-19 15:40:18 +0000119 * integer, becomes 0x0706050403020100 (we could have used a 64-bit
Bjorn Reese45029602001-08-21 09:23:53 +0000120 * integer value instead of a double, but not all platforms supports
121 * that type). The value is automatically encoded with the correct
122 * endianess by the compiler, which means that we can support any
123 * kind of endianess. The individual bytes are then used as an index
124 * for the IEEE 754 bit-patterns and masks.
125 */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000126#define TRIO_DOUBLE_INDEX(x) (((unsigned char *)&internalEndianMagic)[7-(x)])
Bjorn Reese45029602001-08-21 09:23:53 +0000127
Bjorn Reese026d29f2002-01-19 15:40:18 +0000128static TRIO_CONST double internalEndianMagic = 7.949928895127363e-275;
Bjorn Reese45029602001-08-21 09:23:53 +0000129
130/* Mask for the exponent */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000131static TRIO_CONST unsigned char ieee_754_exponent_mask[] = {
Bjorn Reese45029602001-08-21 09:23:53 +0000132 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
133};
134
135/* Mask for the mantissa */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000136static TRIO_CONST unsigned char ieee_754_mantissa_mask[] = {
Bjorn Reese45029602001-08-21 09:23:53 +0000137 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
138};
139
Daniel Veillard21458c82002-03-27 16:12:22 +0000140/* Mask for the sign bit */
141static TRIO_CONST unsigned char ieee_754_sign_mask[] = {
142 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
143};
144
Daniel Veillard5fc1f082002-03-27 09:05:40 +0000145/* Bit-pattern for negative zero */
146static TRIO_CONST unsigned char ieee_754_negzero_array[] = {
147 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
148};
149
Bjorn Reese45029602001-08-21 09:23:53 +0000150/* Bit-pattern for infinity */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000151static TRIO_CONST unsigned char ieee_754_infinity_array[] = {
Bjorn Reese45029602001-08-21 09:23:53 +0000152 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
153};
154
155/* Bit-pattern for quiet NaN */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000156static TRIO_CONST unsigned char ieee_754_qnan_array[] = {
Bjorn Reese45029602001-08-21 09:23:53 +0000157 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
158};
159
160
161/*************************************************************************
Bjorn Reese026d29f2002-01-19 15:40:18 +0000162 * Functions
163 */
164
165/*
Bjorn Reese45029602001-08-21 09:23:53 +0000166 * trio_make_double
167 */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000168TRIO_PRIVATE double
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000169trio_make_double
170TRIO_ARGS1((values),
171 TRIO_CONST unsigned char *values)
Bjorn Reese45029602001-08-21 09:23:53 +0000172{
Bjorn Reese026d29f2002-01-19 15:40:18 +0000173 TRIO_VOLATILE double result;
Bjorn Reese45029602001-08-21 09:23:53 +0000174 int i;
175
176 for (i = 0; i < (int)sizeof(double); i++) {
Bjorn Reese026d29f2002-01-19 15:40:18 +0000177 ((TRIO_VOLATILE unsigned char *)&result)[TRIO_DOUBLE_INDEX(i)] = values[i];
Bjorn Reese45029602001-08-21 09:23:53 +0000178 }
179 return result;
180}
181
Bjorn Reese026d29f2002-01-19 15:40:18 +0000182/*
Daniel Veillard21458c82002-03-27 16:12:22 +0000183 * trio_is_special_quantity
Bjorn Reese45029602001-08-21 09:23:53 +0000184 */
Bjorn Reese026d29f2002-01-19 15:40:18 +0000185TRIO_PRIVATE int
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000186trio_is_special_quantity
187TRIO_ARGS2((number, has_mantissa),
188 double number,
189 int *has_mantissa)
Bjorn Reese45029602001-08-21 09:23:53 +0000190{
191 unsigned int i;
192 unsigned char current;
Daniel Veillard21458c82002-03-27 16:12:22 +0000193 int is_special_quantity = TRIO_TRUE;
Bjorn Reese45029602001-08-21 09:23:53 +0000194
195 *has_mantissa = 0;
196
197 for (i = 0; i < (unsigned int)sizeof(double); i++) {
198 current = ((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)];
199 is_special_quantity
200 &= ((current & ieee_754_exponent_mask[i]) == ieee_754_exponent_mask[i]);
201 *has_mantissa |= (current & ieee_754_mantissa_mask[i]);
202 }
203 return is_special_quantity;
204}
205
Daniel Veillard21458c82002-03-27 16:12:22 +0000206/*
207 * trio_is_negative
208 */
209TRIO_PRIVATE int
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000210trio_is_negative
211TRIO_ARGS1((number),
212 double number)
Daniel Veillard5fc1f082002-03-27 09:05:40 +0000213{
214 unsigned int i;
Daniel Veillard21458c82002-03-27 16:12:22 +0000215 int is_negative = TRIO_FALSE;
Daniel Veillard5fc1f082002-03-27 09:05:40 +0000216
217 for (i = 0; i < (unsigned int)sizeof(double); i++) {
Daniel Veillard21458c82002-03-27 16:12:22 +0000218 is_negative |= (((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)]
219 & ieee_754_sign_mask[i]);
Daniel Veillard5fc1f082002-03-27 09:05:40 +0000220 }
Daniel Veillard21458c82002-03-27 16:12:22 +0000221 return is_negative;
Daniel Veillard5fc1f082002-03-27 09:05:40 +0000222}
223
Bjorn Reese45029602001-08-21 09:23:53 +0000224#endif /* USE_IEEE_754 */
225
226
Bjorn Reese026d29f2002-01-19 15:40:18 +0000227/**
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000228 Generate negative zero.
229
230 @return Floating-point representation of negative zero.
231*/
232TRIO_PUBLIC double
233trio_nzero(TRIO_NOARGS)
234{
235#if defined(USE_IEEE_754)
236 return trio_make_double(ieee_754_negzero_array);
237#else
238 TRIO_VOLATILE double zero = 0.0;
239
240 return -zero;
241#endif
242}
243
244/**
Bjorn Reese026d29f2002-01-19 15:40:18 +0000245 Generate positive infinity.
246
247 @return Floating-point representation of positive infinity.
248*/
Daniel Veillardcda96922001-08-21 10:56:31 +0000249TRIO_PUBLIC double
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000250trio_pinf(TRIO_NOARGS)
Bjorn Reese45029602001-08-21 09:23:53 +0000251{
252 /* Cache the result */
253 static double result = 0.0;
254
255 if (result == 0.0) {
256
257#if defined(INFINITY) && defined(__STDC_IEC_559__)
258 result = (double)INFINITY;
259
260#elif defined(USE_IEEE_754)
261 result = trio_make_double(ieee_754_infinity_array);
262
263#else
264 /*
265 * If HUGE_VAL is different from DBL_MAX, then HUGE_VAL is used
266 * as infinity. Otherwise we have to resort to an overflow
267 * operation to generate infinity.
268 */
269# if defined(TRIO_PLATFORM_UNIX)
270 void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
271# endif
272
273 result = HUGE_VAL;
274 if (HUGE_VAL == DBL_MAX) {
275 /* Force overflow */
276 result += HUGE_VAL;
277 }
278
279# if defined(TRIO_PLATFORM_UNIX)
280 signal(SIGFPE, signal_handler);
281# endif
282
283#endif
284 }
285 return result;
286}
287
Bjorn Reese026d29f2002-01-19 15:40:18 +0000288/**
289 Generate negative infinity.
290
291 @return Floating-point value of negative infinity.
292*/
Daniel Veillardcda96922001-08-21 10:56:31 +0000293TRIO_PUBLIC double
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000294trio_ninf(TRIO_NOARGS)
Bjorn Reese45029602001-08-21 09:23:53 +0000295{
296 static double result = 0.0;
297
298 if (result == 0.0) {
299 /*
300 * Negative infinity is calculated by negating positive infinity,
301 * which can be done because it is legal to do calculations on
302 * infinity (for example, 1 / infinity == 0).
303 */
304 result = -trio_pinf();
305 }
306 return result;
307}
308
Bjorn Reese026d29f2002-01-19 15:40:18 +0000309/**
310 Generate NaN.
311
312 @return Floating-point representation of NaN.
313*/
Daniel Veillardcda96922001-08-21 10:56:31 +0000314TRIO_PUBLIC double
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000315trio_nan(TRIO_NOARGS)
Bjorn Reese45029602001-08-21 09:23:53 +0000316{
317 /* Cache the result */
318 static double result = 0.0;
319
320 if (result == 0.0) {
321
322#if defined(TRIO_COMPILER_SUPPORTS_C99)
Bjorn Reese54d02fb2002-04-19 15:16:01 +0000323 result = nan("");
Bjorn Reese45029602001-08-21 09:23:53 +0000324
325#elif defined(NAN) && defined(__STDC_IEC_559__)
326 result = (double)NAN;
327
328#elif defined(USE_IEEE_754)
329 result = trio_make_double(ieee_754_qnan_array);
330
331#else
332 /*
333 * There are several ways to generate NaN. The one used here is
334 * to divide infinity by infinity. I would have preferred to add
335 * negative infinity to positive infinity, but that yields wrong
336 * result (infinity) on FreeBSD.
337 *
338 * This may fail if the hardware does not support NaN, or if
339 * the Invalid Operation floating-point exception is unmasked.
340 */
341# if defined(TRIO_PLATFORM_UNIX)
342 void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
343# endif
344
345 result = trio_pinf() / trio_pinf();
346
347# if defined(TRIO_PLATFORM_UNIX)
348 signal(SIGFPE, signal_handler);
349# endif
350
351#endif
352 }
353 return result;
354}
355
Bjorn Reese026d29f2002-01-19 15:40:18 +0000356/**
357 Check for NaN.
358
359 @param number An arbitrary floating-point number.
360 @return Boolean value indicating whether or not the number is a NaN.
361*/
Daniel Veillardcda96922001-08-21 10:56:31 +0000362TRIO_PUBLIC int
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000363trio_isnan
364TRIO_ARGS1((number),
365 double number)
Bjorn Reese45029602001-08-21 09:23:53 +0000366{
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000367#if (defined(TRIO_COMPILER_SUPPORTS_C99) && defined(isnan)) \
368 || defined(TRIO_COMPILER_SUPPORTS_UNIX95)
Bjorn Reese45029602001-08-21 09:23:53 +0000369 /*
370 * C99 defines isnan() as a macro. UNIX95 defines isnan() as a
371 * function. This function was already present in XPG4, but this
372 * is a bit tricky to detect with compiler defines, so we choose
373 * the conservative approach and only use it for UNIX95.
374 */
375 return isnan(number);
376
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000377#elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB)
Bjorn Reese45029602001-08-21 09:23:53 +0000378 /*
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000379 * Microsoft Visual C++ and Borland C++ Builder have an _isnan()
380 * function.
Bjorn Reese45029602001-08-21 09:23:53 +0000381 */
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000382 return _isnan(number) ? TRIO_TRUE : TRIO_FALSE;
Bjorn Reese45029602001-08-21 09:23:53 +0000383
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 */
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000410 ((TRIO_VOLATILE double)number != (TRIO_VOLATILE double)number) ||
Bjorn Reese45029602001-08-21 09:23:53 +0000411 /*
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
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000434trio_isinf
435TRIO_ARGS1((number),
436 double number)
Bjorn Reese45029602001-08-21 09:23:53 +0000437{
438#if defined(TRIO_COMPILER_DECC)
439 /*
440 * DECC has an isinf() macro, but it works differently than that
441 * of C99, so we use the fp_class() function instead.
442 */
443 return ((fp_class(number) == FP_POS_INF)
444 ? 1
445 : ((fp_class(number) == FP_NEG_INF) ? -1 : 0));
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000446
Bjorn Reese45029602001-08-21 09:23:53 +0000447#elif defined(isinf)
448 /*
449 * C99 defines isinf() as a macro.
450 */
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000451 return isinf(number)
452 ? ((number > 0.0) ? 1 : -1)
453 : 0;
Bjorn Reese45029602001-08-21 09:23:53 +0000454
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000455#elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB)
Bjorn Reese45029602001-08-21 09:23:53 +0000456 /*
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000457 * Microsoft Visual C++ and Borland C++ Builder have an _fpclass()
458 * function that can be used to detect infinity.
Bjorn Reese45029602001-08-21 09:23:53 +0000459 */
460 return ((_fpclass(number) == _FPCLASS_PINF)
461 ? 1
462 : ((_fpclass(number) == _FPCLASS_NINF) ? -1 : 0));
463
464#elif defined(USE_IEEE_754)
465 /*
466 * Examine IEEE 754 bit-pattern. Infinity must have a special exponent
467 * pattern, and an empty mantissa.
468 */
469 int has_mantissa;
470 int is_special_quantity;
471
472 is_special_quantity = trio_is_special_quantity(number, &has_mantissa);
473
474 return (is_special_quantity && !has_mantissa)
475 ? ((number < 0.0) ? -1 : 1)
476 : 0;
477
478#else
479 /*
480 * Fallback solution.
481 */
482 int status;
483
484# if defined(TRIO_PLATFORM_UNIX)
485 void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
486# endif
487
488 double infinity = trio_pinf();
489
490 status = ((number == infinity)
491 ? 1
492 : ((number == -infinity) ? -1 : 0));
493
494# if defined(TRIO_PLATFORM_UNIX)
495 signal(SIGFPE, signal_handler);
496# endif
497
498 return status;
499
500#endif
501}
502
Daniel Veillard21458c82002-03-27 16:12:22 +0000503
504/**
505 Check for finity.
506
507 @param number An arbitrary floating-point number.
508 @return Boolean value indicating whether or not the number is a finite.
509*/
510TRIO_PUBLIC int
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000511trio_isfinite
512TRIO_ARGS1((number),
513 double number)
Daniel Veillard21458c82002-03-27 16:12:22 +0000514{
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000515#if defined(TRIO_COMPILER_SUPPORTS_C99) && defined(isfinite)
Daniel Veillard21458c82002-03-27 16:12:22 +0000516 /*
517 * C99 defines isfinite() as a macro.
518 */
519 return isfinite(number);
520
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000521#elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB)
Daniel Veillard21458c82002-03-27 16:12:22 +0000522 /*
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000523 * Microsoft Visual C++ and Borland C++ Builder use _finite().
Daniel Veillard21458c82002-03-27 16:12:22 +0000524 */
525 return _finite(number);
526
527#elif defined(USE_IEEE_754)
528 /*
529 * Examine IEEE 754 bit-pattern. For finity we do not care about the
530 * mantissa.
531 */
532 int dummy;
533
534 return (! trio_is_special_quantity(number, &dummy));
535
536#else
537 /*
538 * Fallback solution.
539 */
540 return ((trio_isinf(number) == 0) && (trio_isnan(number) == 0));
541
542#endif
543}
544
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000545
Daniel Veillard21458c82002-03-27 16:12:22 +0000546/*
547 * The sign of NaN is always false
548 */
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000549TRIO_PUBLIC int
550trio_fpclassify_and_signbit
551TRIO_ARGS2((number, is_negative),
552 double number,
553 int *is_negative)
Daniel Veillard21458c82002-03-27 16:12:22 +0000554{
555#if defined(fpclassify) && defined(signbit)
556 /*
557 * C99 defines fpclassify() and signbit() as a macros
558 */
559 *is_negative = signbit(number);
560 switch (fpclassify(number)) {
561 case FP_NAN:
562 return TRIO_FP_NAN;
563 case FP_INFINITE:
564 return TRIO_FP_INFINITE;
565 case FP_SUBNORMAL:
566 return TRIO_FP_SUBNORMAL;
567 case FP_ZERO:
568 return TRIO_FP_ZERO;
569 default:
570 return TRIO_FP_NORMAL;
571 }
572
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000573#else
574# if defined(TRIO_COMPILER_DECC)
Daniel Veillard21458c82002-03-27 16:12:22 +0000575 /*
576 * DECC has an fp_class() function.
577 */
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000578# define TRIO_FPCLASSIFY(n) fp_class(n)
579# define TRIO_QUIET_NAN FP_QNAN
580# define TRIO_SIGNALLING_NAN FP_SNAN
581# define TRIO_POSITIVE_INFINITY FP_POS_INF
582# define TRIO_NEGATIVE_INFINITY FP_NEG_INF
583# define TRIO_POSITIVE_SUBNORMAL FP_POS_DENORM
584# define TRIO_NEGATIVE_SUBNORMAL FP_NEG_DENORM
585# define TRIO_POSITIVE_ZERO FP_POS_ZERO
586# define TRIO_NEGATIVE_ZERO FP_NEG_ZERO
587# define TRIO_POSITIVE_NORMAL FP_POS_NORM
588# define TRIO_NEGATIVE_NORMAL FP_NEG_NORM
589
590# elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB)
Daniel Veillard21458c82002-03-27 16:12:22 +0000591 /*
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000592 * Microsoft Visual C++ and Borland C++ Builder have an _fpclass()
593 * function.
Daniel Veillard21458c82002-03-27 16:12:22 +0000594 */
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000595# define TRIO_FPCLASSIFY(n) _fpclass(n)
596# define TRIO_QUIET_NAN _FPCLASS_QNAN
597# define TRIO_SIGNALLING_NAN _FPCLASS_SNAN
598# define TRIO_POSITIVE_INFINITY _FPCLASS_PINF
599# define TRIO_NEGATIVE_INFINITY _FPCLASS_NINF
600# define TRIO_POSITIVE_SUBNORMAL _FPCLASS_PD
601# define TRIO_NEGATIVE_SUBNORMAL _FPCLASS_ND
602# define TRIO_POSITIVE_ZERO _FPCLASS_PZ
603# define TRIO_NEGATIVE_ZERO _FPCLASS_NZ
604# define TRIO_POSITIVE_NORMAL _FPCLASS_PN
605# define TRIO_NEGATIVE_NORMAL _FPCLASS_NN
606
607# elif defined(FP_PLUS_NORM)
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000608 /*
609 * HP-UX 9.x and 10.x have an fpclassify() function, that is different
610 * from the C99 fpclassify() macro supported on HP-UX 11.x.
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000611 *
612 * AIX has class() for C, and _class() for C++, which returns the
613 * same values as the HP-UX fpclassify() function.
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000614 */
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000615# if defined(TRIO_PLATFORM_AIX)
616# if defined(__cplusplus)
617# define TRIO_FPCLASSIFY(n) _class(n)
618# else
619# define TRIO_FPCLASSIFY(n) class(n)
620# endif
621# else
622# define TRIO_FPCLASSIFY(n) fpclassify(n)
623# endif
624# define TRIO_QUIET_NAN FP_QNAN
625# define TRIO_SIGNALLING_NAN FP_SNAN
626# define TRIO_POSITIVE_INFINITY FP_PLUS_INF
627# define TRIO_NEGATIVE_INFINITY FP_MINUS_INF
628# define TRIO_POSITIVE_SUBNORMAL FP_PLUS_DENORM
629# define TRIO_NEGATIVE_SUBNORMAL FP_MINUS_DENORM
630# define TRIO_POSITIVE_ZERO FP_PLUS_ZERO
631# define TRIO_NEGATIVE_ZERO FP_MINUS_ZERO
632# define TRIO_POSITIVE_NORMAL FP_PLUS_NORM
633# define TRIO_NEGATIVE_NORMAL FP_MINUS_NORM
634# endif
635
636# if defined(TRIO_FPCLASSIFY)
637 switch (TRIO_FPCLASSIFY(number)) {
638 case TRIO_QUIET_NAN:
639 case TRIO_SIGNALLING_NAN:
640 *is_negative = TRIO_FALSE; /* NaN has no sign */
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000641 return TRIO_FP_NAN;
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000642 case TRIO_POSITIVE_INFINITY:
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000643 *is_negative = TRIO_FALSE;
644 return TRIO_FP_INFINITE;
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000645 case TRIO_NEGATIVE_INFINITY:
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000646 *is_negative = TRIO_TRUE;
647 return TRIO_FP_INFINITE;
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000648 case TRIO_POSITIVE_SUBNORMAL:
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000649 *is_negative = TRIO_FALSE;
650 return TRIO_FP_SUBNORMAL;
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000651 case TRIO_NEGATIVE_SUBNORMAL:
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000652 *is_negative = TRIO_TRUE;
653 return TRIO_FP_SUBNORMAL;
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000654 case TRIO_POSITIVE_ZERO:
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000655 *is_negative = TRIO_FALSE;
656 return TRIO_FP_ZERO;
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000657 case TRIO_NEGATIVE_ZERO:
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000658 *is_negative = TRIO_TRUE;
659 return TRIO_FP_ZERO;
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000660 case TRIO_POSITIVE_NORMAL:
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000661 *is_negative = TRIO_FALSE;
662 return TRIO_FP_NORMAL;
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000663 case TRIO_NEGATIVE_NORMAL:
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000664 *is_negative = TRIO_TRUE;
665 return TRIO_FP_NORMAL;
666 default:
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000667 /* Just in case... */
668 *is_negative = (number < 0.0);
669 return TRIO_FP_NORMAL;
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000670 }
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000671
672# else
Daniel Veillard21458c82002-03-27 16:12:22 +0000673 /*
674 * Fallback solution.
675 */
676 int rc;
677
678 if (number == 0.0) {
679 /*
680 * In IEEE 754 the sign of zero is ignored in comparisons, so we
681 * have to handle this as a special case by examining the sign bit
682 * directly.
683 */
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000684# if defined(USE_IEEE_754)
Daniel Veillard21458c82002-03-27 16:12:22 +0000685 *is_negative = trio_is_negative(number);
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000686# else
Daniel Veillard21458c82002-03-27 16:12:22 +0000687 *is_negative = TRIO_FALSE; /* FIXME */
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000688# endif
Daniel Veillard21458c82002-03-27 16:12:22 +0000689 return TRIO_FP_ZERO;
690 }
691 if (trio_isnan(number)) {
692 *is_negative = TRIO_FALSE;
693 return TRIO_FP_NAN;
694 }
695 if ((rc = trio_isinf(number))) {
696 *is_negative = (rc == -1);
697 return TRIO_FP_INFINITE;
698 }
699 if ((number > 0.0) && (number < DBL_MIN)) {
700 *is_negative = TRIO_FALSE;
701 return TRIO_FP_SUBNORMAL;
702 }
703 if ((number < 0.0) && (number > -DBL_MIN)) {
704 *is_negative = TRIO_TRUE;
705 return TRIO_FP_SUBNORMAL;
706 }
707 *is_negative = (number < 0.0);
708 return TRIO_FP_NORMAL;
709
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000710# endif
Daniel Veillard21458c82002-03-27 16:12:22 +0000711#endif
712}
713
714/**
715 Examine the sign of a number.
716
717 @param number An arbitrary floating-point number.
718 @return Boolean value indicating whether or not the number has the
719 sign bit set (i.e. is negative).
720*/
721TRIO_PUBLIC int
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000722trio_signbit
723TRIO_ARGS1((number),
724 double number)
Daniel Veillard21458c82002-03-27 16:12:22 +0000725{
726 int is_negative;
727
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000728 (void)trio_fpclassify_and_signbit(number, &is_negative);
Daniel Veillard21458c82002-03-27 16:12:22 +0000729 return is_negative;
730}
731
732/**
733 Examine the class of a number.
734
735 @param number An arbitrary floating-point number.
736 @return Enumerable value indicating the class of @p number
737*/
738TRIO_PUBLIC int
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000739trio_fpclassify
740TRIO_ARGS1((number),
741 double number)
Daniel Veillard21458c82002-03-27 16:12:22 +0000742{
743 int dummy;
744
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000745 return trio_fpclassify_and_signbit(number, &dummy);
Daniel Veillard21458c82002-03-27 16:12:22 +0000746}
747
748
Bjorn Reese026d29f2002-01-19 15:40:18 +0000749/** @} SpecialQuantities */
750
Bjorn Reese45029602001-08-21 09:23:53 +0000751/*************************************************************************
Bjorn Reese026d29f2002-01-19 15:40:18 +0000752 * For test purposes.
753 *
754 * Add the following compiler option to include this test code.
755 *
756 * Unix : -DSTANDALONE
757 * VMS : /DEFINE=(STANDALONE)
Bjorn Reese45029602001-08-21 09:23:53 +0000758 */
759#if defined(STANDALONE)
760# include <stdio.h>
761
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000762static TRIO_CONST char *
763getClassification
Daniel Veillarde645e8c2002-10-22 17:35:37 +0000764TRIO_ARGS1((type),
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000765 int type)
Daniel Veillard21458c82002-03-27 16:12:22 +0000766{
767 switch (type) {
768 case TRIO_FP_INFINITE:
769 return "FP_INFINITE";
770 case TRIO_FP_NAN:
771 return "FP_NAN";
772 case TRIO_FP_NORMAL:
773 return "FP_NORMAL";
774 case TRIO_FP_SUBNORMAL:
775 return "FP_SUBNORMAL";
776 case TRIO_FP_ZERO:
777 return "FP_ZERO";
778 default:
779 return "FP_UNKNOWN";
780 }
781}
782
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000783static void
784print_class
Daniel Veillarde645e8c2002-10-22 17:35:37 +0000785TRIO_ARGS2((prefix, number),
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000786 TRIO_CONST char *prefix,
787 double number)
Daniel Veillard21458c82002-03-27 16:12:22 +0000788{
789 printf("%-6s: %s %-15s %g\n",
790 prefix,
791 trio_signbit(number) ? "-" : "+",
792 getClassification(trio_fpclassify(number)),
793 number);
794}
795
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000796int main(TRIO_NOARGS)
Bjorn Reese45029602001-08-21 09:23:53 +0000797{
798 double my_nan;
799 double my_pinf;
800 double my_ninf;
801# if defined(TRIO_PLATFORM_UNIX)
Daniel Veillardb7c29c32002-09-25 22:44:43 +0000802 void (*signal_handler) TRIO_PROTO((int));
Bjorn Reese45029602001-08-21 09:23:53 +0000803# endif
804
805 my_nan = trio_nan();
806 my_pinf = trio_pinf();
807 my_ninf = trio_ninf();
808
Daniel Veillard21458c82002-03-27 16:12:22 +0000809 print_class("Nan", my_nan);
810 print_class("PInf", my_pinf);
811 print_class("NInf", my_ninf);
812 print_class("PZero", 0.0);
813 print_class("NZero", -0.0);
814 print_class("PNorm", 1.0);
815 print_class("NNorm", -1.0);
816 print_class("PSub", 1.01e-307 - 1.00e-307);
817 print_class("NSub", 1.00e-307 - 1.01e-307);
818
Bjorn Reese45029602001-08-21 09:23:53 +0000819 printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
820 my_nan,
821 ((unsigned char *)&my_nan)[0],
822 ((unsigned char *)&my_nan)[1],
823 ((unsigned char *)&my_nan)[2],
824 ((unsigned char *)&my_nan)[3],
825 ((unsigned char *)&my_nan)[4],
826 ((unsigned char *)&my_nan)[5],
827 ((unsigned char *)&my_nan)[6],
828 ((unsigned char *)&my_nan)[7],
829 trio_isnan(my_nan), trio_isinf(my_nan));
830 printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
831 my_pinf,
832 ((unsigned char *)&my_pinf)[0],
833 ((unsigned char *)&my_pinf)[1],
834 ((unsigned char *)&my_pinf)[2],
835 ((unsigned char *)&my_pinf)[3],
836 ((unsigned char *)&my_pinf)[4],
837 ((unsigned char *)&my_pinf)[5],
838 ((unsigned char *)&my_pinf)[6],
839 ((unsigned char *)&my_pinf)[7],
840 trio_isnan(my_pinf), trio_isinf(my_pinf));
841 printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
842 my_ninf,
843 ((unsigned char *)&my_ninf)[0],
844 ((unsigned char *)&my_ninf)[1],
845 ((unsigned char *)&my_ninf)[2],
846 ((unsigned char *)&my_ninf)[3],
847 ((unsigned char *)&my_ninf)[4],
848 ((unsigned char *)&my_ninf)[5],
849 ((unsigned char *)&my_ninf)[6],
850 ((unsigned char *)&my_ninf)[7],
851 trio_isnan(my_ninf), trio_isinf(my_ninf));
852
853# if defined(TRIO_PLATFORM_UNIX)
854 signal_handler = signal(SIGFPE, SIG_IGN);
855# endif
856
857 my_pinf = DBL_MAX + DBL_MAX;
858 my_ninf = -my_pinf;
859 my_nan = my_pinf / my_pinf;
860
861# if defined(TRIO_PLATFORM_UNIX)
862 signal(SIGFPE, signal_handler);
863# endif
864
865 printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
866 my_nan,
867 ((unsigned char *)&my_nan)[0],
868 ((unsigned char *)&my_nan)[1],
869 ((unsigned char *)&my_nan)[2],
870 ((unsigned char *)&my_nan)[3],
871 ((unsigned char *)&my_nan)[4],
872 ((unsigned char *)&my_nan)[5],
873 ((unsigned char *)&my_nan)[6],
874 ((unsigned char *)&my_nan)[7],
875 trio_isnan(my_nan), trio_isinf(my_nan));
876 printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
877 my_pinf,
878 ((unsigned char *)&my_pinf)[0],
879 ((unsigned char *)&my_pinf)[1],
880 ((unsigned char *)&my_pinf)[2],
881 ((unsigned char *)&my_pinf)[3],
882 ((unsigned char *)&my_pinf)[4],
883 ((unsigned char *)&my_pinf)[5],
884 ((unsigned char *)&my_pinf)[6],
885 ((unsigned char *)&my_pinf)[7],
886 trio_isnan(my_pinf), trio_isinf(my_pinf));
887 printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
888 my_ninf,
889 ((unsigned char *)&my_ninf)[0],
890 ((unsigned char *)&my_ninf)[1],
891 ((unsigned char *)&my_ninf)[2],
892 ((unsigned char *)&my_ninf)[3],
893 ((unsigned char *)&my_ninf)[4],
894 ((unsigned char *)&my_ninf)[5],
895 ((unsigned char *)&my_ninf)[6],
896 ((unsigned char *)&my_ninf)[7],
897 trio_isnan(my_ninf), trio_isinf(my_ninf));
Daniel Veillarda48ed3d2003-04-03 15:28:28 +0000898
Bjorn Reese45029602001-08-21 09:23:53 +0000899 return 0;
900}
901#endif