[flang-commits] [flang] [flang][runtime] Resume rounding hexadecimal floating-point input (PR #77006)

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Thu Jan 4 13:25:37 PST 2024


https://github.com/klausler created https://github.com/llvm/llvm-project/pull/77006

This reverts commit cab156c4129e5948a6322054480e66d3ca17b919, and adds language to Extensions.md documenting the discrepancy with the letter of the language standard.

>From 5298bbb346917352f69a61fdb85231bab9928300 Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Thu, 4 Jan 2024 13:13:51 -0800
Subject: [PATCH] [flang][runtime] Resume rounding hexadecimal floating-point
 input

This reverts commit cab156c4129e5948a6322054480e66d3ca17b919, and
adds language to Extensions.md documenting the discrepancy with
the letter of the language standard.
---
 flang/docs/Extensions.md     |  9 ++++-----
 flang/runtime/edit-input.cpp | 38 +++++++++++++++++++++++++++++++++---
 2 files changed, 39 insertions(+), 8 deletions(-)

diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md
index 16eb67f2e27c812..c71beb5262439f6 100644
--- a/flang/docs/Extensions.md
+++ b/flang/docs/Extensions.md
@@ -648,11 +648,10 @@ end
   only in function references, but not an explicit `INTRINSIC` statement,
   its name is not brought into other scopes by a `USE` statement.
 
-* Should hexadecimal floating-point input editing apply any rounding?
-  F'2023 subclause 13.7.2.3.8 only discusses rounding in the context of
-  decimal-to-binary conversion; it would seem to not apply, and so
-  we don't round.  This seems to be how the Intel Fortran compilers
-  behave.
+* The subclause on rounding in formatted I/O (13.7.2.3.8 in F'2023)
+  only discusses rounding for decimal-to/from-binary conversions,
+  omitting any mention of rounding for hexadecimal conversions.
+  As other compilers do apply rounding, so does this one.
 
 ## De Facto Standard Features
 
diff --git a/flang/runtime/edit-input.cpp b/flang/runtime/edit-input.cpp
index 6d4fa588cbf60d0..385a36174ed5958 100644
--- a/flang/runtime/edit-input.cpp
+++ b/flang/runtime/edit-input.cpp
@@ -627,6 +627,31 @@ decimal::ConversionToBinaryResult<binaryPrecision> ConvertHexadecimal(
       fraction <<= 1;
       --expo;
     }
+    // Rounding
+    bool increase{false};
+    switch (rounding) {
+    case decimal::RoundNearest: // RN & RP
+      increase = roundingBit && (guardBit | ((int)fraction & 1));
+      break;
+    case decimal::RoundUp: // RU
+      increase = !isNegative && (roundingBit | guardBit);
+      break;
+    case decimal::RoundDown: // RD
+      increase = isNegative && (roundingBit | guardBit);
+      break;
+    case decimal::RoundToZero: // RZ
+      break;
+    case decimal::RoundCompatible: // RC
+      increase = roundingBit != 0;
+      break;
+    }
+    if (increase) {
+      ++fraction;
+      if (fraction >> binaryPrecision) {
+        fraction >>= 1;
+        ++expo;
+      }
+    }
   }
   // Package & return result
   constexpr RawType significandMask{(one << RealType::significandBits) - 1};
@@ -637,9 +662,16 @@ decimal::ConversionToBinaryResult<binaryPrecision> ConvertHexadecimal(
     expo = 0; // subnormal
     flags |= decimal::Underflow;
   } else if (expo >= RealType::maxExponent) {
-    expo = RealType::maxExponent; // +/-Inf
-    fraction = 0;
-    flags |= decimal::Overflow;
+    if (rounding == decimal::RoundToZero ||
+        (rounding == decimal::RoundDown && !isNegative) ||
+        (rounding == decimal::RoundUp && isNegative)) {
+      expo = RealType::maxExponent - 1; // +/-HUGE()
+      fraction = significandMask;
+    } else {
+      expo = RealType::maxExponent; // +/-Inf
+      fraction = 0;
+      flags |= decimal::Overflow;
+    }
   } else {
     fraction &= significandMask; // remove explicit normalization unless x87
   }



More information about the flang-commits mailing list