[v3] Add nextup and nextdown math functions

Message ID 57567324.6030301@pacific.net
State Not applicable
Headers

Commit Message

Rical Jasan June 7, 2016, 7:09 a.m. UTC
  On 06/06/2016 10:15 AM, Rajalakshmi Srinivasaraghavan wrote:
> diff --git a/NEWS b/NEWS
> index 2341697..7aa6133 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -33,6 +33,13 @@ Version 2.24
>    group: files [SUCCESS=merge] nis
>    Implemented by Stephen Gallagher (Red Hat).
>  
> +* nextupl, nextup, nextupf, nextdownl, nextdown and nextdownf are added
> +  to libm. They are defined by TS 18661 and IEEE754-2008. The nextup functions
> +  return the next representable value in the direction of positive infinity
> +  and the nextdown functions return the next representable value in the
> +  direction of negative infinity.  These are currently enabled as GNU
> +  extension.

extensions

> +
>  Security related changes:
>  
>  * An unnecessary stack copy in _nss_dns_getnetbyname_r was removed.  It
> diff --git a/manual/arith.texi b/manual/arith.texi
> index 72682f0..ec46699 100644
> --- a/manual/arith.texi
> +++ b/manual/arith.texi
> @@ -1702,6 +1702,40 @@ These functions are identical to the corresponding versions of
>  double}.
>  @end deftypefun
>  
> +@comment math.h
> +@comment GNU
> +@deftypefun double nextup (double @var{x})
> +@comment math.h
> +@comment GNU
> +@deftypefunx float nextupf (float @var{x})
> +@comment math.h
> +@comment GNU
> +@deftypefunx {long double} nextupl (long double @var{x})
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +The @code{nextup} function returns the next representable neighbor of
> +@var{x} in the direction of positive infinity.  If @math{@var{x} =  @code{0}}

one space after =

> +the function returns the positive number of least magnitude in the type of
> +@var{x}.  If @var{x} is @code{NaN}, @code{NaN} is returned.  @code{nextup}

To adhere to the majority style of the Arithmetic chapter, those NaNs
would not be enclosed in @code{} (57:2).  In fact, their appearance in
@code{} in nextafter is the only place in the chapter that happens (and
only one other time in Mathematics).  Personally, I thought it was
strange they were all unformatted, and they probably should be
@code{NaN}, but I wanted to mention it for the sake of consistent style.

I feel like we lost information here.  Before, you had an example with
HUGE_VAL, which is gone now, but NaN showed up.  I'm not a
floating-point expert, and because of that I would like more detail
regarding the behaviour of the functions (might also be why I have so
many questions :).

The function descriptions in this chapter are pretty minimalistic, which
I think has something to do with the amount of auxiliary information
presented throughout -- this chapter does a very good job of introducing
its subject matter and providing general information on it -- but I
think we can give a description that would make our documentation of
nextup/down superior to the rest.

I've attached the beginnings of how I would approach it, but there are
some questions embedded as comments in there, which I also mention
below.  The general strategy is to attempt to address the functions'
behaviour when given any of the classifications of floating-point
numbers, as outlined in fpclassify, 20.4 Floating-Point Number
Classification Functions (NaN, infinity, 0, subnormal, normal).
Hopefully my understanding of the target values is correct, and I am
referencing the Floating Point Parameters in Appendix A correctly.

I noticed issignaling (20.4) mentions a signalling NaN (sNaN), and its
description also mentions it is part of TS 18661 and is a GNU extension.
 Is that relevant or treated specially in any way?

It seems like the really interesting case is what nextup and nextdown do
when they should increment away from their respective infinities.  I can
reason returning both infinity or the next largest value, and I can't
find anything in your documentation about those cases, so I definitely
think those need clarification.

Are subnormals treated differently than normals?  It sounds like
subnormals have their own special representation, and I'm not sure if
the step sizes between them are different than for normals.  If they
are, then do nextup and nextdown use the step size for subnormals when
given a subnormal or do they convert to the next higher or lower
normalized value (which I guess would essentially be, for example,
+/-FLT_MIN)?  Perhaps this is what "representable" is meant to imply,
but as I mentioned, not my area of expertise.  Maybe a short plug to the
effect of, "If @var{x} is subnormal, the positive/negative number of
least magnitude or zero is returned."?

Lastly, is there anything to say about floating-point exceptions?  From
a brief review of the chapter, that's the only other general topic that
caught my eye.  It's probably fine to not mention them if the behaviour
of nextup/down is as described in 20.5.1 FP Exceptions (actually, looks
like you depend on it in nextup, where you: if (isnan(x) return x + x;).
 My guess is that's why most descriptions don't mention them, but a good
number do (rint/nearbyint [inexact when arg not integer], fmod/drem
[domain error on division by zero], copysign [never]).

> +is based on TS 18661 and currently enabled as a GNU extension.
> +@end deftypefun
> +
> +@comment math.h
> +@comment GNU
> +@deftypefun double nextdown (double @var{x})
> +@comment math.h
> +@comment GNU
> +@deftypefunx float nextdownf (float @var{x})
> +@comment math.h
> +@comment GNU
> +@deftypefunx {long double} nextdownl (long double @var{x})
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +The @code{nextdown} function returns the next representable neighbor of
> +@var{x} in the direction of negative infinity.  If @math{@var{x} =  @code{0}}
> +the function returns the negative number of least magnitude in the type of
> +@var{x}.  If @var{x} is @code{NaN}, @code{NaN} is returned.  @code{nextdown}
> +is based on TS 18661 and currently enabled as a GNU extension.
> +@end deftypefun
> +
>  @cindex NaN
>  @comment math.h
>  @comment ISO

Rical
  

Comments

Joseph Myers June 7, 2016, 5:24 p.m. UTC | #1
On Tue, 7 Jun 2016, Rical Jasan wrote:

> > +the function returns the positive number of least magnitude in the type of
> > +@var{x}.  If @var{x} is @code{NaN}, @code{NaN} is returned.  @code{nextup}
> 
> To adhere to the majority style of the Arithmetic chapter, those NaNs
> would not be enclosed in @code{} (57:2).  In fact, their appearance in
> @code{} in nextafter is the only place in the chapter that happens (and
> only one other time in Mathematics).  Personally, I thought it was
> strange they were all unformatted, and they probably should be
> @code{NaN}, but I wanted to mention it for the sake of consistent style.

I don't think any should use @code, because it's not a literal sequence of 
characters in source code, but a value, that's being referred to.

> I've attached the beginnings of how I would approach it, but there are
> some questions embedded as comments in there, which I also mention
> below.  The general strategy is to attempt to address the functions'
> behaviour when given any of the classifications of floating-point
> numbers, as outlined in fpclassify, 20.4 Floating-Point Number
> Classification Functions (NaN, infinity, 0, subnormal, normal).
> Hopefully my understanding of the target values is correct, and I am
> referencing the Floating Point Parameters in Appendix A correctly.

I think in general that's a bad approach, and very repetitive.  A function 
has semantics from which you can deduce what it does for all those values.  
Some of those semantics may come from general rules; for example, that a 
function with a signaling NaN input raises the "invalid" exception, other 
than for a few non-arithmetic functions such as fabs and copysign; a 
function raising the "invalid" exception and returning a floating-point 
result returns a quiet NaN; and a function with a quiet NaN argument 
returns a quiet NaN without raising any exceptions if it does not have any 
signaling NaN arguments (except for a few special cases such as hypot 
(Inf, NaN), and the possibility of fma (0, Inf, NaN) raising "invalid").  
Pretty much no functions should do anything special for subnormals, or for 
0, and the result for infinity are generally the limits of the 
mathematical function for finite arguments.

> It seems like the really interesting case is what nextup and nextdown do
> when they should increment away from their respective infinities.  I can
> reason returning both infinity or the next largest value, and I can't
> find anything in your documentation about those cases, so I definitely
> think those need clarification.

They do what the nextUp and nextDown operations in IEEE 754-2008 do.  
That's the exact point of these functions.  The most relevant case to 
mention for infinities would seem to be nextup(+Inf) and nextdown(-Inf), 
as the cases where there aren't any more representable values in the 
relevant direction.  (And the other special cases to mention are for zero 
- that a zero result has the sign of the argument and a zero argument of 
either sign results in a nonzero result.)

> Are subnormals treated differently than normals?  It sounds like
> subnormals have their own special representation, and I'm not sure if
> the step sizes between them are different than for normals.  If they

If you aren't familiar with subnormals and other aspects of the set of 
values of an IEEE floating-point type, you aren't likely to have a use for 
these functions.

The functions that are the odd cases out are nextafter / nexttoward, that 
raise "inexact" and "underflow" for subnormal results despite those 
results not depending on the rounding mode.

> Lastly, is there anything to say about floating-point exceptions?  From

Only that these functions raise no exceptions except for sNaNs.
  
Rical Jasan June 8, 2016, 6:46 a.m. UTC | #2
On 06/07/2016 10:24 AM, Joseph Myers wrote:
> On Tue, 7 Jun 2016, Rical Jasan wrote:
> 
>>> +the function returns the positive number of least magnitude in the type of
>>> +@var{x}.  If @var{x} is @code{NaN}, @code{NaN} is returned.  @code{nextup}
>>
>> To adhere to the majority style of the Arithmetic chapter, those NaNs
>> would not be enclosed in @code{} (57:2).  In fact, their appearance in
>> @code{} in nextafter is the only place in the chapter that happens (and
>> only one other time in Mathematics).  Personally, I thought it was
>> strange they were all unformatted, and they probably should be
>> @code{NaN}, but I wanted to mention it for the sake of consistent style.
> 
> I don't think any should use @code, because it's not a literal sequence of 
> characters in source code, but a value, that's being referred to.

True, thanks for pointing that out.

>> I've attached the beginnings of how I would approach it, but there are
>> some questions embedded as comments in there, which I also mention
>> below.  The general strategy is to attempt to address the functions'
>> behaviour when given any of the classifications of floating-point
>> numbers, as outlined in fpclassify, 20.4 Floating-Point Number
>> Classification Functions (NaN, infinity, 0, subnormal, normal).
>> Hopefully my understanding of the target values is correct, and I am
>> referencing the Floating Point Parameters in Appendix A correctly.
> 
> I think in general that's a bad approach, and very repetitive.

Good to know.

> A function 
> has semantics from which you can deduce what it does for all those values.  
> Some of those semantics may come from general rules; for example, that a 
> function with a signaling NaN input raises the "invalid" exception, other 
> than for a few non-arithmetic functions such as fabs and copysign; a 
> function raising the "invalid" exception and returning a floating-point 
> result returns a quiet NaN; and a function with a quiet NaN argument 
> returns a quiet NaN without raising any exceptions if it does not have any 
> signaling NaN arguments (except for a few special cases such as hypot 
> (Inf, NaN), and the possibility of fma (0, Inf, NaN) raising "invalid").  
> Pretty much no functions should do anything special for subnormals, or for 
> 0, and the result for infinity are generally the limits of the 
> mathematical function for finite arguments.

Yes, it's quite clear now.  How did I miss all that about signalling
NaNs and quiet NaNs?  :)  Did you write this chapter?

Really, though, there was a moment where I debated taking the more
verbose approach because, as I mentioned, there was definitely a sense
of minimalism to the function descriptions which seemed to rely on the
fact the underlying material was presented thoroughly throughout the
rest of the chapter---and it generally is.

I don't believe quiet NaNs are mentioned, though, so if that just means
a normal NaN that doesn't make noise by signalling like a sNaN, it might
not hurt to introduce that language in the Infinity and NaN section.

Even weirder, I don't see "quiet" in the entire manual...

$ grep -i quiet manual/*.texi
$

>> It seems like the really interesting case is what nextup and nextdown do
>> when they should increment away from their respective infinities.  I can
>> reason returning both infinity or the next largest value, and I can't
>> find anything in your documentation about those cases, so I definitely
>> think those need clarification.
> 
> They do what the nextUp and nextDown operations in IEEE 754-2008 do.  
> That's the exact point of these functions.  The most relevant case to 
> mention for infinities would seem to be nextup(+Inf) and nextdown(-Inf), 
> as the cases where there aren't any more representable values in the 
> relevant direction.  (And the other special cases to mention are for zero 
> - that a zero result has the sign of the argument and a zero argument of 
> either sign results in a nonzero result.)

>> Are subnormals treated differently than normals?  It sounds like
>> subnormals have their own special representation, and I'm not sure if
>> the step sizes between them are different than for normals.  If they
> 
> If you aren't familiar with subnormals and other aspects of the set of 
> values of an IEEE floating-point type, you aren't likely to have a use for 
> these functions.
> 
> The functions that are the odd cases out are nextafter / nexttoward, that 
> raise "inexact" and "underflow" for subnormal results despite those 
> results not depending on the rounding mode.

So it sounds like the whole NaN issue isn't worth mentioning within
functions unless they deviate from the norm in some way, which these
don't, the infinity behaviour seems expected (though I still think
nextup(-Inf) is more interesting :), as well as the subnormal, but is
the zero behaviour you just described abnormal in some way? That seems
to be what I would expect it to do, which leaves me wondering whether
there is anything to say about these functions at all... besides "read
the rest of the chapter"...

>> Lastly, is there anything to say about floating-point exceptions?  From
> 
> Only that these functions raise no exceptions except for sNaNs.

Well there's something!  ;)


Thank you for your feedback.  I appreciate hearing your views on
documentation and formatting, and I really appreciate your taking the
time to elucidate the extra information about this whole topic.  I'll
quit hijacking this thread and let the actual developer do their thing.

Rical
  
Joseph Myers June 8, 2016, 12:40 p.m. UTC | #3
On Tue, 7 Jun 2016, Rical Jasan wrote:

> I don't believe quiet NaNs are mentioned, though, so if that just means
> a normal NaN that doesn't make noise by signalling like a sNaN, it might
> not hurt to introduce that language in the Infinity and NaN section.

NaNs are quiet by default, as per the usage in the C standard.  Yes, maybe 
the glibc manual needs to say a bit more there.

> nextup(-Inf) is more interesting :), as well as the subnormal, but is
> the zero behaviour you just described abnormal in some way? That seems

The point is that it's not about an ordering (-DBL_TRUE_MIN, -0.0, 0.0, 
DBL_TRUE_MIN) that has both -0.0 and +0.0 (like for the totalorder 
function in TS 18661-1) and goes from one to the other - but about going 
to the next value that is strictly greater or less than the argument 
(depending on the function).  And saying that then leaves the choice of 
-0.0 or +0.0 as ambiguous, so it needs to be specified.
  

Patch

diff --git a/manual/arith.texi b/manual/arith.texi
index 7daf904..5032cc9 100644
--- a/manual/arith.texi
+++ b/manual/arith.texi
@@ -1702,6 +1702,66 @@  These functions are identical to the corresponding versions of
 double}.
 @end deftypefun
 
+@comment math.h
+@comment GNU
+@deftypefun double nextup (double @var{x})
+@comment math.h
+@comment GNU
+@deftypefunx float nextupf (float @var{x})
+@comment math.h
+@comment GNU
+@deftypefunx {long double} nextupl (long double @var{x})
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+The @code{nextup} function returns the next representable neighbor of
+@var{x} in the direction of positive infinity.  The size of the step
+between @var{x} and the result depends on the type.  If
+@math{@var{x} = @code{0}}, the function returns the positive number of
+least magnitude in the type of @var{x} (e.g., @code{FLT_MIN};
+@pxref{Floating Point Parameters}).
+@c What about sNaN?
+If @var{x} is NaN, NaN is returned.
+If @var{x} is @code{INFINITY}, @code{INFINITY} is returned.
+@c Or, seeing as how there is an infinite step between
+@c -INFINITY and -FLT_MAX, is -INFINITY returned?
+If @var{x} is @code{-INFINITY}, the largest representable negative number
+is returned (e.g., @code{-FLT_MAX}; @pxref{Floating Point
+Parameters}).
+@c Any mention of subnormal vs. normal?
+@c Anything to say about exceptions, interesting or otherwise?
+
+This function is based on TS 18661 and is a GNU extension.
+@end deftypefun
+
+@comment math.h
+@comment GNU
+@deftypefun double nextdown (double @var{x})
+@comment math.h
+@comment GNU
+@deftypefunx float nextdownf (float @var{x})
+@comment math.h
+@comment GNU
+@deftypefunx {long double} nextdownl (long double @var{x})
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+The @code{nextdown} function returns the next representable neighbor of
+@var{x} in the direction of negative infinity.  The size of the step
+between @var{x} and the result depends on the type.  If
+@math{@var{x} = @code{0}}, the function returns the negative number of
+least magnitude in the type of @var{x} (e.g., @code{-FLT_MIN};
+@pxref{Floating Point Parameters}).
+@c What about sNaN?
+If @var{x} is NaN, NaN is returned.
+If @var{x} is @code{-INFINITY}, @code{-INFINITY} is returned.
+@c Or, seeing as how there is an infinite step between
+@c INFINITY and FLT_MAX, is INFINITY returned?
+If @var{x} is @code{INFINITY}, the largest representable positive number
+is returned (e.g., @code{FLT_MAX}; @pxref{Floating Point
+Parameters}).
+@c Any mention of subnormal vs. normal?
+@c Anything to say about exceptions, interesting or otherwise?
+
+This function is based on TS 18661 and is a GNU extension.
+@end deftypefun
+
 @cindex NaN
 @comment math.h
 @comment ISO