Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Indeterminate forms for the Num type.

3 views
Skip to first unread message

Audrey Tang

unread,
Jan 17, 2006, 10:26:26 AM1/17/06
to Perl 6 Language
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Assuming "num" uses the underlying floating point semantic (which may
turn 0/0 into NaN without raising exception), what should the default
"Num" do on these forms?

0/0
0*Inf
Inf/Inf
Inf-Inf
0**0
Inf**0
1**Inf

Several options:
- - Use whatever the underlying "num" semantics available
- - Always "fail"
- - Always "die"
- - Specify them to return some definite value.

At this moment, Pugs defines them ad-hocly to:

0/0 == die "Illegal division by zero"
0*Inf == NaN
Inf/Inf == NaN
Inf-Inf == NaN
0**0 == 1
Inf**0 == 1
1**Inf == 1

But I'd like to seek a more definite ruling.

Thanks,
Audrey
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (FreeBSD)

iD8DBQFDzQyitLPdNzw1AaARApaEAKChw0bHNA3M7OBLoeoRpootIjpy0QCfYtvT
/vNWF8SkS7MMXWDsZrDCp8I=
=vI/b
-----END PGP SIGNATURE-----

Jonathan Lang

unread,
Jan 17, 2006, 11:38:51 AM1/17/06
to Audrey Tang, Perl 6 Language
Audrey Tang wrote:
> Assuming "num" uses the underlying floating point semantic (which may
> turn 0/0 into NaN without raising exception), what should the default
> "Num" do on these forms?
>
> 0/0
> 0*Inf
> Inf/Inf
> Inf-Inf
> 0**0
> Inf**0
> 1**Inf
>
> Several options:
> - - Use whatever the underlying "num" semantics available
> - - Always "fail"
> - - Always "die"

Given a choice between the latter two, I'd rather go with Always
"fail" (i.e., return "undefined"). This lets people handle matters
with error-trapping if they like, without removing the possibility of
handling it by testing the result for "definedness".

> - - Specify them to return some definite value.
>
> At this moment, Pugs defines them ad-hocly to:
>
> 0/0 == die "Illegal division by zero"

See above; besides, math classes generally teach that 0/0 is undefined.

> 0*Inf == NaN
> Inf/Inf == NaN
> Inf-Inf == NaN

These expressions are no more NaN than Inf is. I'd handle them as:

0*Inf == undef
Inf/Inf == Inf
Inf-Inf == Inf

> 0**0 == 1
> Inf**0 == 1

I know that x**0 == 1 if x is anything other than 0 or Inf; meanwhile,
0**y == 0 if y is anything other than 0, and Inf**y == Inf if y is
anything other than 0. I'd say that these two should normally be
undef.

> 1**Inf == 1

1**y == 1 when y is anything but Inf; x**Inf == Inf if |x| is greater
than 1; and x**Inf == 0 if |x| is less than 1. Again, 1**Inf ==
undef.

> But I'd like to seek a more definite ruling.

Ditto.

--
Jonathan "Dataweaver" Lang

Doug McNutt

unread,
Jan 17, 2006, 12:38:55 PM1/17/06
to Perl 6 Language
Physicist here. One who believes -2**2 is negative.

At 23:26 +0800 1/17/06, Audrey Tang wrote:
>Several options:
>- - Use whatever the underlying "num" semantics available

That's likely to be in hardware. It might even be hard to detect without looking at the NaN returned and that would be a waste of time. Some formulas can accept a NaN argument and still provide a correct result. At the worst they return a NaN to be tested for later

>- - Always "fail"
>- - Always "die"

Those are non-conforming options See below.

>- - Specify them to return some definite value.

Only on a machine that doesn't do it in hardware or in some special perl function that's unlikely.

>At this moment, Pugs defines them ad-hocly to:
>

> 0/0 == die "Illegal division by zero" <--- wrong. 1/0 should not die either.
> 0*Inf == NaN <--- reasonable but don't re-invent the NaN bit pattern
> Inf/Inf == NaN <--- reasonable but don't re-invent the NaN bit pattern
> Inf-Inf == NaN <--- reasonable but don't re-invent the NaN bit pattern

> 0**0 == 1 <--- Not indeterminate. Answer is correct.
> Inf**0 == 1 <--- Not indeterminate. Answer is correct.
> 1**Inf == 1 <--- Not indeterminate. Answer is correct.

<http://stevehollasch.com/cgindex/coding/ieeefloat.html>


<http://en.wikipedia.org/wiki/Divide_by_zero>
>The IEEE floating-point standard, supported by almost all modern processors, specifies that every floating point arithmetic operation, including division by zero, has a well-defined result.

I can't seem to find the actual assigned NaN bit patterns for the above cases,
<http://docs.sun.com/source/816-2465/iapgCreference.html>
is helpful but doesn't get there. There may be multiple inf/inf returns in some cases depending on just which inf is involved. There are also NaN's for functions implemented in hardware like atan and exp.

--

--> In Christianity, man can have only one wife. This is known as monotony. <--

Rob Kinyon

unread,
Jan 17, 2006, 1:22:53 PM1/17/06
to Audrey Tang, Doug McNutt, Perl 6 Language
On 1/17/06, Audrey Tang <autr...@autrijus.org> wrote:
> But putter on #perl6 reports "1" on his amd64. I'd be happy we spec it
> has to have to return 1 always for boxed Num types, even though it means
> additional cycles for boxed numeric types.

Isn't the point of boxing to provide a hardware-independent dependable
solution at the cost of additional cycles?

Rob

Audrey Tang

unread,
Jan 17, 2006, 1:09:54 PM1/17/06
to Doug McNutt, Perl 6 Language
Doug McNutt wrote:
>> - - Specify them to return some definite value.
> Only on a machine that doesn't do it in hardware or in some special perl function that's unlikely.

This question arises as different platform answer things differently for
the native calculation of eg. 1**Inf.


>
>> At this moment, Pugs defines them ad-hocly to:
>>
>> 0/0 == die "Illegal division by zero" <--- wrong. 1/0 should not die either.

I personally like having 0/0 be NaN and 1/0 be Inf (as in JavaScript),
but all of Python/Perl/Ruby/Scheme/OCaml throws exceptions for them...

>> 0*Inf == NaN <--- reasonable but don't re-invent the NaN bit pattern
>> Inf/Inf == NaN <--- reasonable but don't re-invent the NaN bit pattern
>> Inf-Inf == NaN <--- reasonable but don't re-invent the NaN bit pattern

The NaN as used in Pugs is already a double-precision NaN bit pattern. :-)

>> 0**0 == 1 <--- Not indeterminate. Answer is correct.
>> Inf**0 == 1 <--- Not indeterminate. Answer is correct.
>> 1**Inf == 1 <--- Not indeterminate. Answer is correct.

On my machine (Pentium-M, FreeBSD), 1**Inf yields NaN, as demonstrated
by this Parrot program:

.sub main
$N1 = 1/0
print $N1 # inf
$N2 = 1 ** $N1
print $N2 # nan
.end

But putter on #perl6 reports "1" on his amd64. I'd be happy we spec it
has to have to return 1 always for boxed Num types, even though it means
additional cycles for boxed numeric types.

Audrey

signature.asc

Luke Palmer

unread,
Jan 17, 2006, 2:14:09 PM1/17/06
to Audrey Tang, Doug McNutt, Perl 6 Language
On 1/17/06, Audrey Tang <autr...@autrijus.org> wrote:
> I personally like having 0/0 be NaN and 1/0 be Inf (as in JavaScript),
> but all of Python/Perl/Ruby/Scheme/OCaml throws exceptions for them...

I believe we've been through this before. We go with a standard,
probably IEEE, horridly mathematically unappealing though it may be.
It will be easier to implement and it will be more predictable, both
because most other language follow standards, too.

Luke

Audrey Tang

unread,
Jan 17, 2006, 8:38:04 PM1/17/06
to Luke Palmer, Doug McNutt, Perl 6 Language
Luke Palmer wrote:
> I believe we've been through this before. We go with a standard,
> probably IEEE, horridly mathematically unappealing though it may be.
> It will be easier to implement and it will be more predictable, both
> because most other language follow standards, too.

"The good thing about standards is that there are so many to choose
from". Which IEEE standard are we following? 754-1985? 854-1987?
754r-2006 (still under discussion)?

Also, would you be happy with different treatments of Int/Int versus
Num/Num?

0/0 # fail "illegal division by zero"
0.0/0.0 # NaN

That seems to follow from the standard (ruby, ocaml, mzscheme currently
does that), but some may also argue for NaN bothways (ghc, js) or an
exception bothways (perl5, python).

Audrey

signature.asc

Audrey Tang

unread,
Jan 17, 2006, 8:50:19 PM1/17/06
to Audrey Tang, Luke Palmer, Doug McNutt, Perl 6 Language
Audrey Tang wrote:
> That seems to follow from the standard (ruby, ocaml, mzscheme currently
> does that), but some may also argue for NaN bothways (ghc, js) or an
> exception bothways (perl5, python).

Er, wait, ghc also raises an exception for (div 0 0), because it
distinguishes integer (div) with fractional (/).

However, I think one of P6's idea is that the user should not have
to care between 0 and 0.0's behaviours, so maybe it makes sense to
do the same thing (be it NaN or exception) both ways.

I'm not sure that IEEE 754/854 still applies if we want to merge the
behaviours of int/num/complex/bigint/bigrat/bignum under a Num banner.

(There is always the worse-is-better option of going with whatever
the underlying runtime does, usually determined by hardware/libm.)

Audrey

signature.asc

Darren Duncan

unread,
Jan 17, 2006, 9:59:12 PM1/17/06
to Perl 6 Language
At 9:50 AM +0800 1/18/06, Audrey Tang wrote:
>However, I think one of P6's idea is that the user should not have
>to care between 0 and 0.0's behaviours, so maybe it makes sense to
>do the same thing (be it NaN or exception) both ways.
>
>I'm not sure that IEEE 754/854 still applies if we want to merge the
>behaviours of int/num/complex/bigint/bigrat/bignum under a Num banner.
>
>(There is always the worse-is-better option of going with whatever
>the underlying runtime does, usually determined by hardware/libm.)

I think the best situation is that, at least with boxed types like
Num, behaviour should be well defined, user friendly, and identical
everywhere Perl 6 runs. There's no good reason to have different
behaviour on different platforms; that allows implementation to leak
through to the user when the user shouldn't have to know. And its
also a very good source of bugs. Leave different behaviours to
things that are explicitly connections to external resources, where
it is reasonable for them to change.

As for unboxed types, I'm on the fence here, but you should probably
let the implementation show through here, to an extent, since
presumably the point of using unboxed types is to get bleeding edge
maximum performance, and abstraction would take away from this then,
maybe. Or maybe not. But if anything bleeds through, it should be
the hardware, and not other programming languages.

-- Darren Duncan

Doug McNutt

unread,
Jan 18, 2006, 11:22:43 AM1/18/06
to Perl 6 Language
At 09:38 +0800 1/18/06, Audrey Tang wrote:
>Also, would you be happy with different treatments of Int/Int versus
>Num/Num?
>
> 0/0 # fail "illegal division by zero"
> 0.0/0.0 # NaN

I plead guilty. I was not aware that perl6 was going to allow types to be defined like int and float.

While learning perl 5 I was frustrated by that lack at first but I came to like it after a while because the treatment of strings that happen to be numbers is well done.

$serial = "0000000048";

behaves like a numeric 48 if I add to it but I don't have to perform an sprintf to get the zeros back if my goal is to repeat the value read from some HTML page or cookie. As a Gegenbeispeil try entering that or even a date in M$Excel. It will be immediately converted to a floating point seconds after the epoch and there is no way to recover the input text. I hate it.

So. . .

If perl6 will allow me to define a variable as type int64, int32, or things like that then division by zero should be an exception as should overflow on addition.

If "the perl way" is the goal then users who don't want to go to C should be treated to $numerics that allows for strings, scientific notation, and the like while doing the right thing. For that, converting 0/0 to a floating point division with a NaN result is quite proper.

The important thing is that ($aa + $bb)/$aa should return 1.0 when $bb is a NaN underflow or if $aa is a NaN Inf. Those may not be the best examples but you get the idea. Some intermediate results can return NaN's in a way that inclusion in a later calculation can produce a correct result in spite of the NaN. Numeric values often come from an external source. Unnecessary and confusing validation of that kind of input should not be required just to keep a program running. Just let the final answer show as a NaN and keep the programming clear and short.
--
--> There are 10 kinds of people: those who understand binary, and those who don't <--

Larry Wall

unread,
Jan 18, 2006, 1:51:58 PM1/18/06
to Perl 6 Language
On Wed, Jan 18, 2006 at 09:38:04AM +0800, Audrey Tang wrote:
: Also, would you be happy with different treatments of Int/Int versus

: Num/Num?
:
: 0/0 # fail "illegal division by zero"
: 0.0/0.0 # NaN

I'd like to point out that there's no reason in principle that a failure
undef can't return NaN in numeric context, so we don't actually have
to distinguish those two cases normally (though "use fatal" might
distinguish them).

By and large I agree with Darren. The boxed types should opt for
consistency over efficiency while the unboxed types should opt for
efficiency of consistency. So perhaps we just say that boxed NaN is
indistinguishable from undef--in particular, unboxing one in numeric
context gives you back the NaN. I don't know whether it makes sense
to extend that to 寂nf though. Maybe it does. We're kinda fuzzing
that idea anyway already. Undefined numbers vary in definedness much
like undefined generic prototype objects, aka "classes".

All undefs are created unequal, but some are more unequal than others.

Long term I think we'll end up asking these objects whether they're
defined according to one of their roles. So the infinities know they
have a defined sign, for instance, but not a defined magnitude (except
insofar as infinity is considered a separate defined concept). And
an object might be considered defined as a Mammal but undefined (so far)
as a Dog or Cat. So instead of $num.defined or $animal.defined we
might have $num.defined(Sign) or $animal.defined(Dog|Cat). If you
omit the arg then .defined devolves to something like what we have now,
where the definedness is decided by the class of the object.

Note this is not quite the same as .does(Dog|Cat), since an undefined
proto object returns true for that but false for .defined(Dog|Cat) unless
one of those roles thinks the object is sufficiently initialized to
be considered defined. For most roles that could implicitly determined
by whether the BUILD for that role has run, assuming BUILD always
produces a complete initialization.

Maybe "defined" is the wrong word for it anymore. It's more like "okay"
or "normal" or "nominal" or "functional". I could go for $Fido.good(Dog). :-)

Larry

0 new messages