Skip to content

Commit

Permalink
Slightly speedup exponentiation by Ints
Browse files Browse the repository at this point in the history
Only perform the `$b > 0` check once and check for underflow before
creating the Rat for negative powers.
  • Loading branch information
MasterDuke17 committed Apr 24, 2022
1 parent a2601fb commit 6f6fd1f
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 13 deletions.
28 changes: 17 additions & 11 deletions src/core.c/Int.pm6
Expand Up @@ -379,18 +379,24 @@ multi sub infix:<%%>(int $a, int $b --> Bool:D) {
nqp::hllbool(nqp::iseq_i(nqp::mod_i($a, $b), 0))
}

my constant UINT64_UPPER = nqp::pow_I(2, 64, Num, Int);

multi sub infix:<**>(Int:D $a, Int:D $b --> Real:D) {
my $power := nqp::pow_I($a,nqp::if($b >= 0,$b,-$b),Num,Int);
# when a**b is too big nqp::pow_I returns Inf
nqp::istype($power, Num)
?? Failure.new(
$b >= 0 ?? X::Numeric::Overflow.new !! X::Numeric::Underflow.new
)
!! $b >= 0
?? $power
!! ($power := 1 / $power) == 0 && $a != 0
?? Failure.new(X::Numeric::Underflow.new)
!! $power
my $power;
if nqp::isge_I($b, 0) {
$power := nqp::pow_I($a, $b, Num, Int);
# when a**b is too big nqp::pow_I returns Inf
nqp::istype($power, Int)
?? $power
!! Failure.new(X::Numeric::Overflow.new)
}
else {
$power := nqp::pow_I($a, nqp::neg_I($b, Int), Num, Int);
# when a**b is too big nqp::pow_I returns Inf
nqp::istype($power, Num) || (nqp::isge_I($power, UINT64_UPPER) && nqp::isne_I($a, 0))
?? Failure.new(X::Numeric::Underflow.new)
!! 1 / $power
}
}

multi sub infix:<**>(int $a, int $b --> int) {
Expand Down
2 changes: 0 additions & 2 deletions src/core.c/Rat.pm6
Expand Up @@ -31,8 +31,6 @@ my class Rat is Cool does Rational[Int, Int] {
}
}

my constant UINT64_UPPER = nqp::pow_I(2, 64, Num, Int);

my class FatRat is Cool does Rational[Int, Int] {
method FatRat(FatRat:D:) { self }
method Rat(FatRat:D:) {
Expand Down

0 comments on commit 6f6fd1f

Please sign in to comment.