Annotation of embedaddon/libxml2/trionan.c, revision 1.1.1.2

1.1       misho       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: #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: {
                    181:   TRIO_VOLATILE double result;
                    182:   int i;
                    183: 
                    184:   for (i = 0; i < (int)sizeof(double); i++) {
                    185:     ((TRIO_VOLATILE unsigned char *)&result)[TRIO_DOUBLE_INDEX(i)] = values[i];
                    186:   }
                    187:   return result;
                    188: }
                    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: {
                    199:   unsigned int i;
                    200:   unsigned char current;
                    201:   int is_special_quantity = TRIO_TRUE;
                    202: 
                    203:   *has_mantissa = 0;
                    204: 
                    205:   for (i = 0; i < (unsigned int)sizeof(double); i++) {
                    206:     current = ((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)];
                    207:     is_special_quantity
                    208:       &= ((current & ieee_754_exponent_mask[i]) == ieee_754_exponent_mask[i]);
                    209:     *has_mantissa |= (current & ieee_754_mantissa_mask[i]);
                    210:   }
                    211:   return is_special_quantity;
                    212: }
                    213: 
                    214: /*
                    215:  * trio_is_negative
                    216:  */
                    217: TRIO_PRIVATE int
                    218: trio_is_negative
                    219: TRIO_ARGS1((number),
                    220:           double number)
                    221: {
                    222:   unsigned int i;
                    223:   int is_negative = TRIO_FALSE;
                    224: 
                    225:   for (i = 0; i < (unsigned int)sizeof(double); i++) {
                    226:     is_negative |= (((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)]
                    227:                    & ieee_754_sign_mask[i]);
                    228:   }
                    229:   return is_negative;
                    230: }
                    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: {
                    243: #if defined(USE_IEEE_754)
                    244:   return trio_make_double(ieee_754_negzero_array);
                    245: #else
                    246:   TRIO_VOLATILE double zero = 0.0;
                    247: 
                    248:   return -zero;
                    249: #endif
                    250: }
                    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: {
                    260:   /* Cache the result */
                    261:   static double result = 0.0;
                    262: 
                    263:   if (result == 0.0) {
1.1.1.2 ! misho     264: 
1.1       misho     265: #if defined(INFINITY) && defined(__STDC_IEC_559__)
                    266:     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:     }
1.1.1.2 ! misho     286: 
1.1       misho     287: # if defined(TRIO_PLATFORM_UNIX)
                    288:     signal(SIGFPE, signal_handler);
                    289: # endif
                    290: 
                    291: #endif
                    292:   }
                    293:   return result;
                    294: }
                    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: {
                    304:   static double result = 0.0;
                    305: 
                    306:   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:     result = -trio_pinf();
                    313:   }
                    314:   return result;
                    315: }
                    316: 
                    317: /**
                    318:    Generate NaN.
                    319: 
                    320:    @return Floating-point representation of NaN.
                    321: */
                    322: TRIO_PUBLIC double
                    323: trio_nan(TRIO_NOARGS)
                    324: {
                    325:   /* Cache the result */
                    326:   static double result = 0.0;
                    327: 
                    328:   if (result == 0.0) {
1.1.1.2 ! misho     329: 
1.1       misho     330: #if defined(TRIO_COMPILER_SUPPORTS_C99)
                    331:     result = nan("");
                    332: 
                    333: #elif defined(NAN) && defined(__STDC_IEC_559__)
                    334:     result = (double)NAN;
1.1.1.2 ! misho     335: 
1.1       misho     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
1.1.1.2 ! misho     352: 
1.1       misho     353:     result = trio_pinf() / trio_pinf();
1.1.1.2 ! misho     354: 
1.1       misho     355: # if defined(TRIO_PLATFORM_UNIX)
                    356:     signal(SIGFPE, signal_handler);
                    357: # endif
1.1.1.2 ! misho     358: 
1.1       misho     359: #endif
                    360:   }
                    361:   return result;
                    362: }
                    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: {
                    375: #if (defined(TRIO_COMPILER_SUPPORTS_C99) && defined(isnan)) \
                    376:  || 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:   return isnan(number);
1.1.1.2 ! misho     384: 
1.1       misho     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);
1.1.1.2 ! misho     401: 
1.1       misho     402:   return (is_special_quantity && has_mantissa);
1.1.1.2 ! misho     403: 
1.1       misho     404: #else
                    405:   /*
                    406:    * Fallback solution
                    407:    */
                    408:   int status;
                    409:   double integral, fraction;
1.1.1.2 ! misho     410: 
1.1       misho     411: # if defined(TRIO_PLATFORM_UNIX)
                    412:   void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
                    413: # endif
1.1.1.2 ! misho     414: 
1.1       misho     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)));
1.1.1.2 ! misho     425: 
1.1       misho     426: # if defined(TRIO_PLATFORM_UNIX)
                    427:   signal(SIGFPE, signal_handler);
                    428: # endif
1.1.1.2 ! misho     429: 
1.1       misho     430:   return status;
1.1.1.2 ! misho     431: 
1.1       misho     432: #endif
                    433: }
                    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: {
                    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:   return isinf(number)
                    460:     ? ((number > 0.0) ? 1 : -1)
                    461:     : 0;
1.1.1.2 ! misho     462: 
1.1       misho     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);
1.1.1.2 ! misho     481: 
1.1       misho     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;
1.1.1.2 ! misho     491: 
1.1       misho     492: # if defined(TRIO_PLATFORM_UNIX)
                    493:   void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
                    494: # endif
1.1.1.2 ! misho     495: 
1.1       misho     496:   double infinity = trio_pinf();
1.1.1.2 ! misho     497: 
1.1       misho     498:   status = ((number == infinity)
                    499:            ? 1
                    500:            : ((number == -infinity) ? -1 : 0));
1.1.1.2 ! misho     501: 
1.1       misho     502: # if defined(TRIO_PLATFORM_UNIX)
                    503:   signal(SIGFPE, signal_handler);
                    504: # endif
1.1.1.2 ! misho     505: 
1.1       misho     506:   return status;
1.1.1.2 ! misho     507: 
1.1       misho     508: #endif
                    509: }
                    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);
1.1.1.2 ! misho     529: 
1.1       misho     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));
1.1.1.2 ! misho     550: 
1.1       misho     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: {
                    565: #if defined(fpclassify) && defined(signbit)
                    566:   /*
                    567:    * C99 defines fpclassify() and signbit() as a macros
                    568:    */
                    569:   *is_negative = signbit(number);
                    570:   switch (fpclassify(number)) {
                    571:   case FP_NAN:
                    572:     return TRIO_FP_NAN;
                    573:   case FP_INFINITE:
                    574:     return TRIO_FP_INFINITE;
                    575:   case FP_SUBNORMAL:
                    576:     return TRIO_FP_SUBNORMAL;
                    577:   case FP_ZERO:
                    578:     return TRIO_FP_ZERO;
                    579:   default:
                    580:     return TRIO_FP_NORMAL;
                    581:   }
                    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
1.1.1.2 ! misho     599: 
1.1       misho     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
1.1.1.2 ! misho     616: 
1.1       misho     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:   }
1.1.1.2 ! misho     681: 
1.1       misho     682: # else
                    683:   /*
                    684:    * Fallback solution.
                    685:    */
                    686:   int rc;
1.1.1.2 ! misho     687: 
1.1       misho     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;
1.1.1.2 ! misho     719: 
1.1       misho     720: # endif
                    721: #endif
                    722: }
                    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: {
                    736:   int is_negative;
1.1.1.2 ! misho     737: 
1.1       misho     738:   (void)trio_fpclassify_and_signbit(number, &is_negative);
                    739:   return is_negative;
                    740: }
                    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;
1.1.1.2 ! misho     756: 
1.1       misho     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);
1.1.1.2 ! misho     831: 
1.1       misho     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));
1.1.1.2 ! misho     865: 
1.1       misho     866: # if defined(TRIO_PLATFORM_UNIX)
                    867:   signal_handler = signal(SIGFPE, SIG_IGN);
                    868: # endif
1.1.1.2 ! misho     869: 
1.1       misho     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
1.1.1.2 ! misho     877: 
1.1       misho     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));
1.1.1.2 ! misho     911: 
1.1       misho     912:   return 0;
                    913: }
                    914: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>