mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 714260 - Implement FloatingPoint.h to consolidate all IEEE-754 floating point operations in a single location. r=dmandelin for the js bits, r=Ms2ger for mfbt and the core bits
This commit is contained in:
parent
1a44f1208f
commit
18b2aec6c5
@ -2211,81 +2211,6 @@ public:
|
||||
} \
|
||||
} else
|
||||
|
||||
/**
|
||||
* Macros to workaround math-bugs bugs in various platforms
|
||||
*/
|
||||
|
||||
/**
|
||||
* Stefan Hanske <sh990154@mail.uni-greifswald.de> reports:
|
||||
* ARM is a little endian architecture but 64 bit double words are stored
|
||||
* differently: the 32 bit words are in little endian byte order, the two words
|
||||
* are stored in big endian`s way.
|
||||
*/
|
||||
|
||||
#if defined(__arm) || defined(__arm32__) || defined(__arm26__) || defined(__arm__)
|
||||
#if !defined(__VFP_FP__)
|
||||
#define FPU_IS_ARM_FPA
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef union dpun {
|
||||
struct {
|
||||
#if defined(IS_LITTLE_ENDIAN) && !defined(FPU_IS_ARM_FPA)
|
||||
PRUint32 lo, hi;
|
||||
#else
|
||||
PRUint32 hi, lo;
|
||||
#endif
|
||||
} s;
|
||||
PRFloat64 d;
|
||||
public:
|
||||
operator double() const {
|
||||
return d;
|
||||
}
|
||||
} dpun;
|
||||
|
||||
/**
|
||||
* Utility class for doubles
|
||||
*/
|
||||
#if (__GNUC__ == 2 && __GNUC_MINOR__ > 95) || __GNUC__ > 2
|
||||
/**
|
||||
* This version of the macros is safe for the alias optimizations
|
||||
* that gcc does, but uses gcc-specific extensions.
|
||||
*/
|
||||
#define DOUBLE_HI32(x) (__extension__ ({ dpun u; u.d = (x); u.s.hi; }))
|
||||
#define DOUBLE_LO32(x) (__extension__ ({ dpun u; u.d = (x); u.s.lo; }))
|
||||
|
||||
#else // __GNUC__
|
||||
|
||||
/* We don't know of any non-gcc compilers that perform alias optimization,
|
||||
* so this code should work.
|
||||
*/
|
||||
|
||||
#if defined(IS_LITTLE_ENDIAN) && !defined(FPU_IS_ARM_FPA)
|
||||
#define DOUBLE_HI32(x) (((PRUint32 *)&(x))[1])
|
||||
#define DOUBLE_LO32(x) (((PRUint32 *)&(x))[0])
|
||||
#else
|
||||
#define DOUBLE_HI32(x) (((PRUint32 *)&(x))[0])
|
||||
#define DOUBLE_LO32(x) (((PRUint32 *)&(x))[1])
|
||||
#endif
|
||||
|
||||
#endif // __GNUC__
|
||||
|
||||
#define DOUBLE_HI32_SIGNBIT 0x80000000
|
||||
#define DOUBLE_HI32_EXPMASK 0x7ff00000
|
||||
#define DOUBLE_HI32_MANTMASK 0x000fffff
|
||||
|
||||
#define DOUBLE_IS_NaN(x) \
|
||||
((DOUBLE_HI32(x) & DOUBLE_HI32_EXPMASK) == DOUBLE_HI32_EXPMASK && \
|
||||
(DOUBLE_LO32(x) || (DOUBLE_HI32(x) & DOUBLE_HI32_MANTMASK)))
|
||||
|
||||
#ifdef IS_BIG_ENDIAN
|
||||
#define DOUBLE_NaN {{DOUBLE_HI32_EXPMASK | DOUBLE_HI32_MANTMASK, \
|
||||
0xffffffff}}
|
||||
#else
|
||||
#define DOUBLE_NaN {{0xffffffff, \
|
||||
DOUBLE_HI32_EXPMASK | DOUBLE_HI32_MANTMASK}}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* In the following helper macros we exploit the fact that the result of a
|
||||
* series of additions will not be finite if any one of the operands in the
|
||||
|
@ -70,29 +70,6 @@ public:
|
||||
class txDouble
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Useful constants
|
||||
*/
|
||||
static const dpun NaN;
|
||||
static const dpun POSITIVE_INFINITY;
|
||||
static const dpun NEGATIVE_INFINITY;
|
||||
|
||||
/**
|
||||
* Determines whether the given double represents positive or negative
|
||||
* inifinity.
|
||||
*/
|
||||
static bool isInfinite(double aDbl);
|
||||
|
||||
/**
|
||||
* Determines whether the given double is NaN.
|
||||
*/
|
||||
static bool isNaN(double aDbl);
|
||||
|
||||
/**
|
||||
* Determines whether the given double is negative.
|
||||
*/
|
||||
static bool isNeg(double aDbl);
|
||||
|
||||
/**
|
||||
* Converts the value of the given double to a string, and appends
|
||||
* the result to the destination string.
|
||||
|
@ -35,6 +35,8 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include "nsString.h"
|
||||
#include "txCore.h"
|
||||
#include "txXMLUtils.h"
|
||||
@ -49,42 +51,6 @@
|
||||
* Utility class for doubles
|
||||
*/
|
||||
|
||||
//-- Initialize Double related constants
|
||||
const dpun txDouble::NaN = DOUBLE_NaN;
|
||||
#ifdef IS_BIG_ENDIAN
|
||||
const dpun txDouble::POSITIVE_INFINITY = {{DOUBLE_HI32_EXPMASK, 0}};
|
||||
const dpun txDouble::NEGATIVE_INFINITY = {{DOUBLE_HI32_EXPMASK | DOUBLE_HI32_SIGNBIT, 0}};
|
||||
#else
|
||||
const dpun txDouble::POSITIVE_INFINITY = {{0, DOUBLE_HI32_EXPMASK}};
|
||||
const dpun txDouble::NEGATIVE_INFINITY = {{0, DOUBLE_HI32_EXPMASK | DOUBLE_HI32_SIGNBIT}};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Determines whether the given double represents positive or negative
|
||||
* inifinity
|
||||
*/
|
||||
bool txDouble::isInfinite(double aDbl)
|
||||
{
|
||||
return ((DOUBLE_HI32(aDbl) & ~DOUBLE_HI32_SIGNBIT) == DOUBLE_HI32_EXPMASK &&
|
||||
!DOUBLE_LO32(aDbl));
|
||||
}
|
||||
|
||||
/*
|
||||
* Determines whether the given double is NaN
|
||||
*/
|
||||
bool txDouble::isNaN(double aDbl)
|
||||
{
|
||||
return DOUBLE_IS_NaN(aDbl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determines whether the given double is negative
|
||||
*/
|
||||
bool txDouble::isNeg(double aDbl)
|
||||
{
|
||||
return (DOUBLE_HI32(aDbl) & DOUBLE_HI32_SIGNBIT) != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts the given String to a double, if the String value does not
|
||||
* represent a double, NaN will be returned
|
||||
@ -170,7 +136,7 @@ public:
|
||||
{
|
||||
if (mState == eIllegal || mBuffer.IsEmpty() ||
|
||||
(mBuffer.Length() == 1 && mBuffer[0] == '.')) {
|
||||
return txDouble::NaN;
|
||||
return MOZ_DOUBLE_NaN();
|
||||
}
|
||||
return mSign*PR_strtod(mBuffer.get(), 0);
|
||||
}
|
||||
@ -207,11 +173,11 @@ void txDouble::toString(double aValue, nsAString& aDest)
|
||||
|
||||
// check for special cases
|
||||
|
||||
if (isNaN(aValue)) {
|
||||
if (MOZ_DOUBLE_IS_NaN(aValue)) {
|
||||
aDest.AppendLiteral("NaN");
|
||||
return;
|
||||
}
|
||||
if (isInfinite(aValue)) {
|
||||
if (MOZ_DOUBLE_IS_INFINITE(aValue)) {
|
||||
if (aValue < 0)
|
||||
aDest.Append(PRUnichar('-'));
|
||||
aDest.AppendLiteral("Infinity");
|
||||
|
@ -36,6 +36,7 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#include "txExpr.h"
|
||||
@ -396,8 +397,8 @@ txCoreFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// check for NaN or +/-Inf
|
||||
if (txDouble::isNaN(start) ||
|
||||
txDouble::isInfinite(start) ||
|
||||
if (MOZ_DOUBLE_IS_NaN(start) ||
|
||||
MOZ_DOUBLE_IS_INFINITE(start) ||
|
||||
start >= src.Length() + 0.5) {
|
||||
aContext->recycler()->getEmptyStringResult(aResult);
|
||||
|
||||
@ -412,7 +413,7 @@ txCoreFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
end += start;
|
||||
if (txDouble::isNaN(end) || end < 0) {
|
||||
if (MOZ_DOUBLE_IS_NaN(end) || end < 0) {
|
||||
aContext->recycler()->getEmptyStringResult(aResult);
|
||||
|
||||
return NS_OK;
|
||||
@ -556,8 +557,8 @@ txCoreFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
|
||||
rv = evaluateToNumber(mParams[0], aContext, &dbl);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!txDouble::isNaN(dbl) && !txDouble::isInfinite(dbl)) {
|
||||
if (txDouble::isNeg(dbl) && dbl >= -0.5) {
|
||||
if (!MOZ_DOUBLE_IS_NaN(dbl) && !MOZ_DOUBLE_IS_INFINITE(dbl)) {
|
||||
if (MOZ_DOUBLE_IS_NEGATIVE(dbl) && dbl >= -0.5) {
|
||||
dbl *= 0;
|
||||
}
|
||||
else {
|
||||
@ -573,9 +574,9 @@ txCoreFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
|
||||
rv = evaluateToNumber(mParams[0], aContext, &dbl);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!txDouble::isNaN(dbl) &&
|
||||
!txDouble::isInfinite(dbl) &&
|
||||
!(dbl == 0 && txDouble::isNeg(dbl))) {
|
||||
if (!MOZ_DOUBLE_IS_NaN(dbl) &&
|
||||
!MOZ_DOUBLE_IS_INFINITE(dbl) &&
|
||||
!(dbl == 0 && MOZ_DOUBLE_IS_NEGATIVE(dbl))) {
|
||||
dbl = floor(dbl);
|
||||
}
|
||||
|
||||
@ -587,8 +588,8 @@ txCoreFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
|
||||
rv = evaluateToNumber(mParams[0], aContext, &dbl);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!txDouble::isNaN(dbl) && !txDouble::isInfinite(dbl)) {
|
||||
if (txDouble::isNeg(dbl) && dbl > -1) {
|
||||
if (!MOZ_DOUBLE_IS_NaN(dbl) && !MOZ_DOUBLE_IS_INFINITE(dbl)) {
|
||||
if (MOZ_DOUBLE_IS_NEGATIVE(dbl) && dbl > -1) {
|
||||
dbl *= 0;
|
||||
}
|
||||
else {
|
||||
|
@ -36,6 +36,8 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include "txExpr.h"
|
||||
#include <math.h>
|
||||
#include "txIXPathContext.h"
|
||||
@ -70,16 +72,16 @@ txNumberExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
|
||||
if (rightDbl == 0) {
|
||||
#if defined(XP_WIN)
|
||||
/* XXX MSVC miscompiles such that (NaN == 0) */
|
||||
if (txDouble::isNaN(rightDbl))
|
||||
result = txDouble::NaN;
|
||||
if (MOZ_DOUBLE_IS_NaN(rightDbl))
|
||||
result = MOZ_DOUBLE_NaN();
|
||||
else
|
||||
#endif
|
||||
if (leftDbl == 0 || txDouble::isNaN(leftDbl))
|
||||
result = txDouble::NaN;
|
||||
else if (txDouble::isNeg(leftDbl) ^ txDouble::isNeg(rightDbl))
|
||||
result = txDouble::NEGATIVE_INFINITY;
|
||||
if (leftDbl == 0 || MOZ_DOUBLE_IS_NaN(leftDbl))
|
||||
result = MOZ_DOUBLE_NaN();
|
||||
else if (MOZ_DOUBLE_IS_NEGATIVE(leftDbl) ^ MOZ_DOUBLE_IS_NEGATIVE(rightDbl))
|
||||
result = MOZ_DOUBLE_NEGATIVE_INFINITY();
|
||||
else
|
||||
result = txDouble::POSITIVE_INFINITY;
|
||||
result = MOZ_DOUBLE_POSITIVE_INFINITY();
|
||||
}
|
||||
else
|
||||
result = leftDbl / rightDbl;
|
||||
@ -87,12 +89,12 @@ txNumberExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
|
||||
|
||||
case MODULUS:
|
||||
if (rightDbl == 0) {
|
||||
result = txDouble::NaN;
|
||||
result = MOZ_DOUBLE_NaN();
|
||||
}
|
||||
else {
|
||||
#if defined(XP_WIN)
|
||||
/* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */
|
||||
if (!txDouble::isInfinite(leftDbl) && txDouble::isInfinite(rightDbl))
|
||||
if (!MOZ_DOUBLE_IS_INFINITE(leftDbl) && MOZ_DOUBLE_IS_INFINITE(rightDbl))
|
||||
result = leftDbl;
|
||||
else
|
||||
#endif
|
||||
|
@ -41,6 +41,8 @@
|
||||
* Represents the a number as the result of evaluating an Expr
|
||||
**/
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include "txExprResult.h"
|
||||
|
||||
/**
|
||||
@ -80,7 +82,7 @@ bool NumberResult::booleanValue() {
|
||||
// OG+
|
||||
// As per the XPath spec, the boolean value of a number is true if and only if
|
||||
// it is neither positive 0 nor negative 0 nor NaN
|
||||
return (bool)(value != 0.0 && !txDouble::isNaN(value));
|
||||
return (bool)(value != 0.0 && !MOZ_DOUBLE_IS_NaN(value));
|
||||
// OG-
|
||||
} //-- booleanValue
|
||||
|
||||
|
@ -36,6 +36,8 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include "txExpr.h"
|
||||
#include "txExprResult.h"
|
||||
#include "txSingleNodeContext.h"
|
||||
@ -58,7 +60,7 @@ double
|
||||
txUnionNodeTest::getDefaultPriority()
|
||||
{
|
||||
NS_ERROR("Don't call getDefaultPriority on txUnionPattern");
|
||||
return txDouble::NaN;
|
||||
return MOZ_DOUBLE_NaN();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -37,6 +37,7 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#include "nsIAtom.h"
|
||||
@ -611,20 +612,20 @@ txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
|
||||
|
||||
if (nodes->isEmpty()) {
|
||||
return aContext->recycler()->
|
||||
getNumberResult(txDouble::NaN, aResult);
|
||||
getNumberResult(MOZ_DOUBLE_NaN(), aResult);
|
||||
}
|
||||
|
||||
bool findMax = mType == MAX;
|
||||
|
||||
double res = findMax ? txDouble::NEGATIVE_INFINITY :
|
||||
txDouble::POSITIVE_INFINITY;
|
||||
double res = findMax ? MOZ_DOUBLE_NEGATIVE_INFINITY() :
|
||||
MOZ_DOUBLE_POSITIVE_INFINITY();
|
||||
PRInt32 i, len = nodes->size();
|
||||
for (i = 0; i < len; ++i) {
|
||||
nsAutoString str;
|
||||
txXPathNodeUtils::appendNodeValue(nodes->get(i), str);
|
||||
double val = txDouble::toDouble(str);
|
||||
if (txDouble::isNaN(val)) {
|
||||
res = txDouble::NaN;
|
||||
if (MOZ_DOUBLE_IS_NaN(val)) {
|
||||
res = MOZ_DOUBLE_NaN();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -654,15 +655,15 @@ txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool findMax = mType == HIGHEST;
|
||||
double res = findMax ? txDouble::NEGATIVE_INFINITY :
|
||||
txDouble::POSITIVE_INFINITY;
|
||||
double res = findMax ? MOZ_DOUBLE_NEGATIVE_INFINITY() :
|
||||
MOZ_DOUBLE_POSITIVE_INFINITY();
|
||||
PRInt32 i, len = nodes->size();
|
||||
for (i = 0; i < len; ++i) {
|
||||
nsAutoString str;
|
||||
const txXPathNode& node = nodes->get(i);
|
||||
txXPathNodeUtils::appendNodeValue(node, str);
|
||||
double val = txDouble::toDouble(str);
|
||||
if (txDouble::isNaN(val)) {
|
||||
if (MOZ_DOUBLE_IS_NaN(val)) {
|
||||
resultSet->clear();
|
||||
break;
|
||||
}
|
||||
|
@ -36,6 +36,8 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include "txXSLTFunctions.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "txIXPathContext.h"
|
||||
@ -112,16 +114,16 @@ txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext,
|
||||
}
|
||||
|
||||
// Special cases
|
||||
if (txDouble::isNaN(value)) {
|
||||
if (MOZ_DOUBLE_IS_NaN(value)) {
|
||||
return aContext->recycler()->getStringResult(format->mNaN, aResult);
|
||||
}
|
||||
|
||||
if (value == txDouble::POSITIVE_INFINITY) {
|
||||
if (value == MOZ_DOUBLE_POSITIVE_INFINITY()) {
|
||||
return aContext->recycler()->getStringResult(format->mInfinity,
|
||||
aResult);
|
||||
}
|
||||
|
||||
if (value == txDouble::NEGATIVE_INFINITY) {
|
||||
if (value == MOZ_DOUBLE_NEGATIVE_INFINITY()) {
|
||||
nsAutoString res;
|
||||
res.Append(format->mMinusSign);
|
||||
res.Append(format->mInfinity);
|
||||
@ -143,7 +145,7 @@ txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext,
|
||||
|
||||
// Get right subexpression
|
||||
inQuote = false;
|
||||
if (txDouble::isNeg(value)) {
|
||||
if (MOZ_DOUBLE_IS_NEGATIVE(value)) {
|
||||
while (pos < formatLen &&
|
||||
(inQuote ||
|
||||
formatStr.CharAt(pos) != format->mPatternSeparator)) {
|
||||
|
@ -36,6 +36,8 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include "txStylesheet.h"
|
||||
#include "txExpr.h"
|
||||
#include "txXSLTPatterns.h"
|
||||
@ -442,9 +444,9 @@ txStylesheet::addTemplate(txTemplateItem* aTemplate,
|
||||
PRUint32 unionPos = 1; // only used when unionPattern is set
|
||||
while (simple) {
|
||||
double priority = aTemplate->mPrio;
|
||||
if (txDouble::isNaN(priority)) {
|
||||
if (MOZ_DOUBLE_IS_NaN(priority)) {
|
||||
priority = simple->getDefaultPriority();
|
||||
NS_ASSERTION(!txDouble::isNaN(priority),
|
||||
NS_ASSERTION(!MOZ_DOUBLE_IS_NaN(priority),
|
||||
"simple pattern without default priority");
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#include "txStylesheetCompiler.h"
|
||||
@ -303,7 +304,7 @@ getNumberAttr(txStylesheetAttr* aAttributes,
|
||||
txStylesheetCompilerState& aState,
|
||||
double& aNumber)
|
||||
{
|
||||
aNumber = txDouble::NaN;
|
||||
aNumber = MOZ_DOUBLE_NaN();
|
||||
txStylesheetAttr* attr = nsnull;
|
||||
nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
|
||||
aName, aRequired, &attr);
|
||||
@ -312,7 +313,7 @@ getNumberAttr(txStylesheetAttr* aAttributes,
|
||||
}
|
||||
|
||||
aNumber = txDouble::toDouble(attr->mValue);
|
||||
if (txDouble::isNaN(aNumber) && (aRequired || !aState.fcp())) {
|
||||
if (MOZ_DOUBLE_IS_NaN(aNumber) && (aRequired || !aState.fcp())) {
|
||||
// XXX ErrorReport: number parse failure
|
||||
return NS_ERROR_XSLT_PARSE_FAILURE;
|
||||
}
|
||||
@ -552,7 +553,7 @@ txFnStartLREStylesheet(PRInt32 aNamespaceID,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
txExpandedName nullExpr;
|
||||
double prio = txDouble::NaN;
|
||||
double prio = MOZ_DOUBLE_NaN();
|
||||
|
||||
nsAutoPtr<txPattern> match(new txRootPattern());
|
||||
NS_ENSURE_TRUE(match, NS_ERROR_OUT_OF_MEMORY);
|
||||
@ -1145,7 +1146,7 @@ txFnStartTemplate(PRInt32 aNamespaceID,
|
||||
aState, mode);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
double prio = txDouble::NaN;
|
||||
double prio = MOZ_DOUBLE_NaN();
|
||||
rv = getNumberAttr(aAttributes, aAttrCount, nsGkAtoms::priority,
|
||||
false, aState, prio);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -37,6 +37,8 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include "txXPathResultComparator.h"
|
||||
#include "txExpr.h"
|
||||
#include "txCore.h"
|
||||
@ -246,10 +248,10 @@ int txResultNumberComparator::compareValues(txObject* aVal1, txObject* aVal2)
|
||||
double dval1 = ((NumberValue*)aVal1)->mVal;
|
||||
double dval2 = ((NumberValue*)aVal2)->mVal;
|
||||
|
||||
if (txDouble::isNaN(dval1))
|
||||
return txDouble::isNaN(dval2) ? 0 : -mAscending;
|
||||
if (MOZ_DOUBLE_IS_NaN(dval1))
|
||||
return MOZ_DOUBLE_IS_NaN(dval2) ? 0 : -mAscending;
|
||||
|
||||
if (txDouble::isNaN(dval2))
|
||||
if (MOZ_DOUBLE_IS_NaN(dval2))
|
||||
return mAscending;
|
||||
|
||||
if (dval1 == dval2)
|
||||
|
@ -36,6 +36,8 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include "txXSLTNumber.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "txCore.h"
|
||||
@ -122,7 +124,7 @@ txXSLTNumber::getValueList(Expr* aValueExpr, txPattern* aCountPattern,
|
||||
|
||||
double value = result->numberValue();
|
||||
|
||||
if (txDouble::isInfinite(value) || txDouble::isNaN(value) ||
|
||||
if (MOZ_DOUBLE_IS_INFINITE(value) || MOZ_DOUBLE_IS_NaN(value) ||
|
||||
value < 0.5) {
|
||||
txDouble::toString(value, aValueString);
|
||||
return NS_OK;
|
||||
|
@ -36,6 +36,8 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include "nsReadableUtils.h"
|
||||
#include "txExecutionState.h"
|
||||
#include "txXSLTPatterns.h"
|
||||
@ -54,7 +56,7 @@
|
||||
double txUnionPattern::getDefaultPriority()
|
||||
{
|
||||
NS_ERROR("Don't call getDefaultPriority on txUnionPattern");
|
||||
return txDouble::NaN;
|
||||
return MOZ_DOUBLE_NaN();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -37,6 +37,8 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include "Key.h"
|
||||
#include "nsIStreamBufferAccess.h"
|
||||
#include "jsfriendapi.h"
|
||||
@ -150,7 +152,7 @@ Key::EncodeJSVal(JSContext* aCx, const jsval aVal, PRUint8 aTypeOffset)
|
||||
|
||||
if (JSVAL_IS_DOUBLE(aVal)) {
|
||||
double d = JSVAL_TO_DOUBLE(aVal);
|
||||
if (DOUBLE_IS_NaN(d)) {
|
||||
if (MOZ_DOUBLE_IS_NaN(d)) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
|
||||
}
|
||||
EncodeNumber(d, eFloat + aTypeOffset);
|
||||
|
@ -38,6 +38,8 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include "builtin/MapObject.h"
|
||||
|
||||
#include "jscntxt.h"
|
||||
@ -89,10 +91,10 @@ HashableValue::setValue(JSContext *cx, const Value &v)
|
||||
} else if (v.isDouble()) {
|
||||
double d = v.toDouble();
|
||||
int32_t i;
|
||||
if (JSDOUBLE_IS_INT32(d, &i)) {
|
||||
if (MOZ_DOUBLE_IS_INT32(d, &i)) {
|
||||
/* Normalize int32-valued doubles to int32 for faster hashing and testing. */
|
||||
value = Int32Value(i);
|
||||
} else if (JSDOUBLE_IS_NaN(d)) {
|
||||
} else if (MOZ_DOUBLE_IS_NaN(d)) {
|
||||
/* NaNs with different bits must hash and test identically. */
|
||||
value = DoubleValue(js_NaN);
|
||||
} else {
|
||||
|
@ -37,6 +37,8 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include "CTypes.h"
|
||||
#include "Library.h"
|
||||
#include "jsnum.h"
|
||||
@ -648,14 +650,6 @@ static JSFunctionSpec sModuleFunctions[] = {
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
static inline bool FloatIsFinite(double f) {
|
||||
#ifdef WIN32
|
||||
return _finite(f) != 0;
|
||||
#else
|
||||
return finite(f);
|
||||
#endif
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE JSString*
|
||||
NewUCString(JSContext* cx, const AutoString& from)
|
||||
{
|
||||
@ -1764,7 +1758,7 @@ jsvalToIntegerExplicit(jsval val, IntegerType* result)
|
||||
if (JSVAL_IS_DOUBLE(val)) {
|
||||
// Convert -Inf, Inf, and NaN to 0; otherwise, convert by C-style cast.
|
||||
double d = JSVAL_TO_DOUBLE(val);
|
||||
*result = FloatIsFinite(d) ? IntegerType(d) : 0;
|
||||
*result = MOZ_DOUBLE_IS_FINITE(d) ? IntegerType(d) : 0;
|
||||
return true;
|
||||
}
|
||||
if (!JSVAL_IS_PRIMITIVE(val)) {
|
||||
|
@ -41,6 +41,9 @@
|
||||
/*
|
||||
* JS bytecode generation.
|
||||
*/
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
@ -2298,7 +2301,7 @@ EmitNumberOp(JSContext *cx, double dval, BytecodeEmitter *bce)
|
||||
ptrdiff_t off;
|
||||
jsbytecode *pc;
|
||||
|
||||
if (JSDOUBLE_IS_INT32(dval, &ival)) {
|
||||
if (MOZ_DOUBLE_IS_INT32(dval, &ival)) {
|
||||
if (ival == 0)
|
||||
return Emit1(cx, bce, JSOP_ZERO) >= 0;
|
||||
if (ival == 1)
|
||||
|
@ -38,6 +38,8 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include "frontend/FoldConstants.h"
|
||||
|
||||
#include "jslibmath.h"
|
||||
@ -183,13 +185,13 @@ FoldBinaryNumeric(JSContext *cx, JSOp op, ParseNode *pn1, ParseNode *pn2,
|
||||
if (d2 == 0) {
|
||||
#if defined(XP_WIN)
|
||||
/* XXX MSVC miscompiles such that (NaN == 0) */
|
||||
if (JSDOUBLE_IS_NaN(d2))
|
||||
if (MOZ_DOUBLE_IS_NaN(d2))
|
||||
d = js_NaN;
|
||||
else
|
||||
#endif
|
||||
if (d == 0 || JSDOUBLE_IS_NaN(d))
|
||||
if (d == 0 || MOZ_DOUBLE_IS_NaN(d))
|
||||
d = js_NaN;
|
||||
else if (JSDOUBLE_IS_NEG(d) != JSDOUBLE_IS_NEG(d2))
|
||||
else if (MOZ_DOUBLE_IS_NEGATIVE(d) != MOZ_DOUBLE_IS_NEGATIVE(d2))
|
||||
d = js_NegativeInfinity;
|
||||
else
|
||||
d = js_PositiveInfinity;
|
||||
@ -392,7 +394,7 @@ Boolish(ParseNode *pn)
|
||||
{
|
||||
switch (pn->getOp()) {
|
||||
case JSOP_DOUBLE:
|
||||
return (pn->pn_dval != 0 && !JSDOUBLE_IS_NaN(pn->pn_dval)) ? Truthy : Falsy;
|
||||
return (pn->pn_dval != 0 && !MOZ_DOUBLE_IS_NaN(pn->pn_dval)) ? Truthy : Falsy;
|
||||
|
||||
case JSOP_STRING:
|
||||
return (pn->pn_atom->length() > 0) ? Truthy : Falsy;
|
||||
@ -565,7 +567,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||
/* Reduce 'if (C) T; else E' into T for true C, E for false. */
|
||||
switch (pn1->getKind()) {
|
||||
case PNK_NUMBER:
|
||||
if (pn1->pn_dval == 0 || JSDOUBLE_IS_NaN(pn1->pn_dval))
|
||||
if (pn1->pn_dval == 0 || MOZ_DOUBLE_IS_NaN(pn1->pn_dval))
|
||||
pn2 = pn3;
|
||||
break;
|
||||
case PNK_STRING:
|
||||
@ -839,7 +841,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||
break;
|
||||
|
||||
case JSOP_NOT:
|
||||
if (d == 0 || JSDOUBLE_IS_NaN(d)) {
|
||||
if (d == 0 || MOZ_DOUBLE_IS_NaN(d)) {
|
||||
pn->setKind(PNK_TRUE);
|
||||
pn->setOp(JSOP_TRUE);
|
||||
} else {
|
||||
|
@ -41,6 +41,9 @@
|
||||
/*
|
||||
* JavaScript API.
|
||||
*/
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
@ -547,7 +550,7 @@ JS_ValueToNumber(JSContext *cx, jsval v, double *dp)
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_DoubleIsInt32(double d, int32_t *ip)
|
||||
{
|
||||
return JSDOUBLE_IS_INT32(d, ip);
|
||||
return MOZ_DOUBLE_IS_INT32(d, ip);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(int32_t)
|
||||
|
@ -44,6 +44,8 @@
|
||||
* JavaScript API.
|
||||
*/
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/StandardInteger.h"
|
||||
|
||||
#include <stddef.h>
|
||||
@ -58,7 +60,6 @@
|
||||
#ifdef __cplusplus
|
||||
#include "jsalloc.h"
|
||||
#include "js/Vector.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
@ -361,7 +362,7 @@ class Value
|
||||
JS_ALWAYS_INLINE
|
||||
bool setNumber(double d) {
|
||||
int32_t i;
|
||||
if (JSDOUBLE_IS_INT32(d, &i)) {
|
||||
if (MOZ_DOUBLE_IS_INT32(d, &i)) {
|
||||
setInt32(i);
|
||||
return true;
|
||||
} else {
|
||||
|
@ -96,12 +96,14 @@
|
||||
* SlowArrayClass, but have the same performance characteristics as a dense
|
||||
* array for slot accesses, at some cost in code complexity.
|
||||
*/
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/RangedPtr.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mozilla/RangedPtr.h"
|
||||
|
||||
#include "jstypes.h"
|
||||
#include "jsutil.h"
|
||||
|
||||
@ -2191,7 +2193,7 @@ SortComparatorFunction::operator()(const Value &a, const Value &b, bool *lessOrE
|
||||
* 'consistent compare functions' that don't return NaN, but is silent
|
||||
* about what the result should be. So we currently ignore it.
|
||||
*/
|
||||
*lessOrEqualp = (JSDOUBLE_IS_NaN(cmp) || cmp <= 0);
|
||||
*lessOrEqualp = (MOZ_DOUBLE_IS_NaN(cmp) || cmp <= 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,9 @@
|
||||
/*
|
||||
* JS boolean implementation.
|
||||
*/
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include "jstypes.h"
|
||||
#include "jsutil.h"
|
||||
#include "jsapi.h"
|
||||
@ -227,7 +230,7 @@ js_ValueToBoolean(const Value &v)
|
||||
double d;
|
||||
|
||||
d = v.toDouble();
|
||||
return !JSDOUBLE_IS_NaN(d) && d != 0;
|
||||
return !MOZ_DOUBLE_IS_NaN(d) && d != 0;
|
||||
}
|
||||
JS_ASSERT(v.isBoolean());
|
||||
return v.toBoolean();
|
||||
|
@ -42,6 +42,9 @@
|
||||
* JS date methods.
|
||||
*/
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
/*
|
||||
* "For example, OS/360 devotes 26 bytes of the permanently
|
||||
* resident date-turnover routine to the proper handling of
|
||||
@ -57,8 +60,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#include "jstypes.h"
|
||||
#include "jsprf.h"
|
||||
#include "prmjtime.h"
|
||||
@ -418,7 +419,7 @@ static double
|
||||
DaylightSavingTA(double t, JSContext *cx)
|
||||
{
|
||||
/* abort if NaN */
|
||||
if (JSDOUBLE_IS_NaN(t))
|
||||
if (MOZ_DOUBLE_IS_NaN(t))
|
||||
return t;
|
||||
|
||||
/*
|
||||
@ -608,7 +609,7 @@ date_msecFromArgs(JSContext *cx, CallArgs args, double *rval)
|
||||
if (!ToNumber(cx, args[loop], &d))
|
||||
return JS_FALSE;
|
||||
/* return NaN if any arg is not finite */
|
||||
if (!JSDOUBLE_IS_FINITE(d)) {
|
||||
if (!MOZ_DOUBLE_IS_FINITE(d)) {
|
||||
*rval = js_NaN;
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -1260,7 +1261,7 @@ FillLocalTimes(JSContext *cx, JSObject *obj)
|
||||
|
||||
double utcTime = obj->getDateUTCTime().toNumber();
|
||||
|
||||
if (!JSDOUBLE_IS_FINITE(utcTime)) {
|
||||
if (!MOZ_DOUBLE_IS_FINITE(utcTime)) {
|
||||
for (size_t ind = JSObject::JSSLOT_DATE_COMPONENTS_START;
|
||||
ind < JSObject::DATE_CLASS_RESERVED_SLOTS;
|
||||
ind++) {
|
||||
@ -1478,7 +1479,7 @@ date_getUTCFullYear(JSContext *cx, unsigned argc, Value *vp)
|
||||
return ok;
|
||||
|
||||
double result = obj->getDateUTCTime().toNumber();
|
||||
if (JSDOUBLE_IS_FINITE(result))
|
||||
if (MOZ_DOUBLE_IS_FINITE(result))
|
||||
result = YearFromTime(result);
|
||||
|
||||
args.rval().setNumber(result);
|
||||
@ -1513,7 +1514,7 @@ date_getUTCMonth(JSContext *cx, unsigned argc, Value *vp)
|
||||
return ok;
|
||||
|
||||
double result = obj->getDateUTCTime().toNumber();
|
||||
if (JSDOUBLE_IS_FINITE(result))
|
||||
if (MOZ_DOUBLE_IS_FINITE(result))
|
||||
result = MonthFromTime(result);
|
||||
|
||||
args.rval().setNumber(result);
|
||||
@ -1548,7 +1549,7 @@ date_getUTCDate(JSContext *cx, unsigned argc, Value *vp)
|
||||
return ok;
|
||||
|
||||
double result = obj->getDateUTCTime().toNumber();
|
||||
if (JSDOUBLE_IS_FINITE(result))
|
||||
if (MOZ_DOUBLE_IS_FINITE(result))
|
||||
result = DateFromTime(result);
|
||||
|
||||
args.rval().setNumber(result);
|
||||
@ -1583,7 +1584,7 @@ date_getUTCDay(JSContext *cx, unsigned argc, Value *vp)
|
||||
return ok;
|
||||
|
||||
double result = obj->getDateUTCTime().toNumber();
|
||||
if (JSDOUBLE_IS_FINITE(result))
|
||||
if (MOZ_DOUBLE_IS_FINITE(result))
|
||||
result = WeekDay(result);
|
||||
|
||||
args.rval().setNumber(result);
|
||||
@ -1618,7 +1619,7 @@ date_getUTCHours(JSContext *cx, unsigned argc, Value *vp)
|
||||
return ok;
|
||||
|
||||
double result = obj->getDateUTCTime().toNumber();
|
||||
if (JSDOUBLE_IS_FINITE(result))
|
||||
if (MOZ_DOUBLE_IS_FINITE(result))
|
||||
result = HourFromTime(result);
|
||||
|
||||
args.rval().setNumber(result);
|
||||
@ -1653,7 +1654,7 @@ date_getUTCMinutes(JSContext *cx, unsigned argc, Value *vp)
|
||||
return ok;
|
||||
|
||||
double result = obj->getDateUTCTime().toNumber();
|
||||
if (JSDOUBLE_IS_FINITE(result))
|
||||
if (MOZ_DOUBLE_IS_FINITE(result))
|
||||
result = MinFromTime(result);
|
||||
|
||||
args.rval().setNumber(result);
|
||||
@ -1692,7 +1693,7 @@ date_getUTCMilliseconds(JSContext *cx, unsigned argc, Value *vp)
|
||||
return ok;
|
||||
|
||||
double result = obj->getDateUTCTime().toNumber();
|
||||
if (JSDOUBLE_IS_FINITE(result))
|
||||
if (MOZ_DOUBLE_IS_FINITE(result))
|
||||
result = msFromTime(result);
|
||||
|
||||
args.rval().setNumber(result);
|
||||
@ -1780,7 +1781,7 @@ date_makeTime(JSContext *cx, Native native, unsigned maxargs, JSBool local, unsi
|
||||
for (unsigned i = 0; i < numNums; i++) {
|
||||
if (!ToNumber(cx, args[i], &nums[i]))
|
||||
return false;
|
||||
if (!JSDOUBLE_IS_FINITE(nums[i])) {
|
||||
if (!MOZ_DOUBLE_IS_FINITE(nums[i])) {
|
||||
argIsNotFinite = true;
|
||||
} else {
|
||||
nums[i] = js_DoubleToInteger(nums[i]);
|
||||
@ -1791,7 +1792,7 @@ date_makeTime(JSContext *cx, Native native, unsigned maxargs, JSBool local, unsi
|
||||
* Return NaN if the date is already NaN, but don't short-circuit argument
|
||||
* evaluation.
|
||||
*/
|
||||
if (!JSDOUBLE_IS_FINITE(result)) {
|
||||
if (!MOZ_DOUBLE_IS_FINITE(result)) {
|
||||
args.rval().setNumber(result);
|
||||
return true;
|
||||
}
|
||||
@ -1916,7 +1917,7 @@ date_makeDate(JSContext *cx, Native native, unsigned maxargs, JSBool local, unsi
|
||||
for (unsigned i = 0; i < numNums; i++) {
|
||||
if (!ToNumber(cx, args[i], &nums[i]))
|
||||
return JS_FALSE;
|
||||
if (!JSDOUBLE_IS_FINITE(nums[i])) {
|
||||
if (!MOZ_DOUBLE_IS_FINITE(nums[i])) {
|
||||
argIsNotFinite = true;
|
||||
} else {
|
||||
nums[i] = js_DoubleToInteger(nums[i]);
|
||||
@ -1934,7 +1935,7 @@ date_makeDate(JSContext *cx, Native native, unsigned maxargs, JSBool local, unsi
|
||||
* use 0 as the time.
|
||||
*/
|
||||
double lorutime; /* local or UTC version of *date */
|
||||
if (!JSDOUBLE_IS_FINITE(result)) {
|
||||
if (!MOZ_DOUBLE_IS_FINITE(result)) {
|
||||
if (maxargs < 3) {
|
||||
args.rval().setDouble(result);
|
||||
return true;
|
||||
@ -2030,7 +2031,7 @@ date_setYear(JSContext *cx, unsigned argc, Value *vp)
|
||||
double year;
|
||||
if (!ToNumber(cx, args[0], &year))
|
||||
return false;
|
||||
if (!JSDOUBLE_IS_FINITE(year)) {
|
||||
if (!MOZ_DOUBLE_IS_FINITE(year)) {
|
||||
SetDateToNaN(cx, obj, &args.rval());
|
||||
return true;
|
||||
}
|
||||
@ -2038,7 +2039,7 @@ date_setYear(JSContext *cx, unsigned argc, Value *vp)
|
||||
if (year >= 0 && year <= 99)
|
||||
year += 1900;
|
||||
|
||||
double t = JSDOUBLE_IS_FINITE(result) ? LocalTime(result, cx) : +0.0;
|
||||
double t = MOZ_DOUBLE_IS_FINITE(result) ? LocalTime(result, cx) : +0.0;
|
||||
double day = MakeDay(year, MonthFromTime(t), DateFromTime(t));
|
||||
result = MakeDate(day, TimeWithinDay(t));
|
||||
result = UTC(result, cx);
|
||||
@ -2098,7 +2099,7 @@ date_utc_format(JSContext *cx, Native native, CallArgs args,
|
||||
double utctime = obj->getDateUTCTime().toNumber();
|
||||
|
||||
char buf[100];
|
||||
if (!JSDOUBLE_IS_FINITE(utctime)) {
|
||||
if (!MOZ_DOUBLE_IS_FINITE(utctime)) {
|
||||
if (printFunc == print_iso_string) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INVALID_DATE);
|
||||
return false;
|
||||
@ -2143,7 +2144,7 @@ date_toJSON(JSContext *cx, unsigned argc, Value *vp)
|
||||
return false;
|
||||
|
||||
/* Step 3. */
|
||||
if (tv.isDouble() && !JSDOUBLE_IS_FINITE(tv.toDouble())) {
|
||||
if (tv.isDouble() && !MOZ_DOUBLE_IS_FINITE(tv.toDouble())) {
|
||||
vp->setNull();
|
||||
return true;
|
||||
}
|
||||
@ -2211,7 +2212,7 @@ date_format(JSContext *cx, double date, formatspec format, CallReceiver call)
|
||||
size_t i, tzlen;
|
||||
PRMJTime split;
|
||||
|
||||
if (!JSDOUBLE_IS_FINITE(date)) {
|
||||
if (!MOZ_DOUBLE_IS_FINITE(date)) {
|
||||
JS_snprintf(buf, sizeof buf, js_NaN_date_str);
|
||||
} else {
|
||||
double local = LocalTime(date, cx);
|
||||
@ -2320,7 +2321,7 @@ ToLocaleHelper(JSContext *cx, CallReceiver call, JSObject *obj, const char *form
|
||||
double utctime = obj->getDateUTCTime().toNumber();
|
||||
|
||||
char buf[100];
|
||||
if (!JSDOUBLE_IS_FINITE(utctime)) {
|
||||
if (!MOZ_DOUBLE_IS_FINITE(utctime)) {
|
||||
JS_snprintf(buf, sizeof buf, js_NaN_date_str);
|
||||
} else {
|
||||
int result_len;
|
||||
@ -2641,7 +2642,7 @@ js_Date(JSContext *cx, unsigned argc, Value *vp)
|
||||
if (!date_msecFromArgs(cx, args, &msec_time))
|
||||
return false;
|
||||
|
||||
if (JSDOUBLE_IS_FINITE(msec_time)) {
|
||||
if (MOZ_DOUBLE_IS_FINITE(msec_time)) {
|
||||
msec_time = UTC(msec_time, cx);
|
||||
msec_time = TIMECLIP(msec_time);
|
||||
}
|
||||
@ -2731,7 +2732,7 @@ js_NewDateObject(JSContext* cx, int year, int mon, int mday,
|
||||
JS_FRIEND_API(JSBool)
|
||||
js_DateIsValid(JSContext *cx, JSObject* obj)
|
||||
{
|
||||
return obj->isDate() && !JSDOUBLE_IS_NaN(obj->getDateUTCTime().toNumber());
|
||||
return obj->isDate() && !MOZ_DOUBLE_IS_NaN(obj->getDateUTCTime().toNumber());
|
||||
}
|
||||
|
||||
JS_FRIEND_API(int)
|
||||
@ -2740,10 +2741,8 @@ js_DateGetYear(JSContext *cx, JSObject* obj)
|
||||
double localtime;
|
||||
|
||||
/* Preserve legacy API behavior of returning 0 for invalid dates. */
|
||||
if (!GetAndCacheLocalTime(cx, obj, &localtime) ||
|
||||
JSDOUBLE_IS_NaN(localtime)) {
|
||||
if (!GetAndCacheLocalTime(cx, obj, &localtime) || MOZ_DOUBLE_IS_NaN(localtime))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int) YearFromTime(localtime);
|
||||
}
|
||||
@ -2753,10 +2752,8 @@ js_DateGetMonth(JSContext *cx, JSObject* obj)
|
||||
{
|
||||
double localtime;
|
||||
|
||||
if (!GetAndCacheLocalTime(cx, obj, &localtime) ||
|
||||
JSDOUBLE_IS_NaN(localtime)) {
|
||||
if (!GetAndCacheLocalTime(cx, obj, &localtime) || MOZ_DOUBLE_IS_NaN(localtime))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int) MonthFromTime(localtime);
|
||||
}
|
||||
@ -2766,10 +2763,8 @@ js_DateGetDate(JSContext *cx, JSObject* obj)
|
||||
{
|
||||
double localtime;
|
||||
|
||||
if (!GetAndCacheLocalTime(cx, obj, &localtime) ||
|
||||
JSDOUBLE_IS_NaN(localtime)) {
|
||||
if (!GetAndCacheLocalTime(cx, obj, &localtime) || MOZ_DOUBLE_IS_NaN(localtime))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int) DateFromTime(localtime);
|
||||
}
|
||||
@ -2779,10 +2774,8 @@ js_DateGetHours(JSContext *cx, JSObject* obj)
|
||||
{
|
||||
double localtime;
|
||||
|
||||
if (!GetAndCacheLocalTime(cx, obj, &localtime) ||
|
||||
JSDOUBLE_IS_NaN(localtime)) {
|
||||
if (!GetAndCacheLocalTime(cx, obj, &localtime) || MOZ_DOUBLE_IS_NaN(localtime))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int) HourFromTime(localtime);
|
||||
}
|
||||
@ -2792,10 +2785,8 @@ js_DateGetMinutes(JSContext *cx, JSObject* obj)
|
||||
{
|
||||
double localtime;
|
||||
|
||||
if (!GetAndCacheLocalTime(cx, obj, &localtime) ||
|
||||
JSDOUBLE_IS_NaN(localtime)) {
|
||||
if (!GetAndCacheLocalTime(cx, obj, &localtime) || MOZ_DOUBLE_IS_NaN(localtime))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int) MinFromTime(localtime);
|
||||
}
|
||||
@ -2807,7 +2798,7 @@ js_DateGetSeconds(JSContext *cx, JSObject* obj)
|
||||
return 0;
|
||||
|
||||
double utctime = obj->getDateUTCTime().toNumber();
|
||||
if (JSDOUBLE_IS_NaN(utctime))
|
||||
if (MOZ_DOUBLE_IS_NaN(utctime))
|
||||
return 0;
|
||||
return (int) SecFromTime(utctime);
|
||||
}
|
||||
|
@ -44,11 +44,13 @@
|
||||
#ifndef jsdate_h___
|
||||
#define jsdate_h___
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include "jscntxt.h"
|
||||
|
||||
#define HalfTimeDomain 8.64e15
|
||||
|
||||
#define TIMECLIP(d) ((JSDOUBLE_IS_FINITE(d) \
|
||||
#define TIMECLIP(d) ((MOZ_DOUBLE_IS_FINITE(d) \
|
||||
&& !((d < 0 ? -d : d) > HalfTimeDomain)) \
|
||||
? js_DoubleToInteger(d + (+0.)) : js_NaN)
|
||||
|
||||
|
@ -41,6 +41,9 @@
|
||||
/*
|
||||
* JavaScript bytecode interpreter.
|
||||
*/
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
@ -845,13 +848,13 @@ js::StrictlyEqual(JSContext *cx, const Value &lref, const Value &rref, bool *equ
|
||||
static inline bool
|
||||
IsNegativeZero(const Value &v)
|
||||
{
|
||||
return v.isDouble() && JSDOUBLE_IS_NEGZERO(v.toDouble());
|
||||
return v.isDouble() && MOZ_DOUBLE_IS_NEGATIVE_ZERO(v.toDouble());
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsNaN(const Value &v)
|
||||
{
|
||||
return v.isDouble() && JSDOUBLE_IS_NaN(v.toDouble());
|
||||
return v.isDouble() && MOZ_DOUBLE_IS_NaN(v.toDouble());
|
||||
}
|
||||
|
||||
bool
|
||||
@ -2942,7 +2945,7 @@ BEGIN_CASE(JSOP_TABLESWITCH)
|
||||
i = rref.toInt32();
|
||||
} else {
|
||||
double d;
|
||||
/* Don't use JSDOUBLE_IS_INT32; treat -0 (double) as 0. */
|
||||
/* Don't use MOZ_DOUBLE_IS_INT32; treat -0 (double) as 0. */
|
||||
if (!rref.isDouble() || (d = rref.toDouble()) != (i = int32_t(rref.toDouble())))
|
||||
DO_NEXT_OP(len);
|
||||
}
|
||||
|
@ -42,6 +42,8 @@
|
||||
#ifndef _LIBMATH_H
|
||||
#define _LIBMATH_H
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include <math.h>
|
||||
#include "jsnum.h"
|
||||
|
||||
@ -53,13 +55,7 @@
|
||||
#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
|
||||
#define js_copysign __builtin_copysign
|
||||
#elif defined _WIN32
|
||||
#if _MSC_VER < 1400
|
||||
/* Try to work around apparent _copysign bustage in VC7.x. */
|
||||
#define js_copysign js_copysign
|
||||
extern double js_copysign(double, double);
|
||||
#else
|
||||
#define js_copysign _copysign
|
||||
#endif
|
||||
#else
|
||||
#define js_copysign copysign
|
||||
#endif
|
||||
@ -79,8 +75,8 @@ js_fmod(double d, double d2)
|
||||
* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42.
|
||||
* Workaround MS fmod bug where -0 % -N => 0, not -0.
|
||||
*/
|
||||
if ((JSDOUBLE_IS_FINITE(d) && JSDOUBLE_IS_INFINITE(d2)) ||
|
||||
(d == 0 && JSDOUBLE_IS_FINITE(d2))) {
|
||||
if ((MOZ_DOUBLE_IS_FINITE(d) && MOZ_DOUBLE_IS_INFINITE(d2)) ||
|
||||
(d == 0 && MOZ_DOUBLE_IS_FINITE(d2))) {
|
||||
return d;
|
||||
}
|
||||
#endif
|
||||
@ -90,16 +86,17 @@ js_fmod(double d, double d2)
|
||||
namespace js {
|
||||
|
||||
inline double
|
||||
NumberDiv(double a, double b) {
|
||||
NumberDiv(double a, double b)
|
||||
{
|
||||
if (b == 0) {
|
||||
if (a == 0 || JSDOUBLE_IS_NaN(a)
|
||||
if (a == 0 || MOZ_DOUBLE_IS_NaN(a)
|
||||
#ifdef XP_WIN
|
||||
|| JSDOUBLE_IS_NaN(b) /* XXX MSVC miscompiles such that (NaN == 0) */
|
||||
|| MOZ_DOUBLE_IS_NaN(b) /* XXX MSVC miscompiles such that (NaN == 0) */
|
||||
#endif
|
||||
)
|
||||
return js_NaN;
|
||||
|
||||
if (JSDOUBLE_IS_NEG(a) != JSDOUBLE_IS_NEG(b))
|
||||
if (MOZ_DOUBLE_IS_NEGATIVE(a) != MOZ_DOUBLE_IS_NEGATIVE(b))
|
||||
return js_NegativeInfinity;
|
||||
return js_PositiveInfinity;
|
||||
}
|
||||
|
@ -40,6 +40,9 @@
|
||||
/*
|
||||
* JS math package.
|
||||
*/
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "jstypes.h"
|
||||
#include "prmjtime.h"
|
||||
@ -99,8 +102,8 @@ MathCache::MathCache() {
|
||||
memset(table, 0, sizeof(table));
|
||||
|
||||
/* See comments in lookup(). */
|
||||
JS_ASSERT(JSDOUBLE_IS_NEGZERO(-0.0));
|
||||
JS_ASSERT(!JSDOUBLE_IS_NEGZERO(+0.0));
|
||||
JS_ASSERT(MOZ_DOUBLE_IS_NEGATIVE_ZERO(-0.0));
|
||||
JS_ASSERT(!MOZ_DOUBLE_IS_NEGATIVE_ZERO(+0.0));
|
||||
JS_ASSERT(hash(-0.0) != hash(+0.0));
|
||||
}
|
||||
|
||||
@ -212,7 +215,7 @@ math_atan2_kernel(double x, double y)
|
||||
* - The sign of x determines the sign of the result.
|
||||
* - The sign of y determines the multiplicator, 1 or 3.
|
||||
*/
|
||||
if (JSDOUBLE_IS_INFINITE(x) && JSDOUBLE_IS_INFINITE(y)) {
|
||||
if (MOZ_DOUBLE_IS_INFINITE(x) && MOZ_DOUBLE_IS_INFINITE(y)) {
|
||||
double z = js_copysign(M_PI / 4, x);
|
||||
if (y < 0)
|
||||
z *= 3;
|
||||
@ -222,7 +225,7 @@ math_atan2_kernel(double x, double y)
|
||||
|
||||
#if defined(SOLARIS) && defined(__GNUC__)
|
||||
if (x == 0) {
|
||||
if (JSDOUBLE_IS_NEGZERO(y))
|
||||
if (MOZ_DOUBLE_IS_NEGZERO(y))
|
||||
return js_copysign(M_PI, x);
|
||||
if (y == 0)
|
||||
return x;
|
||||
@ -296,7 +299,7 @@ static double
|
||||
math_exp_body(double d)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (!JSDOUBLE_IS_NaN(d)) {
|
||||
if (!MOZ_DOUBLE_IS_NaN(d)) {
|
||||
if (d == js_PositiveInfinity)
|
||||
return js_PositiveInfinity;
|
||||
if (d == js_NegativeInfinity)
|
||||
@ -387,7 +390,7 @@ js_math_max(JSContext *cx, unsigned argc, Value *vp)
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (!ToNumber(cx, argv[i], &x))
|
||||
return JS_FALSE;
|
||||
if (JSDOUBLE_IS_NaN(x)) {
|
||||
if (MOZ_DOUBLE_IS_NaN(x)) {
|
||||
vp->setDouble(js_NaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -417,7 +420,7 @@ js_math_min(JSContext *cx, unsigned argc, Value *vp)
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (!ToNumber(cx, argv[i], &x))
|
||||
return JS_FALSE;
|
||||
if (JSDOUBLE_IS_NaN(x)) {
|
||||
if (MOZ_DOUBLE_IS_NaN(x)) {
|
||||
vp->setDouble(js_NaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -449,7 +452,7 @@ powi(double x, int y)
|
||||
// given us a finite p. This happens very rarely.
|
||||
|
||||
double result = 1.0 / p;
|
||||
return (result == 0 && JSDOUBLE_IS_INFINITE(p))
|
||||
return (result == 0 && MOZ_DOUBLE_IS_INFINITE(p))
|
||||
? pow(x, static_cast<double>(y)) // Avoid pow(double, int).
|
||||
: result;
|
||||
}
|
||||
@ -475,7 +478,7 @@ js_math_pow(JSContext *cx, unsigned argc, Value *vp)
|
||||
* Special case for square roots. Note that pow(x, 0.5) != sqrt(x)
|
||||
* when x = -0.0, so we have to guard for this.
|
||||
*/
|
||||
if (JSDOUBLE_IS_FINITE(x) && x != 0.0) {
|
||||
if (MOZ_DOUBLE_IS_FINITE(x) && x != 0.0) {
|
||||
if (y == 0.5) {
|
||||
vp->setNumber(sqrt(x));
|
||||
return JS_TRUE;
|
||||
@ -489,7 +492,7 @@ js_math_pow(JSContext *cx, unsigned argc, Value *vp)
|
||||
* Because C99 and ECMA specify different behavior for pow(),
|
||||
* we need to wrap the libm call to make it ECMA compliant.
|
||||
*/
|
||||
if (!JSDOUBLE_IS_FINITE(y) && (x == 1.0 || x == -1.0)) {
|
||||
if (!MOZ_DOUBLE_IS_FINITE(y) && (x == 1.0 || x == -1.0)) {
|
||||
vp->setDouble(js_NaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -559,22 +562,6 @@ math_random(JSContext *cx, unsigned argc, Value *vp)
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#if defined _WIN32 && _MSC_VER < 1400
|
||||
/* Try to work around apparent _copysign bustage in VC7.x. */
|
||||
double
|
||||
js_copysign(double x, double y)
|
||||
{
|
||||
jsdpun xu, yu;
|
||||
|
||||
xu.d = x;
|
||||
yu.d = y;
|
||||
xu.s.hi &= ~JSDOUBLE_HI32_SIGNBIT;
|
||||
xu.s.hi |= yu.s.hi & JSDOUBLE_HI32_SIGNBIT;
|
||||
return xu.d;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
JSBool /* ES5 15.8.2.15. */
|
||||
js_math_round(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
@ -590,17 +577,13 @@ js_math_round(JSContext *cx, unsigned argc, Value *vp)
|
||||
return false;
|
||||
|
||||
int32_t i;
|
||||
if (JSDOUBLE_IS_INT32(x, &i)) {
|
||||
if (MOZ_DOUBLE_IS_INT32(x, &i)) {
|
||||
args.rval().setInt32(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
jsdpun u;
|
||||
u.d = x;
|
||||
|
||||
/* Some numbers are so big that adding 0.5 would give the wrong number */
|
||||
int exponent = ((u.s.hi & JSDOUBLE_HI32_EXPMASK) >> JSDOUBLE_HI32_EXPSHIFT) - JSDOUBLE_EXPBIAS;
|
||||
if (exponent >= 52) {
|
||||
if (MOZ_DOUBLE_EXPONENT(x) >= 52) {
|
||||
args.rval().setNumber(x);
|
||||
return true;
|
||||
}
|
||||
|
@ -41,6 +41,14 @@
|
||||
/*
|
||||
* JS number type and wrapper class.
|
||||
*/
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/RangedPtr.h"
|
||||
|
||||
#include "double-conversion.h"
|
||||
// Avoid warnings about ASSERT being defined by the assembler as well.
|
||||
#undef ASSERT
|
||||
|
||||
#ifdef XP_OS2
|
||||
#define _PC_53 PC_53
|
||||
#define _MCW_EM MCW_EM
|
||||
@ -52,11 +60,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mozilla/RangedPtr.h"
|
||||
#include "double-conversion.h"
|
||||
// Avoid warnings about ASSERT being defined by the assembler as well.
|
||||
#undef ASSERT
|
||||
|
||||
#include "jstypes.h"
|
||||
#include "jsutil.h"
|
||||
#include "jsapi.h"
|
||||
@ -269,7 +272,7 @@ num_isNaN(JSContext *cx, unsigned argc, Value *vp)
|
||||
double x;
|
||||
if (!ToNumber(cx, vp[2], &x))
|
||||
return false;
|
||||
vp->setBoolean(JSDOUBLE_IS_NaN(x));
|
||||
vp->setBoolean(MOZ_DOUBLE_IS_NaN(x));
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
@ -283,7 +286,7 @@ num_isFinite(JSContext *cx, unsigned argc, Value *vp)
|
||||
double x;
|
||||
if (!ToNumber(cx, vp[2], &x))
|
||||
return JS_FALSE;
|
||||
vp->setBoolean(JSDOUBLE_IS_FINITE(x));
|
||||
vp->setBoolean(MOZ_DOUBLE_IS_FINITE(x));
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
@ -927,25 +930,25 @@ InitRuntimeNumberState(JSRuntime *rt)
|
||||
{
|
||||
FIX_FPU();
|
||||
|
||||
jsdpun u;
|
||||
u.s.hi = JSDOUBLE_HI32_NAN;
|
||||
u.s.lo = JSDOUBLE_LO32_NAN;
|
||||
number_constants[NC_NaN].dval = js_NaN = u.d;
|
||||
rt->NaNValue.setDouble(u.d);
|
||||
double d;
|
||||
|
||||
u.s.hi = JSDOUBLE_HI32_EXPMASK;
|
||||
u.s.lo = 0x00000000;
|
||||
number_constants[NC_POSITIVE_INFINITY].dval = js_PositiveInfinity = u.d;
|
||||
rt->positiveInfinityValue.setDouble(u.d);
|
||||
/*
|
||||
* Our NaN must be one particular canonical value, because we rely on NaN
|
||||
* encoding for our value representation. See jsval.h.
|
||||
*/
|
||||
d = MOZ_DOUBLE_SPECIFIC_NaN(0, 0x8000000000000ULL);
|
||||
number_constants[NC_NaN].dval = js_NaN = d;
|
||||
rt->NaNValue.setDouble(d);
|
||||
|
||||
u.s.hi = JSDOUBLE_HI32_SIGNBIT | JSDOUBLE_HI32_EXPMASK;
|
||||
u.s.lo = 0x00000000;
|
||||
number_constants[NC_NEGATIVE_INFINITY].dval = js_NegativeInfinity = u.d;
|
||||
rt->negativeInfinityValue.setDouble(u.d);
|
||||
d = MOZ_DOUBLE_POSITIVE_INFINITY();
|
||||
number_constants[NC_POSITIVE_INFINITY].dval = js_PositiveInfinity = d;
|
||||
rt->positiveInfinityValue.setDouble(d);
|
||||
|
||||
u.s.hi = 0;
|
||||
u.s.lo = 1;
|
||||
number_constants[NC_MIN_VALUE].dval = u.d;
|
||||
d = MOZ_DOUBLE_NEGATIVE_INFINITY();
|
||||
number_constants[NC_NEGATIVE_INFINITY].dval = js_NegativeInfinity = d;
|
||||
rt->negativeInfinityValue.setDouble(d);
|
||||
|
||||
number_constants[NC_MIN_VALUE].dval = MOZ_DOUBLE_MIN_VALUE();
|
||||
|
||||
/* Copy locale-specific separators into the runtime strings. */
|
||||
const char *thousandsSeparator, *decimalPoint, *grouping;
|
||||
@ -1064,7 +1067,7 @@ FracNumberToCString(JSContext *cx, ToCStringBuf *cbuf, double d, int base = 10)
|
||||
#ifdef DEBUG
|
||||
{
|
||||
int32_t _;
|
||||
JS_ASSERT(!JSDOUBLE_IS_INT32(d, &_));
|
||||
JS_ASSERT(!MOZ_DOUBLE_IS_INT32(d, &_));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1092,7 +1095,7 @@ char *
|
||||
NumberToCString(JSContext *cx, ToCStringBuf *cbuf, double d, int base/* = 10*/)
|
||||
{
|
||||
int32_t i;
|
||||
return (JSDOUBLE_IS_INT32(d, &i))
|
||||
return MOZ_DOUBLE_IS_INT32(d, &i)
|
||||
? IntToCString(cbuf, i, base)
|
||||
: FracNumberToCString(cx, cbuf, d, base);
|
||||
}
|
||||
@ -1116,7 +1119,7 @@ js_NumberToStringWithBase(JSContext *cx, double d, int base)
|
||||
JSCompartment *c = cx->compartment;
|
||||
|
||||
int32_t i;
|
||||
if (JSDOUBLE_IS_INT32(d, &i)) {
|
||||
if (MOZ_DOUBLE_IS_INT32(d, &i)) {
|
||||
if (base == 10 && StaticStrings::hasInt(i))
|
||||
return cx->runtime->staticStrings.getInt(i);
|
||||
if (unsigned(i) < unsigned(base)) {
|
||||
@ -1289,10 +1292,6 @@ ToUint32Slow(JSContext *cx, const Value &v, uint32_t *out)
|
||||
return true;
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
namespace js {
|
||||
|
||||
bool
|
||||
NonstandardToInt32Slow(JSContext *cx, const Value &v, int32_t *out)
|
||||
{
|
||||
@ -1304,7 +1303,7 @@ NonstandardToInt32Slow(JSContext *cx, const Value &v, int32_t *out)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (JSDOUBLE_IS_NaN(d) || d <= -2147483649.0 || 2147483648.0 <= d) {
|
||||
if (MOZ_DOUBLE_IS_NaN(d) || d <= -2147483649.0 || 2147483648.0 <= d) {
|
||||
js_ReportValueError(cx, JSMSG_CANT_CONVERT,
|
||||
JSDVG_SEARCH_STACK, v, NULL);
|
||||
return false;
|
||||
@ -1324,7 +1323,7 @@ ValueToUint16Slow(JSContext *cx, const Value &v, uint16_t *out)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (d == 0 || !JSDOUBLE_IS_FINITE(d)) {
|
||||
if (d == 0 || !MOZ_DOUBLE_IS_FINITE(d)) {
|
||||
*out = 0;
|
||||
return true;
|
||||
}
|
||||
|
108
js/src/jsnum.h
108
js/src/jsnum.h
@ -40,94 +40,12 @@
|
||||
#ifndef jsnum_h___
|
||||
#define jsnum_h___
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "jsobj.h"
|
||||
|
||||
/*
|
||||
* JS number (IEEE double) interface.
|
||||
*
|
||||
* JS numbers are optimistically stored in the top 31 bits of 32-bit integers,
|
||||
* but floating point literals, results that overflow 31 bits, and division and
|
||||
* modulus operands and results require a 64-bit IEEE double. These are GC'ed
|
||||
* and pointed to by 32-bit jsvals on the stack and in object properties.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The ARM architecture supports two floating point models: VFP and FPA. When
|
||||
* targetting FPA, doubles are mixed-endian on little endian ARMs (meaning that
|
||||
* the high and low words are in big endian order).
|
||||
*/
|
||||
#if defined(__arm) || defined(__arm32__) || defined(__arm26__) || defined(__arm__)
|
||||
#if !defined(__VFP_FP__)
|
||||
#define FPU_IS_ARM_FPA
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Low-level floating-point predicates. See bug 640494. */
|
||||
#define JSDOUBLE_HI32_SIGNBIT 0x80000000
|
||||
#define JSDOUBLE_HI32_EXPMASK 0x7ff00000
|
||||
#define JSDOUBLE_HI32_MANTMASK 0x000fffff
|
||||
#define JSDOUBLE_HI32_NAN 0x7ff80000
|
||||
#define JSDOUBLE_LO32_NAN 0x00000000
|
||||
|
||||
#define JSDOUBLE_HI32_EXPSHIFT 20
|
||||
#define JSDOUBLE_EXPBIAS 1023
|
||||
|
||||
union jsdpun {
|
||||
struct {
|
||||
#if defined(IS_LITTLE_ENDIAN) && !defined(FPU_IS_ARM_FPA)
|
||||
uint32_t lo, hi;
|
||||
#else
|
||||
uint32_t hi, lo;
|
||||
#endif
|
||||
} s;
|
||||
uint64_t u64;
|
||||
double d;
|
||||
};
|
||||
|
||||
static inline int
|
||||
JSDOUBLE_IS_NaN(double d)
|
||||
{
|
||||
jsdpun u;
|
||||
u.d = d;
|
||||
return (u.u64 & JSDOUBLE_EXPMASK) == JSDOUBLE_EXPMASK &&
|
||||
(u.u64 & JSDOUBLE_MANTMASK) != 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
JSDOUBLE_IS_FINITE(double d)
|
||||
{
|
||||
/* -0 is finite. NaNs are not. */
|
||||
jsdpun u;
|
||||
u.d = d;
|
||||
return (u.u64 & JSDOUBLE_EXPMASK) != JSDOUBLE_EXPMASK;
|
||||
}
|
||||
|
||||
static inline int
|
||||
JSDOUBLE_IS_INFINITE(double d)
|
||||
{
|
||||
jsdpun u;
|
||||
u.d = d;
|
||||
return (u.u64 & ~JSDOUBLE_SIGNBIT) == JSDOUBLE_EXPMASK;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
JSDOUBLE_IS_NEG(double d)
|
||||
{
|
||||
jsdpun u;
|
||||
u.d = d;
|
||||
return (u.s.hi & JSDOUBLE_HI32_SIGNBIT) != 0;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
JS_HASH_DOUBLE(double d)
|
||||
{
|
||||
jsdpun u;
|
||||
u.d = d;
|
||||
return u.s.lo ^ u.s.hi;
|
||||
}
|
||||
|
||||
extern double js_NaN;
|
||||
extern double js_PositiveInfinity;
|
||||
extern double js_NegativeInfinity;
|
||||
@ -303,6 +221,18 @@ num_parseInt(JSContext *cx, unsigned argc, Value *vp);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
union jsdpun {
|
||||
struct {
|
||||
#if defined(IS_LITTLE_ENDIAN) && !defined(FPU_IS_ARM_FPA)
|
||||
uint32_t lo, hi;
|
||||
#else
|
||||
uint32_t hi, lo;
|
||||
#endif
|
||||
} s;
|
||||
uint64_t u64;
|
||||
double d;
|
||||
};
|
||||
|
||||
/*
|
||||
* Specialized ToInt32 and ToUint32 converters for doubles.
|
||||
*/
|
||||
@ -517,7 +447,7 @@ js_DoubleToECMAInt32(double d)
|
||||
int32_t i;
|
||||
double two32, two31;
|
||||
|
||||
if (!JSDOUBLE_IS_FINITE(d))
|
||||
if (!MOZ_DOUBLE_IS_FINITE(d))
|
||||
return 0;
|
||||
|
||||
i = (int32_t) d;
|
||||
@ -548,8 +478,8 @@ js_DoubleToInteger(double d)
|
||||
if (d == 0)
|
||||
return d;
|
||||
|
||||
if (!JSDOUBLE_IS_FINITE(d)) {
|
||||
if (JSDOUBLE_IS_NaN(d))
|
||||
if (!MOZ_DOUBLE_IS_FINITE(d)) {
|
||||
if (MOZ_DOUBLE_IS_NaN(d))
|
||||
return 0;
|
||||
return d;
|
||||
}
|
||||
@ -586,7 +516,7 @@ ValueFitsInInt32(const Value &v, int32_t *pi)
|
||||
*pi = v.toInt32();
|
||||
return true;
|
||||
}
|
||||
return v.isDouble() && JSDOUBLE_IS_INT32(v.toDouble(), pi);
|
||||
return v.isDouble() && MOZ_DOUBLE_IS_INT32(v.toDouble(), pi);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -607,7 +537,7 @@ IsDefinitelyIndex(const Value &v, uint32_t *indexp)
|
||||
}
|
||||
|
||||
int32_t i;
|
||||
if (v.isDouble() && JSDOUBLE_IS_INT32(v.toDouble(), &i) && i >= 0) {
|
||||
if (v.isDouble() && MOZ_DOUBLE_IS_INT32(v.toDouble(), &i) && i >= 0) {
|
||||
*indexp = uint32_t(i);
|
||||
return true;
|
||||
}
|
||||
|
@ -39,6 +39,8 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "jsapi.h"
|
||||
#include "jsarray.h"
|
||||
@ -584,7 +586,7 @@ Str(JSContext *cx, const Value &v, StringifyContext *scx)
|
||||
/* Step 9. */
|
||||
if (v.isNumber()) {
|
||||
if (v.isDouble()) {
|
||||
if (!JSDOUBLE_IS_FINITE(v.toDouble()))
|
||||
if (!MOZ_DOUBLE_IS_FINITE(v.toDouble()))
|
||||
return scx->sb.append("null");
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,10 @@
|
||||
/*
|
||||
* JS bytecode descriptors, disassemblers, and decompilers.
|
||||
*/
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
@ -49,8 +53,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#include "jstypes.h"
|
||||
#include "jsutil.h"
|
||||
#include "jsprf.h"
|
||||
@ -1586,12 +1588,12 @@ SprintDoubleValue(Sprinter *sp, jsval v, JSOp *opp)
|
||||
|
||||
JS_ASSERT(JSVAL_IS_DOUBLE(v));
|
||||
d = JSVAL_TO_DOUBLE(v);
|
||||
if (JSDOUBLE_IS_NEGZERO(d)) {
|
||||
if (MOZ_DOUBLE_IS_NEGATIVE_ZERO(d)) {
|
||||
todo = sp->put("-0");
|
||||
*opp = JSOP_NEG;
|
||||
} else if (!JSDOUBLE_IS_FINITE(d)) {
|
||||
} else if (!MOZ_DOUBLE_IS_FINITE(d)) {
|
||||
/* Don't use Infinity and NaN, as local variables may shadow them. */
|
||||
todo = sp->put(JSDOUBLE_IS_NaN(d)
|
||||
todo = sp->put(MOZ_DOUBLE_IS_NaN(d)
|
||||
? "0 / 0"
|
||||
: (d < 0)
|
||||
? "1 / -0"
|
||||
@ -2128,7 +2130,7 @@ DecompileDestructuring(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc,
|
||||
|
||||
case JSOP_DOUBLE:
|
||||
d = jp->script->getConst(GET_UINT32_INDEX(pc)).toDouble();
|
||||
LOCAL_ASSERT(JSDOUBLE_IS_FINITE(d) && !JSDOUBLE_IS_NEGZERO(d));
|
||||
LOCAL_ASSERT(MOZ_DOUBLE_IS_FINITE(d) && !MOZ_DOUBLE_IS_NEGATIVE_ZERO(d));
|
||||
i = (int)d;
|
||||
|
||||
do_getelem:
|
||||
|
@ -50,6 +50,7 @@
|
||||
*/
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -1240,7 +1241,7 @@ str_lastIndexOf(JSContext *cx, unsigned argc, Value *vp)
|
||||
double d;
|
||||
if (!ToNumber(cx, args[1], &d))
|
||||
return false;
|
||||
if (!JSDOUBLE_IS_NaN(d)) {
|
||||
if (!MOZ_DOUBLE_IS_NaN(d)) {
|
||||
d = js_DoubleToInteger(d);
|
||||
if (d <= 0)
|
||||
i = 0;
|
||||
@ -3300,7 +3301,7 @@ js_ValueToSource(JSContext *cx, const Value &v)
|
||||
return js_QuoteString(cx, v.toString(), '"');
|
||||
if (v.isPrimitive()) {
|
||||
/* Special case to preserve negative zero, _contra_ toString. */
|
||||
if (v.isDouble() && JSDOUBLE_IS_NEGZERO(v.toDouble())) {
|
||||
if (v.isDouble() && MOZ_DOUBLE_IS_NEGATIVE_ZERO(v.toDouble())) {
|
||||
/* NB: _ucNstr rather than _ucstr to indicate non-terminated. */
|
||||
static const jschar js_negzero_ucNstr[] = {'-', '0'};
|
||||
|
||||
|
@ -39,6 +39,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#include "jstypes.h"
|
||||
@ -93,7 +94,7 @@ ValueIsLength(JSContext *cx, const Value &v, uint32_t *len)
|
||||
|
||||
if (v.isDouble()) {
|
||||
double d = v.toDouble();
|
||||
if (JSDOUBLE_IS_NaN(d))
|
||||
if (MOZ_DOUBLE_IS_NaN(d))
|
||||
return false;
|
||||
|
||||
uint32_t length = uint32_t(d);
|
||||
@ -1715,7 +1716,7 @@ class TypedArrayTemplate
|
||||
static NativeType
|
||||
nativeFromDouble(double d)
|
||||
{
|
||||
if (!ArrayTypeIsFloatingPoint() && JS_UNLIKELY(JSDOUBLE_IS_NaN(d)))
|
||||
if (!ArrayTypeIsFloatingPoint() && JS_UNLIKELY(MOZ_DOUBLE_IS_NaN(d)))
|
||||
return NativeType(int32_t(0));
|
||||
if (TypeIsFloatingPoint<NativeType>())
|
||||
return NativeType(d);
|
||||
@ -2058,7 +2059,7 @@ TypedArrayTemplate<float>::copyIndexToValue(JSContext *cx, JSObject *tarray, uin
|
||||
* This could be removed for platforms/compilers known to convert a 32-bit
|
||||
* non-canonical nan to a 64-bit canonical nan.
|
||||
*/
|
||||
if (JS_UNLIKELY(JSDOUBLE_IS_NaN(dval)))
|
||||
if (JS_UNLIKELY(MOZ_DOUBLE_IS_NaN(dval)))
|
||||
dval = js_NaN;
|
||||
|
||||
vp->setDouble(dval);
|
||||
@ -2077,7 +2078,7 @@ TypedArrayTemplate<double>::copyIndexToValue(JSContext *cx, JSObject *tarray, ui
|
||||
* confuse the engine into interpreting a double-typed jsval as an
|
||||
* object-typed jsval.
|
||||
*/
|
||||
if (JS_UNLIKELY(JSDOUBLE_IS_NaN(val)))
|
||||
if (JS_UNLIKELY(MOZ_DOUBLE_IS_NaN(val)))
|
||||
val = js_NaN;
|
||||
|
||||
vp->setDouble(val);
|
||||
|
@ -39,51 +39,17 @@
|
||||
|
||||
#ifndef jsvalimpl_h__
|
||||
#define jsvalimpl_h__
|
||||
|
||||
/*
|
||||
* Implementation details for js::Value in jsapi.h.
|
||||
*/
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include "js/Utility.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/* To avoid a circular dependency, pull in the necessary pieces of jsnum.h. */
|
||||
|
||||
#define JSDOUBLE_SIGNBIT (((uint64_t) 1) << 63)
|
||||
#define JSDOUBLE_EXPMASK (((uint64_t) 0x7ff) << 52)
|
||||
#define JSDOUBLE_MANTMASK ((((uint64_t) 1) << 52) - 1)
|
||||
#define JSDOUBLE_HI32_SIGNBIT 0x80000000
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSDOUBLE_IS_NEGZERO(double d)
|
||||
{
|
||||
union {
|
||||
struct {
|
||||
#if defined(IS_LITTLE_ENDIAN) && !defined(FPU_IS_ARM_FPA)
|
||||
uint32_t lo, hi;
|
||||
#else
|
||||
uint32_t hi, lo;
|
||||
#endif
|
||||
} s;
|
||||
double d;
|
||||
} x;
|
||||
if (d != 0)
|
||||
return JS_FALSE;
|
||||
x.d = d;
|
||||
return (x.s.hi & JSDOUBLE_HI32_SIGNBIT) != 0;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSDOUBLE_IS_INT32(double d, int32_t* pi)
|
||||
{
|
||||
if (JSDOUBLE_IS_NEGZERO(d))
|
||||
return JS_FALSE;
|
||||
return d == (*pi = (int32_t)d);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/*
|
||||
* Try to get jsvals 64-bit aligned. We could almost assert that all values are
|
||||
* aligned, but MSVC and GCC occasionally break alignment.
|
||||
|
@ -38,6 +38,8 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include "jscntxt.h"
|
||||
#include "jsscope.h"
|
||||
#include "jsobj.h"
|
||||
@ -726,13 +728,13 @@ stubs::Div(VMFrame &f)
|
||||
const Value *vp;
|
||||
#ifdef XP_WIN
|
||||
/* XXX MSVC miscompiles such that (NaN == 0) */
|
||||
if (JSDOUBLE_IS_NaN(d2))
|
||||
if (MOZ_DOUBLE_IS_NaN(d2))
|
||||
vp = &rt->NaNValue;
|
||||
else
|
||||
#endif
|
||||
if (d1 == 0 || JSDOUBLE_IS_NaN(d1))
|
||||
if (d1 == 0 || MOZ_DOUBLE_IS_NaN(d1))
|
||||
vp = &rt->NaNValue;
|
||||
else if (JSDOUBLE_IS_NEG(d1) != JSDOUBLE_IS_NEG(d2))
|
||||
else if (MOZ_DOUBLE_IS_NEGATIVE(d1) != MOZ_DOUBLE_IS_NEGATIVE(d2))
|
||||
vp = &rt->negativeInfinityValue;
|
||||
else
|
||||
vp = &rt->positiveInfinityValue;
|
||||
@ -1380,7 +1382,7 @@ stubs::TableSwitch(VMFrame &f, jsbytecode *origPc)
|
||||
if (d == 0) {
|
||||
/* Treat -0 (double) as 0. */
|
||||
tableIdx = 0;
|
||||
} else if (!JSDOUBLE_IS_INT32(d, &tableIdx)) {
|
||||
} else if (!MOZ_DOUBLE_IS_INT32(d, &tableIdx)) {
|
||||
goto finally;
|
||||
}
|
||||
} else {
|
||||
|
254
mfbt/FloatingPoint.h
Normal file
254
mfbt/FloatingPoint.h
Normal file
@ -0,0 +1,254 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Various predicates and operations on IEEE-754 floating point types. */
|
||||
|
||||
#ifndef mozilla_FloatingPoint_h_
|
||||
#define mozilla_FloatingPoint_h_
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/StandardInteger.h"
|
||||
|
||||
/*
|
||||
* It's reasonable to ask why we have this header at all. Don't isnan,
|
||||
* copysign, the built-in comparison operators, and the like solve these
|
||||
* problems? Unfortunately, they don't. We've found that various compilers
|
||||
* (MSVC, MSVC when compiling with PGO, and GCC on OS X, at least) miscompile
|
||||
* the standard methods in various situations, so we can't use them. Some of
|
||||
* these compilers even have problems compiling seemingly reasonable bitwise
|
||||
* algorithms! But with some care we've found algorithms that seem to not
|
||||
* trigger those compiler bugs.
|
||||
*
|
||||
* For the aforementioned reasons, be very wary of making changes to any of
|
||||
* these algorithms. If you must make changes, keep a careful eye out for
|
||||
* compiler bustage, particularly PGO-specific bustage.
|
||||
*
|
||||
* Some users require that this file be C-compatible. Unfortunately, this means
|
||||
* no mozilla namespace to contain everything, no detail namespace clarifying
|
||||
* MozDoublePun to be an internal data structure, and so on.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These implementations all assume |double| is a 64-bit double format number
|
||||
* type, compatible with the IEEE-754 standard. C/C++ don't require this to be
|
||||
* the case. But we required this in implementations of these algorithms that
|
||||
* preceded this header, so we shouldn't break anything if we continue doing so.
|
||||
*/
|
||||
MOZ_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t), "double must be 64 bits");
|
||||
|
||||
/*
|
||||
* Constant expressions in C can't refer to consts, unfortunately, so #define
|
||||
* these rather than use |const uint64_t|.
|
||||
*/
|
||||
#define MOZ_DOUBLE_SIGN_BIT 0x8000000000000000ULL
|
||||
#define MOZ_DOUBLE_EXPONENT_BITS 0x7ff0000000000000ULL
|
||||
#define MOZ_DOUBLE_SIGNIFICAND_BITS 0x000fffffffffffffULL
|
||||
|
||||
#define MOZ_DOUBLE_EXPONENT_BIAS 1023
|
||||
#define MOZ_DOUBLE_EXPONENT_SHIFT 52
|
||||
|
||||
MOZ_STATIC_ASSERT((MOZ_DOUBLE_SIGN_BIT & MOZ_DOUBLE_EXPONENT_BITS) == 0,
|
||||
"sign bit doesn't overlap exponent bits");
|
||||
MOZ_STATIC_ASSERT((MOZ_DOUBLE_SIGN_BIT & MOZ_DOUBLE_SIGNIFICAND_BITS) == 0,
|
||||
"sign bit doesn't overlap significand bits");
|
||||
MOZ_STATIC_ASSERT((MOZ_DOUBLE_EXPONENT_BITS & MOZ_DOUBLE_SIGNIFICAND_BITS) == 0,
|
||||
"exponent bits don't overlap significand bits");
|
||||
|
||||
MOZ_STATIC_ASSERT((MOZ_DOUBLE_SIGN_BIT | MOZ_DOUBLE_EXPONENT_BITS | MOZ_DOUBLE_SIGNIFICAND_BITS)
|
||||
== ~(uint64_t)0,
|
||||
"all bits accounted for");
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This union is NOT a public data structure, and it is not to be used outside
|
||||
* this file!
|
||||
*/
|
||||
union MozDoublePun {
|
||||
/*
|
||||
* Every way to pun the bits of a double introduces an additional layer of
|
||||
* complexity, across a multitude of platforms, architectures, and ABIs.
|
||||
* Use *only* uint64_t to reduce complexity. Don't add new punning here
|
||||
* without discussion!
|
||||
*/
|
||||
uint64_t u;
|
||||
double d;
|
||||
};
|
||||
|
||||
/** Determines whether a double is NaN. */
|
||||
static MOZ_ALWAYS_INLINE int
|
||||
MOZ_DOUBLE_IS_NaN(double d)
|
||||
{
|
||||
union MozDoublePun pun;
|
||||
pun.d = d;
|
||||
|
||||
/*
|
||||
* A double is NaN if all exponent bits are 1 and the significand contains at
|
||||
* least one non-zero bit.
|
||||
*/
|
||||
return (pun.u & MOZ_DOUBLE_EXPONENT_BITS) == MOZ_DOUBLE_EXPONENT_BITS &&
|
||||
(pun.u & MOZ_DOUBLE_SIGNIFICAND_BITS) != 0;
|
||||
}
|
||||
|
||||
/** Determines whether a double is +Infinity or -Infinity. */
|
||||
static MOZ_ALWAYS_INLINE int
|
||||
MOZ_DOUBLE_IS_INFINITE(double d)
|
||||
{
|
||||
union MozDoublePun pun;
|
||||
pun.d = d;
|
||||
|
||||
/* Infinities have all exponent bits set to 1 and an all-0 significand. */
|
||||
return (pun.u & ~MOZ_DOUBLE_SIGN_BIT) == MOZ_DOUBLE_EXPONENT_BITS;
|
||||
}
|
||||
|
||||
/** Determines whether a double is not NaN or infinite. */
|
||||
static MOZ_ALWAYS_INLINE int
|
||||
MOZ_DOUBLE_IS_FINITE(double d)
|
||||
{
|
||||
union MozDoublePun pun;
|
||||
pun.d = d;
|
||||
|
||||
/*
|
||||
* NaN and Infinities are the only non-finite doubles, and both have all
|
||||
* exponent bits set to 1.
|
||||
*/
|
||||
return (pun.u & MOZ_DOUBLE_EXPONENT_BITS) != MOZ_DOUBLE_EXPONENT_BITS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a double is negative. It is an error to call this method
|
||||
* on a double which is NaN.
|
||||
*/
|
||||
static MOZ_ALWAYS_INLINE int
|
||||
MOZ_DOUBLE_IS_NEGATIVE(double d)
|
||||
{
|
||||
union MozDoublePun pun;
|
||||
pun.d = d;
|
||||
|
||||
MOZ_ASSERT(!MOZ_DOUBLE_IS_NaN(d), "NaN does not have a sign");
|
||||
|
||||
/* The sign bit is set if the double is negative. */
|
||||
return (pun.u & MOZ_DOUBLE_SIGN_BIT) != 0;
|
||||
}
|
||||
|
||||
/** Determines whether a double represents -0. */
|
||||
static MOZ_ALWAYS_INLINE int
|
||||
MOZ_DOUBLE_IS_NEGATIVE_ZERO(double d)
|
||||
{
|
||||
union MozDoublePun pun;
|
||||
pun.d = d;
|
||||
|
||||
/* Only the sign bit is set if the double is -0. */
|
||||
return pun.u == MOZ_DOUBLE_SIGN_BIT;
|
||||
}
|
||||
|
||||
/** Returns the exponent portion of the double. */
|
||||
static MOZ_ALWAYS_INLINE int_fast16_t
|
||||
MOZ_DOUBLE_EXPONENT(double d)
|
||||
{
|
||||
union MozDoublePun pun;
|
||||
pun.d = d;
|
||||
|
||||
/*
|
||||
* The exponent component of a double is an unsigned number, biased from its
|
||||
* actual value. Subtract the bias to retrieve the actual exponent.
|
||||
*/
|
||||
return (int_fast16_t)((pun.u & MOZ_DOUBLE_EXPONENT_BITS) >> MOZ_DOUBLE_EXPONENT_SHIFT) -
|
||||
MOZ_DOUBLE_EXPONENT_BIAS;
|
||||
}
|
||||
|
||||
/** Returns +Infinity. */
|
||||
static MOZ_ALWAYS_INLINE double
|
||||
MOZ_DOUBLE_POSITIVE_INFINITY()
|
||||
{
|
||||
union MozDoublePun pun;
|
||||
|
||||
/*
|
||||
* Positive infinity has all exponent bits set, sign bit set to 0, and no
|
||||
* significand.
|
||||
*/
|
||||
pun.u = MOZ_DOUBLE_EXPONENT_BITS;
|
||||
return pun.d;
|
||||
}
|
||||
|
||||
/** Returns -Infinity. */
|
||||
static MOZ_ALWAYS_INLINE double
|
||||
MOZ_DOUBLE_NEGATIVE_INFINITY()
|
||||
{
|
||||
union MozDoublePun pun;
|
||||
|
||||
/*
|
||||
* Negative infinity has all exponent bits set, sign bit set to 1, and no
|
||||
* significand.
|
||||
*/
|
||||
pun.u = MOZ_DOUBLE_SIGN_BIT | MOZ_DOUBLE_EXPONENT_BITS;
|
||||
return pun.d;
|
||||
}
|
||||
|
||||
/** Constructs a NaN value with the specified sign bit and significand bits. */
|
||||
static MOZ_ALWAYS_INLINE double
|
||||
MOZ_DOUBLE_SPECIFIC_NaN(int signbit, uint64_t significand)
|
||||
{
|
||||
union MozDoublePun pun;
|
||||
|
||||
MOZ_ASSERT(signbit == 0 || signbit == 1);
|
||||
MOZ_ASSERT((significand & ~MOZ_DOUBLE_SIGNIFICAND_BITS) == 0);
|
||||
MOZ_ASSERT(significand & MOZ_DOUBLE_SIGNIFICAND_BITS);
|
||||
|
||||
pun.u = (signbit ? MOZ_DOUBLE_SIGN_BIT : 0) |
|
||||
MOZ_DOUBLE_EXPONENT_BITS |
|
||||
significand;
|
||||
MOZ_ASSERT(MOZ_DOUBLE_IS_NaN(pun.d));
|
||||
return pun.d;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a NaN value. Do not use this method if you depend upon a particular
|
||||
* NaN value being returned.
|
||||
*/
|
||||
static MOZ_ALWAYS_INLINE double
|
||||
MOZ_DOUBLE_NaN()
|
||||
{
|
||||
return MOZ_DOUBLE_SPECIFIC_NaN(0, 0xfffffffffffffULL);
|
||||
}
|
||||
|
||||
/** Computes the smallest non-zero positive double value. */
|
||||
static MOZ_ALWAYS_INLINE double
|
||||
MOZ_DOUBLE_MIN_VALUE()
|
||||
{
|
||||
union MozDoublePun pun;
|
||||
pun.u = 1;
|
||||
return pun.d;
|
||||
}
|
||||
|
||||
/** Computes a 32-bit hash of the given double. */
|
||||
static MOZ_ALWAYS_INLINE uint32_t
|
||||
MOZ_HASH_DOUBLE(double d)
|
||||
{
|
||||
union MozDoublePun pun;
|
||||
pun.d = d;
|
||||
|
||||
return ((uint32_t)(pun.u >> 32)) ^ ((uint32_t)(pun.u));
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE int
|
||||
MOZ_DOUBLE_IS_INT32(double d, int32_t* i)
|
||||
{
|
||||
/*
|
||||
* XXX Casting a double that doesn't truncate to int32_t, to int32_t, induces
|
||||
* undefined behavior. We should definitely fix this (bug 744965), but as
|
||||
* apparently it "works" in practice, it's not a pressing concern now.
|
||||
*/
|
||||
return !MOZ_DOUBLE_IS_NEGATIVE_ZERO(d) && d == (*i = (int32_t)d);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* mozilla_FloatingPoint_h_ */
|
@ -45,6 +45,7 @@ EXPORTS_mozilla += \
|
||||
Assertions.h \
|
||||
Attributes.h \
|
||||
BloomFilter.h \
|
||||
FloatingPoint.h \
|
||||
GuardObjects.h \
|
||||
HashFunctions.h \
|
||||
Likely.h \
|
||||
|
Loading…
Reference in New Issue
Block a user