Refine documentation of libm exceptions goals [committed]

Message ID alpine.DEB.2.10.1502172341550.26150@digraph.polyomino.org.uk
State Committed
Headers

Commit Message

Joseph Myers Feb. 17, 2015, 11:42 p.m. UTC
  This patch refines the math.texi documentation of the goals for when
libm function raise the inexact and underflow exceptions.  The
previous text was problematic in some cases around the underflow
threshold.

* Strictly, it would have meant that if the mathematical result of pow
  was very slightly below DBL_MIN, for example, it was required to
  raise the underflow exception; although normally a few ulps error
  would be OK, if that error meant the computed value was slightly
  above DBL_MIN it would fail the previously described underflow
  exception goal.

* Similarly, strict IEEE semantics would imply that sin (DBL_MIN), in
  round-to-nearest mode, underflows on before-rounding but not
  after-rounding architectures, while returning DBL_MIN; the previous
  wording would have required an underflow exception, so preventing
  checks for a result with absolute value below DBL_MIN from being
  sufficient checks to determine whether the exception is required.
  (Under the previous wording, checks for a result with absolute value
  <= DBL_MIN wouldn't have been sufficient either, because in
  FE_TOWARDZERO mode a result of DBL_MIN definitely does not result
  from an underflowing infinite-precision result.)

* The previous wording about rounding infinite-precision values could
  be taken to mean all exceptions including "inexact" must be
  consistent with some such value.  That would mean that a result of
  DBL_MIN in FE_UPWARD mode with "inexact" raised must also have
  "underflow" raised on before-rounding architectures.  Again, that
  would cause problems for computing a result (possibly with spurious
  "inexact" exceptions) and then using a rounding-mode-independent
  test for results with absolute value below DBL_MIN to determine
  whether an underflow exception must be forced in case the underflows
  from intermediate computations happened to be exact.

By refining the documentation, this patch avoids stating goals for
accuracy close to the underflow threshold that were stricter than
applied anywhere else, and allows the implementation strategy of:
compute a result within a few ulps, taking care to avoid underflows in
intermediate computations, then force an underflow exception if that
result was subnormal.  Only fully-defined functions such as fma need
to take greater care about the exact underflow threshold (including
its dependence on whether the architecture is before-rounding or
after-rounding, and on the rounding mode on after-rounding
architectures).

(If the rounding mode is changed as part of the computation, it's
still necessary to ensure that not just intermediate computations, but
the final computation of the result to be returned, do not raise
underflow if that result is the least normal value and underflow would
be inconsistent with the original rounding mode.  Since such code can
readily discard exceptions as part of saving and restoring the
rounding mode - SET_RESTORE_ROUND_NOEX etc. - I don't think that
should be a problem in practice.)

Committed.

2015-02-17  Joseph Myers  <joseph@codesourcery.com>

	* manual/math.texi (Errors in Math Functions): Clarify goals
	regarding inexact and underflow exceptions.
  

Comments

Szabolcs Nagy Feb. 18, 2015, 4:47 p.m. UTC | #1
* Joseph Myers <joseph@codesourcery.com> [2015-02-17 23:42:32 +0000]:
> This patch refines the math.texi documentation of the goals for when
> libm function raise the inexact and underflow exceptions.  The
> previous text was problematic in some cases around the underflow
> threshold.
> 
> * Strictly, it would have meant that if the mathematical result of pow
>   was very slightly below DBL_MIN, for example, it was required to
>   raise the underflow exception; although normally a few ulps error
>   would be OK, if that error meant the computed value was slightly
>   above DBL_MIN it would fail the previously described underflow
>   exception goal.
> 
> * Similarly, strict IEEE semantics would imply that sin (DBL_MIN), in
>   round-to-nearest mode, underflows on before-rounding but not
>   after-rounding architectures, while returning DBL_MIN; the previous
>   wording would have required an underflow exception, so preventing
>   checks for a result with absolute value below DBL_MIN from being
>   sufficient checks to determine whether the exception is required.
>   (Under the previous wording, checks for a result with absolute value
>   <= DBL_MIN wouldn't have been sufficient either, because in
>   FE_TOWARDZERO mode a result of DBL_MIN definitely does not result
>   from an underflowing infinite-precision result.)
> 
> * The previous wording about rounding infinite-precision values could
>   be taken to mean all exceptions including "inexact" must be
>   consistent with some such value.  That would mean that a result of
>   DBL_MIN in FE_UPWARD mode with "inexact" raised must also have
>   "underflow" raised on before-rounding architectures.  Again, that
>   would cause problems for computing a result (possibly with spurious
>   "inexact" exceptions) and then using a rounding-mode-independent
>   test for results with absolute value below DBL_MIN to determine
>   whether an underflow exception must be forced in case the underflows
>   from intermediate computations happened to be exact.
> 
> By refining the documentation, this patch avoids stating goals for
> accuracy close to the underflow threshold that were stricter than
> applied anywhere else, and allows the implementation strategy of:
> compute a result within a few ulps, taking care to avoid underflows in
> intermediate computations, then force an underflow exception if that
> result was subnormal.  Only fully-defined functions such as fma need
> to take greater care about the exact underflow threshold (including
> its dependence on whether the architecture is before-rounding or
> after-rounding, and on the rounding mode on after-rounding
> architectures).
> 

this is an interesting issue because iso c annex f forbids the
omission of underflow right now, which is hard to achive unless
libm checks <= DBL_MIN instead of the sensible < DBL_MIN and
raises spurious underflow for a lot of exact (or non-tiny) DBL_MIN
results (which is allowed by the standard)

(FLT_EVAL_METHOD!=0 platforms add further complication to this
issue on the implementation side, and there builtin operations
like 'a=b*c;' can omit underflow because of double rounding,
but fma in libm is not allowed to..)

i think the requirement in the standard is suboptimal: reasonable
implementations are hard to do, but the slow and useless 'always
raise underflow' is correct.

(this may be worth a wg14 defect report, my guess is that there
does not exist an implementation that has conforming and
reasonable underflow behaviour)

> (If the rounding mode is changed as part of the computation, it's
> still necessary to ensure that not just intermediate computations, but
> the final computation of the result to be returned, do not raise
> underflow if that result is the least normal value and underflow would
> be inconsistent with the original rounding mode.  Since such code can
> readily discard exceptions as part of saving and restoring the
> rounding mode - SET_RESTORE_ROUND_NOEX etc. - I don't think that
> should be a problem in practice.)
> 
> Committed.
> 
> 2015-02-17  Joseph Myers  <joseph@codesourcery.com>
> 
> 	* manual/math.texi (Errors in Math Functions): Clarify goals
> 	regarding inexact and underflow exceptions.
> 
> diff --git a/manual/math.texi b/manual/math.texi
> index 206021c..72f3fda 100644
> --- a/manual/math.texi
> +++ b/manual/math.texi
> @@ -1313,7 +1313,9 @@ exact value passed as the input.  Exceptions are raised appropriately
>  for this value and in accordance with IEEE 754 / ISO C / POSIX
>  semantics, and it is then rounded according to the current rounding
>  direction to the result that is returned to the user.  @code{errno}
> -may also be set (@pxref{Math Error Reporting}).
> +may also be set (@pxref{Math Error Reporting}).  (The ``inexact''
> +exception may be raised, or not raised, even if this is inconsistent
> +with the infinite-precision value.)
>  
>  @item
>  For the IBM @code{long double} format, as used on PowerPC GNU/Linux,
> @@ -1344,11 +1346,16 @@ subnormal (in each case, with the correct sign), according to the
>  current rounding direction and with the underflow exception raised.
>  
>  @item
> -Where the mathematical result underflows and is not exactly
> -representable as a floating-point value, the underflow exception is
> -raised (so there may be spurious underflow exceptions in cases where
> -the underflowing result is exact, but not missing underflow exceptions
> -in cases where it is inexact).
> +Where the mathematical result underflows (before rounding) and is not
> +exactly representable as a floating-point value, the function does not
> +behave as if the computed infinite-precision result is an exact value
> +in the subnormal range.  This means that the underflow exception is
> +raised other than possibly for cases where the mathematical result is
> +very close to the underflow threshold and the function behaves as if
> +it computes an infinite-precision result that does not underflow.  (So
> +there may be spurious underflow exceptions in cases where the
> +underflowing result is exact, but not missing underflow exceptions in
> +cases where it is inexact.)
>  
>  @item
>  @Theglibc{} does not aim for functions to satisfy other properties of
> 
> -- 
> Joseph S. Myers
> joseph@codesourcery.com
  
Joseph Myers Feb. 18, 2015, 5:25 p.m. UTC | #2
On Wed, 18 Feb 2015, Szabolcs Nagy wrote:

> this is an interesting issue because iso c annex f forbids the
> omission of underflow right now, which is hard to achive unless
> libm checks <= DBL_MIN instead of the sensible < DBL_MIN and
> raises spurious underflow for a lot of exact (or non-tiny) DBL_MIN
> results (which is allowed by the standard)

I don't believe it forbids computing an imprecise result that happens to 
be (exactly) DBL_MIN or more, and so doesn't underflow.
  
Szabolcs Nagy Feb. 18, 2015, 6:10 p.m. UTC | #3
* Joseph Myers <joseph@codesourcery.com> [2015-02-18 17:25:38 +0000]:
> On Wed, 18 Feb 2015, Szabolcs Nagy wrote:
> 
> > this is an interesting issue because iso c annex f forbids the
> > omission of underflow right now, which is hard to achive unless
> > libm checks <= DBL_MIN instead of the sensible < DBL_MIN and
> > raises spurious underflow for a lot of exact (or non-tiny) DBL_MIN
> > results (which is allowed by the standard)
> 
> I don't believe it forbids computing an imprecise result that happens to 
> be (exactly) DBL_MIN or more, and so doesn't underflow.
> 

well, there are no precision requirements on not exactly-defined math
functions, but with that interpretation an implementation which never
raises underflow is also correct: it can claim that it exactly computed
an incorrect result so there is no precision loss and thus no underflow

but this kind of makes underflow exceptions in libm unreliable from the
application point of view: they can be omitted anywhere and raised
spuriously anywhere (unless the implementation documents further guarantees
like glibc does).

i consider this as a loophole in the spec
  
Joseph Myers Feb. 18, 2015, 6:45 p.m. UTC | #4
On Wed, 18 Feb 2015, Szabolcs Nagy wrote:

> * Joseph Myers <joseph@codesourcery.com> [2015-02-18 17:25:38 +0000]:
> > On Wed, 18 Feb 2015, Szabolcs Nagy wrote:
> > 
> > > this is an interesting issue because iso c annex f forbids the
> > > omission of underflow right now, which is hard to achive unless
> > > libm checks <= DBL_MIN instead of the sensible < DBL_MIN and
> > > raises spurious underflow for a lot of exact (or non-tiny) DBL_MIN
> > > results (which is allowed by the standard)
> > 
> > I don't believe it forbids computing an imprecise result that happens to 
> > be (exactly) DBL_MIN or more, and so doesn't underflow.
> > 
> 
> well, there are no precision requirements on not exactly-defined math
> functions, but with that interpretation an implementation which never
> raises underflow is also correct: it can claim that it exactly computed
> an incorrect result so there is no precision loss and thus no underflow

Yes.  This falls under the general implementation-defined accuracy of libm 
functions.
  
Rich Felker Feb. 19, 2015, 2:17 a.m. UTC | #5
On Wed, Feb 18, 2015 at 06:45:38PM +0000, Joseph Myers wrote:
> On Wed, 18 Feb 2015, Szabolcs Nagy wrote:
> 
> > * Joseph Myers <joseph@codesourcery.com> [2015-02-18 17:25:38 +0000]:
> > > On Wed, 18 Feb 2015, Szabolcs Nagy wrote:
> > > 
> > > > this is an interesting issue because iso c annex f forbids the
> > > > omission of underflow right now, which is hard to achive unless
> > > > libm checks <= DBL_MIN instead of the sensible < DBL_MIN and
> > > > raises spurious underflow for a lot of exact (or non-tiny) DBL_MIN
> > > > results (which is allowed by the standard)
> > > 
> > > I don't believe it forbids computing an imprecise result that happens to 
> > > be (exactly) DBL_MIN or more, and so doesn't underflow.
> > > 
> > 
> > well, there are no precision requirements on not exactly-defined math
> > functions, but with that interpretation an implementation which never
> > raises underflow is also correct: it can claim that it exactly computed
> > an incorrect result so there is no precision loss and thus no underflow
> 
> Yes.  This falls under the general implementation-defined accuracy of libm 
> functions.

I think this is a stretch to say that implementation-defined accuracy
allows an implementation to falsely report a result as exact when it's
not. For all functions in the math library it's relatively trivial to
know that the result is non-exact; only a small number of functions in
a small number of cases even admit exact results.

Rich
  
Joseph Myers Feb. 19, 2015, 10:29 a.m. UTC | #6
On Wed, 18 Feb 2015, Rich Felker wrote:

> > > well, there are no precision requirements on not exactly-defined math
> > > functions, but with that interpretation an implementation which never
> > > raises underflow is also correct: it can claim that it exactly computed
> > > an incorrect result so there is no precision loss and thus no underflow
> > 
> > Yes.  This falls under the general implementation-defined accuracy of libm 
> > functions.
> 
> I think this is a stretch to say that implementation-defined accuracy
> allows an implementation to falsely report a result as exact when it's
> not. For all functions in the math library it's relatively trivial to

I see that as being potentially a < 1ulp error.  There is *never* any 
requirement (except for fma, sqrt, etc.) for "inexact" exceptions to be 
correct (in either direction), so this is just about whether there is a 
stricter requirement in the underflow case.  And C99 and C11 Annex F bind 
to IEEE 754-1985, which permits denormalization loss as an alternative to 
inexactness for when underflow is raised (and many of the cases where it's 
missed in practice correspond to cases of scaling down a normal result, 
where the scaling is exact - i.e., no denormalization loss).  (Whether 
libm functions not directly bound to IEEE operations are covered by the 
constraint that all operations raise underflow under the same conditions, 
so that they can't use "denormalization loss" where basic arithmetic 
operations use "inexact result", is doubtful.)
  

Patch

diff --git a/manual/math.texi b/manual/math.texi
index 206021c..72f3fda 100644
--- a/manual/math.texi
+++ b/manual/math.texi
@@ -1313,7 +1313,9 @@  exact value passed as the input.  Exceptions are raised appropriately
 for this value and in accordance with IEEE 754 / ISO C / POSIX
 semantics, and it is then rounded according to the current rounding
 direction to the result that is returned to the user.  @code{errno}
-may also be set (@pxref{Math Error Reporting}).
+may also be set (@pxref{Math Error Reporting}).  (The ``inexact''
+exception may be raised, or not raised, even if this is inconsistent
+with the infinite-precision value.)
 
 @item
 For the IBM @code{long double} format, as used on PowerPC GNU/Linux,
@@ -1344,11 +1346,16 @@  subnormal (in each case, with the correct sign), according to the
 current rounding direction and with the underflow exception raised.
 
 @item
-Where the mathematical result underflows and is not exactly
-representable as a floating-point value, the underflow exception is
-raised (so there may be spurious underflow exceptions in cases where
-the underflowing result is exact, but not missing underflow exceptions
-in cases where it is inexact).
+Where the mathematical result underflows (before rounding) and is not
+exactly representable as a floating-point value, the function does not
+behave as if the computed infinite-precision result is an exact value
+in the subnormal range.  This means that the underflow exception is
+raised other than possibly for cases where the mathematical result is
+very close to the underflow threshold and the function behaves as if
+it computes an infinite-precision result that does not underflow.  (So
+there may be spurious underflow exceptions in cases where the
+underflowing result is exact, but not missing underflow exceptions in
+cases where it is inexact.)
 
 @item
 @Theglibc{} does not aim for functions to satisfy other properties of