зеркало из https://github.com/mozilla/gecko-dev.git
53518, fix NaN handling on certain platform. Copied code from js lib to transformiix, license change courtesy of Netscape. checkin on behalf on sicking@bigfoot.com. r=peterv,me, sr=scc
This commit is contained in:
Родитель
1a43ceabff
Коммит
91d3d1c471
|
@ -27,6 +27,10 @@
|
|||
* Eric Du, duxy@leyou.com.cn
|
||||
* -- added fix for FreeBSD
|
||||
*
|
||||
* NaN/Infinity code copied from the JS-library with permission from
|
||||
* Netscape Communications Corporation: http://www.mozilla.org/js
|
||||
* http://lxr.mozilla.org/seamonkey/source/js/src/jsnum.h
|
||||
*
|
||||
*/
|
||||
|
||||
#include "primitives.h"
|
||||
|
@ -53,26 +57,38 @@ fp_except_t allmask = FP_X_INV|FP_X_OFL|FP_X_UFL|FP_X_DZ|FP_X_IMP|FP_X_DNML;
|
|||
fp_except_t oldmask = fpsetmask(~allmask);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Macros to workaround math-bugs bugs in various platforms
|
||||
**/
|
||||
|
||||
#ifdef IS_BIG_ENDIAN
|
||||
#define TX_DOUBLE_HI32(x) (((PRUint32 *)&(x))[0])
|
||||
#define TX_DOUBLE_LO32(x) (((PRUint32 *)&(x))[1])
|
||||
#else
|
||||
#define TX_DOUBLE_HI32(x) (((PRUint32 *)&(x))[1])
|
||||
#define TX_DOUBLE_LO32(x) (((PRUint32 *)&(x))[0])
|
||||
#endif
|
||||
|
||||
#define TX_DOUBLE_HI32_SIGNBIT 0x80000000
|
||||
#define TX_DOUBLE_HI32_EXPMASK 0x7ff00000
|
||||
#define TX_DOUBLE_HI32_MANTMASK 0x000fffff
|
||||
|
||||
//-- Initialize Double related constants
|
||||
double d0 = 0.0;
|
||||
#ifdef IS_BIG_ENDIAN
|
||||
const PRUint32 nanMask[2] = {TX_DOUBLE_HI32_EXPMASK | TX_DOUBLE_HI32_MANTMASK,
|
||||
0xffffffff};
|
||||
const PRUint32 infMask[2] = {TX_DOUBLE_HI32_EXPMASK, 0};
|
||||
const PRUint32 negInfMask[2] = {TX_DOUBLE_HI32_EXPMASK | TX_DOUBLE_HI32_SIGNBIT, 0};
|
||||
#else
|
||||
const PRUint32 nanMask[2] = {0xffffffff,
|
||||
TX_DOUBLE_HI32_EXPMASK | TX_DOUBLE_HI32_MANTMASK};
|
||||
const PRUint32 infMask[2] = {0, TX_DOUBLE_HI32_EXPMASK};
|
||||
const PRUint32 negInfMask[2] = {0, TX_DOUBLE_HI32_EXPMASK | TX_DOUBLE_HI32_SIGNBIT};
|
||||
#endif
|
||||
|
||||
const double Double::NaN = (d0/d0);
|
||||
const double Double::NEGATIVE_INFINITY = (-1.0/d0);
|
||||
const double Double::POSITIVE_INFINITY = (1.0/d0);
|
||||
|
||||
/**
|
||||
* Creates a new Double with it's value initialized to 0;
|
||||
**/
|
||||
Double::Double() {
|
||||
value = 0;
|
||||
} //-- Double
|
||||
|
||||
/**
|
||||
* Creates a new Double with it's value initialized to the given double
|
||||
**/
|
||||
Double::Double(double dbl) {
|
||||
this->value = dbl;
|
||||
} //-- Double
|
||||
const double Double::NaN = *((double*)nanMask);
|
||||
const double Double::POSITIVE_INFINITY = *((double*)infMask);
|
||||
const double Double::NEGATIVE_INFINITY = *((double*)negInfMask);
|
||||
|
||||
/**
|
||||
* Creates a new Double with it's value initialized from the given String.
|
||||
|
@ -100,42 +116,28 @@ int Double::intValue() {
|
|||
} //-- intValue
|
||||
|
||||
/**
|
||||
* Determins whether the given double represents positive or negative
|
||||
* Determines whether the given double represents positive or negative
|
||||
* inifinity
|
||||
**/
|
||||
MBool Double::isInfinite(double dbl) {
|
||||
return (MBool)((dbl == POSITIVE_INFINITY ) || (dbl == NEGATIVE_INFINITY));
|
||||
return ((TX_DOUBLE_HI32(dbl) & ~TX_DOUBLE_HI32_SIGNBIT) == TX_DOUBLE_HI32_EXPMASK &&
|
||||
!TX_DOUBLE_LO32(dbl));
|
||||
} //-- isInfinite
|
||||
|
||||
/**
|
||||
* Determins whether this Double's value represents positive or
|
||||
* negative inifinty
|
||||
**/
|
||||
MBool Double::isInfinite() {
|
||||
return (MBool)(( value == POSITIVE_INFINITY ) || (value == NEGATIVE_INFINITY));
|
||||
} //-- isInfinite
|
||||
|
||||
/**
|
||||
* Determins whether the given double is NaN
|
||||
* Determines whether the given double is NaN
|
||||
**/
|
||||
MBool Double::isNaN(double dbl) {
|
||||
#ifdef WIN32
|
||||
return _isnan(dbl);
|
||||
#else
|
||||
return (MBool) isnan(dbl);
|
||||
#endif
|
||||
return ((TX_DOUBLE_HI32(dbl) & TX_DOUBLE_HI32_EXPMASK) == TX_DOUBLE_HI32_EXPMASK &&
|
||||
(TX_DOUBLE_LO32(dbl) || (TX_DOUBLE_HI32(dbl) & TX_DOUBLE_HI32_MANTMASK)));
|
||||
} //-- isNaN
|
||||
|
||||
/**
|
||||
* Determins whether this Double's value is NaN
|
||||
* Determines whether the given double is negative
|
||||
**/
|
||||
MBool Double::isNaN() {
|
||||
#ifdef WIN32
|
||||
return _isnan(value);
|
||||
#else
|
||||
return (MBool) isnan(value);
|
||||
#endif
|
||||
} //-- isNaN
|
||||
MBool Double::isNeg(double dbl) {
|
||||
return (TX_DOUBLE_HI32(dbl) & TX_DOUBLE_HI32_SIGNBIT) != 0;
|
||||
} //-- isNeg
|
||||
|
||||
/**
|
||||
* Converts the given String to a double, if the String value does not
|
||||
|
@ -191,15 +193,6 @@ double Double::toDouble(const String& src) {
|
|||
} //-- toDouble
|
||||
|
||||
|
||||
/**
|
||||
* Converts the value of this Double to a String, and places
|
||||
* The result into the destination String.
|
||||
* @return the given dest string
|
||||
**/
|
||||
String& Double::toString(String& dest) {
|
||||
return toString(value, dest);
|
||||
} //-- toString
|
||||
|
||||
/**
|
||||
* Converts the value of the given double to a String, and places
|
||||
* The result into the destination String.
|
||||
|
|
|
@ -28,6 +28,10 @@
|
|||
* Eric Du, duxy@leyou.com.cn
|
||||
* -- added fix for FreeBSD
|
||||
*
|
||||
* NaN/Infinity code copied from the JS-library with permission from
|
||||
* Netscape Communications Corporation: http://www.mozilla.org/js
|
||||
* http://lxr.mozilla.org/seamonkey/source/js/src/jsnum.h
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
@ -50,16 +54,6 @@ public:
|
|||
static const double POSITIVE_INFINITY;
|
||||
static const double NEGATIVE_INFINITY;
|
||||
|
||||
/**
|
||||
* Creates a new Double with it's value initialized to 0;
|
||||
**/
|
||||
Double();
|
||||
|
||||
/**
|
||||
* Creates a new Double with it's value initialized to the given double
|
||||
**/
|
||||
Double(double dbl);
|
||||
|
||||
/**
|
||||
* Creates a new Double with it's value initialized from the given String.
|
||||
* The String will be converted to a double. If the String does not
|
||||
|
@ -78,33 +72,20 @@ public:
|
|||
int intValue();
|
||||
|
||||
/**
|
||||
* Determins whether the given double represents positive or negative
|
||||
* Determines whether the given double represents positive or negative
|
||||
* inifinity
|
||||
**/
|
||||
static MBool isInfinite(double dbl);
|
||||
|
||||
/**
|
||||
* Determins whether this Double's value represents positive or
|
||||
* negative inifinty
|
||||
**/
|
||||
MBool isInfinite();
|
||||
|
||||
/**
|
||||
* Determins whether the given double is NaN
|
||||
* Determines whether the given double is NaN
|
||||
**/
|
||||
static MBool isNaN(double dbl);
|
||||
|
||||
/**
|
||||
* Determins whether this Double's value is NaN
|
||||
* Determines whether the given double is negative
|
||||
**/
|
||||
MBool isNaN();
|
||||
|
||||
/**
|
||||
* Converts the value of this Double to a String, and places
|
||||
* The result into the destination String.
|
||||
* @return the given dest string
|
||||
**/
|
||||
String& toString(String& dest);
|
||||
static MBool isNeg(double dbl);
|
||||
|
||||
/**
|
||||
* Converts the value of the given double to a String, and places
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
* Keith Visco, kvisco@ziplink.net
|
||||
* -- original author.
|
||||
*
|
||||
* NaN/Infinity code copied from the JS-library with permission from
|
||||
* Netscape Communications Corporation: http://www.mozilla.org/js
|
||||
* http://lxr.mozilla.org/seamonkey/source/js/src/jsinterp.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -78,10 +82,36 @@ ExprResult* MultiplicativeExpr::evaluate(Node* context, ContextState* cs) {
|
|||
|
||||
switch ( op ) {
|
||||
case DIVIDE:
|
||||
result = (leftDbl / rightDbl);
|
||||
if (rightDbl == 0) {
|
||||
#ifdef XP_PC
|
||||
/* XXX MSVC miscompiles such that (NaN == 0) */
|
||||
if (Double::isNaN(rightDbl))
|
||||
result = Double::NaN;
|
||||
else
|
||||
#endif
|
||||
if (leftDbl == 0 || Double::isNaN(leftDbl))
|
||||
result = Double::NaN;
|
||||
else if (Double::isNeg(leftDbl) ^ Double::isNeg(rightDbl))
|
||||
result = Double::NEGATIVE_INFINITY;
|
||||
else
|
||||
result = Double::POSITIVE_INFINITY;
|
||||
}
|
||||
else
|
||||
result = leftDbl / rightDbl;
|
||||
break;
|
||||
case MODULUS:
|
||||
result = fmod(leftDbl, rightDbl);
|
||||
if (rightDbl == 0) {
|
||||
result = Double::NaN;
|
||||
}
|
||||
else {
|
||||
#ifdef XP_PC
|
||||
/* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */
|
||||
if (!Double::isInfinite(leftDbl) && Double::isInfinite(rightDbl))
|
||||
result = leftDbl;
|
||||
else
|
||||
#endif
|
||||
result = fmod(leftDbl, rightDbl);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
result = leftDbl * rightDbl;
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
* Keith Visco, kvisco@ziplink.net
|
||||
* -- original author.
|
||||
*
|
||||
* NaN/Infinity code copied from the JS-library with permission from
|
||||
* Netscape Communications Corporation: http://www.mozilla.org/js
|
||||
* http://lxr.mozilla.org/seamonkey/source/js/src/jsinterp.c
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Expr.h"
|
||||
|
@ -86,7 +90,16 @@ MBool RelationalExpr::compareResults(ExprResult* left, ExprResult* right) {
|
|||
}
|
||||
else if ((ltype == ExprResult::NUMBER) ||
|
||||
(rtype == ExprResult::NUMBER)) {
|
||||
result = (left->numberValue() != right->numberValue());
|
||||
double lval = left->numberValue();
|
||||
double rval = right->numberValue();
|
||||
#ifdef XP_PC
|
||||
if (Double::isNaN(lval) || Double::isNaN(rval))
|
||||
result = MB_TRUE;
|
||||
else
|
||||
result = (lval != rval);
|
||||
#else
|
||||
result = (lval != rval);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
String lStr;
|
||||
|
@ -104,7 +117,16 @@ MBool RelationalExpr::compareResults(ExprResult* left, ExprResult* right) {
|
|||
}
|
||||
else if ((ltype == ExprResult::NUMBER) ||
|
||||
(rtype == ExprResult::NUMBER)) {
|
||||
result = (left->numberValue() == right->numberValue());
|
||||
double lval = left->numberValue();
|
||||
double rval = right->numberValue();
|
||||
#ifdef XP_PC
|
||||
if (Double::isNaN(lval) || Double::isNaN(rval))
|
||||
result = MB_FALSE;
|
||||
else
|
||||
result = (lval == rval);
|
||||
#else
|
||||
result = (lval == rval);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
String lStr;
|
||||
|
@ -120,16 +142,44 @@ MBool RelationalExpr::compareResults(ExprResult* left, ExprResult* right) {
|
|||
double rightDbl = right->numberValue();
|
||||
switch( op ) {
|
||||
case LESS_THAN:
|
||||
result = (MBool) (leftDbl < rightDbl);
|
||||
#ifdef XP_PC
|
||||
if (Double::isNaN(leftDbl) || Double::isNaN(rightDbl))
|
||||
result = MB_FALSE;
|
||||
else
|
||||
result = (leftDbl < rightDbl);
|
||||
#else
|
||||
result = (leftDbl < rightDbl);
|
||||
#endif
|
||||
break;
|
||||
case LESS_OR_EQUAL:
|
||||
result = (MBool) (leftDbl <= rightDbl);
|
||||
#ifdef XP_PC
|
||||
if (Double::isNaN(leftDbl) || Double::isNaN(rightDbl))
|
||||
result = MB_FALSE;
|
||||
else
|
||||
result = (leftDbl <= rightDbl);
|
||||
#else
|
||||
result = (leftDbl <= rightDbl);
|
||||
#endif
|
||||
break;
|
||||
case GREATER_THAN :
|
||||
result = (MBool) (leftDbl > rightDbl);
|
||||
#ifdef XP_PC
|
||||
if (Double::isNaN(leftDbl) || Double::isNaN(rightDbl))
|
||||
result = MB_FALSE;
|
||||
else
|
||||
result = (leftDbl > rightDbl);
|
||||
#else
|
||||
result = (leftDbl > rightDbl);
|
||||
#endif
|
||||
break;
|
||||
case GREATER_OR_EQUAL:
|
||||
result = (MBool) (leftDbl >= rightDbl);
|
||||
#ifdef XP_PC
|
||||
if (Double::isNaN(leftDbl) || Double::isNaN(rightDbl))
|
||||
result = MB_FALSE;
|
||||
else
|
||||
result = (leftDbl >= rightDbl);
|
||||
#else
|
||||
result = (leftDbl >= rightDbl);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,11 @@
|
|||
* Contributor(s):
|
||||
* Jonas Sicking, sicking@bigfoot.com
|
||||
* -- original author.
|
||||
*
|
||||
* NaN/Infinity code copied from the JS-library with permission from
|
||||
* Netscape Communications Corporation: http://www.mozilla.org/js
|
||||
* http://lxr.mozilla.org/seamonkey/source/js/src/jsinterp.c
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Expr.h"
|
||||
|
@ -42,7 +47,16 @@ ExprResult* UnaryExpr::evaluate(Node* context, ContextState* cs)
|
|||
ExprResult* exprRes = expr->evaluate(context, cs);
|
||||
double value = exprRes->numberValue();
|
||||
delete exprRes;
|
||||
#ifdef HPUX
|
||||
/*
|
||||
* Negation of a zero doesn't produce a negative
|
||||
* zero on HPUX. Perform the operation by multiplying with
|
||||
* -1.
|
||||
*/
|
||||
return new NumberResult(-1 * value);
|
||||
#else
|
||||
return new NumberResult(-value);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Загрузка…
Ссылка в новой задаче