Skip to content

Commit b00e445

Browse files
authored
[libc][NFC] Make EXPONENT_BIAS int32_t (#75046)
`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).
1 parent 6ab663b commit b00e445

File tree

4 files changed

+29
-28
lines changed

4 files changed

+29
-28
lines changed

libc/src/__support/FPUtil/FloatProperties.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,7 @@ struct FPCommonProperties : private FPBaseProperties<fp_type> {
165165
LIBC_INLINE_VAR static constexpr BitsType MANTISSA_MASK =
166166
mask_trailing_ones<UIntType, MANTISSA_WIDTH>();
167167
LIBC_INLINE_VAR static constexpr uint32_t EXPONENT_WIDTH = EXP_BITS;
168-
LIBC_INLINE_VAR static constexpr uint32_t EXPONENT_BIAS =
169-
static_cast<uint32_t>(EXP_BIAS);
168+
LIBC_INLINE_VAR static constexpr int32_t EXPONENT_BIAS = EXP_BIAS;
170169
LIBC_INLINE_VAR static constexpr BitsType SIGN_MASK = SIGN_MASK_;
171170
LIBC_INLINE_VAR static constexpr BitsType EXPONENT_MASK = EXP_MASK;
172171
LIBC_INLINE_VAR static constexpr BitsType EXP_MANT_MASK = EXP_MASK | SIG_MASK;

libc/src/__support/detailed_powers_of_ten.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ constexpr int32_t DETAILED_POWERS_OF_TEN_MIN_EXP_10 = -348;
2929
constexpr int32_t DETAILED_POWERS_OF_TEN_MAX_EXP_10 = 347;
3030

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

3637
static constexpr uint64_t DETAILED_POWERS_OF_TEN[696][2] = {

libc/src/__support/str_to_float.h

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ eisel_lemire(ExpandedFloat<T> init_num,
9494
uint32_t clz = cpp::countl_zero<UIntType>(mantissa);
9595
mantissa <<= clz;
9696

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

100100
// Multiplication
101101
const uint64_t *power_of_ten =
@@ -168,7 +168,7 @@ eisel_lemire(ExpandedFloat<T> init_num,
168168

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

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

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

217217
// Multiplication
218218
const uint64_t *power_of_ten =
@@ -338,17 +338,16 @@ simple_decimal_conversion(const char *__restrict numStart,
338338
// If the exponent is too large and can't be represented in this size of
339339
// float, return inf.
340340
if (hpd.get_decimal_point() > 0 &&
341-
exp10_to_exp2(hpd.get_decimal_point() - 1) >
342-
static_cast<int64_t>(FloatProp::EXPONENT_BIAS)) {
343-
output.num = {0, FPBits::MAX_EXPONENT};
341+
exp10_to_exp2(hpd.get_decimal_point() - 1) > FloatProp::EXPONENT_BIAS) {
342+
output.num = {0, fputil::FPBits<T>::MAX_EXPONENT};
344343
output.error = ERANGE;
345344
return output;
346345
}
347346
// If the exponent is too small even for a subnormal, return 0.
348347
if (hpd.get_decimal_point() < 0 &&
349348
exp10_to_exp2(-hpd.get_decimal_point()) >
350-
static_cast<int64_t>(FloatProp::EXPONENT_BIAS +
351-
FloatProp::MANTISSA_WIDTH)) {
349+
(FloatProp::EXPONENT_BIAS +
350+
static_cast<int32_t>(FloatProp::MANTISSA_WIDTH))) {
352351
output.num = {0, 0};
353352
output.error = ERANGE;
354353
return output;
@@ -607,7 +606,7 @@ clinger_fast_path(ExpandedFloat<T> init_num,
607606
// log10(2^(exponent bias)).
608607
// The generic approximation uses the fact that log10(2^x) ~= x/3
609608
template <typename T> constexpr int32_t get_upper_bound() {
610-
return static_cast<int32_t>(fputil::FloatProperties<T>::EXPONENT_BIAS) / 3;
609+
return fputil::FloatProperties<T>::EXPONENT_BIAS / 3;
611610
}
612611

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

libc/src/math/generic/powf.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -389,22 +389,24 @@ static constexpr DoubleDouble LOG2_R2_DD[] = {
389389
LIBC_INLINE bool is_odd_integer(float x) {
390390
using FloatProp = typename fputil::FloatProperties<float>;
391391
uint32_t x_u = cpp::bit_cast<uint32_t>(x);
392-
int x_e = static_cast<int>((x_u & FloatProp::EXPONENT_MASK) >>
393-
FloatProp::MANTISSA_WIDTH);
394-
int lsb = cpp::countr_zero(x_u | FloatProp::EXPONENT_MASK);
395-
constexpr int UNIT_EXPONENT =
396-
static_cast<int>(FloatProp::EXPONENT_BIAS + FloatProp::MANTISSA_WIDTH);
392+
int32_t x_e = static_cast<int32_t>((x_u & FloatProp::EXPONENT_MASK) >>
393+
FloatProp::MANTISSA_WIDTH);
394+
int32_t lsb = cpp::countr_zero(x_u | FloatProp::EXPONENT_MASK);
395+
constexpr int32_t UNIT_EXPONENT =
396+
FloatProp::EXPONENT_BIAS +
397+
static_cast<int32_t>(FloatProp::MANTISSA_WIDTH);
397398
return (x_e + lsb == UNIT_EXPONENT);
398399
}
399400

400401
LIBC_INLINE bool is_integer(float x) {
401402
using FloatProp = typename fputil::FloatProperties<float>;
402403
uint32_t x_u = cpp::bit_cast<uint32_t>(x);
403-
int x_e = static_cast<int>((x_u & FloatProp::EXPONENT_MASK) >>
404-
FloatProp::MANTISSA_WIDTH);
405-
int lsb = cpp::countr_zero(x_u | FloatProp::EXPONENT_MASK);
406-
constexpr int UNIT_EXPONENT =
407-
static_cast<int>(FloatProp::EXPONENT_BIAS + FloatProp::MANTISSA_WIDTH);
404+
int32_t x_e = static_cast<int32_t>((x_u & FloatProp::EXPONENT_MASK) >>
405+
FloatProp::MANTISSA_WIDTH);
406+
int32_t lsb = cpp::countr_zero(x_u | FloatProp::EXPONENT_MASK);
407+
constexpr int32_t UNIT_EXPONENT =
408+
FloatProp::EXPONENT_BIAS +
409+
static_cast<int32_t>(FloatProp::MANTISSA_WIDTH);
408410
return (x_e + lsb >= UNIT_EXPONENT);
409411
}
410412

0 commit comments

Comments
 (0)