[flang-commits] [flang] [flang][runtime] Fix edge cases with ROUND=UP/DOWN (PR #67508)
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Fri Sep 29 14:19:13 PDT 2023
https://github.com/klausler updated https://github.com/llvm/llvm-project/pull/67508
>From 242b27a50319c511e7209928d655bb3f40b4a83c Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Tue, 26 Sep 2023 17:20:04 -0700
Subject: [PATCH] [flang][runtime] Fix edge cases with ROUND=UP/DOWN
When an unrepresentable nonzero real input value with a
very small exponent is currently being read in as zero,
don't neglect ROUND=UP/DOWN; return the least nonzero
subnormal value instead when appropriate.
---
flang/lib/Decimal/binary-to-decimal.cpp | 3 ++-
flang/lib/Decimal/decimal-to-binary.cpp | 30 +++++++++++++++++--------
2 files changed, 23 insertions(+), 10 deletions(-)
diff --git a/flang/lib/Decimal/binary-to-decimal.cpp b/flang/lib/Decimal/binary-to-decimal.cpp
index 7b31d02b292e48a..55fc548a6979bd3 100644
--- a/flang/lib/Decimal/binary-to-decimal.cpp
+++ b/flang/lib/Decimal/binary-to-decimal.cpp
@@ -373,7 +373,8 @@ STREAM &BigRadixFloatingPointNumber<PREC, LOG10RADIX>::Dump(STREAM &o) const {
if (isNegative_) {
o << '-';
}
- o << "10**(" << exponent_ << ") * ...\n";
+ o << "10**(" << exponent_ << ") * ... (rounding "
+ << static_cast<int>(rounding_) << ")\n";
for (int j{digits_}; --j >= 0;) {
std::string str{std::to_string(digit_[j])};
o << std::string(20 - str.size(), ' ') << str << " [" << j << ']';
diff --git a/flang/lib/Decimal/decimal-to-binary.cpp b/flang/lib/Decimal/decimal-to-binary.cpp
index c8c7b23329e00ce..d5b66b9fb933888 100644
--- a/flang/lib/Decimal/decimal-to-binary.cpp
+++ b/flang/lib/Decimal/decimal-to-binary.cpp
@@ -257,13 +257,20 @@ ConversionToBinaryResult<PREC> IntermediateFloat<PREC>::ToBinary(
flags |= Inexact;
}
if (fraction == 0 && guard <= oneHalf) {
- return {Binary{}, static_cast<enum ConversionResultFlags>(flags)};
- }
- // The value is nonzero; normalize it.
- while (fraction < topBit && expo > 1) {
- --expo;
- fraction = fraction * 2 + (guard >> (guardBits - 2));
- guard = (((guard >> (guardBits - 2)) & 1) << (guardBits - 1)) | (guard & 1);
+ if ((!isNegative && rounding == RoundUp) ||
+ (isNegative && rounding == RoundDown)) {
+ // round to minimum nonzero value
+ } else {
+ return {Binary{}, static_cast<enum ConversionResultFlags>(flags)};
+ }
+ } else {
+ // The value is nonzero; normalize it.
+ while (fraction < topBit && expo > 1) {
+ --expo;
+ fraction = fraction * 2 + (guard >> (guardBits - 2));
+ guard =
+ (((guard >> (guardBits - 2)) & 1) << (guardBits - 1)) | (guard & 1);
+ }
}
// Apply rounding
bool incr{false};
@@ -330,8 +337,13 @@ BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ConvertToBinary() {
exponent_ += digits_ * log10Radix;
// Sanity checks for ridiculous exponents
static constexpr int crazy{2 * Real::decimalRange + log10Radix};
- if (exponent_ < -crazy) { // underflow to +/-0.
- return {Real{SignBit()}, Inexact};
+ if (exponent_ < -crazy) {
+ if ((!isNegative_ && rounding_ == RoundUp) ||
+ (isNegative_ && rounding_ == RoundDown)) {
+ return {Real{Raw{1} | SignBit()}}; // return least nonzero value
+ } else { // underflow to +/-0.
+ return {Real{SignBit()}, Inexact};
+ }
} else if (exponent_ > crazy) { // overflow to +/-Inf.
return {Real{Infinity()}, Overflow};
}
More information about the flang-commits
mailing list