eclipse-archived / ceylon

The Ceylon compiler, language module, and command line tools
http://ceylon-lang.org
Apache License 2.0
399 stars 62 forks source link

1.0^infinity #5615

Closed CeylonMigrationBot closed 8 years ago

CeylonMigrationBot commented 9 years ago

[@gavinking] Wikipedia claims that the IEEE standard mandates that pow(1.0, ∞) evaluates to 1.0, along with pow(0.0, 0.0) and pow(∞, 0.0), and that seems intuitively correct to me. I can see how pow(-1.0, ∞) should be NaN, but that seems a pretty different case.

However, Java's Math.pow() function apparently has its own idea and Math.pow(1.0, Math.POSITIVE_INFINITY) evaluates to NaN, and if I', reading the ECMA spec right, it seems to specify the same thing.

What should Ceylon do here?

Does anyone happen to have a copy of the IEEE spec?

Note also this comment in the Dart issue tracker.

[Migrated from ceylon/ceylon.language#737] [Closed at 2015-09-03 01:02:48]

CeylonMigrationBot commented 9 years ago

[@lucaswerkmeister]

Does anyone happen to have a copy of the IEEE spec?

I can get access via my university account. Does Wikipedia refer to a specific section?

CeylonMigrationBot commented 9 years ago

[@lucaswerkmeister] Found it. 9.2.1 Special values, pp. 43–45.

For the pow function […] pow(x, ±0) is 1 for any x (even a zero, quiet NaN, or infinity) […] pow(+1,y) is 1 for any y (even a quiet NaN)

CeylonMigrationBot commented 9 years ago

[@lucaswerkmeister] Note, however, that the standard also defines pown and powr. The descriptions are:

[…] the pown function (integral exponents only) […] […] the pow function (integral exponents get special treatment) […] […] the powr function (derived by considering only exp(y×log(x))) […]

CeylonMigrationBot commented 9 years ago

[@lucaswerkmeister] And:

powr(±0, ±0) signals the invalid operation exception powr(+∞, ±0) signals the invalid operation exception powr(+1, ±∞) signals the invalid operation exception

CeylonMigrationBot commented 9 years ago

[@lucaswerkmeister] So perhaps Java’s and ECMAScript’s pow is based on IEEE’s powr, replacing “invalid operation exception” with NaN.

CeylonMigrationBot commented 9 years ago

[@jvasileff] It looks like the IEEE spec for this was released in 2008 (after java.lang.Math) - https://en.wikipedia.org/wiki/IEEE_754_revision. Of course, that doesn't tell us what they would have done.

CeylonMigrationBot commented 9 years ago

[@lucaswerkmeister] That’s true… the original IEEE 754-1985 doesn’t define any operations beside

An implementation shall provide the add, subtract, multiply, divide, and remainder operation

and

The square root operation shall be provided.

CeylonMigrationBot commented 9 years ago

[@gavinking] No, Java's pow() isn't powr() either. Look at powr(0,0) and powr(infinity,0).

CeylonMigrationBot commented 9 years ago

[@jvasileff] I think I'd go with IEEE, primarily because it seems like the least opinionated approach. But also, the rules look reasonable enough.

I thought pow(-1.0, ±∞) == 1 was strange at first, but with floats, you've already "lost" once y is a large number, all of which are all even.

Edit: changed Dart API url; the old one stopped working

CeylonMigrationBot commented 9 years ago

[@lucaswerkmeister] This is a mess. Examined languages:

Examined special cases:

My results:

I think we should follow C, Dart, Go, Python.

CeylonMigrationBot commented 9 years ago

[@gavinking] @jvasileff well it does seem to me wrong that pow(-1.0, ∞) == 1.0. I don't see where that comes from. pow(-1.0, n) does not converge as n approaches .

So I don't see where IEEE gets that from.

CeylonMigrationBot commented 9 years ago

[@jvasileff] @gavinking but we're taking about floats, where really big numbers at some point just become "infinity" (instead of triggering an overflow exception). And for big numbers, the answer is 1.0, since in this fake-number-world, all big numbers are even.

So I think the interpretation is that infinity just means a number outside of the representable range (which surely must be an even integer!), and not a proper infinity in a mathematical sense.

Bottom line: folks shouldn't be doing this sort of calculation with floats, but to stop them entirely, we'd have to have pow(-1.0, *) be undefined.

CeylonMigrationBot commented 9 years ago

[@gavinking] @jvasileff That's not true. Really big negative numbers become -infinity, not infinity.

CeylonMigrationBot commented 9 years ago

[@jvasileff] Sure, I was speaking in terms of magnitude.

CeylonMigrationBot commented 9 years ago

[@gavinking] Oh, sorry, I misunderstood your argument. Yeah, OK, so with limited precision, all large floating point exponents are even. That's ... a very weird side-effect of limited-precision floating-point arithmetic.

CeylonMigrationBot commented 9 years ago

[@FroMage] @gavinking: where's that Wikipedia page you talk about, I can't find it?

I can implement that for both JS and JVM, but I'd like to see some better specs, since it's pretty famous math is a foreign language to me.

For the pow function […] pow(x, ±0) is 1 for any x (even a zero, quiet NaN, or infinity) […] pow(+1,y) is 1 for any even y (even a quiet NaN)

@lucaswerkmeister this says infinity but does not say positive/negative. Am I to conclude that it's for both infinities?

I thought pow(-1.0, ±∞) == 1 was strange at first, but with floats, you've already "lost" once y is a large number, all of which are all even.

@jvasileff where did you find that? I can't find it in @gavinking's issue description, nor in the quoted IEEE spec in comments. Should I implement that too?

CeylonMigrationBot commented 9 years ago

[@lucaswerkmeister] @FroMage pretty sure, yes, especially since it’s only a clarification for “any x”.

CeylonMigrationBot commented 9 years ago

[@FroMage] OK fine.

CeylonMigrationBot commented 9 years ago

[@jvasileff] @FroMage in the Dart and Go links here #5615#issuecomment-136228316 which claim to be consistent with IEEE Standard 754-2008.

CeylonMigrationBot commented 9 years ago

[@FroMage] @jvasileff: Dart says:

pow(+1, y) is 1 for any y (even a quiet NaN)

But @lucaswerkmeister quoted IEEE as saying:

pow(+1,y) is 1 for any even y (even a quiet NaN)

Not sure what to make of that.

CeylonMigrationBot commented 9 years ago

[@lucaswerkmeister] hang on, I might’ve misquoted

CeylonMigrationBot commented 9 years ago

[@FroMage] aha :)

CeylonMigrationBot commented 9 years ago

[@lucaswerkmeister] yup, sorry.

pow (+1, y ) is 1 for any y (even a quiet NaN)

CeylonMigrationBot commented 9 years ago

[@lucaswerkmeister] and that’s why I don’t copy+paste out of that stupid document :D

CeylonMigrationBot commented 9 years ago

[@lucaswerkmeister] fixed in my comment above

CeylonMigrationBot commented 9 years ago

[@FroMage] OK thanks.

CeylonMigrationBot commented 9 years ago

[@lucaswerkmeister] Lemme give y’all folks the spec so we can discuss on the same level :)

pow

CeylonMigrationBot commented 9 years ago

[@FroMage] I've updated the JS and JVM runtime to align us with what I believe is the IEEE spec. Please review. If you wish to deviate from the IEEE spec, at least now you can see where in the code it has to be done ;)

I won't close this until you guys come to an agreement, but I vote for following the IEEE spec.

CeylonMigrationBot commented 9 years ago

[@lucaswerkmeister] @FroMage what’s pow(1.5, +∞) now?

CeylonMigrationBot commented 9 years ago

[@lucaswerkmeister] oh I see, that’s a test case. good

CeylonMigrationBot commented 9 years ago

[@gavinking] The consensus seems to be to go with the IEEE definition of pow(). Fine by me. I'll assume @FroMage's impl is good and close this issue.