ISO/ IEC JTC1/SC22/WG14 N1024

Document: WG14 N1024
Date:     09-Sep-2003


CORRECTIONS TO REQUIREMENTS ON
INEXACT FLOATING-POINT EXCEPTIONS

P.J. Plauger
Dinkumware, Ltd.
[email protected]

IEC 60559 says very little about the setting of the inexact
floating-point exception. C99 perhaps says a bit too much.
Inexact is a condition that can arise when computing an expression
as innocuous as 2.0/3.0, so it happens all the time during
floating-point computations. It is thus arguably of little
practical use. And it is rather difficult to avoid in writing
math functions. Requiring math functions to set, or not set,
inexact is thus arguably of more cost than benefit.

What follows is a review of certain statements in the C99
Standard, with suggestions for making them more sensible.

7.12.9.3 promises that nearbyint will *not* set inexact.
This is a tiresome but not onerous requirement. It is also
all that distinguishes nearbyint from rint, so the requirement
should probably be retained.

7.12.9.4 says that rint:

: *may* raise the inexact floating-point exception if the
: result differs in value from the argument.

This grants license to perform faster operations than are permitted
nearbyint, but doesn't promise to reliably set inexact. Note that
it is otherwise foolish for rint to set inexact, because the
rounded result is *always* exactly the expected result. It is
a false analogy to match the behavior of lrint or llrint, where
the library functions are arguably mapping floating-point values
to integer values, using a recipe for making the best of matters
when the integer cannot exactly represent the original value.

Given the small distinction between rint and nearbyint, the
latitude to set inexact should probably also be retained. (It
is also worth an explicit mention, despite the general license
suggested below for all math functions.)

Footnote 301 in F.4 says:

: ANSI/IEEE 854, but not IEC 60559 (ANSI/IEEE 754), directly specifies
: that floating-to-integer conversions raise the inexact
: floating-point exception for non-integer in-range values. In those
: cases where it matters, library functions can be used to effect such
: conversions with or without raising the inexact floating-point
: exception. See rint, lrint, llrint, and nearbyint in <math.h>.

This clearly overstates the case, suggesting as it does that rint
reliably sets inexact.

SUGGESTION: Remove rint from the list in the last sentence.

F.9, para 8 says:

: Whether or when the trigonometric, hyperbolic, base-e exponential,
: base-e logarithmic, error, and log gamma functions raise the
: inexact floating-point exception is implementation-defined.
: For other functions, the inexact floating-point exception is
: raised whenever the rounded result is not identical to the
: mathematical result.

Given the difficulty of avoiding inexact exceptions, and their
consequential uselessness in most cases, this license should be
extended to *all* library functions.

SUGGESTION: Change the above to:

: Whether or when library functions other than nearbyint raise the
: inexact floating-point exception is unspecified.

F.9, para 9 says:

: Whether the inexact floating-point exception can be raised
: when the rounded result actually does equal the mathematical result
: is implementation-defined. Whether the underflow (and inexact)
: floating-point exception can be raised when a result is tiny
: but not inexact is implementation-defined.(312) Otherwise, as
: implied by F.7.6, the <math.h> functions do not raise spurious
: floating-point exceptions (detectable by the user).

The first sentence is mooted by the earlier suggested change.
The second sentence (and the footnote, discussed below) doesn't
go far enough. Avoiding intermediate underflows can be as
annoying, and fruitless, as avoiding intermediate inexact reports.
Library functions *should* report underflow if the final result
underflows, but they should also have the latitude not to avoid
reporting intermediate underflows.

SUGGESTION: Change the above to:

: Whether or when library functions raise an undeserved underflow
:  floating-point exception is unspecified.(312) Otherwise, as
: implied by F.7.6, the <math.h> functions do not raise spurious
: floating-point exceptions (detectable by the user).

Footnote 312 says:

: It is intended that undeserved underflow and inexact
: floating-point exceptions are raised only if determining
: inexactness would be too costly.

SUGGESTION: Change the above to:

: It is intended that undeserved underflow and inexact
: floating-point exceptions are raised only if avoiding them
: would be too costly.

F.9, para 10 says:

: Whether the functions honor the rounding direction mode is
: implementation-defined.

This is inaccurate, since some functions (such as rint) are
obliged to honor the rounding direction mode.

SUGGESTION: Change the above to:

: Whether the functions honor the rounding direction mode is
: implementation-defined, unless explicitly specified otherwise.

F.9.6.4 says:

: The rint functions differ from the nearbyint functions only in
: that they do raise the inexact floating-point exception if
: the result differs in value from the argument.

This contradicts 7.12.9.4, which does not require rint to set
inexact.

SUGGESTION: Change the above to:

: The rint functions differ from the nearbyint functions only in
: that they may raise the inexact floating-point exception if
: the result differs in value from the argument.

F9.8.3 says:

: - nextafter(x, y) raises the overflow and inexact
: floating-point exceptions for x finite and the function value
: infinite.
:  nextafter(x, y) raises the underflow and inexact
: floating-point exceptions for the function value subnormal or
: zero and x != y.

This is inconsistent with the general license for reporting overflow
and underflow in J.3.1.2, which makes the setting of inexact with
either of these exceptions implementation defined. It is also
inconsistent with the general license for not reporting underflow
on tiny results in J.3.6.

SUGGESTION: Change the above to:

: - nextafter(x, y) raises the overflow floating-point
: exception for x finite and the function value infinite.
:  nextafter(x, y) raises the underflow floating-point
: exception for the function value zero and x != y.
:  nextafter(x, y) may raise the underflow floating-point
: exception for the function value subnormal and x != y.

J.3.1.2 includes as implementation-defined behavior:

:  Whether or when the trigonometric, hyperbolic, base-e
: exponential, base-e logarithmic, error, and log gamma
: functions raise the inexact floating-point exception
: in an IEC 60559 conformant implementation (F.9).

This should be unspecified behavior, not implementation defined.

SUGGESTION: Remove the above.