[flang-commits] [flang] e593940 - [flang] Fine-tune NAN formatted input editing

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Tue Mar 28 12:55:47 PDT 2023


Author: Peter Klausler
Date: 2023-03-28T12:39:21-07:00
New Revision: e593940be42862402daab166df1a33a8e86960ae

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

LOG: [flang] Fine-tune NAN formatted input editing

Per Fortran 2018, "NAN" and "NAN()" are to be translated into quiet
NaNs, and the other forms are implementation-dependent;  I've made
them quiet NaNs too.  Also process signs on input NaNs, which seems
wrong but other compilers all do it, and fix some misleading template
argument names noticed along the way.

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

Added: 
    

Modified: 
    flang/lib/Decimal/big-radix-floating-point.h
    flang/lib/Decimal/decimal-to-binary.cpp
    flang/runtime/edit-output.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Decimal/big-radix-floating-point.h b/flang/lib/Decimal/big-radix-floating-point.h
index 7fabc7bb0fce2..03b76e9abe636 100644
--- a/flang/lib/Decimal/big-radix-floating-point.h
+++ b/flang/lib/Decimal/big-radix-floating-point.h
@@ -350,9 +350,9 @@ template <int PREC, int LOG10RADIX = 16> class BigRadixFloatingPointNumber {
   constexpr Raw Infinity() const {
     return (Raw{Real::maxExponent} << Real::significandBits) | SignBit();
   }
-  static constexpr Raw NaN() {
+  constexpr Raw NaN(bool isQuiet = true) {
     return (Raw{Real::maxExponent} << Real::significandBits) |
-        (Raw{1} << (Real::significandBits - 2));
+        (Raw{1} << (Real::significandBits - (isQuiet ? 1 : 2))) | SignBit();
   }
 
   Digit digit_[maxDigits]; // in little-endian order: digit_[0] is LSD

diff  --git a/flang/lib/Decimal/decimal-to-binary.cpp b/flang/lib/Decimal/decimal-to-binary.cpp
index f13f7cebb957d..d77ec7cbca6e7 100644
--- a/flang/lib/Decimal/decimal-to-binary.cpp
+++ b/flang/lib/Decimal/decimal-to-binary.cpp
@@ -407,36 +407,40 @@ BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ConvertToBinary(
     return result;
   } else {
     // Could not parse a decimal floating-point number.  p has been
-    // advanced over any leading spaces.
-    if ((!limit || limit >= p + 3) && toupper(p[0]) == 'N' &&
-        toupper(p[1]) == 'A' && toupper(p[2]) == 'N') {
+    // advanced over any leading spaces.  Most Fortran compilers set
+    // the sign bit for -NaN.
+    const char *q{p};
+    if (!limit || q < limit) {
+      isNegative_ = *q == '-';
+      if (isNegative_ || *q == '+') {
+        ++q;
+      }
+    }
+    if ((!limit || limit >= q + 3) && toupper(q[0]) == 'N' &&
+        toupper(q[1]) == 'A' && toupper(q[2]) == 'N') {
       // NaN
-      p += 3;
+      p = q + 3;
+      bool isQuiet{true};
       if ((!limit || p < limit) && *p == '(') {
         int depth{1};
         do {
           ++p;
           if (limit && p >= limit) {
             // Invalid input
-            return {Real{NaN()}, Invalid};
+            return {Real{NaN(false)}, Invalid};
           } else if (*p == '(') {
             ++depth;
           } else if (*p == ')') {
             --depth;
+          } else if (*p != ' ') {
+            // Implementation dependent, but other compilers
+            // all return quiet NaNs.
           }
         } while (depth > 0);
         ++p;
       }
-      return {Real{NaN()}};
-    } else {
-      // Try to parse Inf, maybe with a sign
-      const char *q{p};
-      if (!limit || q < limit) {
-        isNegative_ = *q == '-';
-        if (isNegative_ || *q == '+') {
-          ++q;
-        }
-      }
+      return {Real{NaN(isQuiet)}};
+    } else { // Inf?
       if ((!limit || limit >= q + 3) && toupper(q[0]) == 'I' &&
           toupper(q[1]) == 'N' && toupper(q[2]) == 'F') {
         if ((!limit || limit >= q + 8) && toupper(q[3]) == 'I' &&

diff  --git a/flang/runtime/edit-output.cpp b/flang/runtime/edit-output.cpp
index bfa8e51b1ec55..08a75822bacd4 100644
--- a/flang/runtime/edit-output.cpp
+++ b/flang/runtime/edit-output.cpp
@@ -247,8 +247,8 @@ bool RealOutputEditingBase::EmitSuffix(const DataEdit &edit) {
   }
 }
 
-template <int binaryPrecision>
-decimal::ConversionToDecimalResult RealOutputEditing<binaryPrecision>::Convert(
+template <int KIND>
+decimal::ConversionToDecimalResult RealOutputEditing<KIND>::Convert(
     int significantDigits, enum decimal::FortranRounding rounding, int flags) {
   auto converted{decimal::ConvertToDecimal<binaryPrecision>(buffer_,
       sizeof buffer_, static_cast<enum decimal::DecimalConversionFlags>(flags),
@@ -262,8 +262,8 @@ decimal::ConversionToDecimalResult RealOutputEditing<binaryPrecision>::Convert(
 }
 
 // 13.7.2.3.3 in F'2018
-template <int binaryPrecision>
-bool RealOutputEditing<binaryPrecision>::EditEorDOutput(const DataEdit &edit) {
+template <int KIND>
+bool RealOutputEditing<KIND>::EditEorDOutput(const DataEdit &edit) {
   addSpaceBeforeCharacter(io_);
   int editDigits{edit.digits.value_or(0)}; // 'd' field
   int editWidth{edit.width.value_or(0)}; // 'w' field
@@ -389,8 +389,8 @@ bool RealOutputEditing<binaryPrecision>::EditEorDOutput(const DataEdit &edit) {
 }
 
 // 13.7.2.3.2 in F'2018
-template <int binaryPrecision>
-bool RealOutputEditing<binaryPrecision>::EditFOutput(const DataEdit &edit) {
+template <int KIND>
+bool RealOutputEditing<KIND>::EditFOutput(const DataEdit &edit) {
   addSpaceBeforeCharacter(io_);
   int fracDigits{edit.digits.value_or(0)}; // 'd' field
   const int editWidth{edit.width.value_or(0)}; // 'w' field
@@ -496,8 +496,8 @@ bool RealOutputEditing<binaryPrecision>::EditFOutput(const DataEdit &edit) {
 }
 
 // 13.7.5.2.3 in F'2018
-template <int binaryPrecision>
-DataEdit RealOutputEditing<binaryPrecision>::EditForGOutput(DataEdit edit) {
+template <int KIND>
+DataEdit RealOutputEditing<KIND>::EditForGOutput(DataEdit edit) {
   edit.descriptor = 'E';
   int editWidth{edit.width.value_or(0)};
   int significantDigits{
@@ -536,9 +536,8 @@ DataEdit RealOutputEditing<binaryPrecision>::EditForGOutput(DataEdit edit) {
 }
 
 // 13.10.4 in F'2018
-template <int binaryPrecision>
-bool RealOutputEditing<binaryPrecision>::EditListDirectedOutput(
-    const DataEdit &edit) {
+template <int KIND>
+bool RealOutputEditing<KIND>::EditListDirectedOutput(const DataEdit &edit) {
   decimal::ConversionToDecimalResult converted{Convert(1, edit.modes.round)};
   if (IsInfOrNaN(converted)) {
     return EditEorDOutput(edit);
@@ -558,8 +557,8 @@ bool RealOutputEditing<binaryPrecision>::EditListDirectedOutput(
 }
 
 // 13.7.5.2.6 in F'2018
-template <int binaryPrecision>
-bool RealOutputEditing<binaryPrecision>::EditEXOutput(const DataEdit &) {
+template <int KIND>
+bool RealOutputEditing<KIND>::EditEXOutput(const DataEdit &) {
   io_.GetIoErrorHandler().Crash(
       "not yet implemented: EX output editing"); // TODO
 }


        


More information about the flang-commits mailing list