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

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