[libc-commits] [PATCH] D156489: [libc] Fix printf g conversion with high precision

Michael Jones via Phabricator via libc-commits libc-commits at lists.llvm.org
Thu Jul 27 14:02:55 PDT 2023


michaelrj created this revision.
michaelrj added reviewers: sivachandra, lntue.
Herald added projects: libc-project, All.
Herald added a subscriber: libc-commits.
michaelrj requested review of this revision.

The number of trailing zeroes was being calculated incorrectly. It was
assuming that it could add all of the implicit leading zeroes in the
final block, not accounting for the number of digits actually reqested
by the precision.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D156489

Files:
  libc/src/stdio/printf_core/float_dec_converter.h
  libc/test/src/stdio/sprintf_test.cpp


Index: libc/test/src/stdio/sprintf_test.cpp
===================================================================
--- libc/test/src/stdio/sprintf_test.cpp
+++ libc/test/src/stdio/sprintf_test.cpp
@@ -2437,6 +2437,10 @@
   written = __llvm_libc::sprintf(buff, "%.3g", 1256.0);
   ASSERT_STREQ_LEN(written, buff, "1.26e+03");
 
+  // Found through large scale testing.
+  written = __llvm_libc::sprintf(buff, "%.15g", 22.25);
+  ASSERT_STREQ_LEN(written, buff, "22.25");
+
   // Subnormal Precision Tests
 
   written = __llvm_libc::sprintf(buff, "%.310g", 0x1.0p-1022);
Index: libc/src/stdio/printf_core/float_dec_converter.h
===================================================================
--- libc/src/stdio/printf_core/float_dec_converter.h
+++ libc/src/stdio/printf_core/float_dec_converter.h
@@ -965,15 +965,6 @@
   if (digits_checked == 0) {
     last_block_size = int_to_str.size();
     implicit_leading_zeroes = 0;
-  } else {
-    // If the block is not the maximum size, that means it has leading
-    // zeroes, and zeroes are not nines.
-    if (implicit_leading_zeroes > 0) {
-      trailing_nines = 0;
-    }
-
-    // But leading zeroes are zeroes (that could be trailing).
-    trailing_zeroes += implicit_leading_zeroes;
   }
 
   int digits_requested = (exp_precision + 1) - digits_checked;
@@ -983,6 +974,19 @@
     digits_to_check = 0;
   }
 
+  // If the block is not the maximum size, that means it has leading
+  // zeroes, and zeroes are not nines.
+  if (implicit_leading_zeroes > 0) {
+    trailing_nines = 0;
+  }
+
+  // But leading zeroes are zeroes (that could be trailing). We take the
+  // minimum of the leading zeroes and digits requested because if there are
+  // more requested digits than leading zeroes we shouldn't count those.
+  trailing_zeroes +=
+      (implicit_leading_zeroes > digits_requested ? digits_requested
+                                                  : implicit_leading_zeroes);
+
   // Check the upper digits of this block.
   for (int i = 0; i < digits_to_check; ++i) {
     if (int_to_str[i] == '9') {
@@ -1103,6 +1107,24 @@
     } else {
       // If alt form isn't set, then we need to determine the number of trailing
       // zeroes and set the precision such that they are removed.
+
+      /*
+      Here's a diagram of an example:
+
+      printf("%.15g", 22.25);
+
+                            +--- init_precision = 15
+                            |
+                            +-------------------+
+                            |                   |
+                            |  ++--- trimmed_precision = 2
+                            |  ||               |
+                            22.250000000000000000
+                            ||   |              |
+                            ++   +--------------+
+                             |   |
+       base_10_exp + 1 = 2 --+   +--- trailing_zeroes = 11
+      */
       int trimmed_precision =
           digits_checked - (base_10_exp + 1) - trailing_zeroes;
       if (trimmed_precision < 0) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D156489.544921.patch
Type: text/x-patch
Size: 3028 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libc-commits/attachments/20230727/6b87ac31/attachment.bin>


More information about the libc-commits mailing list