[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: Rogue comment on Section 9 of draft 1.5.0 of Draft standard P745



Hmm...

I wasn't aware of a P745 draft that was circulating.
This would clearly appear to be a rounding error(:>).

Cheers,
DVJ


-----Original Message-----
From: stds-754@xxxxxxxxxxxxxxxxx [mailto:stds-754@xxxxxxxxxxxxxxxxx]On
Behalf Of Peter Henderson
Sent: Saturday, October 27, 2007 10:31 AM
To: bob@xxxxxxxx; stds-754@xxxxxxxx
Subject: Rogue comment on Section 9 of draft 1.5.0 of Draft standard
P745


Bob Davis,

  thankyou for making the draft available.  Below please find some
comments.  I hope they conform to the format required for rogue comments.

Regards,
Peter Henderson
------------------------- 8>< -------------------------

Subclause 9.1.1, lines 18 -- 29:
--------------------------------

This block of text should largely be removed, leaving only the text on
line 18, i.e. "Attempts to evaluate a function ... shall return a quiet
NaN and signal invalid."

Rationale:

While the procedure to provide a value for essential singularities, as
detailed in lines 19 -- 29 is ingenious, it appears largely an attempt
to justify setting pow(0,0) = 1.0.  I am not aware this approach as
being widely used in the wider mathematical community.  It also looks as
if it will be difficult to apply in general and even more difficult for
many users of numerical software to understand.

A less subjective objection to this proposed procedure is that it does
not look to be invariant with respect to changes of coordinates.  Hence,
it is unlikely to be generally useful.  Further, many functions of
interest have important symmetries and important relations to other
functions.  It is not clear this procedure will preserve these important
relationships.  The pow(x,y) function is an example of this problem, as
discussed below.

The aim of the P754 standard should be to encourage the provision of
fast, accurate implementations of standard mathematical functions, not
to provide novel definitions.  In the case of essential singularities,
it is unlikely any value chosen for the standard will be suitable for
all applications and any programmer using a function with such a
singularity will need to give consideration to how to handle these
cases.  Recommending that a quiet NaN be returned makes it simpler to
deal with these cases.  It is preferable that any functions defined in
the standard have straight forward easily intelligible definitions.

Further, since most such functions of interest in this context are
analytic over most of their domain, the implementation of the
unexceptional regions of their domain will reflect this.  In many cases,
the natural implementation is likely to return a quiet NaN, in which
case, providing a special value for essential singularities only
complicates the implementation.

Many of the points mentioned above are further discussed below, in my
comments on the pow(x,y) function.


Subclause 9.1.1, line 35:
-------------------------

The "if and only if" requirement on the inexact flag is potentially very
difficult to implement, and even when it can be, it is likely to impose
a considerable computational burden.  Preferable would be

"--- inexact:  Functions shall signal the inexact exception if the
numerical result is inexact."

i.e. allow false positives but no false negatives.


Subclause 9.1.2:
-----------------

I feel this clause would be clearer if it was broken into two
subclauses, one dealing with the special case when a function argument
is +/-0 and another with the case when the function value is zero.  In
particular, there is no mention of what value a function should take at
non-zero arguments with zero values.  Perhaps the following should be
inserted.

"If f(x) is continuous at a non-zero argument x and its value is zero at
x, then if f(x) >= 0 in a neighbourhood of x, but takes a non-zero value
for some y in all neighbourhoods of x, then f(x) shall be  +0.  If this
rule applies to -f(x), then f(x) shall be -0."

To be consistent with subclause 6.3, the following may be desirable.
But note the "should".

"If f(x) is zero in a neighbourhood of x, then f(x) should take the
value +0 in all rounding-direction attributes except
roundTowardNegative; under that attribute, the result should be -0."

The reason for the should is that it is in general be preferable to
preserve any sign symmetries of the function,  but I can't think of an
acceptable way to express this.


Subclause 9.1.2, lines 16 and 20:
----------------------------------

On my version of acrobat, the signs following the 0's in the limit
expressions do not appear in subscript font following the subcripted
zero, they appear as signs attached to the function values.  e.g.. as
"lim_{x->0} +f(x)", not "lim_{x->0+} f(x)".


Subclause 9.1.2, lines 18 and 19:
----------------------------------

Delete the reference to essential singularities, to be consisent with my
comments on Section 9.1.1 above.  Otherwise note that it is not clear
what the reference to subclause 9.2.1 is referring to.  Should it refer
to subclause 9.1.1?


Subclause 9.1.2, lines 21 and 22:
----------------------------------

I do not understand what "shall be rounded in a direction consistent
with nearby values of the same sign" refers to or the intent of this
phrase.  I suspect that it refers to the sign zero should take, but even
then, it is not clear.  Maybe "nearby values" should be "nearby
arguments". Also what does "examples include acos(x) (pi/2 is truncated
at zero)" refer to.  Is this using a symmetric definition of acos(x)?
i.e. with a discontinuity at 0 and a range -pi/2 to pi/2.  If so this is
quite non-standard, e.g. Abramowitz and Stegun, specify the range of
acos(x), they call it arccos(x), to be 0 to pi (p.79, 4.4.4).


Subclause 9.1.4, line 34:
-------------------------

Rather than "For example, see the first two cases in 9.2.1.", the
functions referred to should be explicitly named.  This would then be
consistent with the practice in subclause 9.1.2.  As it is now, there is
a real risk of error being introduced if subclause 9.2.1 is rearranged.
In fact, I think this is already in error.  I cannot see how this
subclause applies to hypot(x,y) ot compound(x,n).


Subclause 9.2, line 2:
----------------------

There is an extraneous space before the comma in "according to ,"


Subclause 9.3, Table 13:
-------------------------

sinh(x) appears twice.  In the entries for rsqrt and rootn, the
semicolons are missing between different exceptions in the "Other
exceptions" column.

The pow(x,y) function should be replaced by powr(x,y), as
described below.


Subclause 9.2.1, line 11:
-------------------------

"hypot(+/-0, +/-0) = +0." is not really necessary, as the P754 rules in
general, and also subclause 9.2.1 already imply this.


Subclause 9.2.1, lines 15 -- 18 and lines 23 -- 27:
---------------------------------------------------

I am not sure to express the following correctly, but I feel this makes
the intent of these functions clearer.  Their behaviour with respect to
exceptional arguments is follows automatically.  In particular, the
otherwise abherrant result pow(qNaN, 0) = 1.0 is justified.

State that pown(x,n) is defined as the result of calculating the
following exactly, then rounding according to the current
rounding-direction attribute:

For n=0, return Pow(x,0) = 1.0;
for n>0, return Pow(x,n) = x*Pow(x,n-1);
for n<0, return Pow(x,n) = 1.0/Pow(x, -n),

where Pow(x,n) is pow(x,n) calculated to infinite precision.

Similarly for compound(x,n).


Subclause 9.2.1, lines 28 -- 32, p.54 and lines 1 and 2, p.55:
--------------------------------------------------------------

Remove pow(x,y) and replace it with powr(x,y), defined as follows:

powr(x,y) is the function obtained by evaluating exp(y*ln(x)) exactly
and then rounding the result according to the prevailing
rounding-direction attribute.  powr(x,y) signals the invalid exception
whenever any step of the calculation of exp(y*ln(x)) would signal the
invalid exception.

Rationale:

The name powr has been chosen rather than powf, as on Unix derived
systems at least, the "f" indicates a function variant that takes single
precision arguments and returns a single precision result.

pow(x,y), as defined comes from the C library and is peculiar to C and
those languages that import the C library functionality.  It is a
stitching together of the pown(x,n) function defined in Table 13 and the
powr(x,y) function defined here.  As such, it has many undesirable
properties, especially when used to perform the calculation that
powr(x,y) performs.

In itself, the definition of pow(x,y) is complicated and potentially
confusing.  Users who desire an integral power, expect the functionality
provided by the pown(x,n) function, which will always provide a more
efficient implementation and whose behaviour for quiet NaN arguments
follows naturally from its definition.  Users who desire an real
exponent will tend to expect the behaviour provided by exp(y*ln(x)).
This is, after all, how most users would implement it themselves if it
isn't available as a library function and any implementation of
powr(x,y) is always going to run faster than pow(x,y), with all its
special cases.

Since pown(x,n) and powr(x,y), together provide all the building blocks
for an efficient implementation of pow(x,y), it is not necessary for the
P754 standard to require or define it.  This is similar to the approach
of the Language Independent Arithmetic Standard, part 2.  Leave the
definition of pow(x,y) to the C standards committee.

To see more clearly the problems with pow(x,y), consider any
optimisation problem where x**y occurs (using Fortran notation).  Then
the expectation is that x**y is continuous in x and y and that x<0 is a
range error.  For pow(x,y), if y is a zero and x is a quiet NaN, 1.0 is
returned, but the slightest change in y results in NaN.  Similarly, for
pow(x,y), if y happens to be an integral value, negative x will return a
floating point result, whereas the desired behaviour is to indicate a
range error using a quiet NaN.  Again, the slightest variation of y will
lead to a NaN.  In both cases, the desired behaviour is to return a NaN,
allowing the program to respond appropriately.  Another undesirable
property is that pow(-0,y) = -infinity when y is an odd integer, whereas
pow(+0,y) and pow(-0,z), where z is close to y, will return +infinity,
considerably complicating any program that has to deal with arguments
near the negative y axis.  In all cases, the expected continuity of x**y
does not occur when pow(x,y) is used.  Slight changes in the arguments
can produce significant changes in the result, when the natural
mathematical definition suggests otherwise.

A feature of the definition of powr(x,y) is that for (0,0),
(1,infinity), (1,-infinity) and (0,infinity), a quiet NaN is returned.
This follows naturally from the definition and any implementation based
on directly on this definition.  There is much support for having
pow(0,0)=1.  As for pow(x,y), powr(x,y), as defined above, provides the
basis for an efficient implementation of a function with the desired
behaviour.


Subclause 9.2.1, lines 5 -- 9 and 14 -- 17:
-------------------------------------------

In the definitions of both atan2Pi(y,x) and atan(y,x), the standard
defines return values for both arguments zero.  Having gone this far,
why not continue along the lines presented in  Kahan's "Branch Cuts for
Complex Elementary Functions" and define results for both arguments
infinity?  To be more precise , atan2(+/-inf,  +inf)  =  +/- pi/4 and
atan2(+/-inf, -inf) = +/- 3 pi/4.

It strikes me that the arguments against this would apply equally to the
case where both arguments are zero, in which case a quiet NaN is the
proper result for all the cases where y/x generates a quiet NaN.  The
case for defining non-NaN results for all these cases relies on the fact
that atan2 and atan2Pi have one specific purpose,  rectangular-to-polar
conversion, and it is the requirements of this application that Kahan
uses to justify the values shown above.

754 | revision | FAQ | references | list archive