Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make infix:<**>(Rational, Int) more than 10x as fast
Makes `<50000123/50000000> ** 50_000` run 10.26x as fast Makes `for ^2000 { my $ = (42 / $_) ** $_ }` run 16.72x as fast Closes #1955 R#1955 Rationals are now[^1] guaranteed to be always in reduced form, so the numerator and the denominator cannot have prime factors in common, and raising each of them to a power doesn't change that, so we can omit trying to reduce the result. [1] 5c429e4
- Loading branch information
1 parent
38de1e5
commit d1729da
Showing
1 changed file
with
36 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
d1729da
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forgot to mention in the commit:
Also fixes crash in constructs like
<1/50000000000000> ** 5000000000000
becausethe original code makes incorrect assumption:
we presume it likely already blew up on the numerator
With that, I also tweaked the thrown exceptions: if power is positive, we now always throw Overflow (and always Underflow for negative), as that's the actual reason we fail.
d1729da
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't these both produce the same failure?
d1729da
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can argue both ways:
<1/50000000000000>
as a single number (like you're doing with.Num
), that you're then raising to a power and by doing so making it smaller, then you get anUnderflow
<1/50000000000000>
as aRat
object that has a numerator and denominator, that you're raising to a power and receiving aRat
object with raised numerator/denominator, then you get anOverflow
, because the raising of denominator to that power caused a numeric overflow. In other words, I'm not actually performing any division by requesting a newRat
object, so nothing is underflowing; similar to how((1/0)**42)
just produces aRat
object and isn't a division-by-zero explosion.