Skip to content

[libc] Remove unnecessary FPBits functions and properties #79113

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libc/fuzzing/stdlib/strtofloat_fuzz.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ using LIBC_NAMESPACE::fputil::FPBits;
// exponent. Subnormals have a lower effective precision since they don't
// necessarily use all of the bits of the mantissa.
template <typename F> inline constexpr int effective_precision(int exponent) {
const int full_precision = FPBits<F>::MANTISSA_PRECISION;
const int full_precision = FPBits<F>::FRACTION_LEN + 1;

// This is intended to be 0 when the exponent is the lowest normal and
// increase as the exponent's magnitude increases.
Expand Down
2 changes: 1 addition & 1 deletion libc/src/__support/FPUtil/DivisionAndRemainderOperations.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ LIBC_INLINE T remquo(T x, T y, int &q) {
if (ybits.is_nan())
return y;
if (xbits.is_inf() || ybits.is_zero())
return FPBits<T>::build_quiet_nan(1);
return FPBits<T>::build_quiet_nan(fputil::Sign::POS, 1).get_val();

if (xbits.is_zero()) {
q = 0;
Expand Down
51 changes: 9 additions & 42 deletions libc/src/__support/FPUtil/FPBits.h
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ struct FPRepSem : public FPStorage<fp_type> {
return exp_bits() == encode(BiasedExp::BITS_ALL_ZEROES());
}
LIBC_INLINE constexpr bool is_normal() const {
return is_finite() && !UP::is_subnormal();
return is_finite() && !is_subnormal();
}
// Returns the mantissa with the implicit bit set iff the current
// value is a valid normal number.
Expand Down Expand Up @@ -556,6 +556,14 @@ struct FPRep : public FPRepSem<fp_type, RetT> {
using UP::FRACTION_MASK;
using UP::SIGN_MASK;

// Comparison
LIBC_INLINE constexpr friend bool operator==(FPRep a, FPRep b) {
return a.uintval() == b.uintval();
}
LIBC_INLINE constexpr friend bool operator!=(FPRep a, FPRep b) {
return a.uintval() != b.uintval();
}

// Representation
LIBC_INLINE constexpr StorageType uintval() const { return bits & FP_MASK; }
LIBC_INLINE constexpr void set_uintval(StorageType value) {
Expand Down Expand Up @@ -698,16 +706,6 @@ struct FPBits final : public internal::FPRep<get_fp_type<T>(), FPBits<T>> {
using UP::bits;

// Constants.
LIBC_INLINE_VAR static constexpr uint32_t MANTISSA_PRECISION =
UP::FRACTION_LEN + 1;
LIBC_INLINE_VAR static constexpr StorageType MIN_NORMAL =
UP::min_normal(Sign::POS).uintval();
LIBC_INLINE_VAR static constexpr StorageType MAX_NORMAL =
UP::max_normal(Sign::POS).uintval();
LIBC_INLINE_VAR static constexpr StorageType MIN_SUBNORMAL =
UP::min_subnormal(Sign::POS).uintval();
LIBC_INLINE_VAR static constexpr StorageType MAX_SUBNORMAL =
UP::max_subnormal(Sign::POS).uintval();
LIBC_INLINE_VAR static constexpr int MAX_BIASED_EXPONENT =
(1 << UP::EXP_LEN) - 1;

Expand All @@ -731,37 +729,6 @@ struct FPBits final : public internal::FPRep<get_fp_type<T>(), FPBits<T>> {

LIBC_INLINE constexpr explicit operator T() const { return get_val(); }

// Methods below this are used by tests.
// TODO: inline and remove.
LIBC_INLINE static constexpr T one(Sign sign = Sign::POS) {
return T(UP::one(sign));
}
LIBC_INLINE static constexpr T zero(Sign sign = Sign::POS) {
return T(UP::zero(sign));
}
LIBC_INLINE static constexpr T inf(Sign sign = Sign::POS) {
return T(UP::inf(sign));
}
LIBC_INLINE static constexpr T min_normal() {
return T(UP::min_normal(Sign::POS));
}
LIBC_INLINE static constexpr T max_normal() {
return T(UP::max_normal(Sign::POS));
}
LIBC_INLINE static constexpr T min_denormal() {
return T(UP::min_subnormal(Sign::POS));
}
LIBC_INLINE static constexpr T max_denormal() {
return T(UP::max_subnormal(Sign::POS));
}
LIBC_INLINE static constexpr T build_nan(StorageType v) {
return T(UP::build_nan(Sign::POS, v));
}
LIBC_INLINE static constexpr T build_quiet_nan(StorageType v,
Sign sign = Sign::POS) {
return T(UP::build_quiet_nan(sign, v));
}

// TODO: Use an uint32_t for 'biased_exp'.
LIBC_INLINE static constexpr FPBits<T>
create_value(Sign sign, StorageType biased_exp, StorageType mantissa) {
Expand Down
4 changes: 2 additions & 2 deletions libc/src/__support/FPUtil/Hypot.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ LIBC_INLINE T hypot(T x, T y) {
if (int round_mode = quick_get_round();
round_mode == FE_TONEAREST || round_mode == FE_UPWARD)
return T(FPBits_t::inf());
return T(FPBits_t(FPBits_t::MAX_NORMAL));
return T(FPBits_t::max_normal());
}
} else {
// For denormal result, we simply move the leading bit of the result to
Expand Down Expand Up @@ -254,7 +254,7 @@ LIBC_INLINE T hypot(T x, T y) {
if (out_exp >= FPBits_t::MAX_BIASED_EXPONENT) {
if (round_mode == FE_TONEAREST || round_mode == FE_UPWARD)
return T(FPBits_t::inf());
return T(FPBits_t(FPBits_t::MAX_NORMAL));
return T(FPBits_t::max_normal());
}
}

Expand Down
24 changes: 10 additions & 14 deletions libc/src/__support/FPUtil/ManipulationFunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ LIBC_INLINE T logb(T x) {
return x;
} else if (bits.is_inf()) {
// Return positive infinity.
return T(FPBits<T>::inf(Sign::POS));
return T(FPBits<T>::inf());
}

NormalFloat<T> normal(bits);
Expand All @@ -127,7 +127,7 @@ LIBC_INLINE T ldexp(T x, int exp) {
// that adding |exp| to it does not lead to integer rollover. But, if |exp|
// value is larger the exponent range for type T, then we can return infinity
// early. Because the result of the ldexp operation can be a subnormal number,
// we need to accommodate the (mantissaWidht + 1) worth of shift in
// we need to accommodate the (mantissaWidth + 1) worth of shift in
// calculating the limit.
int exp_limit = FPBits<T>::MAX_BIASED_EXPONENT + FPBits<T>::FRACTION_LEN + 1;
if (exp > exp_limit)
Expand Down Expand Up @@ -164,26 +164,22 @@ LIBC_INLINE T nextafter(T from, U to) {
return static_cast<T>(to);

using StorageType = typename FPBits<T>::StorageType;
StorageType int_val = from_bits.uintval();
if (from != FPBits<T>::zero()) {
if ((static_cast<U>(from) < to) == (from > FPBits<T>::zero())) {
++int_val;
if (from != T(0)) {
if ((static_cast<U>(from) < to) == (from > T(0))) {
from_bits = FPBits<T>(StorageType(from_bits.uintval() + 1));
} else {
--int_val;
from_bits = FPBits<T>(StorageType(from_bits.uintval() - 1));
}
} else {
int_val = FPBits<T>::MIN_SUBNORMAL;
if (to_bits.is_neg())
int_val |= FPBits<T>::SIGN_MASK;
from_bits = FPBits<T>::min_subnormal(to_bits.sign());
}

StorageType exponent_bits = int_val & FPBits<T>::EXP_MASK;
if (exponent_bits == StorageType(0))
if (from_bits.is_subnormal())
raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
else if (exponent_bits == FPBits<T>::EXP_MASK)
else if (from_bits.is_inf())
raise_except_if_required(FE_OVERFLOW | FE_INEXACT);

return cpp::bit_cast<T>(int_val);
return from_bits.get_val();
}

} // namespace fputil
Expand Down
2 changes: 1 addition & 1 deletion libc/src/__support/FPUtil/NormalFloat.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ template <> LIBC_INLINE NormalFloat<long double>::operator long double() const {
// Max exponent is of the form 0xFF...E. That is why -2 and not -1.
constexpr int MAX_EXPONENT_VALUE = (1 << LDBits::EXP_LEN) - 2;
if (biased_exponent > MAX_EXPONENT_VALUE) {
return LDBits::inf(sign);
return LDBits::inf(sign).get_val();
}

FPBits<long double> result(0.0l);
Expand Down
2 changes: 1 addition & 1 deletion libc/src/__support/FPUtil/dyadic_float.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ template <size_t Bits> struct DyadicFloat {
return 0.0;

// Assume that it is normalized, and output is also normal.
constexpr uint32_t PRECISION = FPBits<T>::MANTISSA_PRECISION;
constexpr uint32_t PRECISION = FPBits<T>::FRACTION_LEN + 1;
using output_bits_t = typename FPBits<T>::StorageType;

int exp_hi = exponent + static_cast<int>((Bits - 1) + FPBits<T>::EXP_BIAS);
Expand Down
6 changes: 2 additions & 4 deletions libc/src/__support/FPUtil/except_value_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,13 @@ template <typename T, size_t N> struct ExceptValues {
// Helper functions to set results for exceptional cases.
template <typename T> LIBC_INLINE T round_result_slightly_down(T value_rn) {
volatile T tmp = value_rn;
const T MIN_NORMAL = FPBits<T>::min_normal();
tmp = tmp - MIN_NORMAL;
tmp -= FPBits<T>::min_normal().get_val();
return tmp;
}

template <typename T> LIBC_INLINE T round_result_slightly_up(T value_rn) {
volatile T tmp = value_rn;
const T MIN_NORMAL = FPBits<T>::min_normal();
tmp = tmp + MIN_NORMAL;
tmp += FPBits<T>::min_normal().get_val();
return tmp;
}

Expand Down
10 changes: 4 additions & 6 deletions libc/src/__support/FPUtil/generic/FMA.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,9 @@ template <> LIBC_INLINE double fma<double>(double x, double y, double z) {
return x * y + z;

// Extract mantissa and append hidden leading bits.
UInt128 x_mant = x_bits.get_mantissa() | FPBits::MIN_NORMAL;
UInt128 y_mant = y_bits.get_mantissa() | FPBits::MIN_NORMAL;
UInt128 z_mant = z_bits.get_mantissa() | FPBits::MIN_NORMAL;
UInt128 x_mant = x_bits.get_explicit_mantissa();
UInt128 y_mant = y_bits.get_explicit_mantissa();
UInt128 z_mant = z_bits.get_explicit_mantissa();

// If the exponent of the product x*y > the exponent of z, then no extra
// precision beside the entire product x*y is needed. On the other hand, when
Expand Down Expand Up @@ -255,9 +255,7 @@ template <> LIBC_INLINE double fma<double>(double x, double y, double z) {
if ((round_mode == FE_TOWARDZERO) ||
(round_mode == FE_UPWARD && prod_sign.is_neg()) ||
(round_mode == FE_DOWNWARD && prod_sign.is_pos())) {
result = FPBits::MAX_NORMAL;
return prod_sign.is_neg() ? -cpp::bit_cast<double>(result)
: cpp::bit_cast<double>(result);
return FPBits::max_normal(prod_sign).get_val();
}
return static_cast<double>(FPBits::inf(prod_sign));
}
Expand Down
2 changes: 1 addition & 1 deletion libc/src/__support/FPUtil/generic/FMod.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ template <typename T> struct FModExceptionalInputHandler {

LIBC_INLINE static bool pre_check(T x, T y, T &out) {
using FPB = fputil::FPBits<T>;
const T quiet_nan = FPB::build_quiet_nan(0);
const T quiet_nan = FPB::build_quiet_nan().get_val();
FPB sx(x), sy(y);
if (LIBC_LIKELY(!sy.is_zero() && !sy.is_inf_or_nan() &&
!sx.is_inf_or_nan())) {
Expand Down
18 changes: 11 additions & 7 deletions libc/src/__support/FPUtil/generic/sqrt.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,19 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> sqrt(T x) {
return x86::sqrt(x);
} else {
// IEEE floating points formats.
using StorageType = typename FPBits<T>::StorageType;
constexpr StorageType ONE = StorageType(1) << FPBits<T>::FRACTION_LEN;
using Sign = fputil::Sign;
using FPBits_t = typename fputil::FPBits<T>;
using StorageType = typename FPBits_t::StorageType;
constexpr StorageType ONE = StorageType(1) << FPBits_t::FRACTION_LEN;
constexpr auto FLT_NAN =
FPBits_t::build_quiet_nan(Sign::POS, ONE >> 1).get_val();

FPBits<T> bits(x);
FPBits_t bits(x);

if (bits.is_inf_or_nan()) {
if (bits.is_neg() && (bits.get_mantissa() == 0)) {
// sqrt(-Inf) = NaN
return FPBits<T>::build_quiet_nan(ONE >> 1);
return FLT_NAN;
} else {
// sqrt(NaN) = NaN
// sqrt(+Inf) = +Inf
Expand All @@ -91,7 +95,7 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> sqrt(T x) {
return x;
} else if (bits.is_neg()) {
// sqrt( negative numbers ) = NaN
return FPBits<T>::build_quiet_nan(ONE >> 1);
return FLT_NAN;
} else {
int x_exp = bits.get_exponent();
StorageType x_mant = bits.get_mantissa();
Expand Down Expand Up @@ -145,10 +149,10 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> sqrt(T x) {
}

// Remove hidden bit and append the exponent field.
x_exp = ((x_exp >> 1) + FPBits<T>::EXP_BIAS);
x_exp = ((x_exp >> 1) + FPBits_t::EXP_BIAS);

y = (y - ONE) |
(static_cast<StorageType>(x_exp) << FPBits<T>::FRACTION_LEN);
(static_cast<StorageType>(x_exp) << FPBits_t::FRACTION_LEN);

switch (quick_get_round()) {
case FE_TONEAREST:
Expand Down
8 changes: 5 additions & 3 deletions libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,16 @@ LIBC_INLINE long double sqrt(long double x);
LIBC_INLINE long double sqrt(long double x) {
using LDBits = FPBits<long double>;
using StorageType = typename LDBits::StorageType;
using Sign = fputil::Sign;
constexpr StorageType ONE = StorageType(1) << int(LDBits::FRACTION_LEN);
constexpr auto LDNAN = LDBits::build_quiet_nan(Sign::POS, ONE >> 1).get_val();

FPBits<long double> bits(x);
LDBits bits(x);

if (bits.is_inf_or_nan()) {
if (bits.is_neg() && (bits.get_mantissa() == 0)) {
// sqrt(-Inf) = NaN
return LDBits::build_quiet_nan(ONE >> 1);
return LDNAN;
} else {
// sqrt(NaN) = NaN
// sqrt(+Inf) = +Inf
Expand All @@ -57,7 +59,7 @@ LIBC_INLINE long double sqrt(long double x) {
return x;
} else if (bits.is_neg()) {
// sqrt( negative numbers ) = NaN
return LDBits::build_quiet_nan(ONE >> 1);
return LDNAN;
} else {
int x_exp = bits.get_explicit_exponent();
StorageType x_mant = bits.get_mantissa();
Expand Down
Loading