mirror of
https://github.com/SerenityOS/serenity
synced 2024-09-30 05:05:10 +00:00
AK: Use common ComponentType integer type for float bitfields
This allows us to easily use an appropriate integer type when performing float bitfield operations. This change also adds a comment about the technically-incorrect 80-bit extended float mantissa field.
This commit is contained in:
parent
997828c31a
commit
8443d0a74d
|
@ -18,15 +18,16 @@ union FloatExtractor;
|
|||
#ifdef AK_HAS_FLOAT_128
|
||||
template<>
|
||||
union FloatExtractor<f128> {
|
||||
using ComponentType = unsigned __int128;
|
||||
static constexpr int mantissa_bits = 112;
|
||||
static constexpr unsigned __int128 mantissa_max = (((unsigned __int128)1) << 112) - 1;
|
||||
static constexpr ComponentType mantissa_max = (((ComponentType)1) << 112) - 1;
|
||||
static constexpr int exponent_bias = 16383;
|
||||
static constexpr int exponent_bits = 15;
|
||||
static constexpr unsigned exponent_max = 32767;
|
||||
struct [[gnu::packed]] {
|
||||
unsigned __int128 mantissa : 112;
|
||||
unsigned __int128 exponent : 15;
|
||||
unsigned __int128 sign : 1;
|
||||
ComponentType mantissa : 112;
|
||||
ComponentType exponent : 15;
|
||||
ComponentType sign : 1;
|
||||
};
|
||||
f128 d;
|
||||
};
|
||||
|
@ -38,15 +39,21 @@ static_assert(AssertSize<FloatExtractor<f128>, sizeof(f128)>());
|
|||
#ifdef AK_HAS_FLOAT_80
|
||||
template<>
|
||||
union FloatExtractor<f80> {
|
||||
using ComponentType = unsigned long long;
|
||||
static constexpr int mantissa_bits = 64;
|
||||
static constexpr unsigned long long mantissa_max = ~0u;
|
||||
static constexpr ComponentType mantissa_max = ~0ull;
|
||||
static constexpr int exponent_bias = 16383;
|
||||
static constexpr int exponent_bits = 15;
|
||||
static constexpr unsigned exponent_max = 32767;
|
||||
struct [[gnu::packed]] {
|
||||
unsigned long long mantissa;
|
||||
unsigned long long exponent : 15;
|
||||
unsigned long long sign : 1;
|
||||
// This is technically wrong: Extended floating point values really only have 63 bits of mantissa
|
||||
// and an "integer bit" that behaves in various strange, unintuitive and non-IEEE-754 ways.
|
||||
// However, since all bit-fiddling float code assumes IEEE floats, it cannot handle this properly.
|
||||
// If we pretend that 80-bit floats are IEEE floats with 64-bit mantissas, almost everything works correctly
|
||||
// and we just need a few special cases.
|
||||
ComponentType mantissa : 64;
|
||||
ComponentType exponent : 15;
|
||||
ComponentType sign : 1;
|
||||
};
|
||||
f80 d;
|
||||
};
|
||||
|
@ -55,8 +62,9 @@ static_assert(AssertSize<FloatExtractor<f80>, sizeof(f80)>());
|
|||
|
||||
template<>
|
||||
union FloatExtractor<f64> {
|
||||
using ComponentType = unsigned long long;
|
||||
static constexpr int mantissa_bits = 52;
|
||||
static constexpr unsigned long long mantissa_max = (1ull << 52) - 1;
|
||||
static constexpr ComponentType mantissa_max = (1ull << 52) - 1;
|
||||
static constexpr int exponent_bias = 1023;
|
||||
static constexpr int exponent_bits = 11;
|
||||
static constexpr unsigned exponent_max = 2047;
|
||||
|
@ -68,9 +76,9 @@ union FloatExtractor<f64> {
|
|||
// very intuitive and portable behaviour on windows, but it doesn't
|
||||
// work with the msvc ABI.
|
||||
// See <https://github.com/llvm/llvm-project/issues/24757>
|
||||
unsigned long long mantissa : 52;
|
||||
unsigned long long exponent : 11;
|
||||
unsigned long long sign : 1;
|
||||
ComponentType mantissa : 52;
|
||||
ComponentType exponent : 11;
|
||||
ComponentType sign : 1;
|
||||
};
|
||||
f64 d;
|
||||
};
|
||||
|
@ -78,15 +86,16 @@ static_assert(AssertSize<FloatExtractor<f64>, sizeof(f64)>());
|
|||
|
||||
template<>
|
||||
union FloatExtractor<f32> {
|
||||
using ComponentType = unsigned;
|
||||
static constexpr int mantissa_bits = 23;
|
||||
static constexpr unsigned mantissa_max = (1 << 23) - 1;
|
||||
static constexpr ComponentType mantissa_max = (1 << 23) - 1;
|
||||
static constexpr int exponent_bias = 127;
|
||||
static constexpr int exponent_bits = 8;
|
||||
static constexpr unsigned exponent_max = 255;
|
||||
static constexpr ComponentType exponent_max = 255;
|
||||
struct [[gnu::packed]] {
|
||||
unsigned mantissa : 23;
|
||||
unsigned exponent : 8;
|
||||
unsigned sign : 1;
|
||||
ComponentType mantissa : 23;
|
||||
ComponentType exponent : 8;
|
||||
ComponentType sign : 1;
|
||||
};
|
||||
f32 d;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue