[libc-commits] [libc] [libc][NFC] Make EXPONENT_BIAS int32_t (PR #75046)
Guillaume Chatelet via libc-commits
libc-commits at lists.llvm.org
Mon Dec 11 09:02:24 PST 2023
https://github.com/gchatelet updated https://github.com/llvm/llvm-project/pull/75046
>From b14dc0b2adbd2d743ae8188c6c39a0ab8730dcd9 Mon Sep 17 00:00:00 2001
From: Guillaume Chatelet <gchatelet at google.com>
Date: Mon, 11 Dec 2023 12:56:33 +0000
Subject: [PATCH] [libc][NFC] Make EXPONENT_BIAS int32_t
`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).
---
libc/src/__support/FPUtil/FloatProperties.h | 3 +--
libc/src/__support/detailed_powers_of_ten.h | 5 ++--
libc/src/__support/str_to_float.h | 27 ++++++++++-----------
libc/src/math/generic/powf.cpp | 22 +++++++++--------
4 files changed, 29 insertions(+), 28 deletions(-)
diff --git a/libc/src/__support/FPUtil/FloatProperties.h b/libc/src/__support/FPUtil/FloatProperties.h
index ba54e9d1781cab..fa70072eb3dcff 100644
--- a/libc/src/__support/FPUtil/FloatProperties.h
+++ b/libc/src/__support/FPUtil/FloatProperties.h
@@ -163,8 +163,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;
diff --git a/libc/src/__support/detailed_powers_of_ten.h b/libc/src/__support/detailed_powers_of_ten.h
index f9628484bbe609..c8340fda06eed0 100644
--- a/libc/src/__support/detailed_powers_of_ten.h
+++ b/libc/src/__support/detailed_powers_of_ten.h
@@ -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] = {
diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h
index 7ec6b9947ad2b8..79d35682d0b714 100644
--- a/libc/src/__support/str_to_float.h
+++ b/libc/src/__support/str_to_float.h
@@ -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 =
@@ -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;
}
@@ -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 =
@@ -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;
@@ -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; }
@@ -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);
}
diff --git a/libc/src/math/generic/powf.cpp b/libc/src/math/generic/powf.cpp
index 17ccb41fc462aa..efc866618ef219 100644
--- a/libc/src/math/generic/powf.cpp
+++ b/libc/src/math/generic/powf.cpp
@@ -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);
}
More information about the libc-commits
mailing list