Skip to content

Commit

Permalink
Revert "[libc][NFC] Implement FPBits in terms of FloatProperties
Browse files Browse the repository at this point in the history
…to reduce clutter (#75196)"

This reverts commit f64a057.
  • Loading branch information
gchatelet committed Dec 13, 2023
1 parent 5b32740 commit d5a7456
Show file tree
Hide file tree
Showing 17 changed files with 191 additions and 190 deletions.
68 changes: 34 additions & 34 deletions libc/src/__support/FPUtil/FPBits.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,74 +36,71 @@ template <typename T> struct ExponentWidth {
// floating numbers. On x86 platforms however, the 'long double' type maps to
// an x87 floating point format. This format is an IEEE 754 extension format.
// It is handled as an explicit specialization of this class.
template <typename T> struct FPBits : private FloatProperties<T> {
template <typename T> struct FPBits {
static_assert(cpp::is_floating_point_v<T>,
"FPBits instantiated with invalid type.");
using typename FloatProperties<T>::UIntType;
using FloatProperties<T>::BIT_WIDTH;
using FloatProperties<T>::EXP_MANT_MASK;
using FloatProperties<T>::EXPONENT_MASK;
using FloatProperties<T>::EXPONENT_BIAS;
using FloatProperties<T>::EXPONENT_WIDTH;
using FloatProperties<T>::MANTISSA_MASK;
using FloatProperties<T>::MANTISSA_WIDTH;
using FloatProperties<T>::QUIET_NAN_MASK;
using FloatProperties<T>::SIGN_MASK;

// Reinterpreting bits as an integer value and interpreting the bits of an
// integer value as a floating point value is used in tests. So, a convenient
// type is provided for such reinterpretations.
using FloatProp = FloatProperties<T>;
using UIntType = typename FloatProp::UIntType;

UIntType bits;

LIBC_INLINE constexpr void set_mantissa(UIntType mantVal) {
mantVal &= MANTISSA_MASK;
bits &= ~MANTISSA_MASK;
mantVal &= (FloatProp::MANTISSA_MASK);
bits &= ~(FloatProp::MANTISSA_MASK);
bits |= mantVal;
}

LIBC_INLINE constexpr UIntType get_mantissa() const {
return bits & MANTISSA_MASK;
return bits & FloatProp::MANTISSA_MASK;
}

LIBC_INLINE constexpr void set_biased_exponent(UIntType expVal) {
expVal = (expVal << MANTISSA_WIDTH) & EXPONENT_MASK;
bits &= ~EXPONENT_MASK;
expVal = (expVal << (FloatProp::MANTISSA_WIDTH)) & FloatProp::EXPONENT_MASK;
bits &= ~(FloatProp::EXPONENT_MASK);
bits |= expVal;
}

LIBC_INLINE constexpr uint16_t get_biased_exponent() const {
return uint16_t((bits & EXPONENT_MASK) >> MANTISSA_WIDTH);
return uint16_t((bits & FloatProp::EXPONENT_MASK) >>
(FloatProp::MANTISSA_WIDTH));
}

// The function return mantissa with the implicit bit set iff the current
// value is a valid normal number.
LIBC_INLINE constexpr UIntType get_explicit_mantissa() {
return ((get_biased_exponent() > 0 && !is_inf_or_nan())
? (MANTISSA_MASK + 1)
? (FloatProp::MANTISSA_MASK + 1)
: 0) |
(MANTISSA_MASK & bits);
(FloatProp::MANTISSA_MASK & bits);
}

LIBC_INLINE constexpr void set_sign(bool signVal) {
bits |= SIGN_MASK;
bits |= FloatProp::SIGN_MASK;
if (!signVal)
bits -= SIGN_MASK;
bits -= FloatProp::SIGN_MASK;
}

LIBC_INLINE constexpr bool get_sign() const {
return (bits & SIGN_MASK) != 0;
return (bits & FloatProp::SIGN_MASK) != 0;
}

static_assert(sizeof(T) == sizeof(UIntType),
"Data type and integral representation have different sizes.");

static constexpr int MAX_EXPONENT = (1 << EXPONENT_WIDTH) - 1;
static constexpr int EXPONENT_BIAS = (1 << (ExponentWidth<T>::VALUE - 1)) - 1;
static constexpr int MAX_EXPONENT = (1 << ExponentWidth<T>::VALUE) - 1;

static constexpr UIntType MIN_SUBNORMAL = UIntType(1);
static constexpr UIntType MAX_SUBNORMAL = (UIntType(1) << MANTISSA_WIDTH) - 1;
static constexpr UIntType MIN_NORMAL = (UIntType(1) << MANTISSA_WIDTH);
static constexpr UIntType MAX_SUBNORMAL =
(UIntType(1) << MantissaWidth<T>::VALUE) - 1;
static constexpr UIntType MIN_NORMAL =
(UIntType(1) << MantissaWidth<T>::VALUE);
static constexpr UIntType MAX_NORMAL =
((UIntType(MAX_EXPONENT) - 1) << MANTISSA_WIDTH) | MAX_SUBNORMAL;
((UIntType(MAX_EXPONENT) - 1) << MantissaWidth<T>::VALUE) | MAX_SUBNORMAL;

// We don't want accidental type promotions/conversions, so we require exact
// type match.
Expand Down Expand Up @@ -154,29 +151,32 @@ template <typename T> struct FPBits : private FloatProperties<T> {
}

LIBC_INLINE constexpr bool is_inf() const {
return (bits & EXP_MANT_MASK) == EXPONENT_MASK;
return (bits & FloatProp::EXP_MANT_MASK) == FloatProp::EXPONENT_MASK;
}

LIBC_INLINE constexpr bool is_nan() const {
return (bits & EXP_MANT_MASK) > EXPONENT_MASK;
return (bits & FloatProp::EXP_MANT_MASK) > FloatProp::EXPONENT_MASK;
}

LIBC_INLINE constexpr bool is_quiet_nan() const {
return (bits & EXP_MANT_MASK) == (EXPONENT_MASK | QUIET_NAN_MASK);
return (bits & FloatProp::EXP_MANT_MASK) ==
(FloatProp::EXPONENT_MASK | FloatProp::QUIET_NAN_MASK);
}

LIBC_INLINE constexpr bool is_inf_or_nan() const {
return (bits & EXPONENT_MASK) == EXPONENT_MASK;
return (bits & FloatProp::EXPONENT_MASK) == FloatProp::EXPONENT_MASK;
}

LIBC_INLINE static constexpr T zero(bool sign = false) {
return FPBits(sign ? SIGN_MASK : UIntType(0)).get_val();
return FPBits(sign ? FloatProp::SIGN_MASK : UIntType(0)).get_val();
}

LIBC_INLINE static constexpr T neg_zero() { return zero(true); }

LIBC_INLINE static constexpr T inf(bool sign = false) {
return FPBits((sign ? SIGN_MASK : UIntType(0)) | EXPONENT_MASK).get_val();
return FPBits((sign ? FloatProp::SIGN_MASK : UIntType(0)) |
FloatProp::EXPONENT_MASK)
.get_val();
}

LIBC_INLINE static constexpr T neg_inf() { return inf(true); }
Expand Down Expand Up @@ -204,7 +204,7 @@ template <typename T> struct FPBits : private FloatProperties<T> {
}

LIBC_INLINE static constexpr T build_quiet_nan(UIntType v) {
return build_nan(QUIET_NAN_MASK | v);
return build_nan(FloatProp::QUIET_NAN_MASK | v);
}

// The function convert integer number and unbiased exponent to proper float
Expand All @@ -220,7 +220,7 @@ template <typename T> struct FPBits : private FloatProperties<T> {
LIBC_INLINE static constexpr FPBits<T> make_value(UIntType number, int ep) {
FPBits<T> result;
// offset: +1 for sign, but -1 for implicit first bit
int lz = cpp::countl_zero(number) - EXPONENT_WIDTH;
int lz = cpp::countl_zero(number) - FloatProp::EXPONENT_WIDTH;
number <<= lz;
ep -= lz;

Expand Down
20 changes: 10 additions & 10 deletions libc/src/__support/FPUtil/Hypot.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,14 @@ template <> struct DoubleLength<uint64_t> {
//
template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
LIBC_INLINE T hypot(T x, T y) {
using FPBits = FPBits<T>;
using UIntType = typename FPBits::UIntType;
using FPBits_t = FPBits<T>;
using UIntType = typename FPBits<T>::UIntType;
using DUIntType = typename DoubleLength<UIntType>::Type;

FPBits x_bits(x), y_bits(y);
FPBits_t x_bits(x), y_bits(y);

if (x_bits.is_inf() || y_bits.is_inf()) {
return T(FPBits::inf());
return T(FPBits_t::inf());
}
if (x_bits.is_nan()) {
return x;
Expand Down Expand Up @@ -193,11 +193,11 @@ LIBC_INLINE T hypot(T x, T y) {
sticky_bits = sticky_bits || ((sum & 0x3U) != 0);
sum >>= 2;
++out_exp;
if (out_exp >= FPBits::MAX_EXPONENT) {
if (out_exp >= FPBits_t::MAX_EXPONENT) {
if (int round_mode = quick_get_round();
round_mode == FE_TONEAREST || round_mode == FE_UPWARD)
return T(FPBits::inf());
return T(FPBits(FPBits::MAX_NORMAL));
return T(FPBits_t::inf());
return T(FPBits_t(FPBits_t::MAX_NORMAL));
}
} else {
// For denormal result, we simply move the leading bit of the result to
Expand Down Expand Up @@ -251,10 +251,10 @@ LIBC_INLINE T hypot(T x, T y) {
if (y_new >= (ONE >> 1)) {
y_new -= ONE >> 1;
++out_exp;
if (out_exp >= FPBits::MAX_EXPONENT) {
if (out_exp >= FPBits_t::MAX_EXPONENT) {
if (round_mode == FE_TONEAREST || round_mode == FE_UPWARD)
return T(FPBits::inf());
return T(FPBits(FPBits::MAX_NORMAL));
return T(FPBits_t::inf());
return T(FPBits_t(FPBits_t::MAX_NORMAL));
}
}

Expand Down
74 changes: 37 additions & 37 deletions libc/src/__support/FPUtil/generic/FMod.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,9 @@ template <typename T> struct FModExceptionalInputHandler {
"FModCStandardWrapper instantiated with invalid type.");

LIBC_INLINE static bool pre_check(T x, T y, T &out) {
using FPBits = fputil::FPBits<T>;
const T quiet_nan = FPBits::build_quiet_nan(0);
FPBits sx(x), sy(y);
using FPB = fputil::FPBits<T>;
const T quiet_nan = FPB::build_quiet_nan(0);
FPB sx(x), sy(y);
if (LIBC_LIKELY(!sy.is_zero() && !sy.is_inf_or_nan() &&
!sx.is_inf_or_nan())) {
return false;
Expand Down Expand Up @@ -167,11 +167,11 @@ template <typename T> struct FModFastMathWrapper {

template <typename T> class FModDivisionSimpleHelper {
private:
using UIntType = typename FPBits<T>::UIntType;
using intU_t = typename FPBits<T>::UIntType;

public:
LIBC_INLINE constexpr static UIntType
execute(int exp_diff, int sides_zeroes_count, UIntType m_x, UIntType m_y) {
LIBC_INLINE constexpr static intU_t
execute(int exp_diff, int sides_zeroes_count, intU_t m_x, intU_t m_y) {
while (exp_diff > sides_zeroes_count) {
exp_diff -= sides_zeroes_count;
m_x <<= sides_zeroes_count;
Expand All @@ -185,24 +185,24 @@ template <typename T> class FModDivisionSimpleHelper {

template <typename T> class FModDivisionInvMultHelper {
private:
using FPBits = FPBits<T>;
using UIntType = typename FPBits::UIntType;
using FPB = FPBits<T>;
using intU_t = typename FPB::UIntType;

public:
LIBC_INLINE constexpr static UIntType
execute(int exp_diff, int sides_zeroes_count, UIntType m_x, UIntType m_y) {
LIBC_INLINE constexpr static intU_t
execute(int exp_diff, int sides_zeroes_count, intU_t m_x, intU_t m_y) {
if (exp_diff > sides_zeroes_count) {
UIntType inv_hy = (cpp::numeric_limits<UIntType>::max() / m_y);
intU_t inv_hy = (cpp::numeric_limits<intU_t>::max() / m_y);
while (exp_diff > sides_zeroes_count) {
exp_diff -= sides_zeroes_count;
UIntType hd =
(m_x * inv_hy) >> (FPBits::BIT_WIDTH - sides_zeroes_count);
intU_t hd =
(m_x * inv_hy) >> (FPB::FloatProp::BIT_WIDTH - sides_zeroes_count);
m_x <<= sides_zeroes_count;
m_x -= hd * m_y;
while (LIBC_UNLIKELY(m_x > m_y))
m_x -= m_y;
}
UIntType hd = (m_x * inv_hy) >> (FPBits::BIT_WIDTH - exp_diff);
intU_t hd = (m_x * inv_hy) >> (FPB::FloatProp::BIT_WIDTH - exp_diff);
m_x <<= exp_diff;
m_x -= hd * m_y;
while (LIBC_UNLIKELY(m_x > m_y))
Expand All @@ -222,44 +222,44 @@ class FMod {
"FMod instantiated with invalid type.");

private:
using FPBits = FPBits<T>;
using UIntType = typename FPBits::UIntType;
using FPB = FPBits<T>;
using intU_t = typename FPB::UIntType;

LIBC_INLINE static constexpr FPBits eval_internal(FPBits sx, FPBits sy) {
LIBC_INLINE static constexpr FPB eval_internal(FPB sx, FPB sy) {

if (LIBC_LIKELY(sx.uintval() <= sy.uintval())) {
if (sx.uintval() < sy.uintval())
return sx; // |x|<|y| return x
return FPBits(FPBits::zero()); // |x|=|y| return 0.0
return sx; // |x|<|y| return x
return FPB(FPB::zero()); // |x|=|y| return 0.0
}

int e_x = sx.get_biased_exponent();
int e_y = sy.get_biased_exponent();

// Most common case where |y| is "very normal" and |x/y| < 2^EXPONENT_WIDTH
if (LIBC_LIKELY(e_y > int(FPBits::MANTISSA_WIDTH) &&
e_x - e_y <= int(FPBits::EXPONENT_WIDTH))) {
UIntType m_x = sx.get_explicit_mantissa();
UIntType m_y = sy.get_explicit_mantissa();
UIntType d = (e_x == e_y) ? (m_x - m_y) : (m_x << (e_x - e_y)) % m_y;
if (LIBC_LIKELY(e_y > int(FPB::FloatProp::MANTISSA_WIDTH) &&
e_x - e_y <= int(FPB::FloatProp::EXPONENT_WIDTH))) {
intU_t m_x = sx.get_explicit_mantissa();
intU_t m_y = sy.get_explicit_mantissa();
intU_t d = (e_x == e_y) ? (m_x - m_y) : (m_x << (e_x - e_y)) % m_y;
if (d == 0)
return FPBits(FPBits::zero());
return FPB(FPB::zero());
// iy - 1 because of "zero power" for number with power 1
return FPBits::make_value(d, e_y - 1);
return FPB::make_value(d, e_y - 1);
}
/* Both subnormal special case. */
if (LIBC_UNLIKELY(e_x == 0 && e_y == 0)) {
FPBits d;
FPB d;
d.set_mantissa(sx.uintval() % sy.uintval());
return d;
}

// Note that hx is not subnormal by conditions above.
UIntType m_x = sx.get_explicit_mantissa();
intU_t m_x = sx.get_explicit_mantissa();
e_x--;

UIntType m_y = sy.get_explicit_mantissa();
int lead_zeros_m_y = FPBits::EXPONENT_WIDTH;
intU_t m_y = sy.get_explicit_mantissa();
int lead_zeros_m_y = FPB::FloatProp::EXPONENT_WIDTH;
if (LIBC_LIKELY(e_y > 0)) {
e_y--;
} else {
Expand All @@ -282,34 +282,34 @@ class FMod {

{
// Shift hx left until the end or n = 0
int left_shift = exp_diff < int(FPBits::EXPONENT_WIDTH)
int left_shift = exp_diff < int(FPB::FloatProp::EXPONENT_WIDTH)
? exp_diff
: FPBits::EXPONENT_WIDTH;
: FPB::FloatProp::EXPONENT_WIDTH;
m_x <<= left_shift;
exp_diff -= left_shift;
}

m_x %= m_y;
if (LIBC_UNLIKELY(m_x == 0))
return FPBits(FPBits::zero());
return FPB(FPB::zero());

if (exp_diff == 0)
return FPBits::make_value(m_x, e_y);
return FPB::make_value(m_x, e_y);

/* hx next can't be 0, because hx < hy, hy % 2 == 1 hx * 2^i % hy != 0 */
m_x = DivisionHelper::execute(exp_diff, sides_zeroes_count, m_x, m_y);
return FPBits::make_value(m_x, e_y);
return FPB::make_value(m_x, e_y);
}

public:
LIBC_INLINE static T eval(T x, T y) {
if (T out; Wrapper::pre_check(x, y, out))
return out;
FPBits sx(x), sy(y);
FPB sx(x), sy(y);
bool sign = sx.get_sign();
sx.set_sign(false);
sy.set_sign(false);
FPBits result = eval_internal(sx, sy);
FPB result = eval_internal(sx, sy);
result.set_sign(sign);
return result.get_val();
}
Expand Down

0 comments on commit d5a7456

Please sign in to comment.