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

Re: [Scheme-reports] Definition of expt (was #391 - a selection of error predicates)

On 08/08/2012 07:55 AM, Alex Shinn wrote:
> On Wed, Aug 8, 2012 at 8:44 PM, Mark H Weaver<mhw@x>  wrote:
>> On 08/08/2012 02:49 AM, Alex Shinn wrote (on the WG1 list):
>>> These predicates seem random, reflecting only the
>>> historical precedent of what was stated as "signals
>>> an error" vs "is an error".  I'm not even convinced that
>>> distinction was made by design rather than the
>>> stylistic convention of the editors at the time.
>>> For expt, in particular, we added this note ourselves,
>>> and the actual text is:
>>>     0.0^z is 1.0 if z = 0.0, and 0.0 if (real-part z) is positive.
>>>     For other cases in which the first argument is zero, either
>>>     an error is signalled or an unspecified number is returned.
>>> Apart from the wording being a clumsy, saying
>>> an "error is signalled _or_ an unspecified result
>>> is returned" is the same as saying "the result is
>>> an error."
>> The text does not say "or an unspecified result is returned".  It says "or
>> an unspecified _number_ is returned".  Therefore, it is not the same.
> Not quite the same, but close enough.
> We should signal an error, or do something
> unspecified, not one or the other.

Given the tendency of the R6RS to specify so much more than other 
reports had, I suspect they had good reason to give implementations 
leeway here.  Some of the cases are surely controversial, and yet some 
implementors may have strong opinions on how they should be handled.

For example, I would argue that some of these cases (e.g. exact zero 
raised to any power that's not an exact non-negative integer) ought to 
raise an exception, others (e.g. +0.0 ^ -1.0) ought to return +inf.0, 
and others (e.g. +0.0 ^ -1.0+1.0i) should return a complex infinity 
(which some might represent as +nan.0+nan.0i, but I've recently learned 
that C99 and C11 represent as a complex number with one NaN part and one 
infinity of unspecified sign, with good reason).

>>> I propose changing the text to:
>>>     0^z is 1 if z = 0, and 0 if (real-part z) is positive.
>>>     It is an error if (real-part z) is negative.
>> You've made two questionable changes to the meaning of this definition,
>> beyond the description of what happens in the error/unspecified case.
>> 1. The current text uses "0.0" and "1.0" which suggests inexact numbers.
>> You've changed these to exact numbers.   I interpret the current text to
>> apply only when the base is an _inexact_ zero, and to specify inexact
>> results.  I interpret your proposed text as mandating exact return values,
>> and possibly also applying when the base is an exact zero.
> This was very much intentional.  The current text
> was a derivation from R5RS that was never voted
> on - I simply fixed it.

Actually, the current text is almost precisely taken from the R6RS, and 
while I disagree with many of the choices of the R6RS, they did a very 
competent job on numerics for the most part.

> The general rule we've been taking is exact zero
> causes errors, inexact zero returns whatever the
> floating point processor returns.

As far as I know, most (all?) floating-point processors don't do complex 
arithmetic directly, or at least not exponentials, so we can't rely on 
that rule here.

As Kahan notes in section 10 of "Branch Cuts for Complex Elementary 
Functions (or: Much Ado About Nothing's Sign Bit)":

   The function z^w has two different definitions.  One is recursive and
   applicable only when w is an integer:

      z^0 = 1   and   z(w+1) = z^w * z   whenever z^w exists.

   The second definition is analytic:

      z^w := limit as zeta->z of exp(w * ln(zeta)),

   provided that the limit exists using the principal value and domain
   of ln(zeta).  The limit process is necessary to cope smoothly with

More generally, limit processes are the method of choice in IEEE 754 
style arithmetic to determine the behavior of functions in the presence 
of signed zeroes and infinities.

However, I would strongly argue that limit processes are appropriate 
only for inexact arithmetic in Scheme.  More specifically, a limit 
process must be used only for inexact inputs, and must produce inexact 

An exact result must always agree with the precise mathematically 
correct result of the function in question.

In this case, if z is an exact zero, then we cannot use the analytic 
definition z^w = exp(w * ln(z)) because ln(z) is not defined at zero. 
Limit processes are not appropriate for an exact zero input.  Therefore, 
here we can rely only on the recursive definition, which applies only 
when the exponent is a non-negative integer, and I'd go further and 
require that it be exact, but reasonable people might disagree here.


Scheme-reports mailing list