diff options
author | Nicolas R <atoomic@cpan.org> | 2022-07-20 19:27:46 +0000 |
---|---|---|
committer | ℕicolas ℝ <nicolas@atoomic.org> | 2022-07-20 14:49:02 -0600 |
commit | d18b40dae1e94d9ccfd63e1ba0873a8a77d59226 (patch) | |
tree | 2a120c4466f1a81d8cce014e4004dab213e2b7f5 /cpan/Math-BigRat | |
parent | 119199b1a4e490b69342c09058ab33a628e5c801 (diff) | |
download | perl-d18b40dae1e94d9ccfd63e1ba0873a8a77d59226.tar.gz |
Sync Math::BigRat with CPAN 0.2624
From ChangeLog:
0.2624 2022-06-27
* Improve stringification. Better handling of upgrading/downgrading in
stringification methods. Add new method bfstr() for compatibility
with
Math::BigInt og Math::BigFloat. Add new author test files to confirm.
0.2623 2022-05-16
* Fix rounding issues.
0.2622 2022-04-13
* Add more cases for downgrading, and more tests.
Diffstat (limited to 'cpan/Math-BigRat')
-rw-r--r-- | cpan/Math-BigRat/lib/Math/BigRat.pm | 287 | ||||
-rw-r--r-- | cpan/Math-BigRat/t/bigrat.t | 133 | ||||
-rw-r--r-- | cpan/Math-BigRat/t/bigratpm.inc | 4 | ||||
-rw-r--r-- | cpan/Math-BigRat/t/downgrade.t | 325 |
4 files changed, 570 insertions, 179 deletions
diff --git a/cpan/Math-BigRat/lib/Math/BigRat.pm b/cpan/Math-BigRat/lib/Math/BigRat.pm index 391e6d055f..0d0f246795 100644 --- a/cpan/Math-BigRat/lib/Math/BigRat.pm +++ b/cpan/Math-BigRat/lib/Math/BigRat.pm @@ -21,7 +21,7 @@ use Scalar::Util qw< blessed >; use Math::BigFloat (); -our $VERSION = '0.2621'; +our $VERSION = '0.2624'; our @ISA = qw(Math::BigFloat); @@ -200,12 +200,6 @@ use overload BEGIN { *objectify = \&Math::BigInt::objectify; # inherit this from BigInt *AUTOLOAD = \&Math::BigFloat::AUTOLOAD; # can't inherit AUTOLOAD - # We inherit these from BigFloat because currently it is not possible that - # Math::BigFloat has a different $LIB variable than we, because - # Math::BigFloat also uses Math::BigInt::config->('lib') (there is always - # only one library loaded) - *_e_add = \&Math::BigFloat::_e_add; - *_e_sub = \&Math::BigFloat::_e_sub; *as_number = \&as_int; *is_pos = \&is_positive; *is_neg = \&is_negative; @@ -307,7 +301,8 @@ sub new { unless (defined $d) { #return $n -> copy($n) if $n -> isa('Math::BigRat'); if ($n -> isa('Math::BigRat')) { - return $downgrade -> new($n) if defined($downgrade) && $n -> is_int(); + return $downgrade -> new($n) + if defined($downgrade) && $n -> is_int(); return $class -> copy($n); } @@ -320,7 +315,8 @@ sub new { } if ($n -> isa('Math::BigInt')) { - $self -> {_n} = $LIB -> _new($n -> copy() -> babs() -> bstr()); + $self -> {_n} = $LIB -> _new($n -> copy() -> babs(undef, undef) + -> bstr()); $self -> {_d} = $LIB -> _one(); $self -> {sign} = $n -> sign(); return $downgrade -> new($n) if defined $downgrade; @@ -328,8 +324,8 @@ sub new { } if ($n -> isa('Math::BigFloat')) { - my $m = $n -> mantissa() -> babs(); - my $e = $n -> exponent(); + my $m = $n -> mantissa(undef, undef) -> babs(undef, undef); + my $e = $n -> exponent(undef, undef); $self -> {_n} = $LIB -> _new($m -> bstr()); $self -> {_d} = $LIB -> _one(); @@ -340,7 +336,8 @@ sub new { $self -> {_d} = $LIB -> _lsft($self -> {_d}, $LIB -> _new(-$e -> bstr()), 10); - my $gcd = $LIB -> _gcd($LIB -> _copy($self -> {_n}), $self -> {_d}); + my $gcd = $LIB -> _gcd($LIB -> _copy($self -> {_n}), + $self -> {_d}); if (!$LIB -> _is_one($gcd)) { $self -> {_n} = $LIB -> _div($self->{_n}, $gcd); $self -> {_d} = $LIB -> _div($self->{_d}, $gcd); @@ -348,7 +345,8 @@ sub new { } $self -> {sign} = $n -> sign(); - return $downgrade -> new($n) if defined($downgrade) && $n -> is_int(); + return $downgrade -> new($n, undef, undef) + if defined($downgrade) && $n -> is_int(); return $self; } @@ -677,36 +675,86 @@ sub config { $cfg; } -############################################################################## +############################################################################### +# String conversion methods +############################################################################### sub bstr { - my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_); + my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_); + + carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; + + # Inf and NaN - if ($x->{sign} !~ /^[+-]$/) { # inf, NaN etc - my $s = $x->{sign}; - $s =~ s/^\+//; # +inf => inf - return $s; + if ($x->{sign} ne '+' && $x->{sign} ne '-') { + return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN + return 'inf'; # +inf } + # Upgrade? + + return $upgrade -> bstr($x, @r) + if defined($upgrade) && !$x -> isa($class); + + # Finite number + my $s = ''; $s = $x->{sign} if $x->{sign} ne '+'; # '+3/2' => '3/2' - return $s . $LIB->_str($x->{_n}) if $LIB->_is_one($x->{_d}); - $s . $LIB->_str($x->{_n}) . '/' . $LIB->_str($x->{_d}); + my $str = $x->{sign} eq '-' ? '-' : ''; + $str .= $LIB->_str($x->{_n}); + $str .= '/' . $LIB->_str($x->{_d}) unless $LIB -> _is_one($x->{_d}); + return $str; } sub bsstr { - my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_); + my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_); - if ($x->{sign} !~ /^[+-]$/) { # inf, NaN etc - my $s = $x->{sign}; - $s =~ s/^\+//; # +inf => inf - return $s; + carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; + + # Inf and NaN + + if ($x->{sign} ne '+' && $x->{sign} ne '-') { + return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN + return 'inf'; # +inf } - my $s = ''; - $s = $x->{sign} if $x->{sign} ne '+'; # +3 vs 3 - $s . $LIB->_str($x->{_n}) . '/' . $LIB->_str($x->{_d}); + # Upgrade? + + return $upgrade -> bsstr($x, @r) + if defined($upgrade) && !$x -> isa($class); + + # Finite number + + my $str = $x->{sign} eq '-' ? '-' : ''; + $str .= $LIB->_str($x->{_n}); + $str .= '/' . $LIB->_str($x->{_d}) unless $LIB -> _is_one($x->{_d}); + return $str; +} + +sub bfstr { + my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_); + + carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; + + # Inf and NaN + + if ($x->{sign} ne '+' && $x->{sign} ne '-') { + return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN + return 'inf'; # +inf + } + + # Upgrade? + + return $upgrade -> bfstr($x, @r) + if defined($upgrade) && !$x -> isa($class); + + # Finite number + + my $str = $x->{sign} eq '-' ? '-' : ''; + $str .= $LIB->_str($x->{_n}); + $str .= '/' . $LIB->_str($x->{_d}) unless $LIB -> _is_one($x->{_d}); + return $str; } sub bnorm { @@ -737,7 +785,7 @@ sub bnorm { # n/1 if ($LIB->_is_one($x->{_d})) { - return $downgrade -> new($LIB -> _str($x->{_d})) if defined($downgrade); + return $downgrade -> new($x) if defined($downgrade); return $x; # no need to reduce } @@ -765,61 +813,12 @@ sub bneg { $x->{sign} =~ tr/+-/-+/ unless ($x->{sign} eq '+' && $LIB->_is_zero($x->{_n})); - return $downgrade -> new($LIB -> _str($x->{_n})) + return $downgrade -> new($x) if defined($downgrade) && $LIB -> _is_one($x->{_d}); $x; } ############################################################################## -# special values - -sub _bnan { - # used by parent class bnan() to initialize number to NaN - my $self = shift; - - if ($_trap_nan) { - my $class = ref($self); - # "$self" below will stringify the object, this blows up if $self is a - # partial object (happens under trap_nan), so fix it beforehand - $self->{_d} = $LIB->_zero() unless defined $self->{_d}; - $self->{_n} = $LIB->_zero() unless defined $self->{_n}; - croak ("Tried to set $self to NaN in $class\::_bnan()"); - } - $self->{_n} = $LIB->_zero(); - $self->{_d} = $LIB->_zero(); -} - -sub _binf { - # used by parent class bone() to initialize number to +inf/-inf - my $self = shift; - - if ($_trap_inf) { - my $class = ref($self); - # "$self" below will stringify the object, this blows up if $self is a - # partial object (happens under trap_nan), so fix it beforehand - $self->{_d} = $LIB->_zero() unless defined $self->{_d}; - $self->{_n} = $LIB->_zero() unless defined $self->{_n}; - croak ("Tried to set $self to inf in $class\::_binf()"); - } - $self->{_n} = $LIB->_zero(); - $self->{_d} = $LIB->_zero(); -} - -sub _bone { - # used by parent class bone() to initialize number to +1/-1 - my $self = shift; - $self->{_n} = $LIB->_one(); - $self->{_d} = $LIB->_one(); -} - -sub _bzero { - # used by parent class bzero() to initialize number to 0 - my $self = shift; - $self->{_n} = $LIB->_zero(); - $self->{_d} = $LIB->_one(); -} - -############################################################################## # mul/add/div etc sub badd { @@ -866,7 +865,7 @@ sub badd { my $m = $LIB->_mul($LIB->_copy($y->{_n}), $x->{_d}); # 5 * 3 + 7 * 4 - ($x->{_n}, $x->{sign}) = _e_add($x->{_n}, $m, $x->{sign}, $y->{sign}); + ($x->{_n}, $x->{sign}) = $LIB -> _sadd($x->{_n}, $x->{sign}, $m, $y->{sign}); # 4 * 3 $x->{_d} = $LIB->_mul($x->{_d}, $y->{_d}); @@ -887,10 +886,10 @@ sub bsub { # flip sign of $x, call badd(), then flip sign of result $x->{sign} =~ tr/+-/-+/ - unless $x->{sign} eq '+' && $LIB->_is_zero($x->{_n}); # not -0 - $x->badd($y, @r); # does norm and round + unless $x->{sign} eq '+' && $x -> is_zero(); # not -0 + $x = $x->badd($y, @r); # does norm and round $x->{sign} =~ tr/+-/-+/ - unless $x->{sign} eq '+' && $LIB->_is_zero($x->{_n}); # not -0 + unless $x->{sign} eq '+' && $x -> is_zero(); # not -0 $x->bnorm(); } @@ -919,10 +918,13 @@ sub bmul { } # x == 0 # also: or y == 1 or y == -1 - return wantarray ? ($x, $class->bzero()) : $x if $x -> is_zero(); + if ($x -> is_zero()) { + $x = $downgrade -> bzero($x) if defined $downgrade; + return wantarray ? ($x, $class->bzero()) : $x; + } if ($y -> is_zero()) { - $x -> bzero(); + $x = defined($downgrade) ? $downgrade -> bzero($x) : $x -> bzero(); return wantarray ? ($x, $class->bzero()) : $x; } @@ -971,11 +973,11 @@ sub bdiv { if ($x -> is_nan() || $y -> is_nan()) { if ($wantarray) { return $downgrade -> bnan(), $downgrade -> bnan() - if defined($downgrade) && $LIB -> _is_one($x->{_d}); + if defined($downgrade); return $x -> bnan(), $class -> bnan(); } else { return $downgrade -> bnan() - if defined($downgrade) && $LIB -> _is_one($x->{_d}); + if defined($downgrade); return $x -> bnan(); } } @@ -1387,6 +1389,7 @@ sub bceil { $x->{_d} = $LIB->_one(); # d => 1 $x->{_n} = $LIB->_inc($x->{_n}) if $x->{sign} eq '+'; # +22/7 => 4/1 $x->{sign} = '+' if $x->{sign} eq '-' && $LIB->_is_zero($x->{_n}); # -0 => 0 + return $downgrade -> new($x) if defined $downgrade; $x; } @@ -1403,6 +1406,7 @@ sub bfloor { $x->{_n} = $LIB->_div($x->{_n}, $x->{_d}); # 22/7 => 3/1 w/ truncate $x->{_d} = $LIB->_one(); # d => 1 $x->{_n} = $LIB->_inc($x->{_n}) if $x->{sign} eq '-'; # -22/7 => -4/1 + return $downgrade -> new($x) if defined $downgrade; $x; } @@ -1419,6 +1423,7 @@ sub bint { $x->{_n} = $LIB->_div($x->{_n}, $x->{_d}); # 22/7 => 3/1 w/ truncate $x->{_d} = $LIB->_one(); # d => 1 $x->{sign} = '+' if $x->{sign} eq '-' && $LIB -> _is_zero($x->{_n}); + return $downgrade -> new($x) if defined $downgrade; return $x; } @@ -1587,18 +1592,30 @@ sub blog { } } + # disable upgrading and downgrading + + require Math::BigFloat; + my $upg = Math::BigFloat -> upgrade(); + my $dng = Math::BigFloat -> downgrade(); + Math::BigFloat -> upgrade(undef); + Math::BigFloat -> downgrade(undef); + # At this point we are done handling all exception cases and trivial cases. $base = Math::BigFloat -> new($base) if defined $base; + my $xnum = Math::BigFloat -> new($LIB -> _str($x->{_n})); + my $xden = Math::BigFloat -> new($LIB -> _str($x->{_d})); + my $xstr = $xnum -> bdiv($xden) -> blog($base, @r) -> bsstr(); - my $xn = Math::BigFloat -> new($LIB -> _str($x->{_n})); - my $xd = Math::BigFloat -> new($LIB -> _str($x->{_d})); + # reset upgrading and downgrading - my $xtmp = Math::BigRat -> new($xn -> bdiv($xd) -> blog($base, @r) -> bsstr()); + Math::BigFloat -> upgrade($upg); + Math::BigFloat -> downgrade($dng); - $x -> {sign} = $xtmp -> {sign}; - $x -> {_n} = $xtmp -> {_n}; - $x -> {_d} = $xtmp -> {_d}; + my $xobj = Math::BigRat -> new($xstr); + $x -> {sign} = $xobj -> {sign}; + $x -> {_n} = $xobj -> {_n}; + $x -> {_d} = $xobj -> {_d}; return $neg ? $x -> bneg() : $x; } @@ -1976,19 +1993,22 @@ sub bnot { sub round { my $x = shift; - $x = $downgrade -> new($x) if defined($downgrade) && $x -> is_int(); + return $downgrade -> new($x) if defined($downgrade) && + ($x -> is_int() || $x -> is_inf() || $x -> is_nan()); $x; } sub bround { my $x = shift; - $x = $downgrade -> new($x) if defined($downgrade) && $x -> is_int(); + return $downgrade -> new($x) if defined($downgrade) && + ($x -> is_int() || $x -> is_inf() || $x -> is_nan()); $x; } sub bfround { my $x = shift; - $x = $downgrade -> new($x) if defined($downgrade) && $x -> is_int(); + return $downgrade -> new($x) if defined($downgrade) && + ($x -> is_int() || $x -> is_inf() || $x -> is_nan()); $x; } @@ -2171,37 +2191,70 @@ sub numify { } sub as_int { - my ($self, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_); + my ($class, $x) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); + + return $x -> copy() if $x -> isa("Math::BigInt"); - # NaN, inf etc - return Math::BigInt->new($x->{sign}) if $x->{sign} !~ /^[+-]$/; + # disable upgrading and downgrading - my $u = Math::BigInt->bzero(); - $u->{value} = $LIB->_div($LIB->_copy($x->{_n}), $x->{_d}); # 22/7 => 3 - $u->bneg if $x->{sign} eq '-'; # no negative zero - $u; + require Math::BigInt; + my $upg = Math::BigInt -> upgrade(); + my $dng = Math::BigInt -> downgrade(); + Math::BigInt -> upgrade(undef); + Math::BigInt -> downgrade(undef); + + my $y; + if ($x -> is_inf()) { + $y = Math::BigInt -> binf($x->sign()); + } elsif ($x -> is_nan()) { + $y = Math::BigInt -> bnan(); + } else { + my $int = $LIB -> _div($LIB -> _copy($x->{_n}), $x->{_d}); # 22/7 => 3 + $y = Math::BigInt -> new($LIB -> _str($int)); + $y = $y -> bneg() if $x -> is_neg(); + } + + # reset upgrading and downgrading + + Math::BigInt -> upgrade($upg); + Math::BigInt -> downgrade($dng); + + return $y; } sub as_float { - # return N/D as Math::BigFloat + my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); - # set up parameters - my ($class, $x, @r) = (ref($_[0]), @_); - # objectify is costly, so avoid it - ($class, $x, @r) = objectify(1, @_) unless ref $_[0]; + return $x -> copy() if $x -> isa("Math::BigFloat"); - # NaN, inf etc - return Math::BigFloat->new($x->{sign}) if $x->{sign} !~ /^[+-]$/; + # disable upgrading and downgrading - my $xflt = Math::BigFloat -> new($LIB -> _str($x->{_n})); - $xflt -> {sign} = $x -> {sign}; + require Math::BigFloat; + my $upg = Math::BigFloat -> upgrade(); + my $dng = Math::BigFloat -> downgrade(); + Math::BigFloat -> upgrade(undef); + Math::BigFloat -> downgrade(undef); - unless ($LIB -> _is_one($x->{_d})) { - my $xd = Math::BigFloat -> new($LIB -> _str($x->{_d})); - $xflt -> bdiv($xd, @r); + my $y; + if ($x -> is_inf()) { + $y = Math::BigFloat -> binf($x->sign()); + } elsif ($x -> is_nan()) { + $y = Math::BigFloat -> bnan(); + } else { + $y = Math::BigFloat -> new($LIB -> _str($x->{_n})); + $y -> {sign} = $x -> {sign}; + unless ($LIB -> _is_one($x->{_d})) { + my $xd = Math::BigFloat -> new($LIB -> _str($x->{_d})); + $y -> bdiv($xd, @r); + } } - return $xflt; + # reset upgrading and downgrading + + Math::BigFloat -> upgrade($upg); + Math::BigFloat -> downgrade($dng); + + return $y; } sub as_bin { diff --git a/cpan/Math-BigRat/t/bigrat.t b/cpan/Math-BigRat/t/bigrat.t index 41fcd2d5c6..bd49ea1147 100644 --- a/cpan/Math-BigRat/t/bigrat.t +++ b/cpan/Math-BigRat/t/bigrat.t @@ -19,90 +19,92 @@ my $mbf = 'Math::BigFloat'; my ($x, $y, $z); $x = Math::BigRat->new(1234); -is($x, 1234); +is($x, 1234, 'value of $x'); isa_ok($x, 'Math::BigRat'); -is($x->isa('Math::BigFloat'), 0); -is($x->isa('Math::BigInt'), 0); +ok(!$x->isa('Math::BigInt'), + "An object of class '" . ref($x) . "' isn't a 'Math::BigInt'"); +ok(!$x->isa('Math::BigFloat'), + "An object of class '" . ref($x) . "' isn't a 'Math::BigFloat'"); ############################################################################## # new and bnorm() -foreach my $func (qw/ new bnorm /) { - $x = $mbr->$func(1234); - is($x, 1234, qq|\$x = $mbr->$func(1234)|); +foreach my $method (qw/ new bnorm /) { + $x = $mbr->$method(1234); + is($x, 1234, qq|\$x = $mbr->$method(1234)|); - $x = $mbr->$func("1234/1"); - is($x, 1234, qq|\$x = $mbr->$func("1234/1")|); + $x = $mbr->$method("1234/1"); + is($x, 1234, qq|\$x = $mbr->$method("1234/1")|); - $x = $mbr->$func("1234/2"); - is($x, 617, qq|\$x = $mbr->$func("1234/2")|); + $x = $mbr->$method("1234/2"); + is($x, 617, qq|\$x = $mbr->$method("1234/2")|); - $x = $mbr->$func("100/1.0"); - is($x, 100, qq|\$x = $mbr->$func("100/1.0")|); + $x = $mbr->$method("100/1.0"); + is($x, 100, qq|\$x = $mbr->$method("100/1.0")|); - $x = $mbr->$func("10.0/1.0"); - is($x, 10, qq|\$x = $mbr->$func("10.0/1.0")|); + $x = $mbr->$method("10.0/1.0"); + is($x, 10, qq|\$x = $mbr->$method("10.0/1.0")|); - $x = $mbr->$func("0.1/10"); - is($x, "1/100", qq|\$x = $mbr->$func("0.1/10")|); + $x = $mbr->$method("0.1/10"); + is($x, "1/100", qq|\$x = $mbr->$method("0.1/10")|); - $x = $mbr->$func("0.1/0.1"); - is($x, "1", qq|\$x = $mbr->$func("0.1/0.1")|); + $x = $mbr->$method("0.1/0.1"); + is($x, "1", qq|\$x = $mbr->$method("0.1/0.1")|); - $x = $mbr->$func("1e2/10"); - is($x, 10, qq|\$x = $mbr->$func("1e2/10")|); + $x = $mbr->$method("1e2/10"); + is($x, 10, qq|\$x = $mbr->$method("1e2/10")|); - $x = $mbr->$func("5/1e2"); - is($x, "1/20", qq|\$x = $mbr->$func("5/1e2")|); + $x = $mbr->$method("5/1e2"); + is($x, "1/20", qq|\$x = $mbr->$method("5/1e2")|); - $x = $mbr->$func("1e2/1e1"); - is($x, 10, qq|\$x = $mbr->$func("1e2/1e1")|); + $x = $mbr->$method("1e2/1e1"); + is($x, 10, qq|\$x = $mbr->$method("1e2/1e1")|); - $x = $mbr->$func("1 / 3"); - is($x, "1/3", qq|\$x = $mbr->$func("1 / 3")|); + $x = $mbr->$method("1 / 3"); + is($x, "1/3", qq|\$x = $mbr->$method("1 / 3")|); - $x = $mbr->$func("-1 / 3"); - is($x, "-1/3", qq|\$x = $mbr->$func("-1 / 3")|); + $x = $mbr->$method("-1 / 3"); + is($x, "-1/3", qq|\$x = $mbr->$method("-1 / 3")|); - $x = $mbr->$func("NaN"); - is($x, "NaN", qq|\$x = $mbr->$func("NaN")|); + $x = $mbr->$method("NaN"); + is($x, "NaN", qq|\$x = $mbr->$method("NaN")|); - $x = $mbr->$func("inf"); - is($x, "inf", qq|\$x = $mbr->$func("inf")|); + $x = $mbr->$method("inf"); + is($x, "inf", qq|\$x = $mbr->$method("inf")|); - $x = $mbr->$func("-inf"); - is($x, "-inf", qq|\$x = $mbr->$func("-inf")|); + $x = $mbr->$method("-inf"); + is($x, "-inf", qq|\$x = $mbr->$method("-inf")|); - $x = $mbr->$func("1/"); - is($x, "NaN", qq|\$x = $mbr->$func("1/")|); + $x = $mbr->$method("1/"); + is($x, "NaN", qq|\$x = $mbr->$method("1/")|); - $x = $mbr->$func("0x7e"); - is($x, 126, qq|\$x = $mbr->$func("0x7e")|); + $x = $mbr->$method("0x7e"); + is($x, 126, qq|\$x = $mbr->$method("0x7e")|); # input ala "1+1/3" isn"t parsed ok yet - $x = $mbr->$func("1+1/3"); - is($x, "NaN", qq|\$x = $mbr->$func("1+1/3")|); + $x = $mbr->$method("1+1/3"); + is($x, "NaN", qq|\$x = $mbr->$method("1+1/3")|); - $x = $mbr->$func("1/1.2"); - is($x, "5/6", qq|\$x = $mbr->$func("1/1.2")|); + $x = $mbr->$method("1/1.2"); + is($x, "5/6", qq|\$x = $mbr->$method("1/1.2")|); - $x = $mbr->$func("1.3/1.2"); - is($x, "13/12", qq|\$x = $mbr->$func("1.3/1.2")|); + $x = $mbr->$method("1.3/1.2"); + is($x, "13/12", qq|\$x = $mbr->$method("1.3/1.2")|); - $x = $mbr->$func("1.2/1"); - is($x, "6/5", qq|\$x = $mbr->$func("1.2/1")|); + $x = $mbr->$method("1.2/1"); + is($x, "6/5", qq|\$x = $mbr->$method("1.2/1")|); ############################################################################ # other classes as input - $x = $mbr->$func($mbi->new(1231)); - is($x, "1231", qq|\$x = $mbr->$func($mbi->new(1231))|); + $x = $mbr->$method($mbi->new(1231)); + is($x, "1231", qq|\$x = $mbr->$method($mbi->new(1231))|); - $x = $mbr->$func($mbf->new(1232)); - is($x, "1232", qq|\$x = $mbr->$func($mbf->new(1232))|); + $x = $mbr->$method($mbf->new(1232)); + is($x, "1232", qq|\$x = $mbr->$method($mbf->new(1232))|); - $x = $mbr->$func($mbf->new(1232.3)); - is($x, "12323/10", qq|\$x = $mbr->$func($mbf->new(1232.3))|); + $x = $mbr->$method($mbf->new(1232.3)); + is($x, "12323/10", qq|\$x = $mbr->$method($mbf->new(1232.3))|); } my $n = 'numerator'; @@ -322,14 +324,19 @@ is($x, 'NaN'); ############################################################################## # binc/bdec +note("binc()"); $x = $mbr->new('3/2'); is($x->binc(), '5/2'); + +note("bdec()"); + $x = $mbr->new('15/6'); is($x->bdec(), '3/2'); ############################################################################## -# bfloor/bceil +# bfloor +note("bfloor()"); $x = $mbr->new('-7/7'); is($x->$n(), '-1'); is($x->$d(), '1'); @@ -426,6 +433,8 @@ subtest qq|$mbr -> new("NaN") -> numify()| => sub { ############################################################################## # as_hex(), as_bin(), as_oct() +note("as_hex(), as_bin(), as_oct()"); + $x = $mbr->new('8/8'); is($x->as_hex(), '0x1'); is($x->as_bin(), '0b1'); @@ -439,32 +448,36 @@ is($x->as_oct(), '012'); ############################################################################## # broot(), blog(), bmodpow() and bmodinv() +note("broot(), blog(), bmodpow(), bmodinv()"); + $x = $mbr->new(2) ** 32; $y = $mbr->new(4); $z = $mbr->new(3); is($x->copy()->broot($y), 2 ** 8); -is(ref($x->copy()->broot($y)), $mbr); +is(ref($x->copy()->broot($y)), $mbr, "\$x is a $mbr"); is($x->copy()->bmodpow($y, $z), 1); -is(ref($x->copy()->bmodpow($y, $z)), $mbr); +is(ref($x->copy()->bmodpow($y, $z)), $mbr, "\$x is a $mbr"); $x = $mbr->new(8); $y = $mbr->new(5033); $z = $mbr->new(4404); is($x->copy()->bmodinv($y), $z); -is(ref($x->copy()->bmodinv($y)), $mbr); +is(ref($x->copy()->bmodinv($y)), $mbr, "\$x is a $mbr"); # square root with exact result $x = $mbr->new('1.44'); is($x->copy()->broot(2), '6/5'); -is(ref($x->copy()->broot(2)), $mbr); +is(ref($x->copy()->broot(2)), $mbr, "\$x is a $mbr"); # log with exact result $x = $mbr->new('256.1'); -is($x->copy()->blog(2), '8000563442710106079310294693803606983661/1000000000000000000000000000000000000000'); -is(ref($x->copy()->blog(2)), $mbr); +is($x->copy()->blog(2), + '8000563442710106079310294693803606983661/1000000000000000000000000000000000000000', + "\$x = $mbr->new('256.1')->blog(2)"); +is(ref($x->copy()->blog(2)), $mbr, "\$x is a $mbr"); $x = $mbr->new(144); is($x->copy()->broot('2'), 12, 'v/144 = 12'); @@ -475,6 +488,8 @@ is($x->copy()->broot('3'), 12, '(12*12*12) ** 1/3 = 12'); ############################################################################## # from_hex(), from_bin(), from_oct() +note("from_hex(), from_bin(), from_oct()"); + $x = Math::BigRat->from_hex('0x100'); is($x, '256', 'from_hex'); diff --git a/cpan/Math-BigRat/t/bigratpm.inc b/cpan/Math-BigRat/t/bigratpm.inc index 9d5f77ed09..4c2f270ecb 100644 --- a/cpan/Math-BigRat/t/bigratpm.inc +++ b/cpan/Math-BigRat/t/bigratpm.inc @@ -339,8 +339,8 @@ abc::1 +inf:inf -inf:-inf abcfsstr:NaN -1:1/1 -3/1:3/1 +1:1 +3/1:3 0.1:1/10 &bnorm diff --git a/cpan/Math-BigRat/t/downgrade.t b/cpan/Math-BigRat/t/downgrade.t index d05d78a39a..3a9f52acc9 100644 --- a/cpan/Math-BigRat/t/downgrade.t +++ b/cpan/Math-BigRat/t/downgrade.t @@ -5,7 +5,7 @@ use strict; use warnings; -use Test::More tests => 33; +use Test::More tests => 141; use Math::BigInt upgrade => 'Math::BigRat'; use Math::BigRat downgrade => 'Math::BigInt'; @@ -105,3 +105,326 @@ is(ref $four, "Math::BigRat", "Creating a 4 does not downgrade"); is(ref $zero, "Math::BigRat", "Creating a 0 does not downgrade"); is(ref $inf, "Math::BigRat", "Creating an Inf does not downgrade"); is(ref $nan, "Math::BigRat", "Creating a NaN does not downgrade"); + +################################################################################ +# Verify that other methods downgrade when they should. + +Math::BigRat -> downgrade("Math::BigInt"); + +note("bneg()"); + +$x = $zero -> copy() -> bneg(); +cmp_ok($x, "==", 0, "-(0) = 0"); +is(ref($x), "Math::BigInt", "-(0) => Math::BigInt"); + +$x = $four -> copy() -> bneg(); +cmp_ok($x, "==", -4, "-(4) = -4"); +is(ref($x), "Math::BigInt", "-(4) => Math::BigInt"); + +$x = $inf -> copy() -> bneg(); +cmp_ok($x, "==", "-inf", "-(Inf) = -Inf"); +is(ref($x), "Math::BigInt", "-(Inf) => Math::BigInt"); + +$x = $nan -> copy() -> bneg(); +is($x, "NaN", "-(NaN) = NaN"); +is(ref($x), "Math::BigInt", "-(NaN) => Math::BigInt"); + +note("bnorm()"); + +$x = $zero -> copy() -> bnorm(); +cmp_ok($x, "==", 0, "bnorm(0)"); +is(ref($x), "Math::BigInt", "bnorm(0) => Math::BigInt"); + +$x = $four -> copy() -> bnorm(); +cmp_ok($x, "==", 4, "bnorm(4)"); +is(ref($x), "Math::BigInt", "bnorm(4) => Math::BigInt"); + +$x = $inf -> copy() -> bnorm(); +cmp_ok($x, "==", "inf", "bnorm(Inf)"); +is(ref($x), "Math::BigInt", "bnorm(Inf) => Math::BigInt"); + +$x = $nan -> copy() -> bnorm(); +is($x, "NaN", "bnorm(NaN)"); +is(ref($x), "Math::BigInt", "bnorm(NaN) => Math::BigInt"); + +note("binc()"); + +$x = $zero -> copy() -> binc(); +cmp_ok($x, "==", 1, "binc(0)"); +is(ref($x), "Math::BigInt", "binc(0) => Math::BigInt"); + +$x = $four -> copy() -> binc(); +cmp_ok($x, "==", 5, "binc(4)"); +is(ref($x), "Math::BigInt", "binc(4) => Math::BigInt"); + +$x = $inf -> copy() -> binc(); +cmp_ok($x, "==", "inf", "binc(Inf)"); +is(ref($x), "Math::BigInt", "binc(Inf) => Math::BigInt"); + +$x = $nan -> copy() -> binc(); +is($x, "NaN", "binc(NaN)"); +is(ref($x), "Math::BigInt", "binc(NaN) => Math::BigInt"); + +note("bdec()"); + +$x = $zero -> copy() -> bdec(); +cmp_ok($x, "==", -1, "bdec(0)"); +is(ref($x), "Math::BigInt", "bdec(0) => Math::BigInt"); + +$x = $four -> copy() -> bdec(); +cmp_ok($x, "==", 3, "bdec(4)"); +is(ref($x), "Math::BigInt", "bdec(4) => Math::BigInt"); + +$x = $inf -> copy() -> bdec(); +cmp_ok($x, "==", "inf", "bdec(Inf)"); +is(ref($x), "Math::BigInt", "bdec(Inf) => Math::BigInt"); + +$x = $nan -> copy() -> bdec(); +is($x, "NaN", "bdec(NaN)"); +is(ref($x), "Math::BigInt", "bdec(NaN) => Math::BigInt"); + +note("badd()"); + +$x = $half -> copy() -> badd($nan); +is($x, "NaN", "0.5 + NaN = NaN"); +is(ref($x), "Math::BigInt", "0.5 + NaN => Math::BigInt"); + +$x = $half -> copy() -> badd($inf); +cmp_ok($x, "==", "+Inf", "0.5 + Inf = Inf"); +is(ref($x), "Math::BigInt", "2.5 + Inf => Math::BigInt"); + +$x = $half -> copy() -> badd($half); +cmp_ok($x, "==", 1, "0.5 + 0.5 = 1"); +is(ref($x), "Math::BigInt", "0.5 + 0.5 => Math::BigInt"); + +$x = $half -> copy() -> badd($half -> copy() -> bneg()); +cmp_ok($x, "==", 0, "0.5 + -0.5 = 0"); +is(ref($x), "Math::BigInt", "0.5 + -0.5 => Math::BigInt"); + +$x = $four -> copy() -> badd($zero); +cmp_ok($x, "==", 4, "4 + 0 = 4"); +is(ref($x), "Math::BigInt", "4 + 0 => Math::BigInt"); + +$x = $zero -> copy() -> badd($four); +cmp_ok($x, "==", 4, "0 + 4 = 4"); +is(ref($x), "Math::BigInt", "0 + 4 => Math::BigInt"); + +$x = $inf -> copy() -> badd($four); +cmp_ok($x, "==", "+Inf", "Inf + 4 = Inf"); +is(ref($x), "Math::BigInt", "Inf + 4 => Math::BigInt"); + +$x = $nan -> copy() -> badd($four); +is($x, "NaN", "NaN + 4 = NaN"); +is(ref($x), "Math::BigInt", "NaN + 4 => Math::BigInt"); + +note("bsub()"); + +$x = $half -> copy() -> bsub($nan); +is($x, "NaN", "0.5 - NaN = NaN"); +is(ref($x), "Math::BigInt", "0.5 - NaN => Math::BigInt"); + +$x = $half -> copy() -> bsub($inf); +cmp_ok($x, "==", "-Inf", "2.5 - Inf = -Inf"); +is(ref($x), "Math::BigInt", "2.5 - Inf => Math::BigInt"); + +$x = $half -> copy() -> bsub($half); +cmp_ok($x, "==", 0, "0.5 - 0.5 = 0"); +is(ref($x), "Math::BigInt", "0.5 - 0.5 => Math::BigInt"); + +$x = $half -> copy() -> bsub($half -> copy() -> bneg()); +cmp_ok($x, "==", 1, "0.5 - -0.5 = 1"); +is(ref($x), "Math::BigInt", "0.5 - -0.5 => Math::BigInt"); + +$x = $four -> copy() -> bsub($zero); +cmp_ok($x, "==", 4, "4 - 0 = 4"); +is(ref($x), "Math::BigInt", "4 - 0 => Math::BigInt"); + +$x = $zero -> copy() -> bsub($four); +cmp_ok($x, "==", -4, "0 - 4 = -4"); +is(ref($x), "Math::BigInt", "0 - 4 => Math::BigInt"); + +$x = $inf -> copy() -> bsub($four); +cmp_ok($x, "==", "Inf", "Inf - 4 = Inf"); +is(ref($x), "Math::BigInt", "Inf - 4 => Math::BigInt"); + +$x = $nan -> copy() -> bsub($four); +is($x, "NaN", "NaN - 4 = NaN"); +is(ref($x), "Math::BigInt", "NaN - 4 => Math::BigInt"); + +note("bmul()"); + +$x = $zero -> copy() -> bmul($four); +cmp_ok($x, "==", 0, "bmul(0, 4) = 0"); +is(ref($x), "Math::BigInt", "bmul(0, 4) => Math::BigInt"); + +$x = $four -> copy() -> bmul($four); +cmp_ok($x, "==", 16, "bmul(4, 4) = 16"); +is(ref($x), "Math::BigInt", "bmul(4, 4) => Math::BigInt"); + +$x = $inf -> copy() -> bmul($four); +cmp_ok($x, "==", "inf", "bmul(Inf, 4) = Inf"); +is(ref($x), "Math::BigInt", "bmul(Inf, 4) => Math::BigInt"); + +$x = $nan -> copy() -> bmul($four); +is($x, "NaN", "bmul(NaN, 4) = NaN"); +is(ref($x), "Math::BigInt", "bmul(NaN, 4) => Math::BigInt"); + +$x = $four -> copy() -> bmul("0.5"); +cmp_ok($x, "==", 2, "bmul(4, 0.5) = 2"); +is(ref($x), "Math::BigInt", "bmul(4, 0.5) => Math::BigInt"); + +# bmuladd() + +note("bdiv()"); + +note("bmod()"); + +note("bmodpow()"); + +note("bpow()"); + +note("blog()"); + +note("bexp()"); + +note("bnok()"); + +note("bsin()"); + +note("bcos()"); + +note("batan()"); + +note("batan()"); + +note("bsqrt()"); + +note("broot()"); + +note("bfac()"); + +note("bdfac()"); + +note("btfac()"); + +note("bmfac()"); + +note("blsft()"); + +note("brsft()"); + +note("band()"); + +note("bior()"); + +note("bxor()"); + +note("bnot()"); + +note("bround()"); + +# Add tests for rounding a non-integer to an integer. Fixme! + +$x = $zero -> copy() -> bround(); +cmp_ok($x, "==", 0, "bround(0)"); +is(ref($x), "Math::BigInt", "bround(0) => Math::BigInt"); + +$x = $four -> copy() -> bround(); +cmp_ok($x, "==", 4, "bround(4)"); +is(ref($x), "Math::BigInt", "bround(4) => Math::BigInt"); + +$x = $inf -> copy() -> bround(); +cmp_ok($x, "==", "inf", "bround(Inf)"); +is(ref($x), "Math::BigInt", "bround(Inf) => Math::BigInt"); + +$x = $nan -> copy() -> bround(); +is($x, "NaN", "bround(NaN)"); +is(ref($x), "Math::BigInt", "bround(NaN) => Math::BigInt"); + +note("bfround()"); + +# Add tests for rounding a non-integer to an integer. Fixme! + +$x = $zero -> copy() -> bfround(); +cmp_ok($x, "==", 0, "bfround(0)"); +is(ref($x), "Math::BigInt", "bfround(0) => Math::BigInt"); + +$x = $four -> copy() -> bfround(); +cmp_ok($x, "==", 4, "bfround(4)"); +is(ref($x), "Math::BigInt", "bfround(4) => Math::BigInt"); + +$x = $inf -> copy() -> bfround(); +cmp_ok($x, "==", "inf", "bfround(Inf)"); +is(ref($x), "Math::BigInt", "bfround(Inf) => Math::BigInt"); + +$x = $nan -> copy() -> bfround(); +is($x, "NaN", "bfround(NaN)"); +is(ref($x), "Math::BigInt", "bfround(NaN) => Math::BigInt"); + +note("bfloor()"); + +$x = $half -> copy() -> bfloor(); +cmp_ok($x, "==", 0, "bfloor(0)"); +is(ref($x), "Math::BigInt", "bfloor(0) => Math::BigInt"); + +$x = $inf -> copy() -> bfloor(); +cmp_ok($x, "==", "Inf", "bfloor(Inf)"); +is(ref($x), "Math::BigInt", "bfloor(Inf) => Math::BigInt"); + +$x = $nan -> copy() -> bfloor(); +is($x, "NaN", "bfloor(NaN)"); +is(ref($x), "Math::BigInt", "bfloor(NaN) => Math::BigInt"); + +note("bceil()"); + +$x = $half -> copy() -> bceil(); +cmp_ok($x, "==", 1, "bceil(0)"); +is(ref($x), "Math::BigInt", "bceil(0) => Math::BigInt"); + +$x = $inf -> copy() -> bceil(); +cmp_ok($x, "==", "Inf", "bceil(Inf)"); +is(ref($x), "Math::BigInt", "bceil(Inf) => Math::BigInt"); + +$x = $nan -> copy() -> bceil(); +is($x, "NaN", "bceil(NaN)"); +is(ref($x), "Math::BigInt", "bceil(NaN) => Math::BigInt"); + +note("bint()"); + +$x = $half -> copy() -> bint(); +cmp_ok($x, "==", 0, "bint(0)"); +is(ref($x), "Math::BigInt", "bint(0) => Math::BigInt"); + +$x = $inf -> copy() -> bint(); +cmp_ok($x, "==", "Inf", "bint(Inf)"); +is(ref($x), "Math::BigInt", "bint(Inf) => Math::BigInt"); + +$x = $nan -> copy() -> bint(); +is($x, "NaN", "bint(NaN)"); +is(ref($x), "Math::BigInt", "bint(NaN) => Math::BigInt"); + +note("bgcd()"); + +note("blcm()"); + +# mantissa() ? + +# exponent() ? + +# parts() ? + +# sparts() + +# nparts() + +# eparts() + +# dparts() + +# fparts() + +# numerator() + +# denominator() + +#require 'upgrade.inc'; # all tests here for sharing |