[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
This commit is contained in:
Peter Klausler 2023-05-23 13:55:23 -07:00
parent 1234fc3021
commit d71297ce74
No known key found for this signature in database
3 changed files with 7 additions and 5 deletions

View File

@ -745,12 +745,12 @@ template <typename W, int P> Real<W, P> Real<W, P>::SPACING() const {
return *this;
} else if (IsInfinite()) {
return NotANumber();
} else if (IsZero()) {
return TINY();
} else if (IsZero() || IsSubnormal()) {
return TINY(); // mandated by standard
} else {
Real result;
result.Normalize(false, Exponent(), Fraction::MASKR(1));
return result;
return result.IsZero() ? TINY() : result;
}
}

View File

@ -239,8 +239,9 @@ template <int PREC, typename T> inline T Spacing(T x) {
// subnormal.
return std::numeric_limits<T>::min(); // 0 -> TINY(x)
} else {
return std::ldexp(
static_cast<T>(1.0), std::ilogb(x) + 1 - PREC); // 2**(e-p)
T result{
std::ldexp(static_cast<T>(1.0), std::ilogb(x) + 1 - PREC)}; // 2**(e-p)
return result == 0 ? /*TINY(x)*/ std::numeric_limits<T>::min() : result;
}
}

View File

@ -7,6 +7,7 @@ module m
logical, parameter :: test_4 = spacing(0.) == tiny(0.)
logical, parameter :: test_5 = spacing(tiny(0.)) == 1.e-45
logical, parameter :: test_6 = spacing(8388608.) == 1.
logical, parameter :: test_7 = spacing(spacing(tiny(.0))) == tiny(0.)
logical, parameter :: test_11 = rrspacing(3.0) == scale(0.75, 24)
logical, parameter :: test_12 = rrspacing(-3.0) == scale(0.75, 24)
logical, parameter :: test_13 = rrspacing(3.0d0) == scale(0.75, 53)