mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 798179 - Rewrite ToIntWidth to more simply act upon the actual bits of the IEEE-754 representation. r=froydnj
--HG-- extra : rebase_source : fb2da4e55b258b6b62c1c9449447fccff8c2012d
This commit is contained in:
parent
4ee21886e5
commit
99f84749f1
@ -59,6 +59,7 @@ CPP_SOURCES += [
|
||||
'testSetProperty.cpp',
|
||||
'testSourcePolicy.cpp',
|
||||
'testStringBuffer.cpp',
|
||||
'testToIntWidth.cpp',
|
||||
'testTrap.cpp',
|
||||
'testTypedArrays.cpp',
|
||||
'testUTF8.cpp',
|
||||
|
70
js/src/jsapi-tests/testToIntWidth.cpp
Normal file
70
js/src/jsapi-tests/testToIntWidth.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
*/
|
||||
/* 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/. */
|
||||
|
||||
|
||||
#include "tests.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "vm/NumericConversions.h"
|
||||
|
||||
using js::detail::ToIntWidth;
|
||||
using js::detail::ToUintWidth;
|
||||
|
||||
BEGIN_TEST(testToUint8TwiceUint8Range)
|
||||
{
|
||||
double d = -256;
|
||||
uint8_t expected = 0;
|
||||
do {
|
||||
CHECK(ToUintWidth<uint8_t>(d) == expected);
|
||||
|
||||
d++;
|
||||
expected++;
|
||||
} while (d <= 256);
|
||||
return true;
|
||||
}
|
||||
END_TEST(testToUint8TwiceUint8Range)
|
||||
|
||||
BEGIN_TEST(testToInt8)
|
||||
{
|
||||
double d = -128;
|
||||
int8_t expected = -128;
|
||||
do {
|
||||
CHECK(ToIntWidth<int8_t>(d) == expected);
|
||||
|
||||
d++;
|
||||
expected++;
|
||||
} while (expected < 127);
|
||||
return true;
|
||||
}
|
||||
END_TEST(testToInt8)
|
||||
|
||||
BEGIN_TEST(testToUint32Large)
|
||||
{
|
||||
CHECK(ToUintWidth<uint32_t>(pow(2.0, 83)) == 0);
|
||||
CHECK(ToUintWidth<uint32_t>(pow(2.0, 83) + pow(2.0, 31)) == (1U << 31));
|
||||
CHECK(ToUintWidth<uint32_t>(pow(2.0, 83) + 2 * pow(2.0, 31)) == 0);
|
||||
CHECK(ToUintWidth<uint32_t>(pow(2.0, 83) + 3 * pow(2.0, 31)) == (1U << 31));
|
||||
CHECK(ToUintWidth<uint32_t>(pow(2.0, 84)) == 0);
|
||||
CHECK(ToUintWidth<uint32_t>(pow(2.0, 84) + pow(2.0, 31)) == 0);
|
||||
CHECK(ToUintWidth<uint32_t>(pow(2.0, 84) + pow(2.0, 32)) == 0);
|
||||
return true;
|
||||
}
|
||||
END_TEST(testToUint32Large)
|
||||
|
||||
BEGIN_TEST(testToUint64Large)
|
||||
{
|
||||
CHECK(ToUintWidth<uint64_t>(pow(2.0, 115)) == 0);
|
||||
CHECK(ToUintWidth<uint64_t>(pow(2.0, 115) + pow(2.0, 63)) == (1ULL << 63));
|
||||
CHECK(ToUintWidth<uint64_t>(pow(2.0, 115) + 2 * pow(2.0, 63)) == 0);
|
||||
CHECK(ToUintWidth<uint64_t>(pow(2.0, 115) + 3 * pow(2.0, 63)) == (1ULL << 63));
|
||||
CHECK(ToUintWidth<uint64_t>(pow(2.0, 116)) == 0);
|
||||
CHECK(ToUintWidth<uint64_t>(pow(2.0, 116) + pow(2.0, 63)) == 0);
|
||||
CHECK(ToUintWidth<uint64_t>(pow(2.0, 116) + pow(2.0, 64)) == 0);
|
||||
return true;
|
||||
}
|
||||
END_TEST(testToUint64Large)
|
@ -7,9 +7,10 @@
|
||||
#ifndef NumericConversions_h___
|
||||
#define NumericConversions_h___
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Casting.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include "jscpucfg.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
@ -20,137 +21,113 @@ namespace js {
|
||||
|
||||
namespace detail {
|
||||
|
||||
union DoublePun {
|
||||
struct {
|
||||
#if defined(IS_LITTLE_ENDIAN)
|
||||
uint32_t lo, hi;
|
||||
#else
|
||||
uint32_t hi, lo;
|
||||
#endif
|
||||
} s;
|
||||
uint64_t u64;
|
||||
double d;
|
||||
};
|
||||
/*
|
||||
* Convert a double value to ResultType (an unsigned integral type) using
|
||||
* ECMAScript-style semantics (that is, in like manner to how ECMAScript's
|
||||
* ToInt32 converts to int32_t).
|
||||
*
|
||||
* If d is infinite or NaN, return 0.
|
||||
* Otherwise compute d2 = sign(d) * floor(abs(d)), and return the ResultType
|
||||
* value congruent to d2 mod 2**(bit width of ResultType).
|
||||
*
|
||||
* The algorithm below is inspired by that found in
|
||||
* <http://trac.webkit.org/changeset/67825/trunk/JavaScriptCore/runtime/JSValue.cpp>
|
||||
* but has been generalized to all integer widths.
|
||||
*/
|
||||
template<typename ResultType>
|
||||
inline ResultType
|
||||
ToUintWidth(double d)
|
||||
{
|
||||
MOZ_STATIC_ASSERT(mozilla::IsUnsigned<ResultType>::value,
|
||||
"ResultType must be an unsigned type");
|
||||
|
||||
} /* namespace detail */
|
||||
uint64_t bits = mozilla::BitwiseCast<uint64_t>(d);
|
||||
|
||||
/* Numeric Conversion base. Round doubles to Ints according to ECMA or WEBIDL standards. */
|
||||
template<size_t width, typename ResultType>
|
||||
// Extract the exponent component. (Be careful here! It's not technically
|
||||
// the exponent in NaN, infinities, and subnormals.)
|
||||
int_fast16_t exp =
|
||||
int_fast16_t((bits & mozilla::DoubleExponentBits) >> mozilla::DoubleExponentShift) -
|
||||
int_fast16_t(mozilla::DoubleExponentBias);
|
||||
|
||||
// If the exponent's less than zero, abs(d) < 1, so the result is 0. (This
|
||||
// also handles subnormals.)
|
||||
if (exp < 0)
|
||||
return 0;
|
||||
|
||||
uint_fast16_t exponent = mozilla::SafeCast<uint_fast16_t>(exp);
|
||||
|
||||
// If the exponent is greater than or equal to the bits of precision of a
|
||||
// double plus ResultType's width, the number is either infinite, NaN, or
|
||||
// too large to have lower-order bits in the congruent value. (Example:
|
||||
// 2**84 is exactly representable as a double. The next exact double is
|
||||
// 2**84 + 2**32. Thus if ResultType is int32_t, an exponent >= 84 implies
|
||||
// floor(abs(d)) == 0 mod 2**32.) Return 0 in all these cases.
|
||||
const size_t ResultWidth = CHAR_BIT * sizeof(ResultType);
|
||||
if (exponent >= mozilla::DoubleExponentShift + ResultWidth)
|
||||
return 0;
|
||||
|
||||
// The significand contains the bits that will determine the final result.
|
||||
// Shift those bits left or right, according to the exponent, to their
|
||||
// locations in the unsigned binary representation of floor(abs(d)).
|
||||
MOZ_STATIC_ASSERT(sizeof(ResultType) <= sizeof(uint64_t),
|
||||
"Left-shifting below would lose upper bits");
|
||||
ResultType result = (exponent > mozilla::DoubleExponentShift)
|
||||
? ResultType(bits << (exponent - mozilla::DoubleExponentShift))
|
||||
: ResultType(bits >> (mozilla::DoubleExponentShift - exponent));
|
||||
|
||||
// Two further complications remain. First, |result| may contain bogus
|
||||
// sign/exponent bits. Second, IEEE-754 numbers' significands (excluding
|
||||
// subnormals, but we already handled those) have an implicit leading 1
|
||||
// which may affect the final result.
|
||||
//
|
||||
// It may appear that there's complexity here depending on how ResultWidth
|
||||
// and DoubleExponentShift relate, but it turns out there's not.
|
||||
//
|
||||
// Assume ResultWidth < DoubleExponentShift:
|
||||
// Only right-shifts leave bogus bits in |result|. For this to happen,
|
||||
// we must right-shift by > |DoubleExponentShift - ResultWidth|, implying
|
||||
// |exponent < ResultWidth|.
|
||||
// The implicit leading bit only matters if it appears in the final
|
||||
// result -- if |2**exponent mod 2**ResultWidth != 0|. This implies
|
||||
// |exponent < ResultWidth|.
|
||||
// Otherwise assume ResultWidth >= DoubleExponentShift:
|
||||
// Any left-shift less than |ResultWidth - DoubleExponentShift| leaves
|
||||
// bogus bits in |result|. This implies |exponent < ResultWidth|. Any
|
||||
// right-shift less than |ResultWidth| does too, which implies
|
||||
// |DoubleExponentShift - ResultWidth < exponent|. By assumption, then,
|
||||
// |exponent| is negative, but we excluded that above. So bogus bits
|
||||
// need only |exponent < ResultWidth|.
|
||||
// The implicit leading bit matters identically to the other case, so
|
||||
// again, |exponent < ResultWidth|.
|
||||
if (exponent < ResultWidth) {
|
||||
ResultType implicitOne = ResultType(1) << exponent;
|
||||
result &= implicitOne - 1; // remove bogus bits
|
||||
result += implicitOne; // add the implicit bit
|
||||
}
|
||||
|
||||
// Compute the congruent value in the signed range.
|
||||
return (bits & mozilla::DoubleSignBit) ? ~result + 1 : result;
|
||||
}
|
||||
|
||||
template<typename ResultType>
|
||||
inline ResultType
|
||||
ToIntWidth(double d)
|
||||
{
|
||||
#if defined(__i386__) || defined(__i386) || defined(__x86_64__) || \
|
||||
defined(_M_IX86) || defined(_M_X64)
|
||||
detail::DoublePun du, duh, twoWidth;
|
||||
uint32_t di_h, u_tmp, expon, shift_amount;
|
||||
int32_t mask32;
|
||||
MOZ_STATIC_ASSERT(mozilla::IsSigned<ResultType>::value,
|
||||
"ResultType must be a signed type");
|
||||
|
||||
/*
|
||||
* Algorithm Outline
|
||||
* Step 1. If d is NaN, +/-Inf or |d|>=2^(width + 52) or |d|<1, then return 0
|
||||
* All of this is implemented based on an exponent comparison,
|
||||
* since anything with a higher exponent is either not finite, or
|
||||
* going to round to 0..
|
||||
* Step 2. If |d|<2^(width - 1), then return (int)d
|
||||
* The cast to integer (conversion in RZ mode) returns the correct result.
|
||||
* Step 3. If |d|>=2^width, d:=fmod(d, 2^width) is taken -- but without a call
|
||||
* Step 4. If |d|>=2^(width - 1), then the fractional bits are cleared before
|
||||
* applying the correction by 2^width: d - sign(d)*2^width
|
||||
* Step 5. Return (int)d
|
||||
*/
|
||||
const ResultType MaxValue = (1ULL << (CHAR_BIT * sizeof(ResultType) - 1)) - 1;
|
||||
const ResultType MinValue = -MaxValue - 1;
|
||||
|
||||
du.d = d;
|
||||
di_h = du.s.hi;
|
||||
|
||||
u_tmp = (di_h & 0x7ff00000) - 0x3ff00000;
|
||||
if (u_tmp >= ((width + 52) << 20)) {
|
||||
// d is Nan, +/-Inf or +/-0, or |d|>=2^(width+52) or |d|<1, in which case result=0
|
||||
// If we need to shift by more than (width + 52), there are no data bits
|
||||
// to preserve, and the mod will turn out 0.
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (u_tmp < ((width - 1) << 20)) {
|
||||
// |d|<2^(width - 1)
|
||||
return ResultType(d);
|
||||
}
|
||||
|
||||
if (u_tmp > ((width - 1) << 20)) {
|
||||
// |d|>=2^width
|
||||
// Throw away multiples of 2^width.
|
||||
//
|
||||
// That is, compute du.d = the value in (-2^width, 2^width)
|
||||
// that has the same sign as d and is equal to d modulo 2^width.
|
||||
//
|
||||
// This can't be done simply by masking away bits of du because
|
||||
// the implicit one-bit of the mantissa is one of the ones we want to
|
||||
// eliminate. So instead we compute duh.d = the appropriate multiple
|
||||
// of 2^width, which *can* be computed by masking, and then we
|
||||
// subtract that from du.d.
|
||||
expon = u_tmp >> 20;
|
||||
shift_amount = expon - (width - 11);
|
||||
mask32 = 0x80000000;
|
||||
if (shift_amount < 32) {
|
||||
// Shift only affects top word.
|
||||
mask32 >>= shift_amount;
|
||||
duh.s.hi = du.s.hi & mask32;
|
||||
duh.s.lo = 0;
|
||||
} else {
|
||||
// Top word all 1s, shift affects bottom word.
|
||||
mask32 >>= (shift_amount-32);
|
||||
duh.s.hi = du.s.hi;
|
||||
duh.s.lo = du.s.lo & mask32;
|
||||
}
|
||||
du.d -= duh.d;
|
||||
}
|
||||
|
||||
di_h = du.s.hi;
|
||||
|
||||
// Eliminate fractional bits
|
||||
u_tmp = (di_h & 0x7ff00000);
|
||||
if (u_tmp >= (0x3ff00000 + ((width - 1) << 20))) {
|
||||
// |d|>=2^(width - 1)
|
||||
expon = u_tmp >> 20;
|
||||
|
||||
// Same idea as before, except save everything non-fractional.
|
||||
shift_amount = expon - (0x3ff - 11);
|
||||
mask32 = 0x80000000;
|
||||
if (shift_amount < 32) {
|
||||
// Top word only
|
||||
mask32 >>= shift_amount;
|
||||
du.s.hi &= mask32;
|
||||
du.s.lo = 0;
|
||||
} else {
|
||||
// Bottom word. Top word all 1s.
|
||||
mask32 >>= (shift_amount-32);
|
||||
du.s.lo &= mask32;
|
||||
}
|
||||
// Apply step 4's 2^width correction.
|
||||
twoWidth.s.hi = (0x3ff00000 + (width << 20)) ^ (du.s.hi & 0x80000000);
|
||||
twoWidth.s.lo = 0;
|
||||
du.d -= twoWidth.d;
|
||||
}
|
||||
|
||||
return ResultType(du.d);
|
||||
#else
|
||||
double twoWidth, twoWidthMin1;
|
||||
|
||||
if (!mozilla::IsFinite(d))
|
||||
return 0;
|
||||
|
||||
/* FIXME: This relies on undefined behavior; see bug 667739. */
|
||||
ResultType i = (ResultType) d;
|
||||
if ((double) i == d)
|
||||
return ResultType(i);
|
||||
|
||||
twoWidth = width == 32 ? 4294967296.0 : 18446744073709551616.0;
|
||||
twoWidthMin1 = width == 32 ? 2147483648.0 : 9223372036854775808.0;
|
||||
d = fmod(d, twoWidth);
|
||||
d = (d >= 0) ? floor(d) : ceil(d) + twoWidth;
|
||||
return (ResultType) (d >= twoWidthMin1 ? d - twoWidth : d);
|
||||
#endif
|
||||
typedef typename mozilla::MakeUnsigned<ResultType>::Type UnsignedResult;
|
||||
UnsignedResult u = ToUintWidth<UnsignedResult>(d);
|
||||
if (u <= UnsignedResult(MaxValue))
|
||||
return static_cast<ResultType>(u);
|
||||
return (MinValue + static_cast<ResultType>(u - MaxValue)) - 1;
|
||||
}
|
||||
|
||||
} /* namespace detail */
|
||||
|
||||
/* ES5 9.5 ToInt32 (specialized for doubles). */
|
||||
inline int32_t
|
||||
ToInt32(double d)
|
||||
@ -277,7 +254,7 @@ ToInt32(double d)
|
||||
);
|
||||
return i;
|
||||
#else
|
||||
return ToIntWidth<32, int32_t>(d);
|
||||
return detail::ToIntWidth<int32_t>(d);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -285,21 +262,21 @@ ToInt32(double d)
|
||||
inline uint32_t
|
||||
ToUint32(double d)
|
||||
{
|
||||
return uint32_t(ToInt32(d));
|
||||
return detail::ToUintWidth<uint32_t>(d);
|
||||
}
|
||||
|
||||
/* WEBIDL 4.2.10 */
|
||||
inline int64_t
|
||||
ToInt64(double d)
|
||||
{
|
||||
return ToIntWidth<64, int64_t>(d);
|
||||
return detail::ToIntWidth<int64_t>(d);
|
||||
}
|
||||
|
||||
/* WEBIDL 4.2.11 */
|
||||
inline uint64_t
|
||||
ToUint64(double d)
|
||||
{
|
||||
return uint64_t(ToInt64(d));
|
||||
return detail::ToUintWidth<uint64_t>(d);
|
||||
}
|
||||
|
||||
/* ES5 9.4 ToInteger (specialized for doubles). */
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Casting.h"
|
||||
#include "mozilla/StandardInteger.h"
|
||||
|
||||
namespace mozilla {
|
||||
@ -40,8 +41,6 @@ MOZ_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t), "double must be 64 bits");
|
||||
const unsigned DoubleExponentBias = 1023;
|
||||
const unsigned DoubleExponentShift = 52;
|
||||
|
||||
namespace detail {
|
||||
|
||||
const uint64_t DoubleSignBit = 0x8000000000000000ULL;
|
||||
const uint64_t DoubleExponentBits = 0x7ff0000000000000ULL;
|
||||
const uint64_t DoubleSignificandBits = 0x000fffffffffffffULL;
|
||||
@ -57,58 +56,38 @@ MOZ_STATIC_ASSERT((DoubleSignBit | DoubleExponentBits | DoubleSignificandBits) =
|
||||
~uint64_t(0),
|
||||
"all bits accounted for");
|
||||
|
||||
union DoublePun
|
||||
{
|
||||
/*
|
||||
* 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;
|
||||
};
|
||||
|
||||
} /* namespace detail */
|
||||
|
||||
/** Determines whether a double is NaN. */
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
IsNaN(double d)
|
||||
{
|
||||
union detail::DoublePun 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 & detail::DoubleExponentBits) == detail::DoubleExponentBits &&
|
||||
(pun.u & detail::DoubleSignificandBits) != 0;
|
||||
uint64_t bits = BitwiseCast<uint64_t>(d);
|
||||
return (bits & DoubleExponentBits) == DoubleExponentBits &&
|
||||
(bits & DoubleSignificandBits) != 0;
|
||||
}
|
||||
|
||||
/** Determines whether a double is +Infinity or -Infinity. */
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
IsInfinite(double d)
|
||||
{
|
||||
union detail::DoublePun pun;
|
||||
pun.d = d;
|
||||
|
||||
/* Infinities have all exponent bits set to 1 and an all-0 significand. */
|
||||
return (pun.u & ~detail::DoubleSignBit) == detail::DoubleExponentBits;
|
||||
uint64_t bits = BitwiseCast<uint64_t>(d);
|
||||
return (bits & ~DoubleSignBit) == DoubleExponentBits;
|
||||
}
|
||||
|
||||
/** Determines whether a double is not NaN or infinite. */
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
IsFinite(double d)
|
||||
{
|
||||
union detail::DoublePun 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 & detail::DoubleExponentBits) != detail::DoubleExponentBits;
|
||||
uint64_t bits = BitwiseCast<uint64_t>(d);
|
||||
return (bits & DoubleExponentBits) != DoubleExponentBits;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -120,36 +99,30 @@ IsNegative(double d)
|
||||
{
|
||||
MOZ_ASSERT(!IsNaN(d), "NaN does not have a sign");
|
||||
|
||||
union detail::DoublePun pun;
|
||||
pun.d = d;
|
||||
|
||||
/* The sign bit is set if the double is negative. */
|
||||
return (pun.u & detail::DoubleSignBit) != 0;
|
||||
uint64_t bits = BitwiseCast<uint64_t>(d);
|
||||
return (bits & DoubleSignBit) != 0;
|
||||
}
|
||||
|
||||
/** Determines whether a double represents -0. */
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
IsNegativeZero(double d)
|
||||
{
|
||||
union detail::DoublePun pun;
|
||||
pun.d = d;
|
||||
|
||||
/* Only the sign bit is set if the double is -0. */
|
||||
return pun.u == detail::DoubleSignBit;
|
||||
uint64_t bits = BitwiseCast<uint64_t>(d);
|
||||
return bits == DoubleSignBit;
|
||||
}
|
||||
|
||||
/** Returns the exponent portion of the double. */
|
||||
static MOZ_ALWAYS_INLINE int_fast16_t
|
||||
ExponentComponent(double d)
|
||||
{
|
||||
union detail::DoublePun 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 & detail::DoubleExponentBits) >> DoubleExponentShift) -
|
||||
uint64_t bits = BitwiseCast<uint64_t>(d);
|
||||
return int_fast16_t((bits & DoubleExponentBits) >> DoubleExponentShift) -
|
||||
int_fast16_t(DoubleExponentBias);
|
||||
}
|
||||
|
||||
@ -157,28 +130,22 @@ ExponentComponent(double d)
|
||||
static MOZ_ALWAYS_INLINE double
|
||||
PositiveInfinity()
|
||||
{
|
||||
union detail::DoublePun pun;
|
||||
|
||||
/*
|
||||
* Positive infinity has all exponent bits set, sign bit set to 0, and no
|
||||
* significand.
|
||||
*/
|
||||
pun.u = detail::DoubleExponentBits;
|
||||
return pun.d;
|
||||
return BitwiseCast<double>(DoubleExponentBits);
|
||||
}
|
||||
|
||||
/** Returns -Infinity. */
|
||||
static MOZ_ALWAYS_INLINE double
|
||||
NegativeInfinity()
|
||||
{
|
||||
union detail::DoublePun pun;
|
||||
|
||||
/*
|
||||
* Negative infinity has all exponent bits set, sign bit set to 1, and no
|
||||
* significand.
|
||||
*/
|
||||
pun.u = detail::DoubleSignBit | detail::DoubleExponentBits;
|
||||
return pun.d;
|
||||
return BitwiseCast<double>(DoubleSignBit | DoubleExponentBits);
|
||||
}
|
||||
|
||||
/** Constructs a NaN value with the specified sign bit and significand bits. */
|
||||
@ -186,24 +153,21 @@ static MOZ_ALWAYS_INLINE double
|
||||
SpecificNaN(int signbit, uint64_t significand)
|
||||
{
|
||||
MOZ_ASSERT(signbit == 0 || signbit == 1);
|
||||
MOZ_ASSERT((significand & ~detail::DoubleSignificandBits) == 0);
|
||||
MOZ_ASSERT(significand & detail::DoubleSignificandBits);
|
||||
MOZ_ASSERT((significand & ~DoubleSignificandBits) == 0);
|
||||
MOZ_ASSERT(significand & DoubleSignificandBits);
|
||||
|
||||
union detail::DoublePun pun;
|
||||
pun.u = (signbit ? detail::DoubleSignBit : 0) |
|
||||
detail::DoubleExponentBits |
|
||||
significand;
|
||||
MOZ_ASSERT(IsNaN(pun.d));
|
||||
return pun.d;
|
||||
double d = BitwiseCast<double>((signbit ? DoubleSignBit : 0) |
|
||||
DoubleExponentBits |
|
||||
significand);
|
||||
MOZ_ASSERT(IsNaN(d));
|
||||
return d;
|
||||
}
|
||||
|
||||
/** Computes the smallest non-zero positive double value. */
|
||||
static MOZ_ALWAYS_INLINE double
|
||||
MinDoubleValue()
|
||||
{
|
||||
union detail::DoublePun pun;
|
||||
pun.u = 1;
|
||||
return pun.d;
|
||||
return BitwiseCast<double>(uint64_t(1));
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
@ -224,7 +188,7 @@ DoubleIsInt32(double d, int32_t* i)
|
||||
static MOZ_ALWAYS_INLINE double
|
||||
UnspecifiedNaN()
|
||||
{
|
||||
return mozilla::SpecificNaN(0, 0xfffffffffffffULL);
|
||||
return SpecificNaN(0, 0xfffffffffffffULL);
|
||||
}
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
Loading…
Reference in New Issue
Block a user