Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentrionan.c
Go to the documentation of this file.
00001 /************************************************************************* 00002 * 00003 * $Id$ 00004 * 00005 * Copyright (C) 2001 Bjorn Reese <breese@users.sourceforge.net> 00006 * 00007 * Permission to use, copy, modify, and distribute this software for any 00008 * purpose with or without fee is hereby granted, provided that the above 00009 * copyright notice and this permission notice appear in all copies. 00010 * 00011 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 00012 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 00013 * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND 00014 * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. 00015 * 00016 ************************************************************************ 00017 * 00018 * Functions to handle special quantities in floating-point numbers 00019 * (that is, NaNs and infinity). They provide the capability to detect 00020 * and fabricate special quantities. 00021 * 00022 * Although written to be as portable as possible, it can never be 00023 * guaranteed to work on all platforms, as not all hardware supports 00024 * special quantities. 00025 * 00026 * The approach used here (approximately) is to: 00027 * 00028 * 1. Use C99 functionality when available. 00029 * 2. Use IEEE 754 bit-patterns if possible. 00030 * 3. Use platform-specific techniques. 00031 * 00032 ************************************************************************/ 00033 00034 /* 00035 * TODO: 00036 * o Put all the magic into trio_fpclassify_and_signbit(), and use this from 00037 * trio_isnan() etc. 00038 */ 00039 00040 /************************************************************************* 00041 * Include files 00042 */ 00043 #include "triodef.h" 00044 #include "trionan.h" 00045 00046 #include <math.h> 00047 #include <string.h> 00048 #include <limits.h> 00049 #include <float.h> 00050 #if defined(TRIO_PLATFORM_UNIX) 00051 # include <signal.h> 00052 #endif 00053 #if defined(TRIO_COMPILER_DECC) 00054 # if defined(__linux__) 00055 # include <cpml.h> 00056 # else 00057 # include <fp_class.h> 00058 # endif 00059 #endif 00060 #include <assert.h> 00061 00062 #if defined(TRIO_DOCUMENTATION) 00063 # include "doc/doc_nan.h" 00064 #endif 00065 00069 /************************************************************************* 00070 * Definitions 00071 */ 00072 00073 #define TRIO_TRUE (1 == 1) 00074 #define TRIO_FALSE (0 == 1) 00075 00076 /* 00077 * We must enable IEEE floating-point on Alpha 00078 */ 00079 #if defined(__alpha) && !defined(_IEEE_FP) 00080 # if defined(TRIO_COMPILER_DECC) 00081 # if defined(TRIO_PLATFORM_VMS) 00082 # error "Must be compiled with option /IEEE_MODE=UNDERFLOW_TO_ZERO/FLOAT=IEEE" 00083 # else 00084 # if !defined(_CFE) 00085 # error "Must be compiled with option -ieee" 00086 # endif 00087 # endif 00088 # elif defined(TRIO_COMPILER_GCC) && (defined(__osf__) || defined(__linux__)) 00089 # error "Must be compiled with option -mieee" 00090 # endif 00091 #endif /* __alpha && ! _IEEE_FP */ 00092 00093 /* 00094 * In ANSI/IEEE 754-1985 64-bits double format numbers have the 00095 * following properties (amoungst others) 00096 * 00097 * o FLT_RADIX == 2: binary encoding 00098 * o DBL_MAX_EXP == 1024: 11 bits exponent, where one bit is used 00099 * to indicate special numbers (e.g. NaN and Infinity), so the 00100 * maximum exponent is 10 bits wide (2^10 == 1024). 00101 * o DBL_MANT_DIG == 53: The mantissa is 52 bits wide, but because 00102 * numbers are normalized the initial binary 1 is represented 00103 * implicitly (the so-called "hidden bit"), which leaves us with 00104 * the ability to represent 53 bits wide mantissa. 00105 */ 00106 #if (FLT_RADIX == 2) && (DBL_MAX_EXP == 1024) && (DBL_MANT_DIG == 53) 00107 # define USE_IEEE_754 00108 #endif 00109 00110 00111 /************************************************************************* 00112 * Constants 00113 */ 00114 00115 static TRIO_CONST char rcsid[] = "@(#)$Id$"; 00116 00117 #if defined(USE_IEEE_754) 00118 00119 /* 00120 * Endian-agnostic indexing macro. 00121 * 00122 * The value of internalEndianMagic, when converted into a 64-bit 00123 * integer, becomes 0x0706050403020100 (we could have used a 64-bit 00124 * integer value instead of a double, but not all platforms supports 00125 * that type). The value is automatically encoded with the correct 00126 * endianess by the compiler, which means that we can support any 00127 * kind of endianess. The individual bytes are then used as an index 00128 * for the IEEE 754 bit-patterns and masks. 00129 */ 00130 #define TRIO_DOUBLE_INDEX(x) (((unsigned char *)&internalEndianMagic)[7-(x)]) 00131 00132 #if (defined(__BORLANDC__) && __BORLANDC__ >= 0x0590) 00133 static TRIO_CONST double internalEndianMagic = 7.949928895127362e-275; 00134 #else 00135 static TRIO_CONST double internalEndianMagic = 7.949928895127363e-275; 00136 #endif 00137 00138 /* Mask for the exponent */ 00139 static TRIO_CONST unsigned char ieee_754_exponent_mask[] = { 00140 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 00141 }; 00142 00143 /* Mask for the mantissa */ 00144 static TRIO_CONST unsigned char ieee_754_mantissa_mask[] = { 00145 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 00146 }; 00147 00148 /* Mask for the sign bit */ 00149 static TRIO_CONST unsigned char ieee_754_sign_mask[] = { 00150 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 00151 }; 00152 00153 /* Bit-pattern for negative zero */ 00154 static TRIO_CONST unsigned char ieee_754_negzero_array[] = { 00155 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 00156 }; 00157 00158 /* Bit-pattern for infinity */ 00159 static TRIO_CONST unsigned char ieee_754_infinity_array[] = { 00160 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 00161 }; 00162 00163 /* Bit-pattern for quiet NaN */ 00164 static TRIO_CONST unsigned char ieee_754_qnan_array[] = { 00165 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 00166 }; 00167 00168 00169 /************************************************************************* 00170 * Functions 00171 */ 00172 00173 /* 00174 * trio_make_double 00175 */ 00176 TRIO_PRIVATE double 00177 trio_make_double 00178 TRIO_ARGS1((values), 00179 TRIO_CONST unsigned char *values) 00180 { 00181 TRIO_VOLATILE double result; 00182 int i; 00183 00184 for (i = 0; i < (int)sizeof(double); i++) { 00185 ((TRIO_VOLATILE unsigned char *)&result)[TRIO_DOUBLE_INDEX(i)] = values[i]; 00186 } 00187 return result; 00188 } 00189 00190 /* 00191 * trio_is_special_quantity 00192 */ 00193 TRIO_PRIVATE int 00194 trio_is_special_quantity 00195 TRIO_ARGS2((number, has_mantissa), 00196 double number, 00197 int *has_mantissa) 00198 { 00199 unsigned int i; 00200 unsigned char current; 00201 int is_special_quantity = TRIO_TRUE; 00202 00203 *has_mantissa = 0; 00204 00205 for (i = 0; i < (unsigned int)sizeof(double); i++) { 00206 current = ((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)]; 00207 is_special_quantity 00208 &= ((current & ieee_754_exponent_mask[i]) == ieee_754_exponent_mask[i]); 00209 *has_mantissa |= (current & ieee_754_mantissa_mask[i]); 00210 } 00211 return is_special_quantity; 00212 } 00213 00214 /* 00215 * trio_is_negative 00216 */ 00217 TRIO_PRIVATE int 00218 trio_is_negative 00219 TRIO_ARGS1((number), 00220 double number) 00221 { 00222 unsigned int i; 00223 int is_negative = TRIO_FALSE; 00224 00225 for (i = 0; i < (unsigned int)sizeof(double); i++) { 00226 is_negative |= (((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)] 00227 & ieee_754_sign_mask[i]); 00228 } 00229 return is_negative; 00230 } 00231 00232 #endif /* USE_IEEE_754 */ 00233 00234 00240 TRIO_PUBLIC double 00241 trio_nzero(TRIO_NOARGS) 00242 { 00243 #if defined(USE_IEEE_754) 00244 return trio_make_double(ieee_754_negzero_array); 00245 #else 00246 TRIO_VOLATILE double zero = 0.0; 00247 00248 return -zero; 00249 #endif 00250 } 00251 00257 TRIO_PUBLIC double 00258 trio_pinf(TRIO_NOARGS) 00259 { 00260 /* Cache the result */ 00261 static double result = 0.0; 00262 00263 if (result == 0.0) { 00264 00265 #if defined(INFINITY) && defined(__STDC_IEC_559__) 00266 result = (double)INFINITY; 00267 00268 #elif defined(USE_IEEE_754) 00269 result = trio_make_double(ieee_754_infinity_array); 00270 00271 #else 00272 /* 00273 * If HUGE_VAL is different from DBL_MAX, then HUGE_VAL is used 00274 * as infinity. Otherwise we have to resort to an overflow 00275 * operation to generate infinity. 00276 */ 00277 # if defined(TRIO_PLATFORM_UNIX) 00278 void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN); 00279 # endif 00280 00281 result = HUGE_VAL; 00282 if (HUGE_VAL == DBL_MAX) { 00283 /* Force overflow */ 00284 result += HUGE_VAL; 00285 } 00286 00287 # if defined(TRIO_PLATFORM_UNIX) 00288 signal(SIGFPE, signal_handler); 00289 # endif 00290 00291 #endif 00292 } 00293 return result; 00294 } 00295 00301 TRIO_PUBLIC double 00302 trio_ninf(TRIO_NOARGS) 00303 { 00304 static double result = 0.0; 00305 00306 if (result == 0.0) { 00307 /* 00308 * Negative infinity is calculated by negating positive infinity, 00309 * which can be done because it is legal to do calculations on 00310 * infinity (for example, 1 / infinity == 0). 00311 */ 00312 result = -trio_pinf(); 00313 } 00314 return result; 00315 } 00316 00322 TRIO_PUBLIC double 00323 trio_nan(TRIO_NOARGS) 00324 { 00325 /* Cache the result */ 00326 static double result = 0.0; 00327 00328 if (result == 0.0) { 00329 00330 #if defined(TRIO_COMPILER_SUPPORTS_C99) 00331 result = nan(""); 00332 00333 #elif defined(NAN) && defined(__STDC_IEC_559__) 00334 result = (double)NAN; 00335 00336 #elif defined(USE_IEEE_754) 00337 result = trio_make_double(ieee_754_qnan_array); 00338 00339 #else 00340 /* 00341 * There are several ways to generate NaN. The one used here is 00342 * to divide infinity by infinity. I would have preferred to add 00343 * negative infinity to positive infinity, but that yields wrong 00344 * result (infinity) on FreeBSD. 00345 * 00346 * This may fail if the hardware does not support NaN, or if 00347 * the Invalid Operation floating-point exception is unmasked. 00348 */ 00349 # if defined(TRIO_PLATFORM_UNIX) 00350 void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN); 00351 # endif 00352 00353 result = trio_pinf() / trio_pinf(); 00354 00355 # if defined(TRIO_PLATFORM_UNIX) 00356 signal(SIGFPE, signal_handler); 00357 # endif 00358 00359 #endif 00360 } 00361 return result; 00362 } 00363 00370 TRIO_PUBLIC int 00371 trio_isnan 00372 TRIO_ARGS1((number), 00373 double number) 00374 { 00375 #if (defined(TRIO_COMPILER_SUPPORTS_C99) && defined(isnan)) \ 00376 || defined(TRIO_COMPILER_SUPPORTS_UNIX95) 00377 /* 00378 * C99 defines isnan() as a macro. UNIX95 defines isnan() as a 00379 * function. This function was already present in XPG4, but this 00380 * is a bit tricky to detect with compiler defines, so we choose 00381 * the conservative approach and only use it for UNIX95. 00382 */ 00383 return isnan(number); 00384 00385 #elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB) 00386 /* 00387 * Microsoft Visual C++ and Borland C++ Builder have an _isnan() 00388 * function. 00389 */ 00390 return _isnan(number) ? TRIO_TRUE : TRIO_FALSE; 00391 00392 #elif defined(USE_IEEE_754) 00393 /* 00394 * Examine IEEE 754 bit-pattern. A NaN must have a special exponent 00395 * pattern, and a non-empty mantissa. 00396 */ 00397 int has_mantissa; 00398 int is_special_quantity; 00399 00400 is_special_quantity = trio_is_special_quantity(number, &has_mantissa); 00401 00402 return (is_special_quantity && has_mantissa); 00403 00404 #else 00405 /* 00406 * Fallback solution 00407 */ 00408 int status; 00409 double integral, fraction; 00410 00411 # if defined(TRIO_PLATFORM_UNIX) 00412 void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN); 00413 # endif 00414 00415 status = (/* 00416 * NaN is the only number which does not compare to itself 00417 */ 00418 ((TRIO_VOLATILE double)number != (TRIO_VOLATILE double)number) || 00419 /* 00420 * Fallback solution if NaN compares to NaN 00421 */ 00422 ((number != 0.0) && 00423 (fraction = modf(number, &integral), 00424 integral == fraction))); 00425 00426 # if defined(TRIO_PLATFORM_UNIX) 00427 signal(SIGFPE, signal_handler); 00428 # endif 00429 00430 return status; 00431 00432 #endif 00433 } 00434 00441 TRIO_PUBLIC int 00442 trio_isinf 00443 TRIO_ARGS1((number), 00444 double number) 00445 { 00446 #if defined(TRIO_COMPILER_DECC) && !defined(__linux__) 00447 /* 00448 * DECC has an isinf() macro, but it works differently than that 00449 * of C99, so we use the fp_class() function instead. 00450 */ 00451 return ((fp_class(number) == FP_POS_INF) 00452 ? 1 00453 : ((fp_class(number) == FP_NEG_INF) ? -1 : 0)); 00454 00455 #elif defined(isinf) 00456 /* 00457 * C99 defines isinf() as a macro. 00458 */ 00459 return isinf(number) 00460 ? ((number > 0.0) ? 1 : -1) 00461 : 0; 00462 00463 #elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB) 00464 /* 00465 * Microsoft Visual C++ and Borland C++ Builder have an _fpclass() 00466 * function that can be used to detect infinity. 00467 */ 00468 return ((_fpclass(number) == _FPCLASS_PINF) 00469 ? 1 00470 : ((_fpclass(number) == _FPCLASS_NINF) ? -1 : 0)); 00471 00472 #elif defined(USE_IEEE_754) 00473 /* 00474 * Examine IEEE 754 bit-pattern. Infinity must have a special exponent 00475 * pattern, and an empty mantissa. 00476 */ 00477 int has_mantissa; 00478 int is_special_quantity; 00479 00480 is_special_quantity = trio_is_special_quantity(number, &has_mantissa); 00481 00482 return (is_special_quantity && !has_mantissa) 00483 ? ((number < 0.0) ? -1 : 1) 00484 : 0; 00485 00486 #else 00487 /* 00488 * Fallback solution. 00489 */ 00490 int status; 00491 00492 # if defined(TRIO_PLATFORM_UNIX) 00493 void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN); 00494 # endif 00495 00496 double infinity = trio_pinf(); 00497 00498 status = ((number == infinity) 00499 ? 1 00500 : ((number == -infinity) ? -1 : 0)); 00501 00502 # if defined(TRIO_PLATFORM_UNIX) 00503 signal(SIGFPE, signal_handler); 00504 # endif 00505 00506 return status; 00507 00508 #endif 00509 } 00510 00511 #if 0 00512 /* Temporary fix - this routine is not used anywhere */ 00519 TRIO_PUBLIC int 00520 trio_isfinite 00521 TRIO_ARGS1((number), 00522 double number) 00523 { 00524 #if defined(TRIO_COMPILER_SUPPORTS_C99) && defined(isfinite) 00525 /* 00526 * C99 defines isfinite() as a macro. 00527 */ 00528 return isfinite(number); 00529 00530 #elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB) 00531 /* 00532 * Microsoft Visual C++ and Borland C++ Builder use _finite(). 00533 */ 00534 return _finite(number); 00535 00536 #elif defined(USE_IEEE_754) 00537 /* 00538 * Examine IEEE 754 bit-pattern. For finity we do not care about the 00539 * mantissa. 00540 */ 00541 int dummy; 00542 00543 return (! trio_is_special_quantity(number, &dummy)); 00544 00545 #else 00546 /* 00547 * Fallback solution. 00548 */ 00549 return ((trio_isinf(number) == 0) && (trio_isnan(number) == 0)); 00550 00551 #endif 00552 } 00553 00554 #endif 00555 00556 /* 00557 * The sign of NaN is always false 00558 */ 00559 TRIO_PUBLIC int 00560 trio_fpclassify_and_signbit 00561 TRIO_ARGS2((number, is_negative), 00562 double number, 00563 int *is_negative) 00564 { 00565 #if defined(fpclassify) && defined(signbit) 00566 /* 00567 * C99 defines fpclassify() and signbit() as a macros 00568 */ 00569 *is_negative = signbit(number); 00570 switch (fpclassify(number)) { 00571 case FP_NAN: 00572 return TRIO_FP_NAN; 00573 case FP_INFINITE: 00574 return TRIO_FP_INFINITE; 00575 case FP_SUBNORMAL: 00576 return TRIO_FP_SUBNORMAL; 00577 case FP_ZERO: 00578 return TRIO_FP_ZERO; 00579 default: 00580 return TRIO_FP_NORMAL; 00581 } 00582 00583 #else 00584 # if defined(TRIO_COMPILER_DECC) 00585 /* 00586 * DECC has an fp_class() function. 00587 */ 00588 # define TRIO_FPCLASSIFY(n) fp_class(n) 00589 # define TRIO_QUIET_NAN FP_QNAN 00590 # define TRIO_SIGNALLING_NAN FP_SNAN 00591 # define TRIO_POSITIVE_INFINITY FP_POS_INF 00592 # define TRIO_NEGATIVE_INFINITY FP_NEG_INF 00593 # define TRIO_POSITIVE_SUBNORMAL FP_POS_DENORM 00594 # define TRIO_NEGATIVE_SUBNORMAL FP_NEG_DENORM 00595 # define TRIO_POSITIVE_ZERO FP_POS_ZERO 00596 # define TRIO_NEGATIVE_ZERO FP_NEG_ZERO 00597 # define TRIO_POSITIVE_NORMAL FP_POS_NORM 00598 # define TRIO_NEGATIVE_NORMAL FP_NEG_NORM 00599 00600 # elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB) 00601 /* 00602 * Microsoft Visual C++ and Borland C++ Builder have an _fpclass() 00603 * function. 00604 */ 00605 # define TRIO_FPCLASSIFY(n) _fpclass(n) 00606 # define TRIO_QUIET_NAN _FPCLASS_QNAN 00607 # define TRIO_SIGNALLING_NAN _FPCLASS_SNAN 00608 # define TRIO_POSITIVE_INFINITY _FPCLASS_PINF 00609 # define TRIO_NEGATIVE_INFINITY _FPCLASS_NINF 00610 # define TRIO_POSITIVE_SUBNORMAL _FPCLASS_PD 00611 # define TRIO_NEGATIVE_SUBNORMAL _FPCLASS_ND 00612 # define TRIO_POSITIVE_ZERO _FPCLASS_PZ 00613 # define TRIO_NEGATIVE_ZERO _FPCLASS_NZ 00614 # define TRIO_POSITIVE_NORMAL _FPCLASS_PN 00615 # define TRIO_NEGATIVE_NORMAL _FPCLASS_NN 00616 00617 # elif defined(FP_PLUS_NORM) 00618 /* 00619 * HP-UX 9.x and 10.x have an fpclassify() function, that is different 00620 * from the C99 fpclassify() macro supported on HP-UX 11.x. 00621 * 00622 * AIX has class() for C, and _class() for C++, which returns the 00623 * same values as the HP-UX fpclassify() function. 00624 */ 00625 # if defined(TRIO_PLATFORM_AIX) 00626 # if defined(__cplusplus) 00627 # define TRIO_FPCLASSIFY(n) _class(n) 00628 # else 00629 # define TRIO_FPCLASSIFY(n) class(n) 00630 # endif 00631 # else 00632 # define TRIO_FPCLASSIFY(n) fpclassify(n) 00633 # endif 00634 # define TRIO_QUIET_NAN FP_QNAN 00635 # define TRIO_SIGNALLING_NAN FP_SNAN 00636 # define TRIO_POSITIVE_INFINITY FP_PLUS_INF 00637 # define TRIO_NEGATIVE_INFINITY FP_MINUS_INF 00638 # define TRIO_POSITIVE_SUBNORMAL FP_PLUS_DENORM 00639 # define TRIO_NEGATIVE_SUBNORMAL FP_MINUS_DENORM 00640 # define TRIO_POSITIVE_ZERO FP_PLUS_ZERO 00641 # define TRIO_NEGATIVE_ZERO FP_MINUS_ZERO 00642 # define TRIO_POSITIVE_NORMAL FP_PLUS_NORM 00643 # define TRIO_NEGATIVE_NORMAL FP_MINUS_NORM 00644 # endif 00645 00646 # if defined(TRIO_FPCLASSIFY) 00647 switch (TRIO_FPCLASSIFY(number)) { 00648 case TRIO_QUIET_NAN: 00649 case TRIO_SIGNALLING_NAN: 00650 *is_negative = TRIO_FALSE; /* NaN has no sign */ 00651 return TRIO_FP_NAN; 00652 case TRIO_POSITIVE_INFINITY: 00653 *is_negative = TRIO_FALSE; 00654 return TRIO_FP_INFINITE; 00655 case TRIO_NEGATIVE_INFINITY: 00656 *is_negative = TRIO_TRUE; 00657 return TRIO_FP_INFINITE; 00658 case TRIO_POSITIVE_SUBNORMAL: 00659 *is_negative = TRIO_FALSE; 00660 return TRIO_FP_SUBNORMAL; 00661 case TRIO_NEGATIVE_SUBNORMAL: 00662 *is_negative = TRIO_TRUE; 00663 return TRIO_FP_SUBNORMAL; 00664 case TRIO_POSITIVE_ZERO: 00665 *is_negative = TRIO_FALSE; 00666 return TRIO_FP_ZERO; 00667 case TRIO_NEGATIVE_ZERO: 00668 *is_negative = TRIO_TRUE; 00669 return TRIO_FP_ZERO; 00670 case TRIO_POSITIVE_NORMAL: 00671 *is_negative = TRIO_FALSE; 00672 return TRIO_FP_NORMAL; 00673 case TRIO_NEGATIVE_NORMAL: 00674 *is_negative = TRIO_TRUE; 00675 return TRIO_FP_NORMAL; 00676 default: 00677 /* Just in case... */ 00678 *is_negative = (number < 0.0); 00679 return TRIO_FP_NORMAL; 00680 } 00681 00682 # else 00683 /* 00684 * Fallback solution. 00685 */ 00686 int rc; 00687 00688 if (number == 0.0) { 00689 /* 00690 * In IEEE 754 the sign of zero is ignored in comparisons, so we 00691 * have to handle this as a special case by examining the sign bit 00692 * directly. 00693 */ 00694 # if defined(USE_IEEE_754) 00695 *is_negative = trio_is_negative(number); 00696 # else 00697 *is_negative = TRIO_FALSE; /* FIXME */ 00698 # endif 00699 return TRIO_FP_ZERO; 00700 } 00701 if (trio_isnan(number)) { 00702 *is_negative = TRIO_FALSE; 00703 return TRIO_FP_NAN; 00704 } 00705 if ((rc = trio_isinf(number))) { 00706 *is_negative = (rc == -1); 00707 return TRIO_FP_INFINITE; 00708 } 00709 if ((number > 0.0) && (number < DBL_MIN)) { 00710 *is_negative = TRIO_FALSE; 00711 return TRIO_FP_SUBNORMAL; 00712 } 00713 if ((number < 0.0) && (number > -DBL_MIN)) { 00714 *is_negative = TRIO_TRUE; 00715 return TRIO_FP_SUBNORMAL; 00716 } 00717 *is_negative = (number < 0.0); 00718 return TRIO_FP_NORMAL; 00719 00720 # endif 00721 #endif 00722 } 00723 00731 TRIO_PUBLIC int 00732 trio_signbit 00733 TRIO_ARGS1((number), 00734 double number) 00735 { 00736 int is_negative; 00737 00738 (void)trio_fpclassify_and_signbit(number, &is_negative); 00739 return is_negative; 00740 } 00741 00742 #if 0 00743 /* Temporary fix - this routine is not used in libxml */ 00750 TRIO_PUBLIC int 00751 trio_fpclassify 00752 TRIO_ARGS1((number), 00753 double number) 00754 { 00755 int dummy; 00756 00757 return trio_fpclassify_and_signbit(number, &dummy); 00758 } 00759 00760 #endif 00761 00764 /************************************************************************* 00765 * For test purposes. 00766 * 00767 * Add the following compiler option to include this test code. 00768 * 00769 * Unix : -DSTANDALONE 00770 * VMS : /DEFINE=(STANDALONE) 00771 */ 00772 #if defined(STANDALONE) 00773 # include <stdio.h> 00774 00775 static TRIO_CONST char * 00776 getClassification 00777 TRIO_ARGS1((type), 00778 int type) 00779 { 00780 switch (type) { 00781 case TRIO_FP_INFINITE: 00782 return "FP_INFINITE"; 00783 case TRIO_FP_NAN: 00784 return "FP_NAN"; 00785 case TRIO_FP_NORMAL: 00786 return "FP_NORMAL"; 00787 case TRIO_FP_SUBNORMAL: 00788 return "FP_SUBNORMAL"; 00789 case TRIO_FP_ZERO: 00790 return "FP_ZERO"; 00791 default: 00792 return "FP_UNKNOWN"; 00793 } 00794 } 00795 00796 static void 00797 print_class 00798 TRIO_ARGS2((prefix, number), 00799 TRIO_CONST char *prefix, 00800 double number) 00801 { 00802 printf("%-6s: %s %-15s %g\n", 00803 prefix, 00804 trio_signbit(number) ? "-" : "+", 00805 getClassification(TRIO_FPCLASSIFY(number)), 00806 number); 00807 } 00808 00809 int main(TRIO_NOARGS) 00810 { 00811 double my_nan; 00812 double my_pinf; 00813 double my_ninf; 00814 # if defined(TRIO_PLATFORM_UNIX) 00815 void (*signal_handler) TRIO_PROTO((int)); 00816 # endif 00817 00818 my_nan = trio_nan(); 00819 my_pinf = trio_pinf(); 00820 my_ninf = trio_ninf(); 00821 00822 print_class("Nan", my_nan); 00823 print_class("PInf", my_pinf); 00824 print_class("NInf", my_ninf); 00825 print_class("PZero", 0.0); 00826 print_class("NZero", -0.0); 00827 print_class("PNorm", 1.0); 00828 print_class("NNorm", -1.0); 00829 print_class("PSub", 1.01e-307 - 1.00e-307); 00830 print_class("NSub", 1.00e-307 - 1.01e-307); 00831 00832 printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", 00833 my_nan, 00834 ((unsigned char *)&my_nan)[0], 00835 ((unsigned char *)&my_nan)[1], 00836 ((unsigned char *)&my_nan)[2], 00837 ((unsigned char *)&my_nan)[3], 00838 ((unsigned char *)&my_nan)[4], 00839 ((unsigned char *)&my_nan)[5], 00840 ((unsigned char *)&my_nan)[6], 00841 ((unsigned char *)&my_nan)[7], 00842 trio_isnan(my_nan), trio_isinf(my_nan)); 00843 printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", 00844 my_pinf, 00845 ((unsigned char *)&my_pinf)[0], 00846 ((unsigned char *)&my_pinf)[1], 00847 ((unsigned char *)&my_pinf)[2], 00848 ((unsigned char *)&my_pinf)[3], 00849 ((unsigned char *)&my_pinf)[4], 00850 ((unsigned char *)&my_pinf)[5], 00851 ((unsigned char *)&my_pinf)[6], 00852 ((unsigned char *)&my_pinf)[7], 00853 trio_isnan(my_pinf), trio_isinf(my_pinf)); 00854 printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", 00855 my_ninf, 00856 ((unsigned char *)&my_ninf)[0], 00857 ((unsigned char *)&my_ninf)[1], 00858 ((unsigned char *)&my_ninf)[2], 00859 ((unsigned char *)&my_ninf)[3], 00860 ((unsigned char *)&my_ninf)[4], 00861 ((unsigned char *)&my_ninf)[5], 00862 ((unsigned char *)&my_ninf)[6], 00863 ((unsigned char *)&my_ninf)[7], 00864 trio_isnan(my_ninf), trio_isinf(my_ninf)); 00865 00866 # if defined(TRIO_PLATFORM_UNIX) 00867 signal_handler = signal(SIGFPE, SIG_IGN); 00868 # endif 00869 00870 my_pinf = DBL_MAX + DBL_MAX; 00871 my_ninf = -my_pinf; 00872 my_nan = my_pinf / my_pinf; 00873 00874 # if defined(TRIO_PLATFORM_UNIX) 00875 signal(SIGFPE, signal_handler); 00876 # endif 00877 00878 printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", 00879 my_nan, 00880 ((unsigned char *)&my_nan)[0], 00881 ((unsigned char *)&my_nan)[1], 00882 ((unsigned char *)&my_nan)[2], 00883 ((unsigned char *)&my_nan)[3], 00884 ((unsigned char *)&my_nan)[4], 00885 ((unsigned char *)&my_nan)[5], 00886 ((unsigned char *)&my_nan)[6], 00887 ((unsigned char *)&my_nan)[7], 00888 trio_isnan(my_nan), trio_isinf(my_nan)); 00889 printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", 00890 my_pinf, 00891 ((unsigned char *)&my_pinf)[0], 00892 ((unsigned char *)&my_pinf)[1], 00893 ((unsigned char *)&my_pinf)[2], 00894 ((unsigned char *)&my_pinf)[3], 00895 ((unsigned char *)&my_pinf)[4], 00896 ((unsigned char *)&my_pinf)[5], 00897 ((unsigned char *)&my_pinf)[6], 00898 ((unsigned char *)&my_pinf)[7], 00899 trio_isnan(my_pinf), trio_isinf(my_pinf)); 00900 printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", 00901 my_ninf, 00902 ((unsigned char *)&my_ninf)[0], 00903 ((unsigned char *)&my_ninf)[1], 00904 ((unsigned char *)&my_ninf)[2], 00905 ((unsigned char *)&my_ninf)[3], 00906 ((unsigned char *)&my_ninf)[4], 00907 ((unsigned char *)&my_ninf)[5], 00908 ((unsigned char *)&my_ninf)[6], 00909 ((unsigned char *)&my_ninf)[7], 00910 trio_isnan(my_ninf), trio_isinf(my_ninf)); 00911 00912 return 0; 00913 } 00914 #endif Generated on Sat May 26 2012 04:33:34 for ReactOS by
1.7.6.1
|