mirror of
https://github.com/roytam1/UXP.git
synced 2026-05-26 13:58:49 +00:00
Issue #1240 - Part 3a - Adjust mozilla::FloatingPoint<T>'s definition. So only the barest details are specified for floating-point encodings, with every other number, bit mask, &c. mathematically derived. Also add a bunch of documentation comments. https://bugzilla.mozilla.org/show_bug.cgi?id=1508725 Prerequisite for our V8 fast forward.
This commit is contained in:
+2
-2
@@ -507,7 +507,7 @@ class MOZ_NON_PARAM alignas(8) Value
|
||||
#if defined(JS_NUNBOX32)
|
||||
return uint32_t(toTag()) <= uint32_t(JSVAL_TAG_CLEAR);
|
||||
#elif defined(JS_PUNBOX64)
|
||||
return (data.asBits | mozilla::DoubleTypeTraits::kSignBit) <= JSVAL_SHIFTED_TAG_MAX_DOUBLE;
|
||||
return (data.asBits | mozilla::FloatingPoint<double>::kSignBit) <= JSVAL_SHIFTED_TAG_MAX_DOUBLE;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1090,7 +1090,7 @@ IsCanonicalized(double d)
|
||||
|
||||
uint64_t bits;
|
||||
mozilla::BitwiseCast<uint64_t>(d, &bits);
|
||||
return (bits & ~mozilla::DoubleTypeTraits::kSignBit) == detail::CanonicalizedNaNBits;
|
||||
return (bits & ~mozilla::FloatingPoint<double>::kSignBit) == detail::CanonicalizedNaNBits;
|
||||
}
|
||||
|
||||
static inline Value
|
||||
|
||||
@@ -54,7 +54,7 @@ template<class T>
|
||||
bool
|
||||
js::wasm::RenderNaN(StringBuffer& sb, Raw<T> num)
|
||||
{
|
||||
typedef typename mozilla::SelectTrait<T> Traits;
|
||||
typedef typename mozilla::FloatingPoint<T> Traits;
|
||||
|
||||
MOZ_ASSERT(IsNaN(num.fp()));
|
||||
|
||||
|
||||
+74
-34
@@ -33,33 +33,38 @@ namespace mozilla {
|
||||
* compiler bustage, particularly PGO-specific bustage.
|
||||
*/
|
||||
|
||||
struct FloatTypeTraits
|
||||
namespace detail {
|
||||
|
||||
/*
|
||||
* These implementations assume float/double are 32/64-bit single/double
|
||||
* format number types compatible with the IEEE-754 standard. C++ doesn't
|
||||
* require this, but we required it in implementations of these algorithms that
|
||||
* preceded this header, so we shouldn't break anything to continue doing so.
|
||||
*/
|
||||
template<typename T>
|
||||
struct FloatingPointTrait;
|
||||
|
||||
template<>
|
||||
struct FloatingPointTrait<float>
|
||||
{
|
||||
protected:
|
||||
typedef uint32_t Bits;
|
||||
|
||||
static const unsigned kExponentBias = 127;
|
||||
static const unsigned kExponentShift = 23;
|
||||
|
||||
static const Bits kSignBit = 0x80000000UL;
|
||||
static const Bits kExponentBits = 0x7F800000UL;
|
||||
static const Bits kSignificandBits = 0x007FFFFFUL;
|
||||
static constexpr unsigned kExponentWidth = 8;
|
||||
static constexpr unsigned kSignificandWidth = 23;
|
||||
};
|
||||
|
||||
struct DoubleTypeTraits
|
||||
template<>
|
||||
struct FloatingPointTrait<double>
|
||||
{
|
||||
protected:
|
||||
typedef uint64_t Bits;
|
||||
|
||||
static const unsigned kExponentBias = 1023;
|
||||
static const unsigned kExponentShift = 52;
|
||||
|
||||
static const Bits kSignBit = 0x8000000000000000ULL;
|
||||
static const Bits kExponentBits = 0x7ff0000000000000ULL;
|
||||
static const Bits kSignificandBits = 0x000fffffffffffffULL;
|
||||
static constexpr unsigned kExponentWidth = 11;
|
||||
static constexpr unsigned kSignificandWidth = 52;
|
||||
};
|
||||
|
||||
template<typename T> struct SelectTrait;
|
||||
template<> struct SelectTrait<float> : public FloatTypeTraits {};
|
||||
template<> struct SelectTrait<double> : public DoubleTypeTraits {};
|
||||
} // namespace detail
|
||||
|
||||
/*
|
||||
* This struct contains details regarding the encoding of floating-point
|
||||
@@ -88,30 +93,65 @@ template<> struct SelectTrait<double> : public DoubleTypeTraits {};
|
||||
* http://en.wikipedia.org/wiki/Floating_point#IEEE_754:_floating_point_in_modern_computers
|
||||
*/
|
||||
template<typename T>
|
||||
struct FloatingPoint : public SelectTrait<T>
|
||||
struct FloatingPoint final : private detail::FloatingPointTrait<T>
|
||||
{
|
||||
typedef SelectTrait<T> Base;
|
||||
typedef typename Base::Bits Bits;
|
||||
private:
|
||||
using Base = detail::FloatingPointTrait<T>;
|
||||
|
||||
static_assert((Base::kSignBit & Base::kExponentBits) == 0,
|
||||
public:
|
||||
/**
|
||||
* An unsigned integral type suitable for accessing the bitwise representation
|
||||
* of T.
|
||||
*/
|
||||
using Bits = typename Base::Bits;
|
||||
|
||||
static_assert(sizeof(T) == sizeof(Bits), "Bits must be same size as T");
|
||||
|
||||
/** The bit-width of the exponent component of T. */
|
||||
using Base::kExponentWidth;
|
||||
|
||||
/** The bit-width of the significand component of T. */
|
||||
using Base::kSignificandWidth;
|
||||
|
||||
static_assert(1 + kExponentWidth + kSignificandWidth ==
|
||||
CHAR_BIT * sizeof(T),
|
||||
"sign bit plus bit widths should sum to overall bit width");
|
||||
|
||||
/**
|
||||
* The exponent field in an IEEE-754 floating point number consists of bits
|
||||
* encoding an unsigned number. The *actual* represented exponent (for all
|
||||
* values finite and not denormal) is that value, minus a bias |kExponentBias|
|
||||
* so that a useful range of numbers is represented.
|
||||
*/
|
||||
static constexpr unsigned kExponentBias = (1U << (kExponentWidth - 1)) - 1;
|
||||
|
||||
/**
|
||||
* The amount by which the bits of the exponent-field in an IEEE-754 floating
|
||||
* point number are shifted from the LSB of the floating point type.
|
||||
*/
|
||||
static constexpr unsigned kExponentShift = kSignificandWidth;
|
||||
|
||||
/** The sign bit in the floating point representation. */
|
||||
static constexpr Bits kSignBit =
|
||||
static_cast<Bits>(1) << (CHAR_BIT * sizeof(Bits) - 1);
|
||||
|
||||
/** The exponent bits in the floating point representation. */
|
||||
static constexpr Bits kExponentBits =
|
||||
((static_cast<Bits>(1) << kExponentWidth) - 1) << kSignificandWidth;
|
||||
|
||||
/** The significand bits in the floating point representation. */
|
||||
static constexpr Bits kSignificandBits =
|
||||
(static_cast<Bits>(1) << kSignificandWidth) - 1;
|
||||
|
||||
static_assert((kSignBit & kExponentBits) == 0,
|
||||
"sign bit shouldn't overlap exponent bits");
|
||||
static_assert((Base::kSignBit & Base::kSignificandBits) == 0,
|
||||
static_assert((kSignBit & kSignificandBits) == 0,
|
||||
"sign bit shouldn't overlap significand bits");
|
||||
static_assert((Base::kExponentBits & Base::kSignificandBits) == 0,
|
||||
static_assert((kExponentBits & kSignificandBits) == 0,
|
||||
"exponent bits shouldn't overlap significand bits");
|
||||
|
||||
static_assert((Base::kSignBit | Base::kExponentBits | Base::kSignificandBits) ==
|
||||
~Bits(0),
|
||||
static_assert((kSignBit | kExponentBits | kSignificandBits) == ~Bits(0),
|
||||
"all bits accounted for");
|
||||
|
||||
/*
|
||||
* These implementations assume float/double are 32/64-bit single/double
|
||||
* format number types compatible with the IEEE-754 standard. 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 keep doing so.
|
||||
*/
|
||||
static_assert(sizeof(T) == sizeof(Bits), "Bits must be same size as T");
|
||||
};
|
||||
|
||||
/** Determines whether a float/double is NaN. */
|
||||
|
||||
Reference in New Issue
Block a user