diff --git a/result/XPath/expr/functions b/result/XPath/expr/functions index 10cc27ef..e09eb4a4 100644 --- a/result/XPath/expr/functions +++ b/result/XPath/expr/functions @@ -43,6 +43,26 @@ Object is a number : 5 Expression: floor(-5.2) Object is a number : -6 +======================== +Expression: floor(100000000000000000000) +Object is a number : 1e+20 + +======================== +Expression: floor(-100000000000000000000) +Object is a number : -1e+20 + +======================== +Expression: floor(0 div 0) +Object is a number : NaN + +======================== +Expression: floor(1 div 0) +Object is a number : Infinity + +======================== +Expression: floor(-1 div 0) +Object is a number : -Infinity + ======================== Expression: ceiling(0.1) Object is a number : 1 @@ -67,6 +87,26 @@ Object is a number : 6 Expression: ceiling(-5.2) Object is a number : -5 +======================== +Expression: ceiling(100000000000000000000) +Object is a number : 1e+20 + +======================== +Expression: ceiling(-100000000000000000000) +Object is a number : -1e+20 + +======================== +Expression: ceiling(0 div 0) +Object is a number : NaN + +======================== +Expression: ceiling(1 div 0) +Object is a number : Infinity + +======================== +Expression: ceiling(-1 div 0) +Object is a number : -Infinity + ======================== Expression: round(0.1) Object is a number : 0 @@ -98,3 +138,31 @@ Object is a number : -5 ======================== Expression: round(-5.6) Object is a number : -6 + +======================== +Expression: round(0.5) +Object is a number : 1 + +======================== +Expression: round(-0.5) +Object is a number : 0 + +======================== +Expression: round(100000000000000000000) +Object is a number : 1e+20 + +======================== +Expression: round(-100000000000000000000) +Object is a number : -1e+20 + +======================== +Expression: round(0 div 0) +Object is a number : NaN + +======================== +Expression: round(1 div 0) +Object is a number : Infinity + +======================== +Expression: round(-1 div 0) +Object is a number : -Infinity diff --git a/test/XPath/expr/functions b/test/XPath/expr/functions index d168b189..00b9461f 100644 --- a/test/XPath/expr/functions +++ b/test/XPath/expr/functions @@ -9,12 +9,22 @@ floor(-0) floor(0) floor(5.2) floor(-5.2) +floor(100000000000000000000) +floor(-100000000000000000000) +floor(0 div 0) +floor(1 div 0) +floor(-1 div 0) ceiling(0.1) ceiling(-0.1) ceiling(-0) ceiling(0) ceiling(5.2) ceiling(-5.2) +ceiling(100000000000000000000) +ceiling(-100000000000000000000) +ceiling(0 div 0) +ceiling(1 div 0) +ceiling(-1 div 0) round(0.1) round(5.2) round(5.5) @@ -23,3 +33,10 @@ round(-0.1) round(-5.2) round(-5.5) round(-5.6) +round(0.5) +round(-0.5) +round(100000000000000000000) +round(-100000000000000000000) +round(0 div 0) +round(1 div 0) +round(-1 div 0) diff --git a/xpath.c b/xpath.c index dce11079..0a24be64 100644 --- a/xpath.c +++ b/xpath.c @@ -9675,18 +9675,6 @@ xmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathReleaseObject(ctxt->context, cur); } -/* - * To assure working code on multiple platforms, we want to only depend - * upon the characteristic truncation of converting a floating point value - * to an integer. Unfortunately, because of the different storage sizes - * of our internal floating point value (double) and integer (int), we - * can't directly convert (see bug 301162). This macro is a messy - * 'workaround' - */ -#define XTRUNC(f, v) \ - f = fmod((v), INT_MAX); \ - f = (v) - (f) + (double)((int)(f)); - /** * xmlXPathFloorFunction: * @ctxt: the XPath Parser context @@ -9699,19 +9687,11 @@ xmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs) { */ void xmlXPathFloorFunction(xmlXPathParserContextPtr ctxt, int nargs) { - double f; - CHECK_ARITY(1); CAST_TO_NUMBER; CHECK_TYPE(XPATH_NUMBER); - XTRUNC(f, ctxt->value->floatval); - if (f != ctxt->value->floatval) { - if (ctxt->value->floatval > 0) - ctxt->value->floatval = f; - else - ctxt->value->floatval = f - 1; - } + ctxt->value->floatval = floor(ctxt->value->floatval); } /** @@ -9726,28 +9706,11 @@ xmlXPathFloorFunction(xmlXPathParserContextPtr ctxt, int nargs) { */ void xmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt, int nargs) { - double f; - CHECK_ARITY(1); CAST_TO_NUMBER; CHECK_TYPE(XPATH_NUMBER); -#if 0 ctxt->value->floatval = ceil(ctxt->value->floatval); -#else - XTRUNC(f, ctxt->value->floatval); - if (f != ctxt->value->floatval) { - if (ctxt->value->floatval > 0) - ctxt->value->floatval = f + 1; - else { - if (ctxt->value->floatval < 0 && f == 0) - ctxt->value->floatval = xmlXPathNZERO; - else - ctxt->value->floatval = f; - } - - } -#endif } /** @@ -9759,7 +9722,7 @@ xmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt, int nargs) { * number round(number) * The round function returns the number that is closest to the * argument and that is an integer. If there are two such numbers, - * then the one that is even is returned. + * then the one that is closest to positive infinity is returned. */ void xmlXPathRoundFunction(xmlXPathParserContextPtr ctxt, int nargs) { @@ -9769,25 +9732,21 @@ xmlXPathRoundFunction(xmlXPathParserContextPtr ctxt, int nargs) { CAST_TO_NUMBER; CHECK_TYPE(XPATH_NUMBER); - if ((xmlXPathIsNaN(ctxt->value->floatval)) || - (xmlXPathIsInf(ctxt->value->floatval) == 1) || - (xmlXPathIsInf(ctxt->value->floatval) == -1) || - (ctxt->value->floatval == 0.0)) + f = ctxt->value->floatval; + + /* Test for zero to keep negative zero unchanged. */ + if ((xmlXPathIsNaN(f)) || (f == 0.0)) return; - XTRUNC(f, ctxt->value->floatval); - if (ctxt->value->floatval < 0) { - if (ctxt->value->floatval < f - 0.5) - ctxt->value->floatval = f - 1; - else - ctxt->value->floatval = f; - if (ctxt->value->floatval == 0) - ctxt->value->floatval = xmlXPathNZERO; - } else { - if (ctxt->value->floatval < f + 0.5) - ctxt->value->floatval = f; - else - ctxt->value->floatval = f + 1; + if ((f >= -0.5) && (f < 0.0)) { + /* Negative zero. */ + ctxt->value->floatval = xmlXPathNZERO; + } + else { + double rounded = floor(f); + if (f - rounded >= 0.5) + rounded += 1.0; + ctxt->value->floatval = rounded; } }