[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