summaryrefslogtreecommitdiff
path: root/cpan/Math-BigRat
diff options
context:
space:
mode:
authorNicolas R <atoomic@cpan.org>2022-07-20 19:27:46 +0000
committerℕicolas ℝ <nicolas@atoomic.org>2022-07-20 14:49:02 -0600
commitd18b40dae1e94d9ccfd63e1ba0873a8a77d59226 (patch)
tree2a120c4466f1a81d8cce014e4004dab213e2b7f5 /cpan/Math-BigRat
parent119199b1a4e490b69342c09058ab33a628e5c801 (diff)
downloadperl-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.pm287
-rw-r--r--cpan/Math-BigRat/t/bigrat.t133
-rw-r--r--cpan/Math-BigRat/t/bigratpm.inc4
-rw-r--r--cpan/Math-BigRat/t/downgrade.t325
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