/src/libxml2-2.9.7/trionan.c
Line | Count | Source (jump to first uncovered line) |
1 | | /************************************************************************* |
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 | | ************************************************************************/ |
33 | | |
34 | | /* |
35 | | * TODO: |
36 | | * o Put all the magic into trio_fpclassify_and_signbit(), and use this from |
37 | | * trio_isnan() etc. |
38 | | */ |
39 | | |
40 | | /************************************************************************* |
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 |
53 | | #if defined(TRIO_COMPILER_DECC) |
54 | | # if defined(__linux__) |
55 | | # include <cpml.h> |
56 | | # else |
57 | | # include <fp_class.h> |
58 | | # endif |
59 | | #endif |
60 | | #include <assert.h> |
61 | | |
62 | | #if defined(TRIO_DOCUMENTATION) |
63 | | # include "doc/doc_nan.h" |
64 | | #endif |
65 | | /** @addtogroup SpecialQuantities |
66 | | @{ |
67 | | */ |
68 | | |
69 | | /************************************************************************* |
70 | | * Definitions |
71 | | */ |
72 | | |
73 | | #define TRIO_TRUE (1 == 1) |
74 | | #define TRIO_FALSE (0 == 1) |
75 | | |
76 | | /* |
77 | | * We must enable IEEE floating-point on Alpha |
78 | | */ |
79 | | #if defined(__alpha) && !defined(_IEEE_FP) |
80 | | # if defined(TRIO_COMPILER_DECC) |
81 | | # if defined(TRIO_PLATFORM_VMS) |
82 | | # error "Must be compiled with option /IEEE_MODE=UNDERFLOW_TO_ZERO/FLOAT=IEEE" |
83 | | # else |
84 | | # if !defined(_CFE) |
85 | | # error "Must be compiled with option -ieee" |
86 | | # endif |
87 | | # endif |
88 | | # elif defined(TRIO_COMPILER_GCC) && (defined(__osf__) || defined(__linux__)) |
89 | | # error "Must be compiled with option -mieee" |
90 | | # endif |
91 | | #endif /* __alpha && ! _IEEE_FP */ |
92 | | |
93 | | /* |
94 | | * In ANSI/IEEE 754-1985 64-bits double format numbers have the |
95 | | * following properties (amoungst others) |
96 | | * |
97 | | * o FLT_RADIX == 2: binary encoding |
98 | | * o DBL_MAX_EXP == 1024: 11 bits exponent, where one bit is used |
99 | | * to indicate special numbers (e.g. NaN and Infinity), so the |
100 | | * maximum exponent is 10 bits wide (2^10 == 1024). |
101 | | * o DBL_MANT_DIG == 53: The mantissa is 52 bits wide, but because |
102 | | * numbers are normalized the initial binary 1 is represented |
103 | | * implicitly (the so-called "hidden bit"), which leaves us with |
104 | | * the ability to represent 53 bits wide mantissa. |
105 | | */ |
106 | | #if (FLT_RADIX == 2) && (DBL_MAX_EXP == 1024) && (DBL_MANT_DIG == 53) |
107 | | # define USE_IEEE_754 |
108 | | #endif |
109 | | |
110 | | |
111 | | /************************************************************************* |
112 | | * Constants |
113 | | */ |
114 | | |
115 | | static TRIO_CONST char rcsid[] = "@(#)$Id$"; |
116 | | |
117 | | #if defined(USE_IEEE_754) |
118 | | |
119 | | /* |
120 | | * Endian-agnostic indexing macro. |
121 | | * |
122 | | * The value of internalEndianMagic, when converted into a 64-bit |
123 | | * integer, becomes 0x0706050403020100 (we could have used a 64-bit |
124 | | * integer value instead of a double, but not all platforms supports |
125 | | * that type). The value is automatically encoded with the correct |
126 | | * endianess by the compiler, which means that we can support any |
127 | | * kind of endianess. The individual bytes are then used as an index |
128 | | * for the IEEE 754 bit-patterns and masks. |
129 | | */ |
130 | 112 | #define TRIO_DOUBLE_INDEX(x) (((unsigned char *)&internalEndianMagic)[7-(x)]) |
131 | | |
132 | | #if (defined(__BORLANDC__) && __BORLANDC__ >= 0x0590) |
133 | | static TRIO_CONST double internalEndianMagic = 7.949928895127362e-275; |
134 | | #else |
135 | | static TRIO_CONST double internalEndianMagic = 7.949928895127363e-275; |
136 | | #endif |
137 | | |
138 | | /* Mask for the exponent */ |
139 | | static TRIO_CONST unsigned char ieee_754_exponent_mask[] = { |
140 | | 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
141 | | }; |
142 | | |
143 | | /* Mask for the mantissa */ |
144 | | static TRIO_CONST unsigned char ieee_754_mantissa_mask[] = { |
145 | | 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF |
146 | | }; |
147 | | |
148 | | /* Mask for the sign bit */ |
149 | | static TRIO_CONST unsigned char ieee_754_sign_mask[] = { |
150 | | 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
151 | | }; |
152 | | |
153 | | /* Bit-pattern for negative zero */ |
154 | | static TRIO_CONST unsigned char ieee_754_negzero_array[] = { |
155 | | 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
156 | | }; |
157 | | |
158 | | /* Bit-pattern for infinity */ |
159 | | static TRIO_CONST unsigned char ieee_754_infinity_array[] = { |
160 | | 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
161 | | }; |
162 | | |
163 | | /* Bit-pattern for quiet NaN */ |
164 | | static TRIO_CONST unsigned char ieee_754_qnan_array[] = { |
165 | | 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
166 | | }; |
167 | | |
168 | | |
169 | | /************************************************************************* |
170 | | * Functions |
171 | | */ |
172 | | |
173 | | /* |
174 | | * trio_make_double |
175 | | */ |
176 | | TRIO_PRIVATE double |
177 | | trio_make_double |
178 | | TRIO_ARGS1((values), |
179 | | TRIO_CONST unsigned char *values) |
180 | 14 | { |
181 | 14 | TRIO_VOLATILE double result; |
182 | 14 | int i; |
183 | | |
184 | 126 | for (i = 0; i < (int)sizeof(double); i++) { |
185 | 112 | ((TRIO_VOLATILE unsigned char *)&result)[TRIO_DOUBLE_INDEX(i)] = values[i]; |
186 | 112 | } |
187 | 14 | return result; |
188 | 14 | } |
189 | | |
190 | | /* |
191 | | * trio_is_special_quantity |
192 | | */ |
193 | | TRIO_PRIVATE int |
194 | | trio_is_special_quantity |
195 | | TRIO_ARGS2((number, has_mantissa), |
196 | | double number, |
197 | | int *has_mantissa) |
198 | 0 | { |
199 | 0 | unsigned int i; |
200 | 0 | unsigned char current; |
201 | 0 | int is_special_quantity = TRIO_TRUE; |
202 | 0 |
|
203 | 0 | *has_mantissa = 0; |
204 | 0 |
|
205 | 0 | for (i = 0; i < (unsigned int)sizeof(double); i++) { |
206 | 0 | current = ((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)]; |
207 | 0 | is_special_quantity |
208 | 0 | &= ((current & ieee_754_exponent_mask[i]) == ieee_754_exponent_mask[i]); |
209 | 0 | *has_mantissa |= (current & ieee_754_mantissa_mask[i]); |
210 | 0 | } |
211 | 0 | return is_special_quantity; |
212 | 0 | } |
213 | | |
214 | | /* |
215 | | * trio_is_negative |
216 | | */ |
217 | | TRIO_PRIVATE int |
218 | | trio_is_negative |
219 | | TRIO_ARGS1((number), |
220 | | double number) |
221 | 0 | { |
222 | 0 | unsigned int i; |
223 | 0 | int is_negative = TRIO_FALSE; |
224 | 0 |
|
225 | 0 | for (i = 0; i < (unsigned int)sizeof(double); i++) { |
226 | 0 | is_negative |= (((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)] |
227 | 0 | & ieee_754_sign_mask[i]); |
228 | 0 | } |
229 | 0 | return is_negative; |
230 | 0 | } |
231 | | |
232 | | #endif /* USE_IEEE_754 */ |
233 | | |
234 | | |
235 | | /** |
236 | | Generate negative zero. |
237 | | |
238 | | @return Floating-point representation of negative zero. |
239 | | */ |
240 | | TRIO_PUBLIC double |
241 | | trio_nzero(TRIO_NOARGS) |
242 | 14 | { |
243 | 14 | #if defined(USE_IEEE_754) |
244 | 14 | return trio_make_double(ieee_754_negzero_array); |
245 | | #else |
246 | | TRIO_VOLATILE double zero = 0.0; |
247 | | |
248 | | return -zero; |
249 | | #endif |
250 | 14 | } |
251 | | |
252 | | /** |
253 | | Generate positive infinity. |
254 | | |
255 | | @return Floating-point representation of positive infinity. |
256 | | */ |
257 | | TRIO_PUBLIC double |
258 | | trio_pinf(TRIO_NOARGS) |
259 | 28 | { |
260 | | /* Cache the result */ |
261 | 28 | static double result = 0.0; |
262 | | |
263 | 28 | if (result == 0.0) { |
264 | | |
265 | 14 | #if defined(INFINITY) && defined(__STDC_IEC_559__) |
266 | 14 | result = (double)INFINITY; |
267 | | |
268 | | #elif defined(USE_IEEE_754) |
269 | | result = trio_make_double(ieee_754_infinity_array); |
270 | | |
271 | | #else |
272 | | /* |
273 | | * If HUGE_VAL is different from DBL_MAX, then HUGE_VAL is used |
274 | | * as infinity. Otherwise we have to resort to an overflow |
275 | | * operation to generate infinity. |
276 | | */ |
277 | | # if defined(TRIO_PLATFORM_UNIX) |
278 | | void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN); |
279 | | # endif |
280 | | |
281 | | result = HUGE_VAL; |
282 | | if (HUGE_VAL == DBL_MAX) { |
283 | | /* Force overflow */ |
284 | | result += HUGE_VAL; |
285 | | } |
286 | | |
287 | | # if defined(TRIO_PLATFORM_UNIX) |
288 | | signal(SIGFPE, signal_handler); |
289 | | # endif |
290 | | |
291 | | #endif |
292 | 14 | } |
293 | 28 | return result; |
294 | 28 | } |
295 | | |
296 | | /** |
297 | | Generate negative infinity. |
298 | | |
299 | | @return Floating-point value of negative infinity. |
300 | | */ |
301 | | TRIO_PUBLIC double |
302 | | trio_ninf(TRIO_NOARGS) |
303 | 14 | { |
304 | 14 | static double result = 0.0; |
305 | | |
306 | 14 | if (result == 0.0) { |
307 | | /* |
308 | | * Negative infinity is calculated by negating positive infinity, |
309 | | * which can be done because it is legal to do calculations on |
310 | | * infinity (for example, 1 / infinity == 0). |
311 | | */ |
312 | 14 | result = -trio_pinf(); |
313 | 14 | } |
314 | 14 | return result; |
315 | 14 | } |
316 | | |
317 | | /** |
318 | | Generate NaN. |
319 | | |
320 | | @return Floating-point representation of NaN. |
321 | | */ |
322 | | TRIO_PUBLIC double |
323 | | trio_nan(TRIO_NOARGS) |
324 | 14 | { |
325 | | /* Cache the result */ |
326 | 14 | static double result = 0.0; |
327 | | |
328 | 14 | if (result == 0.0) { |
329 | | |
330 | 14 | #if defined(TRIO_COMPILER_SUPPORTS_C99) |
331 | 14 | result = nan(""); |
332 | | |
333 | | #elif defined(NAN) && defined(__STDC_IEC_559__) |
334 | | result = (double)NAN; |
335 | | |
336 | | #elif defined(USE_IEEE_754) |
337 | | result = trio_make_double(ieee_754_qnan_array); |
338 | | |
339 | | #else |
340 | | /* |
341 | | * There are several ways to generate NaN. The one used here is |
342 | | * to divide infinity by infinity. I would have preferred to add |
343 | | * negative infinity to positive infinity, but that yields wrong |
344 | | * result (infinity) on FreeBSD. |
345 | | * |
346 | | * This may fail if the hardware does not support NaN, or if |
347 | | * the Invalid Operation floating-point exception is unmasked. |
348 | | */ |
349 | | # if defined(TRIO_PLATFORM_UNIX) |
350 | | void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN); |
351 | | # endif |
352 | | |
353 | | result = trio_pinf() / trio_pinf(); |
354 | | |
355 | | # if defined(TRIO_PLATFORM_UNIX) |
356 | | signal(SIGFPE, signal_handler); |
357 | | # endif |
358 | | |
359 | | #endif |
360 | 14 | } |
361 | 14 | return result; |
362 | 14 | } |
363 | | |
364 | | /** |
365 | | Check for NaN. |
366 | | |
367 | | @param number An arbitrary floating-point number. |
368 | | @return Boolean value indicating whether or not the number is a NaN. |
369 | | */ |
370 | | TRIO_PUBLIC int |
371 | | trio_isnan |
372 | | TRIO_ARGS1((number), |
373 | | double number) |
374 | 0 | { |
375 | 0 | #if (defined(TRIO_COMPILER_SUPPORTS_C99) && defined(isnan)) \ |
376 | 0 | || defined(TRIO_COMPILER_SUPPORTS_UNIX95) |
377 | | /* |
378 | | * C99 defines isnan() as a macro. UNIX95 defines isnan() as a |
379 | | * function. This function was already present in XPG4, but this |
380 | | * is a bit tricky to detect with compiler defines, so we choose |
381 | | * the conservative approach and only use it for UNIX95. |
382 | | */ |
383 | 0 | return isnan(number); |
384 | |
|
385 | | #elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB) |
386 | | /* |
387 | | * Microsoft Visual C++ and Borland C++ Builder have an _isnan() |
388 | | * function. |
389 | | */ |
390 | | return _isnan(number) ? TRIO_TRUE : TRIO_FALSE; |
391 | | |
392 | | #elif defined(USE_IEEE_754) |
393 | | /* |
394 | | * Examine IEEE 754 bit-pattern. A NaN must have a special exponent |
395 | | * pattern, and a non-empty mantissa. |
396 | | */ |
397 | | int has_mantissa; |
398 | | int is_special_quantity; |
399 | | |
400 | | is_special_quantity = trio_is_special_quantity(number, &has_mantissa); |
401 | | |
402 | | return (is_special_quantity && has_mantissa); |
403 | | |
404 | | #else |
405 | | /* |
406 | | * Fallback solution |
407 | | */ |
408 | | int status; |
409 | | double integral, fraction; |
410 | | |
411 | | # if defined(TRIO_PLATFORM_UNIX) |
412 | | void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN); |
413 | | # endif |
414 | | |
415 | | status = (/* |
416 | | * NaN is the only number which does not compare to itself |
417 | | */ |
418 | | ((TRIO_VOLATILE double)number != (TRIO_VOLATILE double)number) || |
419 | | /* |
420 | | * Fallback solution if NaN compares to NaN |
421 | | */ |
422 | | ((number != 0.0) && |
423 | | (fraction = modf(number, &integral), |
424 | | integral == fraction))); |
425 | | |
426 | | # if defined(TRIO_PLATFORM_UNIX) |
427 | | signal(SIGFPE, signal_handler); |
428 | | # endif |
429 | | |
430 | | return status; |
431 | | |
432 | | #endif |
433 | 0 | } |
434 | | |
435 | | /** |
436 | | Check for infinity. |
437 | | |
438 | | @param number An arbitrary floating-point number. |
439 | | @return 1 if positive infinity, -1 if negative infinity, 0 otherwise. |
440 | | */ |
441 | | TRIO_PUBLIC int |
442 | | trio_isinf |
443 | | TRIO_ARGS1((number), |
444 | | double number) |
445 | 0 | { |
446 | | #if defined(TRIO_COMPILER_DECC) && !defined(__linux__) |
447 | | /* |
448 | | * DECC has an isinf() macro, but it works differently than that |
449 | | * of C99, so we use the fp_class() function instead. |
450 | | */ |
451 | | return ((fp_class(number) == FP_POS_INF) |
452 | | ? 1 |
453 | | : ((fp_class(number) == FP_NEG_INF) ? -1 : 0)); |
454 | | |
455 | | #elif defined(isinf) |
456 | | /* |
457 | | * C99 defines isinf() as a macro. |
458 | | */ |
459 | 0 | return isinf(number) |
460 | 0 | ? ((number > 0.0) ? 1 : -1) |
461 | 0 | : 0; |
462 | |
|
463 | | #elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB) |
464 | | /* |
465 | | * Microsoft Visual C++ and Borland C++ Builder have an _fpclass() |
466 | | * function that can be used to detect infinity. |
467 | | */ |
468 | | return ((_fpclass(number) == _FPCLASS_PINF) |
469 | | ? 1 |
470 | | : ((_fpclass(number) == _FPCLASS_NINF) ? -1 : 0)); |
471 | | |
472 | | #elif defined(USE_IEEE_754) |
473 | | /* |
474 | | * Examine IEEE 754 bit-pattern. Infinity must have a special exponent |
475 | | * pattern, and an empty mantissa. |
476 | | */ |
477 | | int has_mantissa; |
478 | | int is_special_quantity; |
479 | | |
480 | | is_special_quantity = trio_is_special_quantity(number, &has_mantissa); |
481 | | |
482 | | return (is_special_quantity && !has_mantissa) |
483 | | ? ((number < 0.0) ? -1 : 1) |
484 | | : 0; |
485 | | |
486 | | #else |
487 | | /* |
488 | | * Fallback solution. |
489 | | */ |
490 | | int status; |
491 | | |
492 | | # if defined(TRIO_PLATFORM_UNIX) |
493 | | void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN); |
494 | | # endif |
495 | | |
496 | | double infinity = trio_pinf(); |
497 | | |
498 | | status = ((number == infinity) |
499 | | ? 1 |
500 | | : ((number == -infinity) ? -1 : 0)); |
501 | | |
502 | | # if defined(TRIO_PLATFORM_UNIX) |
503 | | signal(SIGFPE, signal_handler); |
504 | | # endif |
505 | | |
506 | | return status; |
507 | | |
508 | | #endif |
509 | 0 | } |
510 | | |
511 | | #if 0 |
512 | | /* Temporary fix - this routine is not used anywhere */ |
513 | | /** |
514 | | Check for finity. |
515 | | |
516 | | @param number An arbitrary floating-point number. |
517 | | @return Boolean value indicating whether or not the number is a finite. |
518 | | */ |
519 | | TRIO_PUBLIC int |
520 | | trio_isfinite |
521 | | TRIO_ARGS1((number), |
522 | | double number) |
523 | | { |
524 | | #if defined(TRIO_COMPILER_SUPPORTS_C99) && defined(isfinite) |
525 | | /* |
526 | | * C99 defines isfinite() as a macro. |
527 | | */ |
528 | | return isfinite(number); |
529 | | |
530 | | #elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB) |
531 | | /* |
532 | | * Microsoft Visual C++ and Borland C++ Builder use _finite(). |
533 | | */ |
534 | | return _finite(number); |
535 | | |
536 | | #elif defined(USE_IEEE_754) |
537 | | /* |
538 | | * Examine IEEE 754 bit-pattern. For finity we do not care about the |
539 | | * mantissa. |
540 | | */ |
541 | | int dummy; |
542 | | |
543 | | return (! trio_is_special_quantity(number, &dummy)); |
544 | | |
545 | | #else |
546 | | /* |
547 | | * Fallback solution. |
548 | | */ |
549 | | return ((trio_isinf(number) == 0) && (trio_isnan(number) == 0)); |
550 | | |
551 | | #endif |
552 | | } |
553 | | |
554 | | #endif |
555 | | |
556 | | /* |
557 | | * The sign of NaN is always false |
558 | | */ |
559 | | TRIO_PUBLIC int |
560 | | trio_fpclassify_and_signbit |
561 | | TRIO_ARGS2((number, is_negative), |
562 | | double number, |
563 | | int *is_negative) |
564 | 0 | { |
565 | 0 | #if defined(fpclassify) && defined(signbit) |
566 | | /* |
567 | | * C99 defines fpclassify() and signbit() as a macros |
568 | | */ |
569 | 0 | *is_negative = signbit(number); |
570 | 0 | switch (fpclassify(number)) { |
571 | 0 | case FP_NAN: |
572 | 0 | return TRIO_FP_NAN; |
573 | 0 | case FP_INFINITE: |
574 | 0 | return TRIO_FP_INFINITE; |
575 | 0 | case FP_SUBNORMAL: |
576 | 0 | return TRIO_FP_SUBNORMAL; |
577 | 0 | case FP_ZERO: |
578 | 0 | return TRIO_FP_ZERO; |
579 | 0 | default: |
580 | 0 | return TRIO_FP_NORMAL; |
581 | 0 | } |
582 | |
|
583 | | #else |
584 | | # if defined(TRIO_COMPILER_DECC) |
585 | | /* |
586 | | * DECC has an fp_class() function. |
587 | | */ |
588 | | # define TRIO_FPCLASSIFY(n) fp_class(n) |
589 | | # define TRIO_QUIET_NAN FP_QNAN |
590 | | # define TRIO_SIGNALLING_NAN FP_SNAN |
591 | | # define TRIO_POSITIVE_INFINITY FP_POS_INF |
592 | | # define TRIO_NEGATIVE_INFINITY FP_NEG_INF |
593 | | # define TRIO_POSITIVE_SUBNORMAL FP_POS_DENORM |
594 | | # define TRIO_NEGATIVE_SUBNORMAL FP_NEG_DENORM |
595 | | # define TRIO_POSITIVE_ZERO FP_POS_ZERO |
596 | | # define TRIO_NEGATIVE_ZERO FP_NEG_ZERO |
597 | | # define TRIO_POSITIVE_NORMAL FP_POS_NORM |
598 | | # define TRIO_NEGATIVE_NORMAL FP_NEG_NORM |
599 | | |
600 | | # elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB) |
601 | | /* |
602 | | * Microsoft Visual C++ and Borland C++ Builder have an _fpclass() |
603 | | * function. |
604 | | */ |
605 | | # define TRIO_FPCLASSIFY(n) _fpclass(n) |
606 | | # define TRIO_QUIET_NAN _FPCLASS_QNAN |
607 | | # define TRIO_SIGNALLING_NAN _FPCLASS_SNAN |
608 | | # define TRIO_POSITIVE_INFINITY _FPCLASS_PINF |
609 | | # define TRIO_NEGATIVE_INFINITY _FPCLASS_NINF |
610 | | # define TRIO_POSITIVE_SUBNORMAL _FPCLASS_PD |
611 | | # define TRIO_NEGATIVE_SUBNORMAL _FPCLASS_ND |
612 | | # define TRIO_POSITIVE_ZERO _FPCLASS_PZ |
613 | | # define TRIO_NEGATIVE_ZERO _FPCLASS_NZ |
614 | | # define TRIO_POSITIVE_NORMAL _FPCLASS_PN |
615 | | # define TRIO_NEGATIVE_NORMAL _FPCLASS_NN |
616 | | |
617 | | # elif defined(FP_PLUS_NORM) |
618 | | /* |
619 | | * HP-UX 9.x and 10.x have an fpclassify() function, that is different |
620 | | * from the C99 fpclassify() macro supported on HP-UX 11.x. |
621 | | * |
622 | | * AIX has class() for C, and _class() for C++, which returns the |
623 | | * same values as the HP-UX fpclassify() function. |
624 | | */ |
625 | | # if defined(TRIO_PLATFORM_AIX) |
626 | | # if defined(__cplusplus) |
627 | | # define TRIO_FPCLASSIFY(n) _class(n) |
628 | | # else |
629 | | # define TRIO_FPCLASSIFY(n) class(n) |
630 | | # endif |
631 | | # else |
632 | | # define TRIO_FPCLASSIFY(n) fpclassify(n) |
633 | | # endif |
634 | | # define TRIO_QUIET_NAN FP_QNAN |
635 | | # define TRIO_SIGNALLING_NAN FP_SNAN |
636 | | # define TRIO_POSITIVE_INFINITY FP_PLUS_INF |
637 | | # define TRIO_NEGATIVE_INFINITY FP_MINUS_INF |
638 | | # define TRIO_POSITIVE_SUBNORMAL FP_PLUS_DENORM |
639 | | # define TRIO_NEGATIVE_SUBNORMAL FP_MINUS_DENORM |
640 | | # define TRIO_POSITIVE_ZERO FP_PLUS_ZERO |
641 | | # define TRIO_NEGATIVE_ZERO FP_MINUS_ZERO |
642 | | # define TRIO_POSITIVE_NORMAL FP_PLUS_NORM |
643 | | # define TRIO_NEGATIVE_NORMAL FP_MINUS_NORM |
644 | | # endif |
645 | | |
646 | | # if defined(TRIO_FPCLASSIFY) |
647 | | switch (TRIO_FPCLASSIFY(number)) { |
648 | | case TRIO_QUIET_NAN: |
649 | | case TRIO_SIGNALLING_NAN: |
650 | | *is_negative = TRIO_FALSE; /* NaN has no sign */ |
651 | | return TRIO_FP_NAN; |
652 | | case TRIO_POSITIVE_INFINITY: |
653 | | *is_negative = TRIO_FALSE; |
654 | | return TRIO_FP_INFINITE; |
655 | | case TRIO_NEGATIVE_INFINITY: |
656 | | *is_negative = TRIO_TRUE; |
657 | | return TRIO_FP_INFINITE; |
658 | | case TRIO_POSITIVE_SUBNORMAL: |
659 | | *is_negative = TRIO_FALSE; |
660 | | return TRIO_FP_SUBNORMAL; |
661 | | case TRIO_NEGATIVE_SUBNORMAL: |
662 | | *is_negative = TRIO_TRUE; |
663 | | return TRIO_FP_SUBNORMAL; |
664 | | case TRIO_POSITIVE_ZERO: |
665 | | *is_negative = TRIO_FALSE; |
666 | | return TRIO_FP_ZERO; |
667 | | case TRIO_NEGATIVE_ZERO: |
668 | | *is_negative = TRIO_TRUE; |
669 | | return TRIO_FP_ZERO; |
670 | | case TRIO_POSITIVE_NORMAL: |
671 | | *is_negative = TRIO_FALSE; |
672 | | return TRIO_FP_NORMAL; |
673 | | case TRIO_NEGATIVE_NORMAL: |
674 | | *is_negative = TRIO_TRUE; |
675 | | return TRIO_FP_NORMAL; |
676 | | default: |
677 | | /* Just in case... */ |
678 | | *is_negative = (number < 0.0); |
679 | | return TRIO_FP_NORMAL; |
680 | | } |
681 | | |
682 | | # else |
683 | | /* |
684 | | * Fallback solution. |
685 | | */ |
686 | | int rc; |
687 | | |
688 | | if (number == 0.0) { |
689 | | /* |
690 | | * In IEEE 754 the sign of zero is ignored in comparisons, so we |
691 | | * have to handle this as a special case by examining the sign bit |
692 | | * directly. |
693 | | */ |
694 | | # if defined(USE_IEEE_754) |
695 | | *is_negative = trio_is_negative(number); |
696 | | # else |
697 | | *is_negative = TRIO_FALSE; /* FIXME */ |
698 | | # endif |
699 | | return TRIO_FP_ZERO; |
700 | | } |
701 | | if (trio_isnan(number)) { |
702 | | *is_negative = TRIO_FALSE; |
703 | | return TRIO_FP_NAN; |
704 | | } |
705 | | if ((rc = trio_isinf(number))) { |
706 | | *is_negative = (rc == -1); |
707 | | return TRIO_FP_INFINITE; |
708 | | } |
709 | | if ((number > 0.0) && (number < DBL_MIN)) { |
710 | | *is_negative = TRIO_FALSE; |
711 | | return TRIO_FP_SUBNORMAL; |
712 | | } |
713 | | if ((number < 0.0) && (number > -DBL_MIN)) { |
714 | | *is_negative = TRIO_TRUE; |
715 | | return TRIO_FP_SUBNORMAL; |
716 | | } |
717 | | *is_negative = (number < 0.0); |
718 | | return TRIO_FP_NORMAL; |
719 | | |
720 | | # endif |
721 | | #endif |
722 | 0 | } |
723 | | |
724 | | /** |
725 | | Examine the sign of a number. |
726 | | |
727 | | @param number An arbitrary floating-point number. |
728 | | @return Boolean value indicating whether or not the number has the |
729 | | sign bit set (i.e. is negative). |
730 | | */ |
731 | | TRIO_PUBLIC int |
732 | | trio_signbit |
733 | | TRIO_ARGS1((number), |
734 | | double number) |
735 | 0 | { |
736 | 0 | int is_negative; |
737 | |
|
738 | 0 | (void)trio_fpclassify_and_signbit(number, &is_negative); |
739 | 0 | return is_negative; |
740 | 0 | } |
741 | | |
742 | | #if 0 |
743 | | /* Temporary fix - this routine is not used in libxml */ |
744 | | /** |
745 | | Examine the class of a number. |
746 | | |
747 | | @param number An arbitrary floating-point number. |
748 | | @return Enumerable value indicating the class of @p number |
749 | | */ |
750 | | TRIO_PUBLIC int |
751 | | trio_fpclassify |
752 | | TRIO_ARGS1((number), |
753 | | double number) |
754 | | { |
755 | | int dummy; |
756 | | |
757 | | return trio_fpclassify_and_signbit(number, &dummy); |
758 | | } |
759 | | |
760 | | #endif |
761 | | |
762 | | /** @} SpecialQuantities */ |
763 | | |
764 | | /************************************************************************* |
765 | | * For test purposes. |
766 | | * |
767 | | * Add the following compiler option to include this test code. |
768 | | * |
769 | | * Unix : -DSTANDALONE |
770 | | * VMS : /DEFINE=(STANDALONE) |
771 | | */ |
772 | | #if defined(STANDALONE) |
773 | | # include <stdio.h> |
774 | | |
775 | | static TRIO_CONST char * |
776 | | getClassification |
777 | | TRIO_ARGS1((type), |
778 | | int type) |
779 | | { |
780 | | switch (type) { |
781 | | case TRIO_FP_INFINITE: |
782 | | return "FP_INFINITE"; |
783 | | case TRIO_FP_NAN: |
784 | | return "FP_NAN"; |
785 | | case TRIO_FP_NORMAL: |
786 | | return "FP_NORMAL"; |
787 | | case TRIO_FP_SUBNORMAL: |
788 | | return "FP_SUBNORMAL"; |
789 | | case TRIO_FP_ZERO: |
790 | | return "FP_ZERO"; |
791 | | default: |
792 | | return "FP_UNKNOWN"; |
793 | | } |
794 | | } |
795 | | |
796 | | static void |
797 | | print_class |
798 | | TRIO_ARGS2((prefix, number), |
799 | | TRIO_CONST char *prefix, |
800 | | double number) |
801 | | { |
802 | | printf("%-6s: %s %-15s %g\n", |
803 | | prefix, |
804 | | trio_signbit(number) ? "-" : "+", |
805 | | getClassification(TRIO_FPCLASSIFY(number)), |
806 | | number); |
807 | | } |
808 | | |
809 | | int main(TRIO_NOARGS) |
810 | | { |
811 | | double my_nan; |
812 | | double my_pinf; |
813 | | double my_ninf; |
814 | | # if defined(TRIO_PLATFORM_UNIX) |
815 | | void (*signal_handler) TRIO_PROTO((int)); |
816 | | # endif |
817 | | |
818 | | my_nan = trio_nan(); |
819 | | my_pinf = trio_pinf(); |
820 | | my_ninf = trio_ninf(); |
821 | | |
822 | | print_class("Nan", my_nan); |
823 | | print_class("PInf", my_pinf); |
824 | | print_class("NInf", my_ninf); |
825 | | print_class("PZero", 0.0); |
826 | | print_class("NZero", -0.0); |
827 | | print_class("PNorm", 1.0); |
828 | | print_class("NNorm", -1.0); |
829 | | print_class("PSub", 1.01e-307 - 1.00e-307); |
830 | | print_class("NSub", 1.00e-307 - 1.01e-307); |
831 | | |
832 | | printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", |
833 | | my_nan, |
834 | | ((unsigned char *)&my_nan)[0], |
835 | | ((unsigned char *)&my_nan)[1], |
836 | | ((unsigned char *)&my_nan)[2], |
837 | | ((unsigned char *)&my_nan)[3], |
838 | | ((unsigned char *)&my_nan)[4], |
839 | | ((unsigned char *)&my_nan)[5], |
840 | | ((unsigned char *)&my_nan)[6], |
841 | | ((unsigned char *)&my_nan)[7], |
842 | | trio_isnan(my_nan), trio_isinf(my_nan)); |
843 | | printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", |
844 | | my_pinf, |
845 | | ((unsigned char *)&my_pinf)[0], |
846 | | ((unsigned char *)&my_pinf)[1], |
847 | | ((unsigned char *)&my_pinf)[2], |
848 | | ((unsigned char *)&my_pinf)[3], |
849 | | ((unsigned char *)&my_pinf)[4], |
850 | | ((unsigned char *)&my_pinf)[5], |
851 | | ((unsigned char *)&my_pinf)[6], |
852 | | ((unsigned char *)&my_pinf)[7], |
853 | | trio_isnan(my_pinf), trio_isinf(my_pinf)); |
854 | | printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", |
855 | | my_ninf, |
856 | | ((unsigned char *)&my_ninf)[0], |
857 | | ((unsigned char *)&my_ninf)[1], |
858 | | ((unsigned char *)&my_ninf)[2], |
859 | | ((unsigned char *)&my_ninf)[3], |
860 | | ((unsigned char *)&my_ninf)[4], |
861 | | ((unsigned char *)&my_ninf)[5], |
862 | | ((unsigned char *)&my_ninf)[6], |
863 | | ((unsigned char *)&my_ninf)[7], |
864 | | trio_isnan(my_ninf), trio_isinf(my_ninf)); |
865 | | |
866 | | # if defined(TRIO_PLATFORM_UNIX) |
867 | | signal_handler = signal(SIGFPE, SIG_IGN); |
868 | | # endif |
869 | | |
870 | | my_pinf = DBL_MAX + DBL_MAX; |
871 | | my_ninf = -my_pinf; |
872 | | my_nan = my_pinf / my_pinf; |
873 | | |
874 | | # if defined(TRIO_PLATFORM_UNIX) |
875 | | signal(SIGFPE, signal_handler); |
876 | | # endif |
877 | | |
878 | | printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", |
879 | | my_nan, |
880 | | ((unsigned char *)&my_nan)[0], |
881 | | ((unsigned char *)&my_nan)[1], |
882 | | ((unsigned char *)&my_nan)[2], |
883 | | ((unsigned char *)&my_nan)[3], |
884 | | ((unsigned char *)&my_nan)[4], |
885 | | ((unsigned char *)&my_nan)[5], |
886 | | ((unsigned char *)&my_nan)[6], |
887 | | ((unsigned char *)&my_nan)[7], |
888 | | trio_isnan(my_nan), trio_isinf(my_nan)); |
889 | | printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", |
890 | | my_pinf, |
891 | | ((unsigned char *)&my_pinf)[0], |
892 | | ((unsigned char *)&my_pinf)[1], |
893 | | ((unsigned char *)&my_pinf)[2], |
894 | | ((unsigned char *)&my_pinf)[3], |
895 | | ((unsigned char *)&my_pinf)[4], |
896 | | ((unsigned char *)&my_pinf)[5], |
897 | | ((unsigned char *)&my_pinf)[6], |
898 | | ((unsigned char *)&my_pinf)[7], |
899 | | trio_isnan(my_pinf), trio_isinf(my_pinf)); |
900 | | printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", |
901 | | my_ninf, |
902 | | ((unsigned char *)&my_ninf)[0], |
903 | | ((unsigned char *)&my_ninf)[1], |
904 | | ((unsigned char *)&my_ninf)[2], |
905 | | ((unsigned char *)&my_ninf)[3], |
906 | | ((unsigned char *)&my_ninf)[4], |
907 | | ((unsigned char *)&my_ninf)[5], |
908 | | ((unsigned char *)&my_ninf)[6], |
909 | | ((unsigned char *)&my_ninf)[7], |
910 | | trio_isnan(my_ninf), trio_isinf(my_ninf)); |
911 | | |
912 | | return 0; |
913 | | } |
914 | | #endif |