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

via flang-commits flang-commits at lists.llvm.org
Thu Jan 4 13:26:04 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-runtime

Author: Peter Klausler (klausler)

<details>
<summary>Changes</summary>

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

---
Full diff: https://github.com/llvm/llvm-project/pull/77006.diff


2 Files Affected:

- (modified) flang/docs/Extensions.md (+4-5) 
- (modified) flang/runtime/edit-input.cpp (+35-3) 


``````````diff
diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md
index 16eb67f2e27c81..c71beb5262439f 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 6d4fa588cbf60d..385a36174ed595 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
   }

``````````

</details>


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


More information about the flang-commits mailing list