Skip to content

Commit

Permalink
[flang] Fix SPACING() of very small values
Browse files Browse the repository at this point in the history
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
  • Loading branch information
klausler committed May 24, 2023
1 parent 1234fc3 commit d71297c
Show file tree
Hide file tree
Showing 3 changed files with 7 additions and 5 deletions.
6 changes: 3 additions & 3 deletions flang/lib/Evaluate/real.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down
5 changes: 3 additions & 2 deletions flang/runtime/numeric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down
1 change: 1 addition & 0 deletions flang/test/Evaluate/fold-spacing.f90
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit d71297c

Please sign in to comment.