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

Richard A. O'Keefe ok at atlas.otago.ac.nz
Mon Apr 30 12:15:55 AEST 2001


Fergus Henderson <fjh at cs.mu.OZ.AU> wrote:

	Opinions on whether `pow(0, 0)' should be defined differ.

It would make a huge amount of mathematics pointlessly difficult
if the axiom
                 0
    (for all x) x  = 1

did not hold.  Consider for example the usual definition of evaluating
a polynomial:
                       i
    p(x) =  sum   a(i)x
           i=0..n
                             0
That works for p(0) only if 0  = 1.
                                          y
As Knuth points out, the other limit, of 0 , is of vastly less interest
and utility.

The definition of pow() in C99 is
    7.12.7.4 The pow functions
    Synopsis

	#include <math.h>
	double pow(double x, double y);
	float powf(float x, float y);
	long double powl(long double x, long double y);

    Description

    The pow functions compute x raised to the power y.
    A domain error occurs if x is finite and negative
    and y is finite and not an integer value.
    A domain error may occur if x is zero and y is less than or equal to zero.
    A range error may occur.

That is, C99 allows pow(0,0) to be an error, but does not require it.

Section F.9.4.4 The pow functions lists a lot of boundary cases involving
+/- 0 and +/- infinity, but is coyly reticent about pow(0,0).

While LIA-1 specifies bindings for Ada, Basic, C, Common Lisp, Fortran,
Modula 2, Pascal, Extended Pascal, and PL/I, it is completely silent about
pow(-,-), as LIA-1 has nothing whatsoever to say about exponentiation.

NOR DOES IEEE 754 or IEEE 854.  The IEEE standards define +, -, *, /, sqrt,
comparison, and conversion.  They do NOT define exp(), ln(), trig functions,
or anything related to them.

For LIA-2, I only have a working draft, not the actual standard.

The axioms in section 9.3 define POWER:float*float->float(0,0) to be undefined.
The axioms in section 9.4 define POWER:float*int->float(0,0) to be undefined
also, meaning that the core definitional axiom
         0
	x  = 1

has to be stated as

        POWER  (x, 0) = 1 if x ~= 0
             FI

	POWER  (0, y) = undefined if y <= 0
             FI

so we get
         0
        x  = (if x = 0 then undefined else 1)

This kind of mess makes life much harder than it needs to be.

In particular, it would make a mess of set theory.

	I think most mathematicians would define it pow in such a way
	that pow(0, 0) is undefined.

I doubt that very much.  Set theory is pretty standard.  In set theory,
	 A
	B  = the set of all functions from A to B
                               0
What happens when you compute 0  in set theory?   The number 0 is, for
excellent reasons, identified with the empty set.  The set of functions
from {} to {} has exactly one member.  So 0**0 = 1 in set theory.

Then of course you have the very foundations of computing, where for
example the natural numbers are sometimes defined as

	[0] f x = x
	[n+1] f x = [n] f (f x)

so that	[0] (BOTTOM) x is perfectly well defined.

	Personally, I think it would be better to leave pow(0, 0) undefined.

Mercury is supposed to be a language you could give to a software engineer
with a straight face.  One of the key points about software engineering is,
as Dijkstra pointed out in the 60s, "our heads are very small".  The key
question, therefore, is

     What definition would make Mercury easier to reason in and about?

My rule of thumb for such questions is "reduce the number of special cases".

If we adopt the definition
	x**0 = 1
	x**(n+1) = (x**n)*x for n > 0
in agreement with pretty much _everything_ we need for computing, that
will reduce the number of special cases.

	However, I also think that on these kinds of minor issues, if there is an
	existing standard, then it is usually better for Mercury to conform to the
	appropriate standard rather than to strike out on our own course.
	
Common Lisp:

    When power-number is a 0 (a zero of type integer),
    then the result is always one in the type of base-number,
    even if the base-number is zero (of any type).  That is:

    (expt x 0) = (coerce 1 (type-of x))

ANSI Smalltalk:

    5.6.2.27 Message:   raisedTo: operand
    Synopsis
	Answer the receiver raised to the power operand.
    Definition: <number>
	If operand conforms to <integer>, answer the result of
	sending #raisedToInteger: with argument operand to the receiver.
	...
    5.6.2.28 Message:	raisedtoInteger: operand
    Synopsis
	Answer the receiver raised to the power operand.
    Definition: <number>
	Answer the receiver raised to the power operand, which must be
	a whole number.  If the operand is a whole number greater than
	or equal to zero, then the result is the receiver raised to
	the power operand.  If operand is a negative whole number then
	the result is equivalent to the reciprocal of ... the receiver
	raised to the power operand.

which is not as clear as it might be, but turns out to mean that

	x raisedTo: 0	=> some version of 1

for any numeric x.  ANSI Common Lisp and ANSI Smalltalk count as standards,
no?

pow(0,0) is defined to be 1 in a lot of UNIX libraries.

I got really sick of having to define my own pow() function to patch around
C; it would *not* be helpful to perpetuate that muddle in Mercury.

--------------------------------------------------------------------------
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