[mercury-users] Re:[mercury-users] Re: [mercury-users] difference between is and =?

Richard A. O'Keefe ok at atlas.otago.ac.nz
Fri Jul 6 13:53:12 AEST 2001


I wrote:                                 vvvvvvvvvvv
	> It would make a huge amount of mathematics pointlessly difficult
                                         ^^^^^^^^^^^
	> if the axiom
	>                  0
	>     (for all x) x  = 1
	> 
	> did not hold.
	
Fergus Henderson replied
(much much later):                             vvvvvvvvv
	Not pointlessly; the point is to avoid computing erroneous results
                                               ^^^^^^^^^
	in cases where the other limit (the limit as x->0 of 0^x = 0)
	is the one desired.
	
(A) We seem to be talking past each other.  Every mathematics text I
    have checked defines x^0 as 1, no exceptions.  This is a fact
    about mathematics.  There is no *MATHEMATICAL* benefit in defining
    x^0 to be anything else.

(B) I can count on the fingers of one spleen the number of times when
    limit x->0 of 0^x has been of even the remotest relevance to any code
    I have written.  (Come to think of it:  to anyone else's code that I
    have inspected.)  That's in 25 years, much of the first few in Fortran.

(C) It is important to understand that there are two different cases,
    with potentially different criteria.

    x^n =			x: number, polynomial, matrix, &c, n: integral
        if n > 0 then (x^(n-1)) * x
	elif n = 0 then unit(x)
        else inverse(x^(-n))
        fi

    This definition even makes sense for x:A->A a function,
    where unit(x) = the identity function.

    For this case, where the exponent is constrained to be an integer,
    it is simply unforgiveable to leave x^0 undefined for any x.

    x^y =			x, y: some mix of real, complex
	exp(y * ln(x))	        some matrix cases make sense too.

    In THIS case, it makes sense to use limits in the definition, and you
    do get the 0.0^0.0 = undefined answer.

	This issue has been discussed on the C/C++ standards mailing lists
	recently.  Nick Maclaren wrote:
	
	 | The cost of returning the wrong value quietly is vastly more than the
	 | cost of having to special-case the code.

It is easy to WRITE such things.  But where is his EVIDENCE?
Note that you could make exactly the same argument for defining the
usual transcendental functions (including square root) on complex numbers,
because wherever you place the branch cuts you are pretty much certain to
"return the wrong value quietly" for someone, but that hasn't stopped the
Fortran, Lisp, Ada, C++, or C standardisers from putting them in none-the-less.

	 |  As has been known for many
	 | decades in software engineering (back to the days when it was known
	 | as good programming and language design), requiring the programmer
	 | to check for every error is disastrously unreliable - the only safe
	 | solution is to have such checks inserted automatically.
	
But requiring the programmer to check for things that are *NOT* errors
is *ALSO* disastrously unreliable.

The problem is perceived as particularly pressing in C, simply because
C tries to pretend that the two notions of power are exactly the same thing,
and applies to the integer case a restriction whose only pretext is a
certain view of the non-integer case.

0^y where y is non-integeral is a debatable case.
0^n where n is of integral type is NOT.

	However, it turns out that for LIA-2 (the Language Independent Arithmetic
	standard, part 2), Richard O'Keefe's view has in the end prevailed, at least
	for the pow(float, int) case -- see below.
	
You could equally well say that your point of view prevailed for the
non-integral case.  What really happened is that the LIA-2 people realised
that there were two DIFFERENT functions to define, and didn't make the
blunder of constraining the integral version in a way that is unmotivated
for that case.

Now, since mathematically x^y for non-integral y is an extension of x^n,
and this is a far more important defining property than the behaviour for
any particular x, there is a strong case to be made for defining 0^y = 1
also.  The floating-point power is sufficiently peculiar (note for
example that if
    rtp :: Real -> Rational -> Real
is the exponentiation function for Rational exponents,
    rtp (-27) (1/3)
is defined and equal to -3, but that
    pow(-27.0, 1.0/3.0)
would not be expected to work.  This kind of thing makes the floating-point
power an operation which is so dangerous to use _anyway_ that it doesn't
make a lot of difference _how_ you define it.

--------------------------------------------------------------------------
mercury-users mailing list
post:  mercury-users at cs.mu.oz.au
administrative address: owner-mercury-users at cs.mu.oz.au
unsubscribe: Address: mercury-users-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-users-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the users mailing list