Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge remote branch 'origin/rat-vs-fatrat' into nom
  • Loading branch information
moritz committed Feb 13, 2012
2 parents 29f5cf7 + 85196e7 commit dc7bcfb
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 50 deletions.
195 changes: 145 additions & 50 deletions src/core/Rat.pm
@@ -1,5 +1,6 @@
# XXX: should also be Cool, but attributes and MI don't seem to mix yet
my class Rat is Real {
my Int $UINT64_UPPER = nqp::pow_I(2, 64, Num, Int);

my role Rational is Real {
has Int $.numerator;
has Int $.denominator;

Expand All @@ -17,7 +18,7 @@ my class Rat is Real {
}

method new(Int \$nu = 0, Int \$de = 1) {
my Rat $new := nqp::create(self);
my $new := nqp::create(self);
my Int $gcd := $nu gcd $de;
my $numerator = $nu div $gcd;
my $denominator = $de div $gcd;
Expand All @@ -39,7 +40,6 @@ my class Rat is Real {
method Int() { $!numerator div $!denominator }

method Bridge() { self.Num }
method Rat(Rat:D: Real $?) { self }
multi method Str(Rat:D:) {
self.Num.Str
}
Expand All @@ -55,65 +55,160 @@ my class Rat is Real {
}
}

multi prefix:<->(Rat \$a) {
Rat.new(-$a.numerator, $a.denominator);
}

multi infix:<+>(Rat \$a, Rat \$b) {
my $gcd = $a.denominator gcd $b.denominator;
($a.numerator * ($b.denominator div $gcd) + $b.numerator * ($a.denominator div $gcd))
/ (($a.denominator div $gcd) * $b.denominator);
}
multi sub infix:<+>(Rat \$a, Int \$b) {
($a.numerator + $b * $a.denominator) / $a.denominator;
}
multi sub infix:<+>(Int \$a, Rat \$b) {
($a * $b.denominator + $b.numerator) / $b.denominator;
}

multi sub infix:<->(Rat \$a, Rat \$b) {
my $gcd = $a.denominator gcd $b.denominator;
($a.numerator * ($b.denominator div $gcd) - $b.numerator * ($a.denominator div $gcd))
/ (($a.denominator div $gcd) * $b.denominator);
my class FatRat { ... }
# XXX: should also be Cool
my class Rat does Rational {
method Rat (Rat:D: Real $?) { self }
method FatRat(Rat:D: Real $?) { FatRat.new($.numerator, $.denominator); }
}

multi sub infix:<->(Rat \$a, Int \$b) {
($a.numerator - $b * $a.denominator) / $a.denominator;
}

multi sub infix:<->(Int \$a, Rat \$b) {
($a * $b.denominator - $b.numerator) / $b.denominator;
}

multi sub infix:<*>(Rat \$a, Rat \$b) {
($a.numerator * $b.numerator) / ($a.denominator * $b.denominator);
}

multi sub infix:<*>(Rat \$a, Int \$b) {
($a.numerator * $b) / $a.denominator;
my class FatRat does Rational {
method FatRat(FatRat:D: Real $?) { self }
method Rat (FatRat:D: Real $?) {
$.denominator < $UINT64_UPPER
?? Rat.new($.numerator, $.denominator)
!! fail "Cannot convert from FatRat to Rat because denominator is too big";
}
}

multi sub infix:<*>(Int \$a, Rat \$b) {
($a * $b.numerator) / $b.denominator;
sub DIVIDE_NUMBERS(Int:D \$nu, Int:D \$de, $t1, $t2) {
my Int $gcd := $nu gcd $de;
my Int $numerator = $nu div $gcd;
my Int $denominator = $de div $gcd;
if $denominator < 0 {
$numerator = -$numerator;
$denominator = -$denominator;
}
if nqp::istype($t1, FatRat) || nqp::istype($t1, FatRat) {
my $r := nqp::create(FatRat);
nqp::bindattr($r, FatRat, '$!numerator', nqp::p6decont($numerator));
nqp::bindattr($r, FatRat, '$!denominator', nqp::p6decont($denominator));
$r;
} elsif $denominator < $UINT64_UPPER {
my $r := nqp::create(Rat);
nqp::bindattr($r, Rat, '$!numerator', nqp::p6decont($numerator));
nqp::bindattr($r, Rat, '$!denominator', nqp::p6decont($denominator));
$r;
} else {
# TODO: be smarter here if both integers are big
nqp::p6box_n(nqp::div_n(
nqp::tonum_I(nqp::p6decont $numerator),
nqp::tonum_I(nqp::p6decont $denominator)
)
);
}
}

multi sub infix:</>(Rat \$a, Rat \$b) {
($a.numerator * $b.denominator) / ($a.denominator * $b.numerator);
multi prefix:<->(Rat \$a) {
Rat.new(-$a.numerator, $a.denominator);
}

multi sub infix:</>(Rat \$a, Int \$b) {
multi prefix:<->(FatRat \$a) {
FatRat.new(-$a.numerator, $a.denominator);
}

multi infix:<+>(Rational \$a, Rational \$b) {
my Int $gcd := $a.denominator gcd $b.denominator;
DIVIDE_NUMBERS(
($a.numerator * ($b.denominator div $gcd) + $b.numerator * ($a.denominator div $gcd)),
(($a.denominator div $gcd) * $b.denominator),
$a,
$b,
);
}
multi sub infix:<+>(Rational \$a, Int \$b) {
DIVIDE_NUMBERS(
($a.numerator + $b * $a.denominator),
$a.denominator,
$a,
$b,
);
}
multi sub infix:<+>(Int \$a, Rational \$b) {
DIVIDE_NUMBERS(
($a * $b.denominator + $b.numerator),
$b.denominator,
$a,
$b,
);
}

multi sub infix:<->(Rational \$a, Rational \$b) {
my Int $gcd = $a.denominator gcd $b.denominator;
DIVIDE_NUMBERS
$a.numerator * ($b.denominator div $gcd) - $b.numerator * ($a.denominator div $gcd),
($a.denominator div $gcd) * $b.denominator,
$a,
$b;
}

multi sub infix:<->(Rational \$a, Int \$b) {
DIVIDE_NUMBERS
$a.numerator - $b * $a.denominator,
$a.denominator,
$a,
$b;
}

multi sub infix:<->(Int \$a, Rational \$b) {
DIVIDE_NUMBERS
$a * $b.denominator - $b.numerator,
$b.denominator,
$a,
$b;
}

multi sub infix:<*>(Rational \$a, Rational \$b) {
DIVIDE_NUMBERS
$a.numerator * $b.numerator,
$a.denominator * $b.denominator,
$a,
$b;
}

multi sub infix:<*>(Rational \$a, Int \$b) {
DIVIDE_NUMBERS
$a.numerator * $b,
$a.denominator,
$a,
$b;
}

multi sub infix:<*>(Int \$a, Rational \$b) {
DIVIDE_NUMBERS
$a * $b.numerator,
$b.denominator,
$a,
$b;
}

multi sub infix:</>(Rational \$a, Rational \$b) {
DIVIDE_NUMBERS
$a.numerator * $b.denominator,
$a.denominator * $b.numerator,
$a,
$b;
}

multi sub infix:</>(Rational \$a, Int \$b) {
$a.numerator / ($a.denominator * $b);
}

multi sub infix:</>(Int \$a, Rat \$b) {
($b.denominator * $a) / $b.numerator;
multi sub infix:</>(Int \$a, Rational \$b) {
DIVIDE_NUMBERS
$b.denominator * $a,
$b.numerator,
$a,
$b;
}

multi sub infix:</>(Int \$a, Int \$b) {
Rat.new($a, $b);
DIVIDE_NUMBERS $a, $b, $a, $b
}

multi sub infix:<**>(Rat \$a, Int \$b) {
Rat.new($a.numerator ** $b,$a.denominator ** $b);
multi sub infix:<**>(Rational \$a, Int \$b) {
DIVIDE_NUMBERS
$a.numerator ** $b,
$a.denominator ** $b,
$a,
$b;
}

1 change: 1 addition & 0 deletions t/spectest.data
Expand Up @@ -21,6 +21,7 @@ S02-types/bool.t
S02-types/capture.t
S02-types/catch_type_cast_mismatch.t
S02-types/declare.t
S02-types/fatrat.t
S02-types/flattening.t
S02-types/hash_ref.t
S02-types/hash.t
Expand Down

0 comments on commit dc7bcfb

Please sign in to comment.