Skip to content

Commit

Permalink
[libc][NFC] Make EXPONENT_BIAS int32_t (#75046)
Browse files Browse the repository at this point in the history
`EXPONENT_BIAS` is almost always used with signed arithmetic. Making it
an `int32_t` from the start reduces the chances to run into
implementation defined behavior (cast from unsigned to signed is
implementation-defined until C++20).


https://en.cppreference.com/w/cpp/language/implicit_conversion#:~:text=If%20the%20destination%20type%20is%20signed,arithmetic%20overflow%2C%20which%20is%20undefined).
  • Loading branch information
gchatelet committed Dec 12, 2023
1 parent 6ab663b commit b00e445
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 28 deletions.
3 changes: 1 addition & 2 deletions libc/src/__support/FPUtil/FloatProperties.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,7 @@ struct FPCommonProperties : private FPBaseProperties<fp_type> {
LIBC_INLINE_VAR static constexpr BitsType MANTISSA_MASK =
mask_trailing_ones<UIntType, MANTISSA_WIDTH>();
LIBC_INLINE_VAR static constexpr uint32_t EXPONENT_WIDTH = EXP_BITS;
LIBC_INLINE_VAR static constexpr uint32_t EXPONENT_BIAS =
static_cast<uint32_t>(EXP_BIAS);
LIBC_INLINE_VAR static constexpr int32_t EXPONENT_BIAS = EXP_BIAS;
LIBC_INLINE_VAR static constexpr BitsType SIGN_MASK = SIGN_MASK_;
LIBC_INLINE_VAR static constexpr BitsType EXPONENT_MASK = EXP_MASK;
LIBC_INLINE_VAR static constexpr BitsType EXP_MANT_MASK = EXP_MASK | SIG_MASK;
Expand Down
5 changes: 3 additions & 2 deletions libc/src/__support/detailed_powers_of_ten.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ constexpr int32_t DETAILED_POWERS_OF_TEN_MIN_EXP_10 = -348;
constexpr int32_t DETAILED_POWERS_OF_TEN_MAX_EXP_10 = 347;

// This rescales the base 10 exponent by a factor of log(10)/log(2).
LIBC_INLINE int64_t exp10_to_exp2(int64_t exp10) {
return (217706 * exp10) >> 16;
LIBC_INLINE int32_t exp10_to_exp2(int32_t exp10) {
// Valid if exp10 < 646 456 636.
return static_cast<int32_t>((217706 * static_cast<int64_t>(exp10)) >> 16);
}

static constexpr uint64_t DETAILED_POWERS_OF_TEN[696][2] = {
Expand Down
27 changes: 13 additions & 14 deletions libc/src/__support/str_to_float.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ eisel_lemire(ExpandedFloat<T> init_num,
uint32_t clz = cpp::countl_zero<UIntType>(mantissa);
mantissa <<= clz;

uint32_t exp2 = static_cast<uint32_t>(exp10_to_exp2(exp10)) +
BITS_IN_MANTISSA + FloatProp::EXPONENT_BIAS - clz;
int32_t exp2 =
exp10_to_exp2(exp10) + BITS_IN_MANTISSA + FloatProp::EXPONENT_BIAS - clz;

// Multiplication
const uint64_t *power_of_ten =
Expand Down Expand Up @@ -168,7 +168,7 @@ eisel_lemire(ExpandedFloat<T> init_num,

// The if block is equivalent to (but has fewer branches than):
// if exp2 <= 0 || exp2 >= 0x7FF { etc }
if (exp2 - 1 >= (1 << FloatProp::EXPONENT_WIDTH) - 2) {
if (static_cast<uint32_t>(exp2) - 1 >= (1 << FloatProp::EXPONENT_WIDTH) - 2) {
return cpp::nullopt;
}

Expand Down Expand Up @@ -211,8 +211,8 @@ eisel_lemire<long double>(ExpandedFloat<long double> init_num,
uint32_t clz = cpp::countl_zero<UIntType>(mantissa);
mantissa <<= clz;

uint32_t exp2 = static_cast<uint32_t>(exp10_to_exp2(exp10)) +
BITS_IN_MANTISSA + FloatProp::EXPONENT_BIAS - clz;
int32_t exp2 =
exp10_to_exp2(exp10) + BITS_IN_MANTISSA + FloatProp::EXPONENT_BIAS - clz;

// Multiplication
const uint64_t *power_of_ten =
Expand Down Expand Up @@ -338,17 +338,16 @@ simple_decimal_conversion(const char *__restrict numStart,
// If the exponent is too large and can't be represented in this size of
// float, return inf.
if (hpd.get_decimal_point() > 0 &&
exp10_to_exp2(hpd.get_decimal_point() - 1) >
static_cast<int64_t>(FloatProp::EXPONENT_BIAS)) {
output.num = {0, FPBits::MAX_EXPONENT};
exp10_to_exp2(hpd.get_decimal_point() - 1) > FloatProp::EXPONENT_BIAS) {
output.num = {0, fputil::FPBits<T>::MAX_EXPONENT};
output.error = ERANGE;
return output;
}
// If the exponent is too small even for a subnormal, return 0.
if (hpd.get_decimal_point() < 0 &&
exp10_to_exp2(-hpd.get_decimal_point()) >
static_cast<int64_t>(FloatProp::EXPONENT_BIAS +
FloatProp::MANTISSA_WIDTH)) {
(FloatProp::EXPONENT_BIAS +
static_cast<int32_t>(FloatProp::MANTISSA_WIDTH))) {
output.num = {0, 0};
output.error = ERANGE;
return output;
Expand Down Expand Up @@ -607,7 +606,7 @@ clinger_fast_path(ExpandedFloat<T> init_num,
// log10(2^(exponent bias)).
// The generic approximation uses the fact that log10(2^x) ~= x/3
template <typename T> constexpr int32_t get_upper_bound() {
return static_cast<int32_t>(fputil::FloatProperties<T>::EXPONENT_BIAS) / 3;
return fputil::FloatProperties<T>::EXPONENT_BIAS / 3;
}

template <> constexpr int32_t get_upper_bound<float>() { return 39; }
Expand All @@ -623,9 +622,9 @@ template <> constexpr int32_t get_upper_bound<double>() { return 309; }
// other out, and subnormal numbers allow for the result to be at the very low
// end of the final mantissa.
template <typename T> constexpr int32_t get_lower_bound() {
return -(static_cast<int32_t>(fputil::FloatProperties<T>::EXPONENT_BIAS +
fputil::FloatProperties<T>::MANTISSA_WIDTH +
(sizeof(T) * 8)) /
return -((fputil::FloatProperties<T>::EXPONENT_BIAS +
static_cast<int32_t>(fputil::FloatProperties<T>::MANTISSA_WIDTH +
(sizeof(T) * 8))) /
3);
}

Expand Down
22 changes: 12 additions & 10 deletions libc/src/math/generic/powf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -389,22 +389,24 @@ static constexpr DoubleDouble LOG2_R2_DD[] = {
LIBC_INLINE bool is_odd_integer(float x) {
using FloatProp = typename fputil::FloatProperties<float>;
uint32_t x_u = cpp::bit_cast<uint32_t>(x);
int x_e = static_cast<int>((x_u & FloatProp::EXPONENT_MASK) >>
FloatProp::MANTISSA_WIDTH);
int lsb = cpp::countr_zero(x_u | FloatProp::EXPONENT_MASK);
constexpr int UNIT_EXPONENT =
static_cast<int>(FloatProp::EXPONENT_BIAS + FloatProp::MANTISSA_WIDTH);
int32_t x_e = static_cast<int32_t>((x_u & FloatProp::EXPONENT_MASK) >>
FloatProp::MANTISSA_WIDTH);
int32_t lsb = cpp::countr_zero(x_u | FloatProp::EXPONENT_MASK);
constexpr int32_t UNIT_EXPONENT =
FloatProp::EXPONENT_BIAS +
static_cast<int32_t>(FloatProp::MANTISSA_WIDTH);
return (x_e + lsb == UNIT_EXPONENT);
}

LIBC_INLINE bool is_integer(float x) {
using FloatProp = typename fputil::FloatProperties<float>;
uint32_t x_u = cpp::bit_cast<uint32_t>(x);
int x_e = static_cast<int>((x_u & FloatProp::EXPONENT_MASK) >>
FloatProp::MANTISSA_WIDTH);
int lsb = cpp::countr_zero(x_u | FloatProp::EXPONENT_MASK);
constexpr int UNIT_EXPONENT =
static_cast<int>(FloatProp::EXPONENT_BIAS + FloatProp::MANTISSA_WIDTH);
int32_t x_e = static_cast<int32_t>((x_u & FloatProp::EXPONENT_MASK) >>
FloatProp::MANTISSA_WIDTH);
int32_t lsb = cpp::countr_zero(x_u | FloatProp::EXPONENT_MASK);
constexpr int32_t UNIT_EXPONENT =
FloatProp::EXPONENT_BIAS +
static_cast<int32_t>(FloatProp::MANTISSA_WIDTH);
return (x_e + lsb >= UNIT_EXPONENT);
}

Expand Down

0 comments on commit b00e445

Please sign in to comment.