[libc-commits] [libc] 3fb63c2 - [libc] simplify printf float writing

Michael Jones via libc-commits libc-commits at lists.llvm.org
Wed Sep 13 13:53:44 PDT 2023


Author: Michael Jones
Date: 2023-09-13T13:53:29-07:00
New Revision: 3fb63c2921798cf4f417d0907900bcaba01cdd40

URL: https://github.com/llvm/llvm-project/commit/3fb63c2921798cf4f417d0907900bcaba01cdd40
DIFF: https://github.com/llvm/llvm-project/commit/3fb63c2921798cf4f417d0907900bcaba01cdd40.diff

LOG: [libc] simplify printf float writing

The two decimal float printing styles are similar, but different in how
they end. For simplicity of writing I initially gave them different
"write_last_block" functions. This patch unifies them into one function.

Reviewed By: sivachandra

Differential Revision: https://reviews.llvm.org/D158036

Added: 
    

Modified: 
    libc/src/stdio/printf_core/float_dec_converter.h

Removed: 
    


################################################################################
diff  --git a/libc/src/stdio/printf_core/float_dec_converter.h b/libc/src/stdio/printf_core/float_dec_converter.h
index df7f8165ba49d95..5e6f1d127370ce7 100644
--- a/libc/src/stdio/printf_core/float_dec_converter.h
+++ b/libc/src/stdio/printf_core/float_dec_converter.h
@@ -299,100 +299,11 @@ class FloatWriter {
     return 0;
   }
 
-  int write_last_block_dec(BlockInt block, size_t block_digits,
-                           RoundDirection round) {
-    char end_buff[BLOCK_SIZE];
-
-    const DecimalString buf(block + (MAX_BLOCK + 1));
-    const cpp::string_view int_to_str = buf.view();
-
-    // copy the last block_digits characters into the start of end_buff.
-    // TODO: Replace with memcpy
-    for (size_t count = 0; count < block_digits; ++count) {
-      end_buff[count] = int_to_str[count + 1 + (BLOCK_SIZE - block_digits)];
-    }
-
-    char low_digit = '0';
-    if (block_digits > 0) {
-      low_digit = end_buff[block_digits - 1];
-    } else if (max_block_count > 0) {
-      low_digit = '9';
-    } else if (buffered_digits > 0) {
-      low_digit = block_buffer[buffered_digits - 1];
-    }
-
-    bool round_up_max_blocks = false;
-
-    // Round up
-    if (round == RoundDirection::Up ||
-        (round == RoundDirection::Even && low_digit % 2 != 0)) {
-      bool has_carry = true;
-      round_up_max_blocks = true; // if we're rounding up, we might need to
-                                  // round up the max blocks that are buffered.
-      // handle the low block that we're adding
-      for (int count = static_cast<int>(block_digits) - 1;
-           count >= 0 && has_carry; --count) {
-        if (end_buff[count] == '9') {
-          end_buff[count] = '0';
-        } else {
-          end_buff[count] += 1;
-          has_carry = false;
-          round_up_max_blocks = false; // If the low block isn't all nines, then
-                                       // the max blocks aren't rounded up.
-        }
-      }
-      // handle the high block that's buffered
-      for (int count = static_cast<int>(buffered_digits) - 1;
-           count >= 0 && has_carry; --count) {
-        if (block_buffer[count] == '9') {
-          block_buffer[count] = '0';
-        } else {
-          block_buffer[count] += 1;
-          has_carry = false;
-        }
-      }
-
-      // has_carry should only be true here if every previous digit is 9, which
-      // implies that the number has never been written.
-      if (has_carry /* && !has_written */) {
-        ++total_digits;
-        ++digits_before_decimal;
-        // Normally write_left_padding is called by flush_buffer but since we're
-        // rounding up all of the digits, the ones in the buffer are wrong and
-        // can't be flushed.
-        RET_IF_RESULT_NEGATIVE(
-            padding_writer.write_left_padding(writer, total_digits));
-        // Now we know we need to print a leading 1, zeroes up to the decimal
-        // point, the decimal point, and then finally digits after it.
-        RET_IF_RESULT_NEGATIVE(writer->write('1'));
-        // digits_before_decimal - 1 to account for the leading '1'
-        RET_IF_RESULT_NEGATIVE(writer->write('0', digits_before_decimal - 1));
-        if (has_decimal_point) {
-          RET_IF_RESULT_NEGATIVE(writer->write(DECIMAL_POINT));
-          // add one to digits_before_decimal to account for the decimal point
-          // itself.
-          if (total_digits > digits_before_decimal + 1) {
-            RET_IF_RESULT_NEGATIVE(
-                writer->write('0', total_digits - (digits_before_decimal + 1)));
-          }
-        }
-        total_digits_written = total_digits;
-        return 0;
-      }
-    }
-    // Either we intend to round down, or the rounding up is complete. Flush the
-    // buffers.
-
-    RET_IF_RESULT_NEGATIVE(flush_buffer(round_up_max_blocks));
+  int write_last_block(BlockInt block, size_t block_digits,
+                       RoundDirection round, int exponent = 0,
+                       char exp_char = '\0') {
+    bool has_exp = (exp_char != '\0');
 
-    // And then write the final block.
-    RET_IF_RESULT_NEGATIVE(writer->write({end_buff, block_digits}));
-    total_digits_written += block_digits;
-    return 0;
-  }
-
-  int write_last_block_exp(uint32_t block, size_t block_digits,
-                           RoundDirection round, int exponent, char exp_char) {
     char end_buff[BLOCK_SIZE];
 
     {
@@ -450,48 +361,74 @@ class FloatWriter {
       // has_carry should only be true here if every previous digit is 9, which
       // implies that the number has never been written.
       if (has_carry /* && !has_written */) {
-        // Since this is exponential notation, we don't write any more digits
-        // but we do increment the exponent.
-        ++exponent;
-
-        const ExponentString buf(exponent);
-        const cpp::string_view int_to_str = buf.view();
-
-        // TODO: also change this to calculate the width of the number more
-        // efficiently.
-        size_t exponent_width = int_to_str.size();
-        size_t number_digits =
-            buffered_digits + (max_block_count * BLOCK_SIZE) + block_digits;
-
-        // Here we have to recalculate the total number of digits since the
-        // exponent's width may have changed. We're only adding 1 to exponent
-        // width since exp_str appends the sign.
-        total_digits =
-            (has_decimal_point ? 1 : 0) + number_digits + 1 + exponent_width;
-
-        // Normally write_left_padding is called by flush_buffer but since we're
-        // rounding up all of the digits, the ones in the buffer are wrong and
-        // can't be flushed.
-        RET_IF_RESULT_NEGATIVE(
-            padding_writer.write_left_padding(writer, total_digits));
-        // Now we know we need to print a leading 1, the decimal point, and then
-        // zeroes after it.
-        RET_IF_RESULT_NEGATIVE(writer->write('1'));
-        // digits_before_decimal - 1 to account for the leading '1'
-        if (has_decimal_point) {
-          RET_IF_RESULT_NEGATIVE(writer->write(DECIMAL_POINT));
-          // This is just the length of the number, not including the decimal
-          // point, or exponent.
-
-          if (number_digits > 1) {
-            RET_IF_RESULT_NEGATIVE(writer->write('0', number_digits - 1));
+        if (has_exp) { // This is in %e style
+          // Since this is exponential notation, we don't write any more digits
+          // but we do increment the exponent.
+          ++exponent;
+
+          const ExponentString buf(exponent);
+          const cpp::string_view int_to_str = buf.view();
+
+          // TODO: also change this to calculate the width of the number more
+          // efficiently.
+          size_t exponent_width = int_to_str.size();
+          size_t number_digits =
+              buffered_digits + (max_block_count * BLOCK_SIZE) + block_digits;
+
+          // Here we have to recalculate the total number of digits since the
+          // exponent's width may have changed. We're only adding 1 to exponent
+          // width since exp_str appends the sign.
+          total_digits =
+              (has_decimal_point ? 1 : 0) + number_digits + 1 + exponent_width;
+
+          // Normally write_left_padding is called by flush_buffer but since
+          // we're rounding up all of the digits, the ones in the buffer are
+          // wrong and can't be flushed.
+          RET_IF_RESULT_NEGATIVE(
+              padding_writer.write_left_padding(writer, total_digits));
+          // Now we know we need to print a leading 1, the decimal point, and
+          // then zeroes after it.
+          RET_IF_RESULT_NEGATIVE(writer->write('1'));
+          // digits_before_decimal - 1 to account for the leading '1'
+          if (has_decimal_point) {
+            RET_IF_RESULT_NEGATIVE(writer->write(DECIMAL_POINT));
+            // This is just the length of the number, not including the decimal
+            // point, or exponent.
+
+            if (number_digits > 1) {
+              RET_IF_RESULT_NEGATIVE(writer->write('0', number_digits - 1));
+            }
           }
+          RET_IF_RESULT_NEGATIVE(writer->write(exp_char));
+          RET_IF_RESULT_NEGATIVE(writer->write(int_to_str));
+
+          total_digits_written = total_digits;
+          return WRITE_OK;
+        } else { // This is in %f style
+          ++total_digits;
+          ++digits_before_decimal;
+          // Normally write_left_padding is called by flush_buffer but since
+          // we're rounding up all of the digits, the ones in the buffer are
+          // wrong and can't be flushed.
+          RET_IF_RESULT_NEGATIVE(
+              padding_writer.write_left_padding(writer, total_digits));
+          // Now we know we need to print a leading 1, zeroes up to the decimal
+          // point, the decimal point, and then finally digits after it.
+          RET_IF_RESULT_NEGATIVE(writer->write('1'));
+          // digits_before_decimal - 1 to account for the leading '1'
+          RET_IF_RESULT_NEGATIVE(writer->write('0', digits_before_decimal - 1));
+          if (has_decimal_point) {
+            RET_IF_RESULT_NEGATIVE(writer->write(DECIMAL_POINT));
+            // add one to digits_before_decimal to account for the decimal point
+            // itself.
+            if (total_digits > digits_before_decimal + 1) {
+              RET_IF_RESULT_NEGATIVE(writer->write(
+                  '0', total_digits - (digits_before_decimal + 1)));
+            }
+          }
+          total_digits_written = total_digits;
+          return WRITE_OK;
         }
-        RET_IF_RESULT_NEGATIVE(writer->write(exp_char));
-        RET_IF_RESULT_NEGATIVE(writer->write(int_to_str));
-
-        total_digits_written = total_digits;
-        return WRITE_OK;
       }
     }
     // Either we intend to round down, or the rounding up is complete. Flush the
@@ -509,10 +446,11 @@ class FloatWriter {
     buffered_digits = block_digits;
     RET_IF_RESULT_NEGATIVE(flush_buffer());
 
-    RET_IF_RESULT_NEGATIVE(writer->write(exp_char));
-    const ExponentString buf(exponent);
-    RET_IF_RESULT_NEGATIVE(writer->write(buf.view()));
-
+    if (has_exp) {
+      RET_IF_RESULT_NEGATIVE(writer->write(exp_char));
+      const ExponentString buf(exponent);
+      RET_IF_RESULT_NEGATIVE(writer->write(buf.view()));
+    }
     total_digits_written = total_digits;
 
     return WRITE_OK;
@@ -634,7 +572,7 @@ LIBC_INLINE int convert_float_decimal_typed(Writer *writer,
         round = get_round_direction(last_digit, truncated, is_negative);
 
         RET_IF_RESULT_NEGATIVE(
-            float_writer.write_last_block_dec(digits, maximum, round));
+            float_writer.write_last_block(digits, maximum, round));
         break;
       }
     }
@@ -800,7 +738,7 @@ LIBC_INLINE int convert_float_dec_exp_typed(Writer *writer,
   }
   round = get_round_direction(last_digit, truncated, is_negative);
 
-  RET_IF_RESULT_NEGATIVE(float_writer.write_last_block_exp(
+  RET_IF_RESULT_NEGATIVE(float_writer.write_last_block(
       digits, maximum, round, final_exponent, a + 'E' - 'A'));
 
   RET_IF_RESULT_NEGATIVE(float_writer.right_pad());


        


More information about the libc-commits mailing list