File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libxml2 / trionan.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 19:53:29 2014 UTC (9 years, 11 months ago) by misho
Branches: libxml2, MAIN
CVS tags: v2_9_1p0, v2_9_1, HEAD
libxml2 2.9.1

    1: /*************************************************************************
    2:  *
    3:  * $Id: trionan.c,v 1.1.1.2 2014/06/15 19:53:29 misho Exp $
    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: trionan.c,v 1.1.1.2 2014/06/15 19:53:29 misho Exp $";
  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) {
  264: 
  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:     }
  286: 
  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) {
  329: 
  330: #if defined(TRIO_COMPILER_SUPPORTS_C99)
  331:     result = nan("");
  332: 
  333: #elif defined(NAN) && defined(__STDC_IEC_559__)
  334:     result = (double)NAN;
  335: 
  336: #elif defined(USE_IEEE_754)
  337:     result = trio_make_double(ieee_754_qnan_array);
  338: 
  339: #else
  340:     /*
  341:      * There are several ways to generate NaN. The one used here is
  342:      * to divide infinity by infinity. I would have preferred to add
  343:      * negative infinity to positive infinity, but that yields wrong
  344:      * result (infinity) on FreeBSD.
  345:      *
  346:      * This may fail if the hardware does not support NaN, or if
  347:      * the Invalid Operation floating-point exception is unmasked.
  348:      */
  349: # if defined(TRIO_PLATFORM_UNIX)
  350:     void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
  351: # endif
  352: 
  353:     result = trio_pinf() / trio_pinf();
  354: 
  355: # if defined(TRIO_PLATFORM_UNIX)
  356:     signal(SIGFPE, signal_handler);
  357: # endif
  358: 
  359: #endif
  360:   }
  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);
  384: 
  385: #elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB)
  386:   /*
  387:    * Microsoft Visual C++ and Borland C++ Builder have an _isnan()
  388:    * function.
  389:    */
  390:   return _isnan(number) ? TRIO_TRUE : TRIO_FALSE;
  391: 
  392: #elif defined(USE_IEEE_754)
  393:   /*
  394:    * Examine IEEE 754 bit-pattern. A NaN must have a special exponent
  395:    * pattern, and a non-empty mantissa.
  396:    */
  397:   int has_mantissa;
  398:   int is_special_quantity;
  399: 
  400:   is_special_quantity = trio_is_special_quantity(number, &has_mantissa);
  401: 
  402:   return (is_special_quantity && has_mantissa);
  403: 
  404: #else
  405:   /*
  406:    * Fallback solution
  407:    */
  408:   int status;
  409:   double integral, fraction;
  410: 
  411: # if defined(TRIO_PLATFORM_UNIX)
  412:   void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
  413: # endif
  414: 
  415:   status = (/*
  416: 	     * NaN is the only number which does not compare to itself
  417: 	     */
  418: 	    ((TRIO_VOLATILE double)number != (TRIO_VOLATILE double)number) ||
  419: 	    /*
  420: 	     * Fallback solution if NaN compares to NaN
  421: 	     */
  422: 	    ((number != 0.0) &&
  423: 	     (fraction = modf(number, &integral),
  424: 	      integral == fraction)));
  425: 
  426: # if defined(TRIO_PLATFORM_UNIX)
  427:   signal(SIGFPE, signal_handler);
  428: # endif
  429: 
  430:   return status;
  431: 
  432: #endif
  433: }
  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;
  462: 
  463: #elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB)
  464:   /*
  465:    * Microsoft Visual C++ and Borland C++ Builder have an _fpclass()
  466:    * function that can be used to detect infinity.
  467:    */
  468:   return ((_fpclass(number) == _FPCLASS_PINF)
  469: 	  ? 1
  470: 	  : ((_fpclass(number) == _FPCLASS_NINF) ? -1 : 0));
  471: 
  472: #elif defined(USE_IEEE_754)
  473:   /*
  474:    * Examine IEEE 754 bit-pattern. Infinity must have a special exponent
  475:    * pattern, and an empty mantissa.
  476:    */
  477:   int has_mantissa;
  478:   int is_special_quantity;
  479: 
  480:   is_special_quantity = trio_is_special_quantity(number, &has_mantissa);
  481: 
  482:   return (is_special_quantity && !has_mantissa)
  483:     ? ((number < 0.0) ? -1 : 1)
  484:     : 0;
  485: 
  486: #else
  487:   /*
  488:    * Fallback solution.
  489:    */
  490:   int status;
  491: 
  492: # if defined(TRIO_PLATFORM_UNIX)
  493:   void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
  494: # endif
  495: 
  496:   double infinity = trio_pinf();
  497: 
  498:   status = ((number == infinity)
  499: 	    ? 1
  500: 	    : ((number == -infinity) ? -1 : 0));
  501: 
  502: # if defined(TRIO_PLATFORM_UNIX)
  503:   signal(SIGFPE, signal_handler);
  504: # endif
  505: 
  506:   return status;
  507: 
  508: #endif
  509: }
  510: 
  511: #if 0
  512: 	/* Temporary fix - this routine is not used anywhere */
  513: /**
  514:    Check for finity.
  515: 
  516:    @param number An arbitrary floating-point number.
  517:    @return Boolean value indicating whether or not the number is a finite.
  518: */
  519: TRIO_PUBLIC int
  520: trio_isfinite
  521: TRIO_ARGS1((number),
  522: 	   double number)
  523: {
  524: #if defined(TRIO_COMPILER_SUPPORTS_C99) && defined(isfinite)
  525:   /*
  526:    * C99 defines isfinite() as a macro.
  527:    */
  528:   return isfinite(number);
  529: 
  530: #elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB)
  531:   /*
  532:    * Microsoft Visual C++ and Borland C++ Builder use _finite().
  533:    */
  534:   return _finite(number);
  535: 
  536: #elif defined(USE_IEEE_754)
  537:   /*
  538:    * Examine IEEE 754 bit-pattern. For finity we do not care about the
  539:    * mantissa.
  540:    */
  541:   int dummy;
  542: 
  543:   return (! trio_is_special_quantity(number, &dummy));
  544: 
  545: #else
  546:   /*
  547:    * Fallback solution.
  548:    */
  549:   return ((trio_isinf(number) == 0) && (trio_isnan(number) == 0));
  550: 
  551: #endif
  552: }
  553: 
  554: #endif
  555: 
  556: /*
  557:  * The sign of NaN is always false
  558:  */
  559: TRIO_PUBLIC int
  560: trio_fpclassify_and_signbit
  561: TRIO_ARGS2((number, is_negative),
  562: 	   double number,
  563: 	   int *is_negative)
  564: {
  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
  599: 
  600: # elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB)
  601:   /*
  602:    * Microsoft Visual C++ and Borland C++ Builder have an _fpclass()
  603:    * function.
  604:    */
  605: #  define TRIO_FPCLASSIFY(n) _fpclass(n)
  606: #  define TRIO_QUIET_NAN _FPCLASS_QNAN
  607: #  define TRIO_SIGNALLING_NAN _FPCLASS_SNAN
  608: #  define TRIO_POSITIVE_INFINITY _FPCLASS_PINF
  609: #  define TRIO_NEGATIVE_INFINITY _FPCLASS_NINF
  610: #  define TRIO_POSITIVE_SUBNORMAL _FPCLASS_PD
  611: #  define TRIO_NEGATIVE_SUBNORMAL _FPCLASS_ND
  612: #  define TRIO_POSITIVE_ZERO _FPCLASS_PZ
  613: #  define TRIO_NEGATIVE_ZERO _FPCLASS_NZ
  614: #  define TRIO_POSITIVE_NORMAL _FPCLASS_PN
  615: #  define TRIO_NEGATIVE_NORMAL _FPCLASS_NN
  616: 
  617: # elif defined(FP_PLUS_NORM)
  618:   /*
  619:    * HP-UX 9.x and 10.x have an fpclassify() function, that is different
  620:    * from the C99 fpclassify() macro supported on HP-UX 11.x.
  621:    *
  622:    * AIX has class() for C, and _class() for C++, which returns the
  623:    * same values as the HP-UX fpclassify() function.
  624:    */
  625: #  if defined(TRIO_PLATFORM_AIX)
  626: #   if defined(__cplusplus)
  627: #    define TRIO_FPCLASSIFY(n) _class(n)
  628: #   else
  629: #    define TRIO_FPCLASSIFY(n) class(n)
  630: #   endif
  631: #  else
  632: #   define TRIO_FPCLASSIFY(n) fpclassify(n)
  633: #  endif
  634: #  define TRIO_QUIET_NAN FP_QNAN
  635: #  define TRIO_SIGNALLING_NAN FP_SNAN
  636: #  define TRIO_POSITIVE_INFINITY FP_PLUS_INF
  637: #  define TRIO_NEGATIVE_INFINITY FP_MINUS_INF
  638: #  define TRIO_POSITIVE_SUBNORMAL FP_PLUS_DENORM
  639: #  define TRIO_NEGATIVE_SUBNORMAL FP_MINUS_DENORM
  640: #  define TRIO_POSITIVE_ZERO FP_PLUS_ZERO
  641: #  define TRIO_NEGATIVE_ZERO FP_MINUS_ZERO
  642: #  define TRIO_POSITIVE_NORMAL FP_PLUS_NORM
  643: #  define TRIO_NEGATIVE_NORMAL FP_MINUS_NORM
  644: # endif
  645: 
  646: # if defined(TRIO_FPCLASSIFY)
  647:   switch (TRIO_FPCLASSIFY(number)) {
  648:   case TRIO_QUIET_NAN:
  649:   case TRIO_SIGNALLING_NAN:
  650:     *is_negative = TRIO_FALSE; /* NaN has no sign */
  651:     return TRIO_FP_NAN;
  652:   case TRIO_POSITIVE_INFINITY:
  653:     *is_negative = TRIO_FALSE;
  654:     return TRIO_FP_INFINITE;
  655:   case TRIO_NEGATIVE_INFINITY:
  656:     *is_negative = TRIO_TRUE;
  657:     return TRIO_FP_INFINITE;
  658:   case TRIO_POSITIVE_SUBNORMAL:
  659:     *is_negative = TRIO_FALSE;
  660:     return TRIO_FP_SUBNORMAL;
  661:   case TRIO_NEGATIVE_SUBNORMAL:
  662:     *is_negative = TRIO_TRUE;
  663:     return TRIO_FP_SUBNORMAL;
  664:   case TRIO_POSITIVE_ZERO:
  665:     *is_negative = TRIO_FALSE;
  666:     return TRIO_FP_ZERO;
  667:   case TRIO_NEGATIVE_ZERO:
  668:     *is_negative = TRIO_TRUE;
  669:     return TRIO_FP_ZERO;
  670:   case TRIO_POSITIVE_NORMAL:
  671:     *is_negative = TRIO_FALSE;
  672:     return TRIO_FP_NORMAL;
  673:   case TRIO_NEGATIVE_NORMAL:
  674:     *is_negative = TRIO_TRUE;
  675:     return TRIO_FP_NORMAL;
  676:   default:
  677:     /* Just in case... */
  678:     *is_negative = (number < 0.0);
  679:     return TRIO_FP_NORMAL;
  680:   }
  681: 
  682: # else
  683:   /*
  684:    * Fallback solution.
  685:    */
  686:   int rc;
  687: 
  688:   if (number == 0.0) {
  689:     /*
  690:      * In IEEE 754 the sign of zero is ignored in comparisons, so we
  691:      * have to handle this as a special case by examining the sign bit
  692:      * directly.
  693:      */
  694: #  if defined(USE_IEEE_754)
  695:     *is_negative = trio_is_negative(number);
  696: #  else
  697:     *is_negative = TRIO_FALSE; /* FIXME */
  698: #  endif
  699:     return TRIO_FP_ZERO;
  700:   }
  701:   if (trio_isnan(number)) {
  702:     *is_negative = TRIO_FALSE;
  703:     return TRIO_FP_NAN;
  704:   }
  705:   if ((rc = trio_isinf(number))) {
  706:     *is_negative = (rc == -1);
  707:     return TRIO_FP_INFINITE;
  708:   }
  709:   if ((number > 0.0) && (number < DBL_MIN)) {
  710:     *is_negative = TRIO_FALSE;
  711:     return TRIO_FP_SUBNORMAL;
  712:   }
  713:   if ((number < 0.0) && (number > -DBL_MIN)) {
  714:     *is_negative = TRIO_TRUE;
  715:     return TRIO_FP_SUBNORMAL;
  716:   }
  717:   *is_negative = (number < 0.0);
  718:   return TRIO_FP_NORMAL;
  719: 
  720: # endif
  721: #endif
  722: }
  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;
  737: 
  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;
  756: 
  757:   return trio_fpclassify_and_signbit(number, &dummy);
  758: }
  759: 
  760: #endif
  761: 
  762: /** @} SpecialQuantities */
  763: 
  764: /*************************************************************************
  765:  * For test purposes.
  766:  *
  767:  * Add the following compiler option to include this test code.
  768:  *
  769:  *  Unix : -DSTANDALONE
  770:  *  VMS  : /DEFINE=(STANDALONE)
  771:  */
  772: #if defined(STANDALONE)
  773: # include <stdio.h>
  774: 
  775: static TRIO_CONST char *
  776: getClassification
  777: TRIO_ARGS1((type),
  778: 	   int type)
  779: {
  780:   switch (type) {
  781:   case TRIO_FP_INFINITE:
  782:     return "FP_INFINITE";
  783:   case TRIO_FP_NAN:
  784:     return "FP_NAN";
  785:   case TRIO_FP_NORMAL:
  786:     return "FP_NORMAL";
  787:   case TRIO_FP_SUBNORMAL:
  788:     return "FP_SUBNORMAL";
  789:   case TRIO_FP_ZERO:
  790:     return "FP_ZERO";
  791:   default:
  792:     return "FP_UNKNOWN";
  793:   }
  794: }
  795: 
  796: static void
  797: print_class
  798: TRIO_ARGS2((prefix, number),
  799: 	   TRIO_CONST char *prefix,
  800: 	   double number)
  801: {
  802:   printf("%-6s: %s %-15s %g\n",
  803: 	 prefix,
  804: 	 trio_signbit(number) ? "-" : "+",
  805: 	 getClassification(TRIO_FPCLASSIFY(number)),
  806: 	 number);
  807: }
  808: 
  809: int main(TRIO_NOARGS)
  810: {
  811:   double my_nan;
  812:   double my_pinf;
  813:   double my_ninf;
  814: # if defined(TRIO_PLATFORM_UNIX)
  815:   void (*signal_handler) TRIO_PROTO((int));
  816: # endif
  817: 
  818:   my_nan = trio_nan();
  819:   my_pinf = trio_pinf();
  820:   my_ninf = trio_ninf();
  821: 
  822:   print_class("Nan", my_nan);
  823:   print_class("PInf", my_pinf);
  824:   print_class("NInf", my_ninf);
  825:   print_class("PZero", 0.0);
  826:   print_class("NZero", -0.0);
  827:   print_class("PNorm", 1.0);
  828:   print_class("NNorm", -1.0);
  829:   print_class("PSub", 1.01e-307 - 1.00e-307);
  830:   print_class("NSub", 1.00e-307 - 1.01e-307);
  831: 
  832:   printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
  833: 	 my_nan,
  834: 	 ((unsigned char *)&my_nan)[0],
  835: 	 ((unsigned char *)&my_nan)[1],
  836: 	 ((unsigned char *)&my_nan)[2],
  837: 	 ((unsigned char *)&my_nan)[3],
  838: 	 ((unsigned char *)&my_nan)[4],
  839: 	 ((unsigned char *)&my_nan)[5],
  840: 	 ((unsigned char *)&my_nan)[6],
  841: 	 ((unsigned char *)&my_nan)[7],
  842: 	 trio_isnan(my_nan), trio_isinf(my_nan));
  843:   printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
  844: 	 my_pinf,
  845: 	 ((unsigned char *)&my_pinf)[0],
  846: 	 ((unsigned char *)&my_pinf)[1],
  847: 	 ((unsigned char *)&my_pinf)[2],
  848: 	 ((unsigned char *)&my_pinf)[3],
  849: 	 ((unsigned char *)&my_pinf)[4],
  850: 	 ((unsigned char *)&my_pinf)[5],
  851: 	 ((unsigned char *)&my_pinf)[6],
  852: 	 ((unsigned char *)&my_pinf)[7],
  853: 	 trio_isnan(my_pinf), trio_isinf(my_pinf));
  854:   printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
  855: 	 my_ninf,
  856: 	 ((unsigned char *)&my_ninf)[0],
  857: 	 ((unsigned char *)&my_ninf)[1],
  858: 	 ((unsigned char *)&my_ninf)[2],
  859: 	 ((unsigned char *)&my_ninf)[3],
  860: 	 ((unsigned char *)&my_ninf)[4],
  861: 	 ((unsigned char *)&my_ninf)[5],
  862: 	 ((unsigned char *)&my_ninf)[6],
  863: 	 ((unsigned char *)&my_ninf)[7],
  864: 	 trio_isnan(my_ninf), trio_isinf(my_ninf));
  865: 
  866: # if defined(TRIO_PLATFORM_UNIX)
  867:   signal_handler = signal(SIGFPE, SIG_IGN);
  868: # endif
  869: 
  870:   my_pinf = DBL_MAX + DBL_MAX;
  871:   my_ninf = -my_pinf;
  872:   my_nan = my_pinf / my_pinf;
  873: 
  874: # if defined(TRIO_PLATFORM_UNIX)
  875:   signal(SIGFPE, signal_handler);
  876: # endif
  877: 
  878:   printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
  879: 	 my_nan,
  880: 	 ((unsigned char *)&my_nan)[0],
  881: 	 ((unsigned char *)&my_nan)[1],
  882: 	 ((unsigned char *)&my_nan)[2],
  883: 	 ((unsigned char *)&my_nan)[3],
  884: 	 ((unsigned char *)&my_nan)[4],
  885: 	 ((unsigned char *)&my_nan)[5],
  886: 	 ((unsigned char *)&my_nan)[6],
  887: 	 ((unsigned char *)&my_nan)[7],
  888: 	 trio_isnan(my_nan), trio_isinf(my_nan));
  889:   printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
  890: 	 my_pinf,
  891: 	 ((unsigned char *)&my_pinf)[0],
  892: 	 ((unsigned char *)&my_pinf)[1],
  893: 	 ((unsigned char *)&my_pinf)[2],
  894: 	 ((unsigned char *)&my_pinf)[3],
  895: 	 ((unsigned char *)&my_pinf)[4],
  896: 	 ((unsigned char *)&my_pinf)[5],
  897: 	 ((unsigned char *)&my_pinf)[6],
  898: 	 ((unsigned char *)&my_pinf)[7],
  899: 	 trio_isnan(my_pinf), trio_isinf(my_pinf));
  900:   printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
  901: 	 my_ninf,
  902: 	 ((unsigned char *)&my_ninf)[0],
  903: 	 ((unsigned char *)&my_ninf)[1],
  904: 	 ((unsigned char *)&my_ninf)[2],
  905: 	 ((unsigned char *)&my_ninf)[3],
  906: 	 ((unsigned char *)&my_ninf)[4],
  907: 	 ((unsigned char *)&my_ninf)[5],
  908: 	 ((unsigned char *)&my_ninf)[6],
  909: 	 ((unsigned char *)&my_ninf)[7],
  910: 	 trio_isnan(my_ninf), trio_isinf(my_ninf));
  911: 
  912:   return 0;
  913: }
  914: #endif

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