ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

trionan.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.