diff --git a/src/core/Num.pm b/src/core/Num.pm index e3911e98256..62643ed3957 100644 --- a/src/core/Num.pm +++ b/src/core/Num.pm @@ -1,7 +1,6 @@ my class X::Cannot::Capture { ... } my class X::Numeric::DivideByZero { ... } my class X::Numeric::CannotConvert { ... } -my role Rational { ... } my class Num does Real { # declared in BOOTSTRAP # class Num is Cool @@ -44,8 +43,12 @@ my class Num does Real { # declared in BOOTSTRAP } method Rat(Num:D: Real $epsilon = 1.0e-6, :$fat) { - return Rational[Num,Int].new(self,0) - if nqp::isnanorinf(nqp::unbox_n(self)); + my \RAT = $fat ?? FatRat !! Rat; + + return RAT.new: ( + nqp::iseq_n(self, self) ?? nqp::iseq_n(self, Inf) ?? 1 !! -1 !! 0 + ), 0 + if nqp::isnanorinf(nqp::unbox_n(self)); my Num $num = self; $num = -$num if (my int $signum = $num < 0); @@ -53,9 +56,7 @@ my class Num does Real { # declared in BOOTSTRAP # basically have an Int if nqp::iseq_n($r,0e0) { - $fat - ?? FatRat.new(nqp::fromnum_I(self,Int),1) - !! Rat.new(nqp::fromnum_I(self,Int),1) + RAT.new(nqp::fromnum_I(self,Int),1) } # find convergents of the continued fraction. @@ -84,9 +85,7 @@ my class Num does Real { # declared in BOOTSTRAP # smaller denominator but it is not (necessarily) the Rational # with the smallest denominator that has less than $epsilon error. # However, to find that Rational would take more processing. - $fat - ?? FatRat.new($signum ?? -$b !! $b, $d) - !! Rat.new($signum ?? -$b !! $b, $d) + RAT.new($signum ?? -$b !! $b, $d) } } method FatRat(Num:D: Real $epsilon = 1.0e-6) { diff --git a/src/core/Rational.pm b/src/core/Rational.pm index a85b1d34293..be07864bcf9 100644 --- a/src/core/Rational.pm +++ b/src/core/Rational.pm @@ -46,12 +46,9 @@ my role Rational[::NuT = Int, ::DeT = ::("NuT")] does Real { method nude() { self.REDUCE-ME; $!numerator, $!denominator } method Num() { - nqp::istype($!numerator,Int) - ?? nqp::p6box_n(nqp::div_In( - nqp::decont($!numerator), - nqp::decont($!denominator) - )) - !! $!numerator + nqp::p6box_n(nqp::div_In( + nqp::decont($!numerator), + nqp::decont($!denominator))) } method floor(Rational:D:) { @@ -75,10 +72,8 @@ my role Rational[::NuT = Int, ::DeT = ::("NuT")] does Real { } method Bridge() { self.Num } method Range(::?CLASS:U:) { Range.new(-Inf, Inf) } - method isNaN { - nqp::p6bool( - nqp::isfalse(self.numerator) && nqp::isfalse(self.denominator) - ) + method isNaN (--> Bool:D) { + nqp::p6bool(nqp::isfalse($!denominator) && nqp::isfalse($!numerator)) } method is-prime(--> Bool:D) { @@ -87,38 +82,33 @@ my role Rational[::NuT = Int, ::DeT = ::("NuT")] does Real { } multi method Str(::?CLASS:D:) { - if nqp::istype($!numerator,Int) { - my $whole = self.abs.floor; - my $fract = self.abs - $whole; - - # fight floating point noise issues RT#126016 - if $fract.Num == 1e0 { ++$whole; $fract = 0 } - - my $result = nqp::if( - nqp::islt_I($!numerator, 0), '-', '' - ) ~ $whole; - - if $fract { - my $precision = $!denominator < 100_000 - ?? 6 !! $!denominator.Str.chars + 1; - - my $fract-result = ''; - while $fract and $fract-result.chars < $precision { - $fract *= 10; - given $fract.floor { - $fract-result ~= $_; - $fract -= $_; - } - } - ++$fract-result if 2*$fract >= 1; # round off fractional result + my $whole = self.abs.floor; + my $fract = self.abs - $whole; - $result ~= '.' ~ $fract-result; + # fight floating point noise issues RT#126016 + if $fract.Num == 1e0 { ++$whole; $fract = 0 } + + my $result = nqp::if( + nqp::islt_I($!numerator, 0), '-', '' + ) ~ $whole; + + if $fract { + my $precision = $!denominator < 100_000 + ?? 6 !! $!denominator.Str.chars + 1; + + my $fract-result = ''; + while $fract and $fract-result.chars < $precision { + $fract *= 10; + given $fract.floor { + $fract-result ~= $_; + $fract -= $_; + } } - $result - } - else { - $!numerator.Str + ++$fract-result if 2*$fract >= 1; # round off fractional result + + $result ~= '.' ~ $fract-result; } + $result } method base($base, Any $digits? is copy) {