<commit_before>class Rat {
    has $.numerator;
    has $.denominator;

    sub gcd(Int $a is copy, Int $b is copy) {
        $a = -$a if ($a < 0);
        $b = -$b if ($b < 0);
        while $a > 0 && $b > 0 {
            ($a, $b) = ($b, $a) if ($b > $a);
            $a %= $b;
        }
        return $a + $b;
    }

    multi method new(Int $numerator is copy, Int $denominator is copy) {
        if $denominator < 0 {
            $numerator = -$numerator;
            $denominator = -$denominator;
        }
        my $gcd = gcd($numerator, $denominator);
        $numerator = $numerator div $gcd;
        $denominator = $denominator div $gcd;
        self.bless(*, :numerator($numerator), :denominator($denominator));
    }

    multi method perl() { "$!numerator/$!denominator"; }

    our Bool multi method Bool() { $!numerator != 0 ?? Bool::True !! Bool::False }

    multi method Num() {
        $!denominator == 0 ?? Inf * $!numerator.sign
                           !! $!numerator.Num / $!denominator.Num;
    }

    multi method Rat() { self; }

    multi method Int() { self.Num.Int; }

    multi method Str() { $.Num.Str; }

    multi method nude() { $.numerator, $.denominator; }

    # Most of the trig functions for Rat are in Any-num.pm, but
    # sec is a special case.
    our Num multi method sec($base = Radians) {
        self.Num.sec($base);
    }

    multi method succ {
        Rat.new($!numerator + $!denominator, $!denominator);
    }
    multi method pred {
        Rat.new($!numerator - $!denominator, $!denominator);
    }

    multi method abs() {
        self < 0 ?? -self !! self;
    }

    our Int multi method sign {
        # self ~~ NaN ?? NaN !! self <=> 0;
        self < 0 ?? -1 !! ( self == 0 ?? 0 !! 1);
    }
}

multi sub infix:<+>(Rat $a, Rat $b) {
    my $gcd = Rat::gcd($a.denominator, $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 = Rat::gcd($a.denominator, $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 prefix:<->(Rat $a) {
    Rat.new(-$a.numerator, $a.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;
}

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

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

multi sub infix:</>(Rat $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, Int $b) {
    Rat.new($a, $b);
}

augment class Int {
    # CHEAT: Comes from Int.pm, moved here for the moment.
    our Rat multi method Rat() { Rat.new(self, 1); }
}

# vim: ft=perl6 sw=4 ts=4 expandtab<commit_msg>Add Rat versions of cmp which allow it to be compared with other numeric types.<commit_after>class Rat {
    has $.numerator;
    has $.denominator;

    sub gcd(Int $a is copy, Int $b is copy) {
        $a = -$a if ($a < 0);
        $b = -$b if ($b < 0);
        while $a > 0 && $b > 0 {
            ($a, $b) = ($b, $a) if ($b > $a);
            $a %= $b;
        }
        return $a + $b;
    }

    multi method new(Int $numerator is copy, Int $denominator is copy) {
        if $denominator < 0 {
            $numerator = -$numerator;
            $denominator = -$denominator;
        }
        my $gcd = gcd($numerator, $denominator);
        $numerator = $numerator div $gcd;
        $denominator = $denominator div $gcd;
        self.bless(*, :numerator($numerator), :denominator($denominator));
    }

    multi method perl() { "$!numerator/$!denominator"; }

    our Bool multi method Bool() { $!numerator != 0 ?? Bool::True !! Bool::False }

    multi method Num() {
        $!denominator == 0 ?? Inf * $!numerator.sign
                           !! $!numerator.Num / $!denominator.Num;
    }

    multi method Rat() { self; }

    multi method Int() { self.Num.Int; }

    multi method Str() { $.Num.Str; }

    multi method nude() { $.numerator, $.denominator; }

    # Most of the trig functions for Rat are in Any-num.pm, but
    # sec is a special case.
    our Num multi method sec($base = Radians) {
        self.Num.sec($base);
    }

    multi method succ {
        Rat.new($!numerator + $!denominator, $!denominator);
    }
    multi method pred {
        Rat.new($!numerator - $!denominator, $!denominator);
    }

    multi method abs() {
        self < 0 ?? -self !! self;
    }

    our Int multi method sign {
        # self ~~ NaN ?? NaN !! self <=> 0;
        self < 0 ?? -1 !! ( self == 0 ?? 0 !! 1);
    }
}

multi sub infix:<+>(Rat $a, Rat $b) {
    my $gcd = Rat::gcd($a.denominator, $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 = Rat::gcd($a.denominator, $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 prefix:<->(Rat $a) {
    Rat.new(-$a.numerator, $a.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;
}

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

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

multi sub infix:</>(Rat $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, Int $b) {
    Rat.new($a, $b);
}

multi sub infix:<cmp>(Rat $a, Rat $b) { $a.Num <=> $b.Num; }
multi sub infix:<cmp>(Rat $a, $b)     { $a.Num <=> $b.Num; }
multi sub infix:<cmp>($a, Rat $b)     { $a.Num <=> $b.Num; }

augment class Int {
    # CHEAT: Comes from Int.pm, moved here for the moment.
    our Rat multi method Rat() { Rat.new(self, 1); }
}

# vim: ft=perl6 sw=4 ts=4 expandtab
{'fraction_non_alphanumeric': 0.19690326116744314, 'fraction_numerical': 0.004932858317347218, 'mean_word_length': 2.39804469273743, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3549448', 'n_tokens_mistral': 2946, 'n_tokens_neox': 2852, 'n_words': 735}