Skip to content

Commit cab156c

Browse files
authored
[flang][runtime] Don't round hexadecimal floating-point input (llvm#76586)
Fortran 2023 subclause 13.7.2.3.8 discusses input rounding only in the context of decimal-to-binary conversion. There is no mention of rounding for hexadecimal floating-point input conversion. At least one Fortran compiler seems to have interpreted this silence as implying no rounding. (Note that this is not the same thing as rounding to zero (RZ), which would return +/-HUGE() for overflow.)
1 parent 289eb99 commit cab156c

File tree

2 files changed

+9
-35
lines changed

2 files changed

+9
-35
lines changed

flang/docs/Extensions.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,12 @@ end
648648
only in function references, but not an explicit `INTRINSIC` statement,
649649
its name is not brought into other scopes by a `USE` statement.
650650

651+
* Should hexadecimal floating-point input editing apply any rounding?
652+
F'2023 subclause 13.7.2.3.8 only discusses rounding in the context of
653+
decimal-to-binary conversion; it would seem to not apply, and so
654+
we don't round. This seems to be how the Intel Fortran compilers
655+
behave.
656+
651657
## De Facto Standard Features
652658

653659
* `EXTENDS_TYPE_OF()` returns `.TRUE.` if both of its arguments have the

flang/runtime/edit-input.cpp

Lines changed: 3 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -625,31 +625,6 @@ decimal::ConversionToBinaryResult<binaryPrecision> ConvertHexadecimal(
625625
fraction <<= 1;
626626
--expo;
627627
}
628-
// Rounding
629-
bool increase{false};
630-
switch (rounding) {
631-
case decimal::RoundNearest: // RN & RP
632-
increase = roundingBit && (guardBit | ((int)fraction & 1));
633-
break;
634-
case decimal::RoundUp: // RU
635-
increase = !isNegative && (roundingBit | guardBit);
636-
break;
637-
case decimal::RoundDown: // RD
638-
increase = isNegative && (roundingBit | guardBit);
639-
break;
640-
case decimal::RoundToZero: // RZ
641-
break;
642-
case decimal::RoundCompatible: // RC
643-
increase = roundingBit != 0;
644-
break;
645-
}
646-
if (increase) {
647-
++fraction;
648-
if (fraction >> binaryPrecision) {
649-
fraction >>= 1;
650-
++expo;
651-
}
652-
}
653628
}
654629
// Package & return result
655630
constexpr RawType significandMask{(one << RealType::significandBits) - 1};
@@ -660,16 +635,9 @@ decimal::ConversionToBinaryResult<binaryPrecision> ConvertHexadecimal(
660635
expo = 0; // subnormal
661636
flags |= decimal::Underflow;
662637
} else if (expo >= RealType::maxExponent) {
663-
if (rounding == decimal::RoundToZero ||
664-
(rounding == decimal::RoundDown && !isNegative) ||
665-
(rounding == decimal::RoundUp && isNegative)) {
666-
expo = RealType::maxExponent - 1; // +/-HUGE()
667-
fraction = significandMask;
668-
} else {
669-
expo = RealType::maxExponent; // +/-Inf
670-
fraction = 0;
671-
flags |= decimal::Overflow;
672-
}
638+
expo = RealType::maxExponent; // +/-Inf
639+
fraction = 0;
640+
flags |= decimal::Overflow;
673641
} else {
674642
fraction &= significandMask; // remove explicit normalization unless x87
675643
}

0 commit comments

Comments
 (0)