Skip to content

Commit

Permalink
Shave off a few % off of Rational.new
Browse files Browse the repository at this point in the history
- only allow for instantiated NuT and DeT
- create object at one place
- use cheaper bindattr instead of bindattrvinres where possible
- simplify -1 0 1 logic when denominator is 0
- about 1-2% faster
  • Loading branch information
lizmat committed Jan 3, 2019
1 parent 3f8fea9 commit 91f6749
Showing 1 changed file with 38 additions and 21 deletions.
59 changes: 38 additions & 21 deletions src/core/Rational.pm6
Expand Up @@ -21,29 +21,46 @@ my role Rational[::NuT = Int, ::DeT = ::("NuT")] does Real {
)
}

method new(NuT \nu = 0, DeT \de = 1) {
nqp::unless(
method new(NuT:D \nu = 0, DeT:D \de = 1) {
my \object := nqp::create(self);
nqp::if(
de,
nqp::p6bindattrinvres( # zero-denominator-rational; normalize
nqp::p6bindattrinvres(
nqp::create(self),
::?CLASS, '$!denominator', nqp::decont(de)),
::?CLASS, '$!numerator', nqp::box_i(
nqp::isgt_I(nqp::decont(nu), 0) ?? 1 !! nu ?? -1 !! 0, nu.WHAT)),
nqp::stmts( # normal rational
(my $gcd := nqp::gcd_I(nqp::decont(nu), nqp::decont(de), Int)),
(my $nu := nqp::div_I(nqp::decont(nu), $gcd, NuT)),
(my $de := nqp::div_I(nqp::decont(de), $gcd, DeT)),
nqp::stmts( # normal rational
(my \gcd := nqp::gcd_I(nqp::decont(nu), nqp::decont(de), Int)),
(my \numerator := nqp::div_I(nqp::decont(nu), gcd, NuT)),
(my \denominator := nqp::div_I(nqp::decont(de), gcd, DeT)),
nqp::if(
nqp::islt_I($de, 0),
nqp::stmts(
($nu := nqp::neg_I($nu, $nu.WHAT)),
($de := nqp::neg_I($de, $de.WHAT)))),
nqp::p6bindattrinvres( # zero-denominator-rational
nqp::p6bindattrinvres(
nqp::create(self),
::?CLASS, '$!denominator', $de),
::?CLASS, '$!numerator', $nu)))
nqp::islt_I(denominator,0), # need to switch sign?
nqp::stmts( # yup, so switch
nqp::bindattr(
object,::?CLASS,'$!numerator',nqp::neg_I(numerator,Int)
),
nqp::p6bindattrinvres(
object,::?CLASS,'$!denominator',nqp::neg_I(denominator,Int)
)
),
nqp::stmts( # no, so just store
nqp::bindattr(
object,::?CLASS,'$!numerator',numerator
),
nqp::p6bindattrinvres(
object,::?CLASS,'$!denominator',denominator
)
)
)
),
nqp::stmts( # Inf / NaN
nqp::bindattr(object,::?CLASS,'$!numerator',
nqp::box_i(
nqp::isgt_I(nqp::decont(nu),0) || nqp::neg_i(nqp::istrue(nu)),
nu.WHAT
)
),
nqp::p6bindattrinvres(object,::?CLASS,'$!denominator',
nqp::decont(de)
)
)
)
}

method nude() { $!numerator, $!denominator }
Expand Down

0 comments on commit 91f6749

Please sign in to comment.