From 21458c85e209cd2621ac3eadfee075ae2dc0121d Mon Sep 17 00:00:00 2001 From: Daniel Veillard Date: Wed, 27 Mar 2002 16:12:22 +0000 Subject: [PATCH] more patches from Richard Jinks Updated tests though they show a * trionan.c trionan.h xpath.c: more patches from Richard Jinks * test/XPath/expr/compare test/XPath/expr/equality test/XPath/expr/floats test/XPath/expr/functions test/XPath/expr/strings result/XPath/expr/compare result/XPath/expr/equality result/XPath/expr/floats result/XPath/expr/functions result/XPath/expr/strings: Updated tests though they show a divergence on Linux Daniel --- ChangeLog | 10 ++ result/XPath/expr/compare | 88 +++++++++++ result/XPath/expr/equality | 8 + result/XPath/expr/floats | 138 ++++++++++++++++- result/XPath/expr/functions | 84 +++++++++- result/XPath/expr/strings | 8 + test/XPath/expr/compare | 22 +++ test/XPath/expr/equality | 3 +- test/XPath/expr/floats | 34 ++++ test/XPath/expr/functions | 23 ++- test/XPath/expr/strings | 2 + trionan.c | 300 ++++++++++++++++++++++++++++++++---- trionan.h | 20 +++ xpath.c | 43 ++++-- 14 files changed, 734 insertions(+), 49 deletions(-) diff --git a/ChangeLog b/ChangeLog index 39be6a12..de178e2c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Wed Mar 27 17:09:43 CET 2002 Daniel Veillard + + * trionan.c trionan.h xpath.c: more patches from Richard Jinks + * test/XPath/expr/compare test/XPath/expr/equality + test/XPath/expr/floats test/XPath/expr/functions + test/XPath/expr/strings result/XPath/expr/compare + result/XPath/expr/equality result/XPath/expr/floats + result/XPath/expr/functions result/XPath/expr/strings: Updated + tests though they show a divergence on Linux + Wed Mar 27 10:06:53 CET 2002 Daniel Veillard * xpath.c trionan.c: previous commit also included patches diff --git a/result/XPath/expr/compare b/result/XPath/expr/compare index a0dcdc42..21a88d0e 100644 --- a/result/XPath/expr/compare +++ b/result/XPath/expr/compare @@ -1,4 +1,20 @@ +======================== +Expression: 0<0 +Object is a Boolean : false + +======================== +Expression: 0<=0 +Object is a Boolean : true + +======================== +Expression: 0>0 +Object is a Boolean : false + +======================== +Expression: 0>=0 +Object is a Boolean : true + ======================== Expression: 0<1 Object is a Boolean : true @@ -79,6 +95,22 @@ Object is a Boolean : false Expression: 0>='1.2' Object is a Boolean : false +======================== +Expression: 0<'-0.2' +Object is a Boolean : false + +======================== +Expression: 0<='-0.2' +Object is a Boolean : false + +======================== +Expression: 0>'-0.2' +Object is a Boolean : true + +======================== +Expression: 0>='-0.2' +Object is a Boolean : true + ======================== Expression: false()<1 Object is a Boolean : true @@ -94,3 +126,59 @@ Object is a Boolean : false ======================== Expression: 0>=true() Object is a Boolean : false + +======================== +Expression: 'a' > 'a' +Object is a Boolean : false + +======================== +Expression: 'a' > 'b' +Object is a Boolean : false + +======================== +Expression: 'b' > 'a' +Object is a Boolean : false + +======================== +Expression: 'a' < 'a' +Object is a Boolean : false + +======================== +Expression: 'a' < 'b' +Object is a Boolean : false + +======================== +Expression: 'b' < 'a' +Object is a Boolean : false + +======================== +Expression: 'a' >= 'a' +Object is a Boolean : false + +======================== +Expression: 'a' >= 'b' +Object is a Boolean : false + +======================== +Expression: 'b' >= 'a' +Object is a Boolean : false + +======================== +Expression: 'a' <= 'a' +Object is a Boolean : false + +======================== +Expression: 'a' <= 'b' +Object is a Boolean : false + +======================== +Expression: 'b' <= 'a' +Object is a Boolean : false + +======================== +Expression: 'a' > '0.0' +Object is a Boolean : false + +======================== +Expression: 'a' < '0.0' +Object is a Boolean : false diff --git a/result/XPath/expr/equality b/result/XPath/expr/equality index 594b101e..44b4c221 100644 --- a/result/XPath/expr/equality +++ b/result/XPath/expr/equality @@ -94,3 +94,11 @@ Object is a Boolean : false ======================== Expression: 'test'!=false() Object is a Boolean : true + +======================== +Expression: 'a'=0.0 +Object is a Boolean : false + +======================== +Expression: 'a'!=0.0 +Object is a Boolean : true diff --git a/result/XPath/expr/floats b/result/XPath/expr/floats index c121b8e9..7a44f8df 100644 --- a/result/XPath/expr/floats +++ b/result/XPath/expr/floats @@ -25,7 +25,7 @@ Object is a number : 0.00123 ======================== Expression: 1 div 0 -Object is a number : +Infinity +Object is a number : Infinity ======================== Expression: -1 div 0 @@ -35,6 +35,10 @@ Object is a number : -Infinity Expression: 0 div 0 Object is a number : NaN +======================== +Expression: 1 div -0 +Object is a number : -Infinity + ======================== Expression: (1 div 0) > 0 Object is a Boolean : true @@ -58,3 +62,135 @@ Object is a Boolean : false ======================== Expression: (0 div 0) < 0 Object is a Boolean : false + +======================== +Expression: (1 div -0) > 0 +Object is a Boolean : false + +======================== +Expression: (1 div -0) < 0 +Object is a Boolean : true + +======================== +Expression: 0 div 0 = 0 div 0 +Object is a Boolean : false + +======================== +Expression: 0 div 0 != 0 div 0 +Object is a Boolean : true + +======================== +Expression: 0 div 0 > 0 div 0 +Object is a Boolean : false + +======================== +Expression: 0 div 0 < 0 div 0 +Object is a Boolean : false + +======================== +Expression: 0 div 0 >= 0 div 0 +Object is a Boolean : false + +======================== +Expression: 0 div 0 <= 0 div 0 +Object is a Boolean : false + +======================== +Expression: 1 div 0 = -1 div 0 +Object is a Boolean : false + +======================== +Expression: 1 div 0 != -1 div 0 +Object is a Boolean : true + +======================== +Expression: 1 div 0 > -1 div 0 +Object is a Boolean : true + +======================== +Expression: 1 div 0 < -1 div 0 +Object is a Boolean : false + +======================== +Expression: 1 div 0 >= -1 div 0 +Object is a Boolean : true + +======================== +Expression: 1 div 0 <= -1 div 0 +Object is a Boolean : false + +======================== +Expression: 1 div 0 = 1 div 0 +Object is a Boolean : true + +======================== +Expression: 1 div 0 != 1 div 0 +Object is a Boolean : false + +======================== +Expression: 1 div 0 > 1 div 0 +Object is a Boolean : false + +======================== +Expression: 1 div 0 < 1 div 0 +Object is a Boolean : false + +======================== +Expression: 1 div 0 >= -1 div 0 +Object is a Boolean : true + +======================== +Expression: 1 div 0 <= -1 div 0 +Object is a Boolean : false + +======================== +Expression: -2 div 0 = -1 div 0 +Object is a Boolean : true + +======================== +Expression: 1 div floor(0.1) +Object is a number : Infinity + +======================== +Expression: 1 div floor(-0.1) +Object is a number : -1 + +======================== +Expression: 1 div floor(-0) +Object is a number : -Infinity + +======================== +Expression: 1 div floor(0) +Object is a number : Infinity + +======================== +Expression: 1 div ceiling(0.1) +Object is a number : 1 + +======================== +Expression: 1 div ceiling(-0.1) +Object is a number : -Infinity + +======================== +Expression: 1 div ceiling(-0) +Object is a number : -Infinity + +======================== +Expression: 1 div ceiling(0) +Object is a number : Infinity + +======================== +Expression: 1 div round(0.1) +Object is a number : Infinity + +======================== +Expression: 1 div round(-0.1) +Object is a number : -Infinity + +======================== +Expression: 1 div round(-0) +Object is a number : -Infinity + +======================== +Expression: 1 div round(0) +Object is a number : Infinity diff --git a/result/XPath/expr/functions b/result/XPath/expr/functions index 29f44f7d..30b47715 100644 --- a/result/XPath/expr/functions +++ b/result/XPath/expr/functions @@ -12,9 +12,85 @@ Expression: number("1.5") Object is a number : 1.5 ======================== -Expression: concat("titi",'toto') -Object is a string : tititoto +Expression: number('abc') +Object is a number : NaN ======================== -Expression: concat("titi",'toto',"tata","last") -Object is a string : tititototatalast +Expression: floor(0.1) +Object is a number : 0 + +======================== +Expression: floor(-0.1) +Object is a number : -1 + +======================== +Expression: floor(-0) +Object is a number : 0 + +======================== +Expression: floor(0) +Object is a number : 0 + +======================== +Expression: floor(5.2) +Object is a number : 5 + +======================== +Expression: floor(-5.2) +Object is a number : -6 + +======================== +Expression: ceiling(0.1) +Object is a number : 1 + +======================== +Expression: ceiling(-0.1) +Object is a number : 0 + +======================== +Expression: ceiling(-0) +Object is a number : 0 + +======================== +Expression: ceiling(0) +Object is a number : 0 + +======================== +Expression: ceiling(5.2) +Object is a number : 6 + +======================== +Expression: ceiling(-5.2) +Object is a number : -5 + +======================== +Expression: round(0.1) +Object is a number : 0 + +======================== +Expression: round(5.2) +Object is a number : 5 + +======================== +Expression: round(5.5) +Object is a number : 6 + +======================== +Expression: round(5.6) +Object is a number : 6 + +======================== +Expression: round(-0.1) +Object is a number : 0 + +======================== +Expression: round(-5.2) +Object is a number : -5 + +======================== +Expression: round(-5.5) +Object is a number : -5 + +======================== +Expression: round(-5.6) +Object is a number : -6 diff --git a/result/XPath/expr/strings b/result/XPath/expr/strings index 85a35c90..09ccdec0 100644 --- a/result/XPath/expr/strings +++ b/result/XPath/expr/strings @@ -27,6 +27,14 @@ Object is a string : tititoto Expression: concat("titi","toto","tata") Object is a string : tititototata +======================== +Expression: concat("titi",'toto') +Object is a string : tititoto + +======================== +Expression: concat("titi",'toto',"tata","last") +Object is a string : tititototatalast + ======================== Expression: starts-with("tititoto","titi") Object is a Boolean : true diff --git a/test/XPath/expr/compare b/test/XPath/expr/compare index 81b26322..2d52eaf3 100644 --- a/test/XPath/expr/compare +++ b/test/XPath/expr/compare @@ -1,3 +1,7 @@ +0<0 +0<=0 +0>0 +0>=0 0<1 0<=1 0>1 @@ -18,7 +22,25 @@ 0<='1.2' 0>'1.2' 0>='1.2' +0<'-0.2' +0<='-0.2' +0>'-0.2' +0>='-0.2' false()<1 false()<=1 0>true() 0>=true() +'a' > 'a' +'a' > 'b' +'b' > 'a' +'a' < 'a' +'a' < 'b' +'b' < 'a' +'a' >= 'a' +'a' >= 'b' +'b' >= 'a' +'a' <= 'a' +'a' <= 'b' +'b' <= 'a' +'a' > '0.0' +'a' < '0.0' diff --git a/test/XPath/expr/equality b/test/XPath/expr/equality index 2a8c84fc..79821731 100644 --- a/test/XPath/expr/equality +++ b/test/XPath/expr/equality @@ -22,4 +22,5 @@ true()='test' false()='test' 'test'!=true() 'test'!=false() - +'a'=0.0 +'a'!=0.0 diff --git a/test/XPath/expr/floats b/test/XPath/expr/floats index ccad20e9..00ac6573 100644 --- a/test/XPath/expr/floats +++ b/test/XPath/expr/floats @@ -7,9 +7,43 @@ 1 div 0 -1 div 0 0 div 0 +1 div -0 (1 div 0) > 0 (1 div 0) < 0 (-1 div 0) > 0 (-1 div 0) < 0 (0 div 0) > 0 (0 div 0) < 0 +(1 div -0) > 0 +(1 div -0) < 0 +0 div 0 = 0 div 0 +0 div 0 != 0 div 0 +0 div 0 > 0 div 0 +0 div 0 < 0 div 0 +0 div 0 >= 0 div 0 +0 div 0 <= 0 div 0 +1 div 0 = -1 div 0 +1 div 0 != -1 div 0 +1 div 0 > -1 div 0 +1 div 0 < -1 div 0 +1 div 0 >= -1 div 0 +1 div 0 <= -1 div 0 +1 div 0 = 1 div 0 +1 div 0 != 1 div 0 +1 div 0 > 1 div 0 +1 div 0 < 1 div 0 +1 div 0 >= -1 div 0 +1 div 0 <= -1 div 0 +-2 div 0 = -1 div 0 +1 div floor(0.1) +1 div floor(-0.1) +1 div floor(-0) +1 div floor(0) +1 div ceiling(0.1) +1 div ceiling(-0.1) +1 div ceiling(-0) +1 div ceiling(0) +1 div round(0.1) +1 div round(-0.1) +1 div round(-0) +1 div round(0) diff --git a/test/XPath/expr/functions b/test/XPath/expr/functions index d2cba4e2..d8c9e10d 100644 --- a/test/XPath/expr/functions +++ b/test/XPath/expr/functions @@ -1,5 +1,24 @@ true() false() number("1.5") -concat("titi",'toto') -concat("titi",'toto',"tata","last") +number('abc') +floor(0.1) +floor(-0.1) +floor(-0) +floor(0) +floor(5.2) +floor(-5.2) +ceiling(0.1) +ceiling(-0.1) +ceiling(-0) +ceiling(0) +ceiling(5.2) +ceiling(-5.2) +round(0.1) +round(5.2) +round(5.5) +round(5.6) +round(-0.1) +round(-5.2) +round(-5.5) +round(-5.6) diff --git a/test/XPath/expr/strings b/test/XPath/expr/strings index 299b3007..c54cdf33 100644 --- a/test/XPath/expr/strings +++ b/test/XPath/expr/strings @@ -5,6 +5,8 @@ string(true()) string(false()) concat("titi","toto") concat("titi","toto","tata") +concat("titi",'toto') +concat("titi",'toto',"tata","last") starts-with("tititoto","titi") starts-with("tititoto","to") contains("tititototata","titi") diff --git a/trionan.c b/trionan.c index 59e63a9f..138d2aae 100644 --- a/trionan.c +++ b/trionan.c @@ -93,6 +93,9 @@ static const char rcsid[] = "@(#)$Id$"; * Definitions */ +#define TRIO_TRUE (1 == 1) +#define TRIO_FALSE (0 == 1) + /* We must enable IEEE floating-point on Alpha */ #if defined(__alpha) && !defined(_IEEE_FP) # if defined(TRIO_COMPILER_DECC) @@ -145,11 +148,6 @@ static const char rcsid[] = "@(#)$Id$"; static TRIO_CONST double internalEndianMagic = 7.949928895127363e-275; -/* Mask for the sign */ -static TRIO_CONST unsigned char ieee_754_sign_mask[] = { - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - /* Mask for the exponent */ static TRIO_CONST unsigned char ieee_754_exponent_mask[] = { 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 @@ -160,6 +158,11 @@ static TRIO_CONST unsigned char ieee_754_mantissa_mask[] = { 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; +/* Mask for the sign bit */ +static TRIO_CONST unsigned char ieee_754_sign_mask[] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + /* Bit-pattern for negative zero */ static TRIO_CONST unsigned char ieee_754_negzero_array[] = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 @@ -196,7 +199,7 @@ trio_make_double(TRIO_CONST unsigned char *values) } /* - * trio_examine_double + * trio_is_special_quantity */ TRIO_PRIVATE int trio_is_special_quantity(double number, @@ -204,7 +207,7 @@ trio_is_special_quantity(double number, { unsigned int i; unsigned char current; - int is_special_quantity = (1 == 1); + int is_special_quantity = TRIO_TRUE; *has_mantissa = 0; @@ -217,33 +220,24 @@ trio_is_special_quantity(double number, return is_special_quantity; } -/** - Get the sign value - - @return 1 for negative, 0 for positive -*/ -TRIO_PUBLIC int -trio_get_sign(double number) +/* + * trio_is_negative + */ +TRIO_PRIVATE int +trio_is_negative(double number) { unsigned int i; - unsigned char current; - int sign = (1 == 1); + int is_negative = TRIO_FALSE; for (i = 0; i < (unsigned int)sizeof(double); i++) { - current = ((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)]; - sign - &= ((current & ieee_754_sign_mask[i]) == ieee_754_sign_mask[i]); + is_negative |= (((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)] + & ieee_754_sign_mask[i]); } - return sign; + return is_negative; } -/** - Generate negative zero - - @return Floating-point representation of negative zero. -*/ TRIO_PUBLIC double -trio_nzero(void) +trio_nzero(void) { return trio_make_double(ieee_754_negzero_array); } @@ -383,7 +377,7 @@ trio_isnan(TRIO_VOLATILE double number) #elif defined(TRIO_COMPILER_MSVC) /* - * MSC has an _isnan() function + * MSVC has an _isnan() function */ return _isnan(number); @@ -501,6 +495,221 @@ trio_isinf(TRIO_VOLATILE double number) #endif } + +/** + Check for finity. + + @param number An arbitrary floating-point number. + @return Boolean value indicating whether or not the number is a finite. +*/ +TRIO_PUBLIC int +trio_isfinite(TRIO_VOLATILE double number) +{ +#if defined(isfinite) + /* + * C99 defines isfinite() as a macro. + */ + return isfinite(number); + +#elif defined(TRIO_COMPILER_MSVC) + /* + * MSVC uses _finite(). + */ + return _finite(number); + +#elif defined(USE_IEEE_754) + /* + * Examine IEEE 754 bit-pattern. For finity we do not care about the + * mantissa. + */ + int dummy; + + return (! trio_is_special_quantity(number, &dummy)); + +#else + /* + * Fallback solution. + */ + return ((trio_isinf(number) == 0) && (trio_isnan(number) == 0)); + +#endif +} + +/* + * The sign of NaN is always false + */ +TRIO_PRIVATE int +trio_fpclass(TRIO_VOLATILE double number, + int *is_negative) +{ +#if defined(fpclassify) && defined(signbit) + /* + * C99 defines fpclassify() and signbit() as a macros + */ + *is_negative = signbit(number); + switch (fpclassify(number)) { + case FP_NAN: + return TRIO_FP_NAN; + case FP_INFINITE: + return TRIO_FP_INFINITE; + case FP_SUBNORMAL: + return TRIO_FP_SUBNORMAL; + case FP_ZERO: + return TRIO_FP_ZERO; + default: + return TRIO_FP_NORMAL; + } + +#elif defined(TRIO_COMPILER_DECC) + /* + * DECC has an fp_class() function. + */ + switch (fp_class(number)) { + case FP_QNAN: + case FP_SNAN: + *is_negative = TRIO_FALSE; /* NaN has no sign */ + return TRIO_FP_NAN; + case FP_POS_INF: + *is_negative = TRIO_FALSE; + return TRIO_FP_INFINITE; + case FP_NEG_INF: + *is_negative = TRIO_TRUE; + return TRIO_FP_INFINITE; + case FP_POS_DENORM: + *is_negative = TRIO_FALSE; + return TRIO_FP_SUBNORMAL; + case FP_NEG_DENORM: + *is_negative = TRIO_TRUE; + return TRIO_FP_SUBNORMAL; + case FP_POS_ZERO: + *is_negative = TRIO_FALSE; + return TRIO_FP_ZERO; + case FP_NEG_ZERO: + *is_negative = TRIO_TRUE; + return TRIO_FP_ZERO; + case FP_POS_NORM: + *is_negative = TRIO_FALSE; + return TRIO_FP_NORMAL; + case FP_NEG_NORM: + *is_negative = TRIO_TRUE; + return TRIO_FP_NORMAL; + default: + /* Just in case... */ + *is_negative = (number < 0.0); + return TRIO_FP_NORMAL; + } + +#elif defined(TRIO_COMPILER_MSVC) + /* + * MSVC has an _fpclass() function. + */ + switch (_fpclass(number)) { + case _FPCLASS_QNAN: + case _FPCLASS_SNAN: + *is_negative = TRIO_FALSE; + return TRIO_FP_NAN; + case _FPCLASS_PINF: + *is_negative = TRIO_FALSE; + return TRIO_FP_INFINITE; + case _FPCLASS_NINF: + *is_negative = TRIO_TRUE; + return TRIO_FP_INFINITE; + case _FPCLASS_PD: + *is_negative = TRIO_FALSE; + return TRIO_FP_SUBNORMAL; + case _FPCLASS_ND: + *is_negative = TRIO_TRUE; + return TRIO_FP_SUBNORMAL; + case _FPCLASS_PZ: + *is_negative = TRIO_FALSE; + return TRIO_FP_ZERO; + case _FPCLASS_NZ: + *is_negative = TRIO_TRUE; + return TRIO_FP_ZERO; + case _FPCLASS_PN: + *is_negative = TRIO_FALSE; + return TRIO_FP_NORMAL; + case _FPCLASS_NN: + *is_negative = TRIO_TRUE; + return TRIO_FP_NORMAL; + default: + /* Just in case... */ + *is_negative = (number < 0.0); + return TRIO_FP_NORMAL; + } + +#else + /* + * Fallback solution. + */ + int rc; + + if (number == 0.0) { + /* + * In IEEE 754 the sign of zero is ignored in comparisons, so we + * have to handle this as a special case by examining the sign bit + * directly. + */ +#if defined(USE_IEEE_754) + *is_negative = trio_is_negative(number); +#else + *is_negative = TRIO_FALSE; /* FIXME */ +#endif + return TRIO_FP_ZERO; + } + if (trio_isnan(number)) { + *is_negative = TRIO_FALSE; + return TRIO_FP_NAN; + } + if ((rc = trio_isinf(number))) { + *is_negative = (rc == -1); + return TRIO_FP_INFINITE; + } + if ((number > 0.0) && (number < DBL_MIN)) { + *is_negative = TRIO_FALSE; + return TRIO_FP_SUBNORMAL; + } + if ((number < 0.0) && (number > -DBL_MIN)) { + *is_negative = TRIO_TRUE; + return TRIO_FP_SUBNORMAL; + } + *is_negative = (number < 0.0); + return TRIO_FP_NORMAL; + +#endif +} + +/** + Examine the sign of a number. + + @param number An arbitrary floating-point number. + @return Boolean value indicating whether or not the number has the + sign bit set (i.e. is negative). +*/ +TRIO_PUBLIC int +trio_signbit(TRIO_VOLATILE double number) +{ + int is_negative; + + (void)trio_fpclass(number, &is_negative); + return is_negative; +} + +/** + Examine the class of a number. + + @param number An arbitrary floating-point number. + @return Enumerable value indicating the class of @p number +*/ +TRIO_PUBLIC int +trio_fpclassify(TRIO_VOLATILE double number) +{ + int dummy; + + return trio_fpclass(number, &dummy); +} + + /** @} SpecialQuantities */ /************************************************************************* @@ -514,6 +723,33 @@ trio_isinf(TRIO_VOLATILE double number) #if defined(STANDALONE) # include +static const char *getClassification(int type) +{ + switch (type) { + case TRIO_FP_INFINITE: + return "FP_INFINITE"; + case TRIO_FP_NAN: + return "FP_NAN"; + case TRIO_FP_NORMAL: + return "FP_NORMAL"; + case TRIO_FP_SUBNORMAL: + return "FP_SUBNORMAL"; + case TRIO_FP_ZERO: + return "FP_ZERO"; + default: + return "FP_UNKNOWN"; + } +} + +static void print_class(const char *prefix, double number) +{ + printf("%-6s: %s %-15s %g\n", + prefix, + trio_signbit(number) ? "-" : "+", + getClassification(trio_fpclassify(number)), + number); +} + int main(void) { double my_nan; @@ -527,6 +763,16 @@ int main(void) my_pinf = trio_pinf(); my_ninf = trio_ninf(); + print_class("Nan", my_nan); + print_class("PInf", my_pinf); + print_class("NInf", my_ninf); + print_class("PZero", 0.0); + print_class("NZero", -0.0); + print_class("PNorm", 1.0); + print_class("NNorm", -1.0); + print_class("PSub", 1.01e-307 - 1.00e-307); + print_class("NSub", 1.00e-307 - 1.01e-307); + printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", my_nan, ((unsigned char *)&my_nan)[0], diff --git a/trionan.h b/trionan.h index d80a3481..ab2102d7 100644 --- a/trionan.h +++ b/trionan.h @@ -23,6 +23,15 @@ #ifdef __cplusplus extern "C" { #endif + +enum { + TRIO_FP_INFINITE, + TRIO_FP_NAN, + TRIO_FP_NORMAL, + TRIO_FP_SUBNORMAL, + TRIO_FP_ZERO +}; + /* * Return NaN (Not-a-Number). */ @@ -49,6 +58,17 @@ TRIO_PUBLIC int trio_isnan(double number); */ TRIO_PUBLIC int trio_isinf(double number); +/* + * If number is finite return non-zero, otherwise return zero. + */ +TRIO_PUBLIC int trio_isfinite(double number); + +TRIO_PUBLIC int trio_signbit(double number); + +TRIO_PUBLIC int trio_fpclassify(double number); + +TRIO_PUBLIC double trio_nzero(void); + #ifdef __cplusplus } #endif diff --git a/xpath.c b/xpath.c index bbb02f6a..e3f89cec 100644 --- a/xpath.c +++ b/xpath.c @@ -155,9 +155,9 @@ xmlXPathIsInf(double val) { * * Returns 1 if the value is Negative, 0 if positive */ -int +static int xmlXPathGetSign(double val) { - return(trio_get_sign(val)); + return(trio_signbit(val)); } @@ -1275,8 +1275,8 @@ static const char *xmlXPathErrorMessages[] = { * Formats an error message. */ void -xmlXPatherror(xmlXPathParserContextPtr ctxt, const char *file, - int line, int no) { +xmlXPatherror(xmlXPathParserContextPtr ctxt, ATTRIBUTE_UNUSED const char *file, + ATTRIBUTE_UNUSED int line, int no) { int n; const xmlChar *cur; const xmlChar *base; @@ -4472,7 +4472,12 @@ xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) { arg2 = valuePop(ctxt); /* no break on purpose */ case XPATH_NUMBER: - ret = (arg1->floatval == arg2->floatval); + /* Hand checking NaNs for VC6++'s benefit... */ + if (xmlXPathIsNaN(arg1->floatval) || xmlXPathIsNaN(arg2->floatval)) { + ret = 0; + } else { + ret = (arg1->floatval == arg2->floatval); + } break; case XPATH_USERS: case XPATH_POINT: @@ -4508,7 +4513,12 @@ xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) { valuePush(ctxt, arg1); xmlXPathNumberFunction(ctxt, 1); arg1 = valuePop(ctxt); - ret = (arg1->floatval == arg2->floatval); + /* Hand checking NaNs for VC6++'s benefit... */ + if (xmlXPathIsNaN(arg1->floatval) || xmlXPathIsNaN(arg2->floatval)) { + ret = 0; + } else { + ret = (arg1->floatval == arg2->floatval); + } break; case XPATH_USERS: case XPATH_POINT: @@ -4610,14 +4620,19 @@ xmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict) { * Add tests for infinity and nan * => feedback on 3.4 for Inf and NaN */ - if (inf && strict) - ret = (arg1->floatval < arg2->floatval); - else if (inf && !strict) - ret = (arg1->floatval <= arg2->floatval); - else if (!inf && strict) - ret = (arg1->floatval > arg2->floatval); - else if (!inf && !strict) - ret = (arg1->floatval >= arg2->floatval); + /* Hand checking NaNs for VC++6's benefit... */ + if (xmlXPathIsNaN(arg1->floatval) || xmlXPathIsNaN(arg2->floatval)) { + ret=0; + } else { + if (inf && strict) + ret = (arg1->floatval < arg2->floatval); + else if (inf && !strict) + ret = (arg1->floatval <= arg2->floatval); + else if (!inf && strict) + ret = (arg1->floatval > arg2->floatval); + else if (!inf && !strict) + ret = (arg1->floatval >= arg2->floatval); + } xmlXPathFreeObject(arg1); xmlXPathFreeObject(arg2); return(ret);