[libc-commits] [libc] [libc][NFC] Remove custom leading_zeroes, factor in frequent typenames (PR #74825)

Guillaume Chatelet via libc-commits libc-commits at lists.llvm.org
Fri Dec 8 03:15:15 PST 2023


https://github.com/gchatelet created https://github.com/llvm/llvm-project/pull/74825

None

>From 1d351c71c3618b9321c4897b2ee5a06de369c9f1 Mon Sep 17 00:00:00 2001
From: Guillaume Chatelet <gchatelet at google.com>
Date: Fri, 8 Dec 2023 11:14:31 +0000
Subject: [PATCH] [libc][NFC] Remove custom leading_zeroes, factor in frequent
 typenames

---
 libc/src/__support/str_to_float.h             | 262 ++++++++----------
 libc/test/src/__support/str_to_float_test.cpp |  39 ---
 2 files changed, 111 insertions(+), 190 deletions(-)

diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h
index ad73e93f6faa81..cf5f7f1c5516af 100644
--- a/libc/src/__support/str_to_float.h
+++ b/libc/src/__support/str_to_float.h
@@ -37,45 +37,6 @@ template <class T> struct FloatConvertReturn {
   int error = 0;
 };
 
-template <class T> LIBC_INLINE uint32_t leading_zeroes(T inputNumber) {
-  constexpr uint32_t BITS_IN_T = sizeof(T) * 8;
-  if (inputNumber == 0) {
-    return BITS_IN_T;
-  }
-  uint32_t cur_guess = BITS_IN_T / 2;
-  uint32_t range_size = BITS_IN_T / 2;
-  // while either shifting by curGuess does not get rid of all of the bits or
-  // shifting by one less also gets rid of all of the bits then we have not
-  // found the first bit.
-  while (((inputNumber >> cur_guess) > 0) ||
-         ((inputNumber >> (cur_guess - 1)) == 0)) {
-    // Binary search for the first set bit
-    range_size /= 2;
-    if (range_size == 0) {
-      break;
-    }
-    if ((inputNumber >> cur_guess) > 0) {
-      cur_guess += range_size;
-    } else {
-      cur_guess -= range_size;
-    }
-  }
-  if (inputNumber >> cur_guess > 0) {
-    cur_guess++;
-  }
-  return BITS_IN_T - cur_guess;
-}
-
-template <>
-LIBC_INLINE uint32_t leading_zeroes<uint32_t>(uint32_t inputNumber) {
-  return cpp::countl_zero(inputNumber);
-}
-
-template <>
-LIBC_INLINE uint32_t leading_zeroes<uint64_t>(uint64_t inputNumber) {
-  return cpp::countl_zero(inputNumber);
-}
-
 LIBC_INLINE uint64_t low64(const UInt128 &num) {
   return static_cast<uint64_t>(num & 0xffffffffffffffff);
 }
@@ -108,10 +69,11 @@ template <class T>
 LIBC_INLINE cpp::optional<ExpandedFloat<T>>
 eisel_lemire(ExpandedFloat<T> init_num,
              RoundDirection round = RoundDirection::Nearest) {
+  using FPBits = typename fputil::FPBits<T>;
+  using FloatProp = typename FPBits::FloatProp;
+  using UIntType = typename FPBits::UIntType;
 
-  using BitsType = typename fputil::FPBits<T>::UIntType;
-
-  BitsType mantissa = init_num.mantissa;
+  UIntType mantissa = init_num.mantissa;
   int32_t exp10 = init_num.exponent;
 
   constexpr uint32_t BITS_IN_MANTISSA = sizeof(mantissa) * 8;
@@ -128,12 +90,11 @@ eisel_lemire(ExpandedFloat<T> init_num,
   }
 
   // Normalization
-  uint32_t clz = leading_zeroes<BitsType>(mantissa);
+  uint32_t clz = cpp::countl_zero<UIntType>(mantissa);
   mantissa <<= clz;
 
   uint32_t exp2 = static_cast<uint32_t>(exp10_to_exp2(exp10)) +
-                  BITS_IN_MANTISSA + fputil::FloatProperties<T>::EXPONENT_BIAS -
-                  clz;
+                  BITS_IN_MANTISSA + FloatProp::EXPONENT_BIAS - clz;
 
   // Multiplication
   const uint64_t *power_of_ten =
@@ -150,9 +111,7 @@ eisel_lemire(ExpandedFloat<T> init_num,
   // accuracy, and the most significant bit is ignored.) = 9 bits. Similarly,
   // it's 6 bits for floats in this case.
   const uint64_t halfway_constant =
-      (uint64_t(1) << (BITS_IN_MANTISSA -
-                       fputil::FloatProperties<T>::MANTISSA_WIDTH - 3)) -
-      1;
+      (uint64_t(1) << (BITS_IN_MANTISSA - FloatProp::MANTISSA_WIDTH - 3)) - 1;
   if ((high64(first_approx) & halfway_constant) == halfway_constant &&
       low64(first_approx) + mantissa < mantissa) {
     UInt128 low_bits =
@@ -171,12 +130,11 @@ eisel_lemire(ExpandedFloat<T> init_num,
   }
 
   // Shifting to 54 bits for doubles and 25 bits for floats
-  BitsType msb =
-      static_cast<BitsType>(high64(final_approx) >> (BITS_IN_MANTISSA - 1));
-  BitsType final_mantissa =
-      static_cast<BitsType>(high64(final_approx) >>
-                            (msb + BITS_IN_MANTISSA -
-                             (fputil::FloatProperties<T>::MANTISSA_WIDTH + 3)));
+  UIntType msb =
+      static_cast<UIntType>(high64(final_approx) >> (BITS_IN_MANTISSA - 1));
+  UIntType final_mantissa = static_cast<UIntType>(
+      high64(final_approx) >>
+      (msb + BITS_IN_MANTISSA - (FloatProp::MANTISSA_WIDTH + 3)));
   exp2 -= static_cast<uint32_t>(1 ^ msb); // same as !msb
 
   if (round == RoundDirection::Nearest) {
@@ -202,15 +160,14 @@ eisel_lemire(ExpandedFloat<T> init_num,
 
   // From 54 to 53 bits for doubles and 25 to 24 bits for floats
   final_mantissa >>= 1;
-  if ((final_mantissa >> (fputil::FloatProperties<T>::MANTISSA_WIDTH + 1)) >
-      0) {
+  if ((final_mantissa >> (FloatProp::MANTISSA_WIDTH + 1)) > 0) {
     final_mantissa >>= 1;
     ++exp2;
   }
 
   // The if block is equivalent to (but has fewer branches than):
   //   if exp2 <= 0 || exp2 >= 0x7FF { etc }
-  if (exp2 - 1 >= (1 << fputil::FloatProperties<T>::EXPONENT_WIDTH) - 2) {
+  if (exp2 - 1 >= (1 << FloatProp::EXPONENT_WIDTH) - 2) {
     return cpp::nullopt;
   }
 
@@ -225,9 +182,11 @@ template <>
 LIBC_INLINE cpp::optional<ExpandedFloat<long double>>
 eisel_lemire<long double>(ExpandedFloat<long double> init_num,
                           RoundDirection round) {
-  using BitsType = typename fputil::FPBits<long double>::UIntType;
+  using FPBits = typename fputil::FPBits<long double>;
+  using FloatProp = typename FPBits::FloatProp;
+  using UIntType = typename FPBits::UIntType;
 
-  BitsType mantissa = init_num.mantissa;
+  UIntType mantissa = init_num.mantissa;
   int32_t exp10 = init_num.exponent;
 
   constexpr uint32_t BITS_IN_MANTISSA = sizeof(mantissa) * 8;
@@ -248,12 +207,11 @@ eisel_lemire<long double>(ExpandedFloat<long double> init_num,
   }
 
   // Normalization
-  uint32_t clz = leading_zeroes<BitsType>(mantissa);
+  uint32_t clz = cpp::countl_zero<UIntType>(mantissa);
   mantissa <<= clz;
 
   uint32_t exp2 = static_cast<uint32_t>(exp10_to_exp2(exp10)) +
-                  BITS_IN_MANTISSA +
-                  fputil::FloatProperties<long double>::EXPONENT_BIAS - clz;
+                  BITS_IN_MANTISSA + FloatProp::EXPONENT_BIAS - clz;
 
   // Multiplication
   const uint64_t *power_of_ten =
@@ -290,10 +248,7 @@ eisel_lemire<long double>(ExpandedFloat<long double> init_num,
   // accuracy, and the most significant bit is ignored.) = 61 bits. Similarly,
   // it's 12 bits for 128 bit floats in this case.
   constexpr UInt128 HALFWAY_CONSTANT =
-      (UInt128(1) << (BITS_IN_MANTISSA -
-                      fputil::FloatProperties<long double>::MANTISSA_WIDTH -
-                      3)) -
-      1;
+      (UInt128(1) << (BITS_IN_MANTISSA - (FloatProp::MANTISSA_WIDTH + 3))) - 1;
 
   if ((final_approx_upper & HALFWAY_CONSTANT) == HALFWAY_CONSTANT &&
       final_approx_lower + mantissa < mantissa) {
@@ -303,10 +258,9 @@ eisel_lemire<long double>(ExpandedFloat<long double> init_num,
   // Shifting to 65 bits for 80 bit floats and 113 bits for 128 bit floats
   uint32_t msb =
       static_cast<uint32_t>(final_approx_upper >> (BITS_IN_MANTISSA - 1));
-  BitsType final_mantissa =
+  UIntType final_mantissa =
       final_approx_upper >>
-      (msb + BITS_IN_MANTISSA -
-       (fputil::FloatProperties<long double>::MANTISSA_WIDTH + 3));
+      (msb + BITS_IN_MANTISSA - (FloatProp::MANTISSA_WIDTH + 3));
   exp2 -= static_cast<uint32_t>(1 ^ msb); // same as !msb
 
   if (round == RoundDirection::Nearest) {
@@ -331,16 +285,14 @@ eisel_lemire<long double>(ExpandedFloat<long double> init_num,
   // From 65 to 64 bits for 80 bit floats and 113  to 112 bits for 128 bit
   // floats
   final_mantissa >>= 1;
-  if ((final_mantissa >>
-       (fputil::FloatProperties<long double>::MANTISSA_WIDTH + 1)) > 0) {
+  if ((final_mantissa >> (FloatProp::MANTISSA_WIDTH + 1)) > 0) {
     final_mantissa >>= 1;
     ++exp2;
   }
 
   // The if block is equivalent to (but has fewer branches than):
   //   if exp2 <= 0 || exp2 >= MANTISSA_MAX { etc }
-  if (exp2 - 1 >=
-      (1 << fputil::FloatProperties<long double>::EXPONENT_WIDTH) - 2) {
+  if (exp2 - 1 >= (1 << FloatProp::EXPONENT_WIDTH) - 2) {
     return cpp::nullopt;
   }
 
@@ -368,6 +320,9 @@ template <class T>
 LIBC_INLINE FloatConvertReturn<T>
 simple_decimal_conversion(const char *__restrict numStart,
                           RoundDirection round = RoundDirection::Nearest) {
+  using FPBits = typename fputil::FPBits<T>;
+  using FloatProp = typename FPBits::FloatProp;
+  using UIntType = typename FPBits::UIntType;
 
   int32_t exp2 = 0;
   HighPrecisionDecimal hpd = HighPrecisionDecimal(numStart);
@@ -383,16 +338,16 @@ simple_decimal_conversion(const char *__restrict numStart,
   // float, return inf.
   if (hpd.get_decimal_point() > 0 &&
       exp10_to_exp2(hpd.get_decimal_point() - 1) >
-          static_cast<int64_t>(fputil::FloatProperties<T>::EXPONENT_BIAS)) {
-    output.num = {0, fputil::FPBits<T>::MAX_EXPONENT};
+          static_cast<int64_t>(FloatProp::EXPONENT_BIAS)) {
+    output.num = {0, FPBits::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>(fputil::FloatProperties<T>::EXPONENT_BIAS +
-                               fputil::FloatProperties<T>::MANTISSA_WIDTH)) {
+          static_cast<int64_t>(FloatProp::EXPONENT_BIAS +
+                               FloatProp::MANTISSA_WIDTH)) {
     output.num = {0, 0};
     output.error = ERANGE;
     return output;
@@ -431,19 +386,18 @@ simple_decimal_conversion(const char *__restrict numStart,
   hpd.shift(1);
 
   // Get the biased exponent
-  exp2 += fputil::FloatProperties<T>::EXPONENT_BIAS;
+  exp2 += FloatProp::EXPONENT_BIAS;
 
   // Handle the exponent being too large (and return inf).
-  if (exp2 >= fputil::FPBits<T>::MAX_EXPONENT) {
-    output.num = {0, fputil::FPBits<T>::MAX_EXPONENT};
+  if (exp2 >= FPBits::MAX_EXPONENT) {
+    output.num = {0, FPBits::MAX_EXPONENT};
     output.error = ERANGE;
     return output;
   }
 
   // Shift left to fill the mantissa
-  hpd.shift(fputil::FloatProperties<T>::MANTISSA_WIDTH);
-  typename fputil::FPBits<T>::UIntType final_mantissa =
-      hpd.round_to_integer_type<typename fputil::FPBits<T>::UIntType>();
+  hpd.shift(FloatProp::MANTISSA_WIDTH);
+  UIntType final_mantissa = hpd.round_to_integer_type<UIntType>();
 
   // Handle subnormals
   if (exp2 <= 0) {
@@ -455,25 +409,23 @@ simple_decimal_conversion(const char *__restrict numStart,
     // Shift right one more time to compensate for the left shift to get it
     // between 1 and 2.
     hpd.shift(-1);
-    final_mantissa =
-        hpd.round_to_integer_type<typename fputil::FPBits<T>::UIntType>(round);
+    final_mantissa = hpd.round_to_integer_type<UIntType>(round);
 
     // Check if by shifting right we've caused this to round to a normal number.
-    if ((final_mantissa >> fputil::FloatProperties<T>::MANTISSA_WIDTH) != 0) {
+    if ((final_mantissa >> FloatProp::MANTISSA_WIDTH) != 0) {
       ++exp2;
     }
   }
 
   // Check if rounding added a bit, and shift down if that's the case.
-  if (final_mantissa == typename fputil::FPBits<T>::UIntType(2)
-                            << fputil::FloatProperties<T>::MANTISSA_WIDTH) {
+  if (final_mantissa == UIntType(2) << FloatProp::MANTISSA_WIDTH) {
     final_mantissa >>= 1;
     ++exp2;
 
     // Check if this rounding causes exp2 to go out of range and make the result
     // INF. If this is the case, then finalMantissa and exp2 are already the
     // correct values for an INF result.
-    if (exp2 >= fputil::FPBits<T>::MAX_EXPONENT) {
+    if (exp2 >= FPBits::MAX_EXPONENT) {
       output.error = ERANGE;
     }
   }
@@ -563,18 +515,20 @@ template <class T>
 LIBC_INLINE cpp::optional<ExpandedFloat<T>>
 clinger_fast_path(ExpandedFloat<T> init_num,
                   RoundDirection round = RoundDirection::Nearest) {
+  using FPBits = typename fputil::FPBits<T>;
+  using FloatProp = typename FPBits::FloatProp;
+  using UIntType = typename FPBits::UIntType;
 
-  typename fputil::FPBits<T>::UIntType mantissa = init_num.mantissa;
+  UIntType mantissa = init_num.mantissa;
   int32_t exp10 = init_num.exponent;
 
-  if (mantissa >> fputil::FloatProperties<T>::MANTISSA_WIDTH > 0) {
+  if ((mantissa >> FloatProp::MANTISSA_WIDTH) > 0) {
     return cpp::nullopt;
   }
 
-  fputil::FPBits<T> result;
+  FPBits result;
   T float_mantissa;
-  if constexpr (cpp::is_same_v<typename fputil::FPBits<T>::UIntType,
-                               cpp::UInt<128>>) {
+  if constexpr (cpp::is_same_v<UIntType, cpp::UInt<128>>) {
     float_mantissa = static_cast<T>(fputil::DyadicFloat<128>(
         false, 0,
         fputil::DyadicFloat<128>::MantissaType(
@@ -584,7 +538,7 @@ clinger_fast_path(ExpandedFloat<T> init_num,
   }
 
   if (exp10 == 0) {
-    result = fputil::FPBits<T>(float_mantissa);
+    result = FPBits(float_mantissa);
   }
   if (exp10 > 0) {
     if (exp10 > ClingerConsts<T>::EXACT_POWERS_OF_TEN +
@@ -600,14 +554,14 @@ clinger_fast_path(ExpandedFloat<T> init_num,
     if (float_mantissa > ClingerConsts<T>::MAX_EXACT_INT) {
       return cpp::nullopt;
     }
-    result = fputil::FPBits<T>(float_mantissa *
-                               ClingerConsts<T>::POWERS_OF_TEN_ARRAY[exp10]);
+    result =
+        FPBits(float_mantissa * ClingerConsts<T>::POWERS_OF_TEN_ARRAY[exp10]);
   } else if (exp10 < 0) {
     if (-exp10 > ClingerConsts<T>::EXACT_POWERS_OF_TEN) {
       return cpp::nullopt;
     }
-    result = fputil::FPBits<T>(float_mantissa /
-                               ClingerConsts<T>::POWERS_OF_TEN_ARRAY[-exp10]);
+    result =
+        FPBits(float_mantissa / ClingerConsts<T>::POWERS_OF_TEN_ARRAY[-exp10]);
   }
 
   // If the rounding mode is not nearest, then the sign of the number may affect
@@ -615,15 +569,15 @@ clinger_fast_path(ExpandedFloat<T> init_num,
   // calculation is redone with a negative result, and the rounding mode is used
   // to select the correct result.
   if (round != RoundDirection::Nearest) {
-    fputil::FPBits<T> negative_result;
+    FPBits negative_result;
     // I'm 99% sure this will break under fast math optimizations.
-    negative_result = fputil::FPBits<T>(
-        (-float_mantissa) * ClingerConsts<T>::POWERS_OF_TEN_ARRAY[exp10]);
+    negative_result = FPBits((-float_mantissa) *
+                             ClingerConsts<T>::POWERS_OF_TEN_ARRAY[exp10]);
 
     // If the results are equal, then we don't need to use the rounding mode.
     if (T(result) != -T(negative_result)) {
-      fputil::FPBits<T> lower_result;
-      fputil::FPBits<T> higher_result;
+      FPBits lower_result;
+      FPBits higher_result;
 
       if (T(result) < -T(negative_result)) {
         lower_result = result;
@@ -691,8 +645,10 @@ template <class T>
 LIBC_INLINE FloatConvertReturn<T>
 decimal_exp_to_float(ExpandedFloat<T> init_num, const char *__restrict numStart,
                      bool truncated, RoundDirection round) {
+  using FPBits = typename fputil::FPBits<T>;
+  using UIntType = typename FPBits::UIntType;
 
-  typename fputil::FPBits<T>::UIntType mantissa = init_num.mantissa;
+  UIntType mantissa = init_num.mantissa;
   int32_t exp10 = init_num.exponent;
 
   FloatConvertReturn<T> output;
@@ -702,7 +658,7 @@ decimal_exp_to_float(ExpandedFloat<T> init_num, const char *__restrict numStart,
   // float, return inf. These bounds are relatively loose, but are mostly
   // serving as a first pass. Some close numbers getting through is okay.
   if (exp10 > get_upper_bound<T>()) {
-    output.num = {0, fputil::FPBits<T>::MAX_EXPONENT};
+    output.num = {0, FPBits::MAX_EXPONENT};
     output.error = ERANGE;
     return output;
   }
@@ -766,40 +722,39 @@ template <class T>
 LIBC_INLINE FloatConvertReturn<T> binary_exp_to_float(ExpandedFloat<T> init_num,
                                                       bool truncated,
                                                       RoundDirection round) {
-  using BitsType = typename fputil::FPBits<T>::UIntType;
+  using FPBits = typename fputil::FPBits<T>;
+  using FloatProp = typename FPBits::FloatProp;
+  using UIntType = typename FPBits::UIntType;
 
-  BitsType mantissa = init_num.mantissa;
+  UIntType mantissa = init_num.mantissa;
   int32_t exp2 = init_num.exponent;
 
   FloatConvertReturn<T> output;
 
   // This is the number of leading zeroes a properly normalized float of type T
   // should have.
-  constexpr int32_t NUMBITS = sizeof(BitsType) * 8;
-  constexpr int32_t INF_EXP =
-      (1 << fputil::FloatProperties<T>::EXPONENT_WIDTH) - 1;
+  constexpr int32_t NUMBITS = sizeof(UIntType) * 8;
+  constexpr int32_t INF_EXP = (1 << FloatProp::EXPONENT_WIDTH) - 1;
 
-  // Normalization step 1: Bring the leading bit to the highest bit of BitsType.
-  uint32_t amount_to_shift_left = leading_zeroes<BitsType>(mantissa);
+  // Normalization step 1: Bring the leading bit to the highest bit of UIntType.
+  uint32_t amount_to_shift_left = cpp::countl_zero<UIntType>(mantissa);
   mantissa <<= amount_to_shift_left;
 
-  // Keep exp2 representing the exponent of the lowest bit of BitsType.
+  // Keep exp2 representing the exponent of the lowest bit of UIntType.
   exp2 -= amount_to_shift_left;
 
   // biasedExponent represents the biased exponent of the most significant bit.
-  int32_t biased_exponent =
-      exp2 + NUMBITS + fputil::FPBits<T>::EXPONENT_BIAS - 1;
+  int32_t biased_exponent = exp2 + NUMBITS + FPBits::EXPONENT_BIAS - 1;
 
   // Handle numbers that're too large and get squashed to inf
   if (biased_exponent >= INF_EXP) {
     // This indicates an overflow, so we make the result INF and set errno.
-    output.num = {0, (1 << fputil::FloatProperties<T>::EXPONENT_WIDTH) - 1};
+    output.num = {0, (1 << FloatProp::EXPONENT_WIDTH) - 1};
     output.error = ERANGE;
     return output;
   }
 
-  uint32_t amount_to_shift_right =
-      NUMBITS - fputil::FloatProperties<T>::MANTISSA_WIDTH - 1;
+  uint32_t amount_to_shift_right = NUMBITS - FloatProp::MANTISSA_WIDTH - 1;
 
   // Handle subnormals.
   if (biased_exponent <= 0) {
@@ -814,19 +769,19 @@ LIBC_INLINE FloatConvertReturn<T> binary_exp_to_float(ExpandedFloat<T> init_num,
     }
   }
 
-  BitsType round_bit_mask = BitsType(1) << (amount_to_shift_right - 1);
-  BitsType sticky_mask = round_bit_mask - 1;
+  UIntType round_bit_mask = UIntType(1) << (amount_to_shift_right - 1);
+  UIntType sticky_mask = round_bit_mask - 1;
   bool round_bit = static_cast<bool>(mantissa & round_bit_mask);
   bool sticky_bit = static_cast<bool>(mantissa & sticky_mask) || truncated;
 
   if (amount_to_shift_right < NUMBITS) {
     // Shift the mantissa and clear the implicit bit.
     mantissa >>= amount_to_shift_right;
-    mantissa &= fputil::FloatProperties<T>::MANTISSA_MASK;
+    mantissa &= FloatProp::MANTISSA_MASK;
   } else {
     mantissa = 0;
   }
-  bool least_significant_bit = static_cast<bool>(mantissa & BitsType(1));
+  bool least_significant_bit = static_cast<bool>(mantissa & UIntType(1));
 
   // TODO: check that this rounding behavior is correct.
 
@@ -845,7 +800,7 @@ LIBC_INLINE FloatConvertReturn<T> binary_exp_to_float(ExpandedFloat<T> init_num,
     }
   }
 
-  if (mantissa > fputil::FloatProperties<T>::MANTISSA_MASK) {
+  if (mantissa > FloatProp::MANTISSA_MASK) {
     // Rounding causes the exponent to increase.
     ++biased_exponent;
 
@@ -858,8 +813,7 @@ LIBC_INLINE FloatConvertReturn<T> binary_exp_to_float(ExpandedFloat<T> init_num,
     output.error = ERANGE;
   }
 
-  output.num = {mantissa & fputil::FloatProperties<T>::MANTISSA_MASK,
-                biased_exponent};
+  output.num = {mantissa & FloatProp::MANTISSA_MASK, biased_exponent};
   return output;
 }
 
@@ -887,14 +841,16 @@ template <class T>
 LIBC_INLINE StrToNumResult<ExpandedFloat<T>>
 decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT,
                         RoundDirection round) {
-  using BitsType = typename fputil::FPBits<T>::UIntType;
+  using FPBits = typename fputil::FPBits<T>;
+  using UIntType = typename FPBits::UIntType;
+
   constexpr uint32_t BASE = 10;
   constexpr char EXPONENT_MARKER = 'e';
 
   bool truncated = false;
   bool seen_digit = false;
   bool after_decimal = false;
-  BitsType mantissa = 0;
+  UIntType mantissa = 0;
   int32_t exponent = 0;
 
   size_t index = 0;
@@ -905,8 +861,8 @@ decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT,
   // the format mantissa * (base ^ exponent)
 
   // The loop fills the mantissa with as many digits as it can hold
-  const BitsType bitstype_max_div_by_base =
-      cpp::numeric_limits<BitsType>::max() / BASE;
+  const UIntType bitstype_max_div_by_base =
+      cpp::numeric_limits<UIntType>::max() / BASE;
   while (true) {
     if (isdigit(src[index])) {
       uint32_t digit = src[index] - '0';
@@ -962,10 +918,10 @@ decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT,
 
       // If the result is in the valid range, then we use it. The valid range is
       // also within the int32 range, so this prevents overflow issues.
-      if (temp_exponent > fputil::FPBits<T>::MAX_EXPONENT) {
-        exponent = fputil::FPBits<T>::MAX_EXPONENT;
-      } else if (temp_exponent < -fputil::FPBits<T>::MAX_EXPONENT) {
-        exponent = -fputil::FPBits<T>::MAX_EXPONENT;
+      if (temp_exponent > FPBits::MAX_EXPONENT) {
+        exponent = FPBits::MAX_EXPONENT;
+      } else if (temp_exponent < -FPBits::MAX_EXPONENT) {
+        exponent = -FPBits::MAX_EXPONENT;
       } else {
         exponent = static_cast<int32_t>(temp_exponent);
       }
@@ -994,14 +950,16 @@ template <class T>
 LIBC_INLINE StrToNumResult<ExpandedFloat<T>>
 hexadecimal_string_to_float(const char *__restrict src,
                             const char DECIMAL_POINT, RoundDirection round) {
-  using BitsType = typename fputil::FPBits<T>::UIntType;
+  using FPBits = typename fputil::FPBits<T>;
+  using UIntType = typename FPBits::UIntType;
+
   constexpr uint32_t BASE = 16;
   constexpr char EXPONENT_MARKER = 'p';
 
   bool truncated = false;
   bool seen_digit = false;
   bool after_decimal = false;
-  BitsType mantissa = 0;
+  UIntType mantissa = 0;
   int32_t exponent = 0;
 
   size_t index = 0;
@@ -1012,8 +970,8 @@ hexadecimal_string_to_float(const char *__restrict src,
   // the format mantissa * (base ^ exponent)
 
   // The loop fills the mantissa with as many digits as it can hold
-  const BitsType bitstype_max_div_by_base =
-      cpp::numeric_limits<BitsType>::max() / BASE;
+  const UIntType bitstype_max_div_by_base =
+      cpp::numeric_limits<UIntType>::max() / BASE;
   while (true) {
     if (isalnum(src[index])) {
       uint32_t digit = b36_char_to_int(src[index]);
@@ -1074,10 +1032,10 @@ hexadecimal_string_to_float(const char *__restrict src,
 
       // If the result is in the valid range, then we use it. The valid range is
       // also within the int32 range, so this prevents overflow issues.
-      if (temp_exponent > fputil::FPBits<T>::MAX_EXPONENT) {
-        exponent = fputil::FPBits<T>::MAX_EXPONENT;
-      } else if (temp_exponent < -fputil::FPBits<T>::MAX_EXPONENT) {
-        exponent = -fputil::FPBits<T>::MAX_EXPONENT;
+      if (temp_exponent > FPBits::MAX_EXPONENT) {
+        exponent = FPBits::MAX_EXPONENT;
+      } else if (temp_exponent < -FPBits::MAX_EXPONENT) {
+        exponent = -FPBits::MAX_EXPONENT;
       } else {
         exponent = static_cast<int32_t>(temp_exponent);
       }
@@ -1099,8 +1057,10 @@ hexadecimal_string_to_float(const char *__restrict src,
 // is used as the backend for all of the string to float functions.
 template <class T>
 LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
-  using BitsType = typename fputil::FPBits<T>::UIntType;
-  fputil::FPBits<T> result = fputil::FPBits<T>();
+  using FPBits = typename fputil::FPBits<T>;
+  using UIntType = typename FPBits::UIntType;
+
+  FPBits result = FPBits();
   bool seen_digit = false;
   char sign = '+';
 
@@ -1172,7 +1132,7 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
         tolower(src[index + 2]) == nan_string[2]) {
       seen_digit = true;
       index += 3;
-      BitsType nan_mantissa = 0;
+      UIntType nan_mantissa = 0;
       // this handles the case of `NaN(n-character-sequence)`, where the
       // n-character-sequence is made of 0 or more letters and numbers in any
       // order.
@@ -1186,7 +1146,7 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
         if (src[index] == ')') {
           ++index;
           if (isdigit(src[left_paren + 1])) {
-            // This is to prevent errors when BitsType is larger than 64 bits,
+            // This is to prevent errors when UIntType is larger than 64 bits,
             // since strtointeger only supports up to 64 bits. This is actually
             // more than is required by the specification, which says for the
             // input type "NAN(n-char-sequence)" that "the meaning of
@@ -1197,7 +1157,7 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
             if (strtoint_result.has_error()) {
               error = strtoint_result.error;
             }
-            nan_mantissa = static_cast<BitsType>(strtoint_result.value);
+            nan_mantissa = static_cast<UIntType>(strtoint_result.value);
             if (src[left_paren + 1 + strtoint_result.parsed_len] != ')')
               nan_mantissa = 0;
           }
@@ -1207,11 +1167,11 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
       }
       nan_mantissa |= fputil::FloatProperties<T>::QUIET_NAN_MASK;
       if (result.get_sign()) {
-        result = fputil::FPBits<T>(result.build_quiet_nan(nan_mantissa));
+        result = FPBits(result.build_quiet_nan(nan_mantissa));
         result.set_sign(true);
       } else {
         result.set_sign(false);
-        result = fputil::FPBits<T>(result.build_quiet_nan(nan_mantissa));
+        result = FPBits(result.build_quiet_nan(nan_mantissa));
       }
     }
   } else if (tolower(src[index]) == 'i') { // INF
@@ -1219,9 +1179,9 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
         tolower(src[index + 2]) == inf_string[2]) {
       seen_digit = true;
       if (result.get_sign())
-        result = fputil::FPBits<T>(result.neg_inf());
+        result = FPBits(result.neg_inf());
       else
-        result = fputil::FPBits<T>(result.inf());
+        result = FPBits(result.inf());
       if (tolower(src[index + 3]) == inf_string[3] &&
           tolower(src[index + 4]) == inf_string[4] &&
           tolower(src[index + 5]) == inf_string[5] &&
diff --git a/libc/test/src/__support/str_to_float_test.cpp b/libc/test/src/__support/str_to_float_test.cpp
index f9d12d95a50bee..35f7318fb9c78d 100644
--- a/libc/test/src/__support/str_to_float_test.cpp
+++ b/libc/test/src/__support/str_to_float_test.cpp
@@ -93,45 +93,6 @@ class LlvmLibcStrToFloatTest : public LIBC_NAMESPACE::testing::Test {
   }
 };
 
-TEST(LlvmLibcStrToFloatTest, LeadingZeroes) {
-  uint64_t test_num64 = 1;
-  uint32_t num_of_zeroes = 63;
-  EXPECT_EQ(LIBC_NAMESPACE::internal::leading_zeroes<uint64_t>(0), 64u);
-  for (; num_of_zeroes < 64; test_num64 <<= 1, num_of_zeroes--) {
-    EXPECT_EQ(LIBC_NAMESPACE::internal::leading_zeroes<uint64_t>(test_num64),
-              num_of_zeroes);
-  }
-
-  test_num64 = 3;
-  num_of_zeroes = 62;
-  for (; num_of_zeroes > 63; test_num64 <<= 1, num_of_zeroes--) {
-    EXPECT_EQ(LIBC_NAMESPACE::internal::leading_zeroes<uint64_t>(test_num64),
-              num_of_zeroes);
-  }
-
-  EXPECT_EQ(
-      LIBC_NAMESPACE::internal::leading_zeroes<uint64_t>(0xffffffffffffffff),
-      0u);
-
-  test_num64 = 1;
-  num_of_zeroes = 63;
-  for (; num_of_zeroes > 63;
-       test_num64 = (test_num64 << 1) + 1, num_of_zeroes--) {
-    EXPECT_EQ(LIBC_NAMESPACE::internal::leading_zeroes<uint64_t>(test_num64),
-              num_of_zeroes);
-  }
-
-  uint64_t test_num32 = 1;
-  num_of_zeroes = 31;
-  EXPECT_EQ(LIBC_NAMESPACE::internal::leading_zeroes<uint32_t>(0), 32u);
-  for (; num_of_zeroes < 32; test_num32 <<= 1, num_of_zeroes--) {
-    EXPECT_EQ(LIBC_NAMESPACE::internal::leading_zeroes<uint32_t>(test_num32),
-              num_of_zeroes);
-  }
-
-  EXPECT_EQ(LIBC_NAMESPACE::internal::leading_zeroes<uint32_t>(0xffffffff), 0u);
-}
-
 TEST_F(LlvmLibcStrToFloatTest, ClingerFastPathFloat64Simple) {
   clinger_fast_path_test<double>(123, 0, 0xEC00000000000, 1029);
   clinger_fast_path_test<double>(1234567890123456, 1, 0x5ee2a2eb5a5c0, 1076);



More information about the libc-commits mailing list