Skip to content

Commit d71297c

Browse files
committed
[flang] Fix SPACING() of very small values
SPACING() must return TINY() for zero arguments (which we do) and also for subnormal values smaller than TINY() in absolute value, which we get wrong. Fix folding and the runtime. Differential Revision: https://reviews.llvm.org/D151272
1 parent 1234fc3 commit d71297c

File tree

3 files changed

+7
-5
lines changed

3 files changed

+7
-5
lines changed

flang/lib/Evaluate/real.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -745,12 +745,12 @@ template <typename W, int P> Real<W, P> Real<W, P>::SPACING() const {
745745
return *this;
746746
} else if (IsInfinite()) {
747747
return NotANumber();
748-
} else if (IsZero()) {
749-
return TINY();
748+
} else if (IsZero() || IsSubnormal()) {
749+
return TINY(); // mandated by standard
750750
} else {
751751
Real result;
752752
result.Normalize(false, Exponent(), Fraction::MASKR(1));
753-
return result;
753+
return result.IsZero() ? TINY() : result;
754754
}
755755
}
756756

flang/runtime/numeric.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,9 @@ template <int PREC, typename T> inline T Spacing(T x) {
239239
// subnormal.
240240
return std::numeric_limits<T>::min(); // 0 -> TINY(x)
241241
} else {
242-
return std::ldexp(
243-
static_cast<T>(1.0), std::ilogb(x) + 1 - PREC); // 2**(e-p)
242+
T result{
243+
std::ldexp(static_cast<T>(1.0), std::ilogb(x) + 1 - PREC)}; // 2**(e-p)
244+
return result == 0 ? /*TINY(x)*/ std::numeric_limits<T>::min() : result;
244245
}
245246
}
246247

flang/test/Evaluate/fold-spacing.f90

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ module m
77
logical, parameter :: test_4 = spacing(0.) == tiny(0.)
88
logical, parameter :: test_5 = spacing(tiny(0.)) == 1.e-45
99
logical, parameter :: test_6 = spacing(8388608.) == 1.
10+
logical, parameter :: test_7 = spacing(spacing(tiny(.0))) == tiny(0.)
1011
logical, parameter :: test_11 = rrspacing(3.0) == scale(0.75, 24)
1112
logical, parameter :: test_12 = rrspacing(-3.0) == scale(0.75, 24)
1213
logical, parameter :: test_13 = rrspacing(3.0d0) == scale(0.75, 53)

0 commit comments

Comments
 (0)