[libc-commits] [llvm] [libc] [libc] Move printf long double to simple calc (PR #75414)

Guillaume Chatelet via libc-commits libc-commits at lists.llvm.org
Thu Jan 11 08:24:30 PST 2024


================
@@ -567,197 +574,264 @@ class FloatToString {
   }
 
   LIBC_INLINE constexpr size_t get_positive_blocks() {
-    if (exponent >= -FRACTION_LEN) {
-      const uint32_t idx =
-          exponent < 0
-              ? 0
-              : static_cast<uint32_t>(exponent + (IDX_SIZE - 1)) / IDX_SIZE;
-      const uint32_t len =
-          internal::length_for_num(idx * IDX_SIZE, FRACTION_LEN);
-      return len;
-    } else {
+    if (exponent < -FRACTION_LEN)
       return 0;
-    }
+    const uint32_t idx =
+        exponent < 0
+            ? 0
+            : static_cast<uint32_t>(exponent + (IDX_SIZE - 1)) / IDX_SIZE;
+    return internal::length_for_num(idx * IDX_SIZE, FRACTION_LEN);
   }
 
   // This takes the index of a block after the decimal point (a negative block)
   // and return if it's sure that all of the digits after it are zero.
-  LIBC_INLINE constexpr bool is_lowest_block(size_t block_index) {
+  LIBC_INLINE constexpr bool is_lowest_block(size_t negative_block_index) {
 #ifdef LIBC_COPT_FLOAT_TO_STR_NO_TABLE
-    return false;
+    // The decimal representation of 2**(-i) will have exactly i digits after
+    // the decimal point.
+    int num_requested_digits =
+        static_cast<int>((negative_block_index + 1) * BLOCK_SIZE);
+
+    return num_requested_digits > -exponent;
 #else
     const int32_t idx = -exponent / IDX_SIZE;
-    const size_t p = POW10_OFFSET_2[idx] + block_index - MIN_BLOCK_2[idx];
+    const size_t p =
+        POW10_OFFSET_2[idx] + negative_block_index - MIN_BLOCK_2[idx];
     // If the remaining digits are all 0, then this is the lowest block.
     return p >= POW10_OFFSET_2[idx + 1];
 #endif
   }
 
   LIBC_INLINE constexpr size_t zero_blocks_after_point() {
 #ifdef LIBC_COPT_FLOAT_TO_STR_NO_TABLE
+    if (exponent < -FRACTION_LEN) {
+      const int pos_exp = -exponent - 1;
+      const uint32_t pos_idx =
+          static_cast<uint32_t>(pos_exp + (IDX_SIZE - 1)) / IDX_SIZE;
+      const int32_t pos_len = ((internal::ceil_log10_pow2(pos_idx * IDX_SIZE) -
+                                internal::ceil_log10_pow2(FRACTION_LEN + 1)) /
+                               BLOCK_SIZE) -
+                              1;
+      return static_cast<uint32_t>(pos_len > 0 ? pos_len : 0);
+    }
     return 0;
-    // TODO (michaelrj): Find a good algorithm for this that doesn't use a
-    // table.
 #else
     return MIN_BLOCK_2[-exponent / IDX_SIZE];
 #endif
   }
 };
 
-#ifndef LIBC_LONG_DOUBLE_IS_FLOAT64
+#if !defined(LIBC_LONG_DOUBLE_IS_FLOAT64) &&                                   \
+    !defined(LIBC_COPT_FLOAT_TO_STR_NO_SPECIALIZE_LD)
 // --------------------------- LONG DOUBLE FUNCTIONS ---------------------------
 
-template <>
-LIBC_INLINE constexpr size_t FloatToString<long double>::get_positive_blocks() {
-  if (exponent >= -FRACTION_LEN) {
-    const uint32_t idx =
-        exponent < 0
-            ? 0
-            : static_cast<uint32_t>(exponent + (IDX_SIZE - 1)) / IDX_SIZE;
-    const uint32_t len = internal::length_for_num(idx * IDX_SIZE, FRACTION_LEN);
-    return len;
-  } else {
-    return 0;
+template <> class FloatToString<long double> {
+  fputil::FPBits<long double> float_bits;
+  bool is_negative = 0;
+  int exponent = 0;
+  FPBits::StorageType mantissa = 0;
+
+  static constexpr int FRACTION_LEN = fputil::FPBits<long double>::FRACTION_LEN;
+  static constexpr int EXP_BIAS = fputil::FPBits<long double>::EXP_BIAS;
+
+  static constexpr size_t FLOAT_AS_INT_WIDTH =
+      internal::div_ceil(fputil::FPBits<long double>::MAX_BIASED_EXPONENT -
+                             FPBits::EXP_BIAS,
+                         64) *
+      64;
+  static constexpr size_t EXTRA_INT_WIDTH =
+      internal::div_ceil(sizeof(long double) * 8, 64) * 64;
----------------
gchatelet wrote:

nit: `CHAR_T` instead of `8`

https://github.com/llvm/llvm-project/pull/75414


More information about the libc-commits mailing list