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:
axel%pike.org 2001-07-11 09:43:00 +00:00
Родитель 1a43ceabff
Коммит 91d3d1c471
5 изменённых файлов: 154 добавлений и 86 удалений

Просмотреть файл

@ -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
}
/*