[flang-commits] [flang] fa465b4 - [flang][runtime] Improve confusing list-directed REAL(2) output (#89846)

via flang-commits flang-commits at lists.llvm.org
Wed Apr 24 15:40:07 PDT 2024


Author: Peter Klausler
Date: 2024-04-24T15:40:02-07:00
New Revision: fa465b479b09b638e95c8b92ecf358c38910f8b0

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

LOG: [flang][runtime] Improve confusing list-directed REAL(2) output (#89846)

List-directed output editing of REAL values will minimize the number of
digits that are emitted by calculating a decimal value that, if read
back in to a REAL variable of the same kind, would compare equal.

This behavior is causing some confusion when applied to list-directed
output of large REAL(2) values. Specifically, the value HUGE(0._2)
(which is 0x7bff in hex) is exactly 65504, but is edited to 65500. by
list-directed output, which selects F0 editing, minimizes the value to
6.55e4, and then formats it without the exponent.

This small patch changes that behavior for cases where the output of
digit-minimized F editing has no digits after the decimal point and
zeroes need to be emitted before it due to the decimal exponent. Digit
minimization is disabled in this case and the exact digits are emitted
instead.

Added: 
    

Modified: 
    flang/runtime/edit-output.cpp
    flang/unittests/Runtime/NumericalFormatTest.cpp

Removed: 
    


################################################################################
diff  --git a/flang/runtime/edit-output.cpp b/flang/runtime/edit-output.cpp
index c3e11e6e4ce6de..13ab91fc56eade 100644
--- a/flang/runtime/edit-output.cpp
+++ b/flang/runtime/edit-output.cpp
@@ -446,6 +446,7 @@ RT_API_ATTRS bool RealOutputEditing<KIND>::EditFOutput(const DataEdit &edit) {
       fracDigits = sizeof buffer_ - 2; // sign & NUL
     }
   }
+  bool emitTrailingZeroes{!(flags & decimal::Minimize)};
   // Multiple conversions may be needed to get the right number of
   // effective rounded fractional digits.
   bool canIncrease{true};
@@ -526,11 +527,18 @@ RT_API_ATTRS bool RealOutputEditing<KIND>::EditFOutput(const DataEdit &edit) {
     }
     int digitsBeforePoint{std::max(0, std::min(expo, convertedDigits))};
     int zeroesBeforePoint{std::max(0, expo - digitsBeforePoint)};
+    if (zeroesBeforePoint > 0 && (flags & decimal::Minimize)) {
+      // If a minimized result looks like an integer, emit all of
+      // its digits rather than clipping some to zeroes.
+      // This can happen with HUGE(0._2) == 65504._2.
+      flags &= ~decimal::Minimize;
+      continue;
+    }
     int zeroesAfterPoint{std::min(fracDigits, std::max(0, -expo))};
     int digitsAfterPoint{convertedDigits - digitsBeforePoint};
-    int trailingZeroes{flags & decimal::Minimize
-            ? 0
-            : std::max(0, fracDigits - (zeroesAfterPoint + digitsAfterPoint))};
+    int trailingZeroes{emitTrailingZeroes
+            ? std::max(0, fracDigits - (zeroesAfterPoint + digitsAfterPoint))
+            : 0};
     if (digitsBeforePoint + zeroesBeforePoint + zeroesAfterPoint +
             digitsAfterPoint + trailingZeroes ==
         0) {

diff  --git a/flang/unittests/Runtime/NumericalFormatTest.cpp b/flang/unittests/Runtime/NumericalFormatTest.cpp
index dee4dda4a22869..2a9f8f8d1dc4f3 100644
--- a/flang/unittests/Runtime/NumericalFormatTest.cpp
+++ b/flang/unittests/Runtime/NumericalFormatTest.cpp
@@ -958,3 +958,20 @@ TEST(IOApiTests, EditDoubleInputValues) {
                            << "', want " << want << ", got " << u.raw;
   }
 }
+
+// regression test for confusing digit minimization
+TEST(IOApiTests, ConfusingMinimization) {
+  char buffer[8]{};
+  auto cookie{IONAME(BeginInternalListOutput)(buffer, sizeof buffer)};
+  StaticDescriptor<0> staticDescriptor;
+  Descriptor &desc{staticDescriptor.descriptor()};
+  std::uint16_t x{0x7bff}; // HUGE(0._2)
+  desc.Establish(TypeCode{CFI_type_half_float}, sizeof x, &x, 0, nullptr);
+  desc.Check();
+  EXPECT_TRUE(IONAME(OutputDescriptor)(cookie, desc));
+  auto status{IONAME(EndIoStatement)(cookie)};
+  EXPECT_EQ(status, 0);
+  std::string got{std::string{buffer, sizeof buffer}};
+  EXPECT_TRUE(CompareFormattedStrings(" 65504. ", got))
+      << "expected ' 65504. ', got '" << got << '\''; // not 65500.!
+}


        


More information about the flang-commits mailing list