[flang-commits] [flang] 0df6f8f - [flang] Fix F5.3 formatting of 0.025

peter klausler via flang-commits flang-commits at lists.llvm.org
Fri Jun 19 18:10:26 PDT 2020


Author: peter klausler
Date: 2020-06-19T18:09:10-07:00
New Revision: 0df6f8fe8ed09d52af293b1d548a73f0672ece70

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

LOG: [flang] Fix F5.3 formatting of 0.025

Fix F output editing in the Fortran runtime so that it
respects the 'd' count of digits after the decimal mark.

Reviewed By: tskeith

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

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/flang/runtime/edit-output.cpp b/flang/runtime/edit-output.cpp
index 2afa40fbfb82..a162726a592b 100644
--- a/flang/runtime/edit-output.cpp
+++ b/flang/runtime/edit-output.cpp
@@ -205,7 +205,7 @@ bool RealOutputEditing<binaryPrecision>::EditEorDOutput(const DataEdit &edit) {
   while (true) {
     decimal::ConversionToDecimalResult converted{
         Convert(significantDigits, edit, flags)};
-    if (converted.length > 0 && !IsDecimalNumber(converted.str)) { // Inf, NaN
+    if (IsInfOrNaN(converted)) {
       return EmitPrefix(edit, converted.length, editWidth) &&
           io_.Emit(converted.str, converted.length) && EmitSuffix(edit);
     }
@@ -260,8 +260,7 @@ bool RealOutputEditing<binaryPrecision>::EditEorDOutput(const DataEdit &edit) {
 template <int binaryPrecision>
 bool RealOutputEditing<binaryPrecision>::EditFOutput(const DataEdit &edit) {
   int fracDigits{edit.digits.value_or(0)}; // 'd' field
-  int extraDigits{0};
-  int editWidth{edit.width.value_or(0)}; // 'w' field
+  const int editWidth{edit.width.value_or(0)}; // 'w' field
   int flags{0};
   if (editWidth == 0) { // "the processor selects the field width"
     if (!edit.digits.has_value()) { // F0
@@ -271,27 +270,31 @@ bool RealOutputEditing<binaryPrecision>::EditFOutput(const DataEdit &edit) {
   }
   // Multiple conversions may be needed to get the right number of
   // effective rounded fractional digits.
+  int extraDigits{0};
   while (true) {
     decimal::ConversionToDecimalResult converted{
         Convert(extraDigits + fracDigits, edit, flags)};
-    if (converted.length > 0 && !IsDecimalNumber(converted.str)) { // Inf, NaN
+    if (IsInfOrNaN(converted)) {
       return EmitPrefix(edit, converted.length, editWidth) &&
           io_.Emit(converted.str, converted.length) && EmitSuffix(edit);
     }
     int scale{IsZero() ? -1 : edit.modes.scale};
     int expo{converted.decimalExponent - scale};
-    if (expo > extraDigits) {
+    if (expo > extraDigits && extraDigits >= 0) {
       extraDigits = expo;
-      if (flags & decimal::Minimize) {
+      if (!edit.digits.has_value()) { // F0
         fracDigits = sizeof buffer_ - extraDigits - 2; // sign & NUL
       }
-      continue; // try again
+      continue;
+    } else if (expo < extraDigits && extraDigits > -fracDigits) {
+      extraDigits = std::max(expo, -fracDigits);
+      continue;
     }
     int signLength{*converted.str == '-' || *converted.str == '+' ? 1 : 0};
     int convertedDigits{static_cast<int>(converted.length) - signLength};
     int digitsBeforePoint{std::max(0, std::min(expo, convertedDigits))};
     int zeroesBeforePoint{std::max(0, expo - digitsBeforePoint)};
-    int zeroesAfterPoint{std::max(0, -expo)};
+    int zeroesAfterPoint{std::min(fracDigits, std::max(0, -expo))};
     int digitsAfterPoint{convertedDigits - digitsBeforePoint};
     int trailingZeroes{flags & decimal::Minimize
             ? 0
@@ -299,7 +302,7 @@ bool RealOutputEditing<binaryPrecision>::EditFOutput(const DataEdit &edit) {
     if (digitsBeforePoint + zeroesBeforePoint + zeroesAfterPoint +
             digitsAfterPoint + trailingZeroes ==
         0) {
-      ++zeroesBeforePoint; // "." -> "0."
+      zeroesBeforePoint = 1; // "." -> "0."
     }
     int totalLength{signLength + digitsBeforePoint + zeroesBeforePoint +
         1 /*'.'*/ + zeroesAfterPoint + digitsAfterPoint + trailingZeroes};
@@ -332,7 +335,7 @@ DataEdit RealOutputEditing<binaryPrecision>::EditForGOutput(DataEdit edit) {
     return edit; // Gw.0 -> Ew.0 for w > 0
   }
   decimal::ConversionToDecimalResult converted{Convert(1, edit)};
-  if (!IsDecimalNumber(converted.str)) { // Inf, NaN
+  if (IsInfOrNaN(converted)) {
     return edit;
   }
   int expo{IsZero() ? 1 : converted.decimalExponent}; // 's'
@@ -361,7 +364,7 @@ template <int binaryPrecision>
 bool RealOutputEditing<binaryPrecision>::EditListDirectedOutput(
     const DataEdit &edit) {
   decimal::ConversionToDecimalResult converted{Convert(1, edit)};
-  if (!IsDecimalNumber(converted.str)) { // Inf, NaN
+  if (IsInfOrNaN(converted)) {
     return EditEorDOutput(edit);
   }
   int expo{converted.decimalExponent};

diff  --git a/flang/runtime/edit-output.h b/flang/runtime/edit-output.h
index aa324c3ca0d2..d819c1007caf 100644
--- a/flang/runtime/edit-output.h
+++ b/flang/runtime/edit-output.h
@@ -37,14 +37,18 @@ class RealOutputEditingBase {
 protected:
   explicit RealOutputEditingBase(IoStatementState &io) : io_{io} {}
 
-  static bool IsDecimalNumber(const char *p) {
-    if (!p) {
+  static bool IsInfOrNaN(const decimal::ConversionToDecimalResult &res) {
+    const char *p{res.str};
+    if (!p || res.length < 1) {
       return false;
     }
     if (*p == '-' || *p == '+') {
+      if (res.length == 1) {
+        return false;
+      }
       ++p;
     }
-    return *p >= '0' && *p <= '9';
+    return *p < '0' || *p > '9';
   }
 
   const char *FormatExponent(int, const DataEdit &edit, int &length);

diff  --git a/flang/unittests/Runtime/hello.cpp b/flang/unittests/Runtime/hello.cpp
index 22e7380128f3..ff806523eb5f 100644
--- a/flang/unittests/Runtime/hello.cpp
+++ b/flang/unittests/Runtime/hello.cpp
@@ -402,6 +402,21 @@ int main() {
       "4040261841248583680000+306;");
   realTest("(G0,';')", u.d, ".17976931348623157+309;");
 
+  realTest("(F5.3,';')", 25., "*****;");
+  realTest("(F5.3,';')", 2.5, "2.500;");
+  realTest("(F5.3,';')", 0.25, "0.250;");
+  realTest("(F5.3,';')", 0.025, "0.025;");
+  realTest("(F5.3,';')", 0.0025, "0.003;");
+  realTest("(F5.3,';')", 0.00025, "0.000;");
+  realTest("(F5.3,';')", 0.000025, "0.000;");
+  realTest("(F5.3,';')", -25., "*****;");
+  realTest("(F5.3,';')", -2.5, "*****;");
+  realTest("(F5.3,';')", -0.25, "-.250;");
+  realTest("(F5.3,';')", -0.025, "-.025;");
+  realTest("(F5.3,';')", -0.0025, "-.003;");
+  realTest("(F5.3,';')", -0.00025, "-.000;");
+  realTest("(F5.3,';')", -0.000025, "-.000;");
+
   realInTest("(F18.0)", "                 0", 0x0);
   realInTest("(F18.0)", "                  ", 0x0);
   realInTest("(F18.0)", "                -0", 0x8000000000000000);


        


More information about the flang-commits mailing list