summaryrefslogtreecommitdiff
path: root/lib/Math/BigInt
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Math/BigInt')
-rw-r--r--lib/Math/BigInt/Calc.pm303
-rwxr-xr-xlib/Math/BigInt/t/bigfltpm.t203
-rw-r--r--lib/Math/BigInt/t/bigintc.t139
-rwxr-xr-xlib/Math/BigInt/t/bigintpm.t227
-rw-r--r--lib/Math/BigInt/t/mbimbf.t2
5 files changed, 693 insertions, 181 deletions
diff --git a/lib/Math/BigInt/Calc.pm b/lib/Math/BigInt/Calc.pm
index 23ff06329d..c42fc4043d 100644
--- a/lib/Math/BigInt/Calc.pm
+++ b/lib/Math/BigInt/Calc.pm
@@ -2,7 +2,7 @@ package Math::BigInt::Calc;
use 5.005;
use strict;
-use warnings;
+# use warnings; # dont use warnings for older Perls
require Exporter;
@@ -17,8 +17,9 @@ use vars qw/ @ISA @EXPORT $VERSION/;
_is_zero _is_one
_is_even _is_odd
_check _zero _one _copy _zeros
+ _rsft _lsft
);
-$VERSION = '0.06';
+$VERSION = '0.09';
# Package to store unsigned big integers in decimal and do math with them
@@ -39,10 +40,37 @@ $VERSION = '0.06';
# constants for easier life
my $nan = 'NaN';
-my $BASE_LEN = 5;
+
+my $BASE_LEN = 7;
my $BASE = int("1e".$BASE_LEN); # var for trying to change it to 1e7
-my $RBASE = 1e-5; # see USE_MUL
-my $class = 'Math::BigInt::Calc';
+my $RBASE = abs('1e-'.$BASE_LEN); # see USE_MUL
+
+BEGIN
+ {
+ # Daniel Pfeiffer: determine largest group of digits that is precisely
+ # multipliable with itself plus carry
+ my ($e, $num) = 4;
+ do {
+ $num = ('9' x ++$e) + 0;
+ $num *= $num + 1;
+ } until ($num == $num - 1 or $num - 1 == $num - 2);
+ $BASE_LEN = $e-1;
+ $BASE = int("1e".$BASE_LEN);
+ $RBASE = abs('1e-'.$BASE_LEN); # see USE_MUL
+ }
+
+# for quering and setting, to debug/benchmark things
+sub _base_len
+ {
+ my $b = shift;
+ if (defined $b)
+ {
+ $BASE_LEN = $b;
+ $BASE = int("1e".$BASE_LEN);
+ $RBASE = abs('1e-'.$BASE_LEN); # see USE_MUL
+ }
+ $BASE_LEN;
+ }
##############################################################################
# create objects from various representations
@@ -52,12 +80,12 @@ sub _new
# (string) return ref to num_array
# Convert a number from string format to internal base 100000 format.
# Assumes normalized value as input.
- shift @_ if $_[0] eq $class;
- my $d = shift;
+ my $d = $_[1];
# print "_new $d $$d\n";
my $il = CORE::length($$d)-1;
# these leaves '00000' instead of int 0 and will be corrected after any op
- return [ reverse(unpack("a" . ($il%5+1) . ("a5" x ($il/5)), $$d)) ];
+ return [ reverse(unpack("a" . ($il % $BASE_LEN+1)
+ . ("a$BASE_LEN" x ($il / $BASE_LEN)), $$d)) ];
}
sub _zero
@@ -74,9 +102,7 @@ sub _one
sub _copy
{
- shift @_ if $_[0] eq $class;
- my $x = shift;
- return [ @$x ];
+ return [ @{$_[1]} ];
}
##############################################################################
@@ -87,8 +113,7 @@ sub _str
# (ref to BINT) return num_str
# Convert number from internal base 100000 format to string format.
# internal format is always normalized (no leading zeros, "-0" => "+0")
- shift @_ if $_[0] eq $class;
- my $ar = shift;
+ my $ar = $_[1];
my $ret = "";
my $l = scalar @$ar; # number of parts
return $nan if $l < 1; # should not happen
@@ -96,10 +121,11 @@ sub _str
# leading zero parts in internal representation)
$l --; $ret .= $ar->[$l]; $l--;
# Interestingly, the pre-padd method uses more time
- # the old grep variant takes longer (14 to 10 sec)
+ # the old grep variant takes longer (14 to 10 sec)
+ my $z = '0' x ($BASE_LEN-1);
while ($l >= 0)
{
- $ret .= substr('0000'.$ar->[$l],-5); # fastest way I could think of
+ $ret .= substr($z.$ar->[$l],-$BASE_LEN); # fastest way I could think of
$l--;
}
return \$ret;
@@ -108,8 +134,7 @@ sub _str
sub _num
{
# Make a number (scalar int/float) from a BigInt object
- shift @_ if $_[0] eq $class;
- my $x = shift;
+ my $x = $_[1];
return $x->[0] if scalar @$x == 1; # below $BASE
my $fac = 1;
my $num = 0;
@@ -126,13 +151,12 @@ sub _num
sub _add
{
# (ref to int_num_array, ref to int_num_array)
- # routine to add two base 1e5 numbers
+ # routine to add two base 1eX numbers
# stolen from Knuth Vol 2 Algorithm A pg 231
# there are separate routines to add and sub as per Knuth pg 233
# This routine clobbers up array x, but not y.
- shift @_ if $_[0] eq $class;
- my ($x,$y) = @_;
+ my ($c,$x,$y) = @_;
# for each in Y, add Y to X and carry. If after that, something is left in
# X, foreach in X add carry to X and then return X, carry
@@ -155,10 +179,9 @@ sub _add
sub _sub
{
# (ref to int_num_array, ref to int_num_array)
- # subtract base 1e5 numbers -- stolen from Knuth Vol 2 pg 232, $x > $y
+ # subtract base 1eX numbers -- stolen from Knuth Vol 2 pg 232, $x > $y
# subtract Y from X (X is always greater/equal!) by modifying x in place
- shift @_ if $_[0] eq $class;
- my ($sx,$sy,$s) = @_;
+ my ($c,$sx,$sy,$s) = @_;
my $car = 0; my $i; my $j = 0;
if (!$s)
@@ -198,41 +221,39 @@ sub _mul
# (BINT, BINT) return nothing
# multiply two numbers in internal representation
# modifies first arg, second need not be different from first
- shift @_ if $_[0] eq $class;
- my ($xv,$yv) = @_;
+ my ($c,$xv,$yv) = @_;
my @prod = (); my ($prod,$car,$cty,$xi,$yi);
# since multiplying $x with $x fails, make copy in this case
- $yv = [@$xv] if "$xv" eq "$yv";
- # looping through @$y if $xi == 0 is silly! optimize it!
+ $yv = [@$xv] if "$xv" eq "$yv"; # same references?
for $xi (@$xv)
{
$car = 0; $cty = 0;
+
+ # slow variant
+# for $yi (@$yv)
+# {
+# $prod = $xi * $yi + ($prod[$cty] || 0) + $car;
+# $prod[$cty++] =
+# $prod - ($car = int($prod * RBASE)) * $BASE; # see USE_MUL
+# }
+# $prod[$cty] += $car if $car; # need really to check for 0?
+# $xi = shift @prod;
+
+ # faster variant
+ # looping through this if $xi == 0 is silly - so optimize it away!
+ $xi = (shift @prod || 0), next if $xi == 0;
for $yi (@$yv)
{
$prod = $xi * $yi + ($prod[$cty] || 0) + $car;
+## this is actually a tad slower
+## $prod = $prod[$cty]; $prod += ($car + $xi * $yi); # no ||0 here
$prod[$cty++] =
- $prod - ($car = int($prod * 1e-5)) * $BASE; # see USE_MUL
+ $prod - ($car = int($prod * $RBASE)) * $BASE; # see USE_MUL
}
$prod[$cty] += $car if $car; # need really to check for 0?
$xi = shift @prod;
}
-# for $xi (@$xv)
-# {
-# $car = 0; $cty = 0;
-# # looping through this if $xi == 0 is silly! optimize it!
-# if (($xi||0) != 0)
-# {
-# for $yi (@$yv)
-# {
-# $prod = $prod[$cty]; $prod += ($car + $xi * $yi); # no ||0 here
-# $prod[$cty++] =
-# $prod - ($car = int($prod * 1e-5)) * $BASE; # see USE_MUL
-# }
-# }
-# $prod[$cty] += $car if $car; # need really to check for 0?
-# $xi = shift @prod;
-# }
push @$xv, @prod;
__strip_zeros($xv);
# normalize (handled last to save check for $y->is_zero()
@@ -244,8 +265,7 @@ sub _div
# ref to array, ref to array, modify first array and return remainder if
# in list context
# no longer handles sign
- shift @_ if $_[0] eq $class;
- my ($x,$yorg) = @_;
+ my ($c,$x,$yorg) = @_;
my ($car,$bar,$prd,$dd,$xi,$yi,@q,$v2,$v1);
my (@d,$tmp,$q,$u2,$u1,$u0);
@@ -280,7 +300,7 @@ sub _div
#warn "oups v1 is 0, u0: $u0 $y->[-2] $y->[-1] l ",scalar @$y,"\n"
# if $v1 == 0;
$q = (($u0 == $v1) ? 99999 : int(($u0*$BASE+$u1)/$v1));
- --$q while ($v2*$q > ($u0*1e5+$u1-$q*$v1)*$BASE+$u2);
+ --$q while ($v2*$q > ($u0*$BASE+$u1-$q*$v1)*$BASE+$u2);
if ($q)
{
($car, $bar) = (0,0);
@@ -288,14 +308,14 @@ sub _div
{
$prd = $q * $y->[$yi] + $car;
$prd -= ($car = int($prd * $RBASE)) * $BASE; # see USE_MUL
- $x->[$xi] += 1e5 if ($bar = (($x->[$xi] -= $prd + $bar) < 0));
+ $x->[$xi] += $BASE if ($bar = (($x->[$xi] -= $prd + $bar) < 0));
}
if ($x->[-1] < $car + $bar)
{
$car = 0; --$q;
for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)
{
- $x->[$xi] -= 1e5
+ $x->[$xi] -= $BASE
if ($car = (($x->[$xi] += $y->[$yi] + $car) > $BASE));
}
}
@@ -330,6 +350,98 @@ sub _div
}
##############################################################################
+# shifts
+
+sub _rsft
+ {
+ my ($c,$x,$y,$n) = @_;
+
+ if ($n != 10)
+ {
+ return; # we cant do this here, due to now _pow, so signal failure
+ }
+ else
+ {
+ # shortcut (faster) for shifting by 10)
+ # multiples of $BASE_LEN
+ my $dst = 0; # destination
+ my $src = _num($c,$y); # as normal int
+ my $rem = $src % $BASE_LEN; # reminder to shift
+ $src = int($src / $BASE_LEN); # source
+ if ($rem == 0)
+ {
+ splice (@$x,0,$src); # even faster, 38.4 => 39.3
+ }
+ else
+ {
+ my $len = scalar @$x - $src; # elems to go
+ my $vd; my $z = '0'x $BASE_LEN;
+ $x->[scalar @$x] = 0; # avoid || 0 test inside loop
+ while ($dst < $len)
+ {
+ $vd = $z.$x->[$src];
+ #print "$dst $src '$vd' ";
+ $vd = substr($vd,-$BASE_LEN,$BASE_LEN-$rem);
+ #print "'$vd' ";
+ $src++;
+ $vd = substr($z.$x->[$src],-$rem,$rem) . $vd;
+ #print "'$vd1' ";
+ #print "'$vd'\n";
+ $vd = substr($vd,-$BASE_LEN,$BASE_LEN) if length($vd) > $BASE_LEN;
+ $x->[$dst] = int($vd);
+ $dst++;
+ }
+ splice (@$x,$dst) if $dst > 0; # kill left-over array elems
+ pop @$x if $x->[-1] == 0; # kill last element if 0
+ } # else rem == 0
+ }
+ $x;
+ }
+
+sub _lsft
+ {
+ my ($c,$x,$y,$n) = @_;
+
+ if ($n != 10)
+ {
+ return; # we cant do this here, due to now _pow, so signal failure
+ }
+ else
+ {
+ # shortcut (faster) for shifting by 10) since we are in base 10eX
+ # multiples of $BASE_LEN:
+ my $src = scalar @$x; # source
+ my $len = _num($c,$y); # shift-len as normal int
+ my $rem = $len % $BASE_LEN; # reminder to shift
+ my $dst = $src + int($len/$BASE_LEN); # destination
+ my $vd; # further speedup
+ #print "src $src:",$x->[$src]||0," dst $dst:",$v->[$dst]||0," rem $rem\n";
+ $x->[$src] = 0; # avoid first ||0 for speed
+ my $z = '0' x $BASE_LEN;
+ while ($src >= 0)
+ {
+ $vd = $x->[$src]; $vd = $z.$vd;
+ #print "s $src d $dst '$vd' ";
+ $vd = substr($vd,-$BASE_LEN+$rem,$BASE_LEN-$rem);
+ #print "'$vd' ";
+ $vd .= $src > 0 ? substr($z.$x->[$src-1],-$BASE_LEN,$rem) : '0' x $rem;
+ #print "'$vd' ";
+ $vd = substr($vd,-$BASE_LEN,$BASE_LEN) if length($vd) > $BASE_LEN;
+ #print "'$vd'\n";
+ $x->[$dst] = int($vd);
+ $dst--; $src--;
+ }
+ # set lowest parts to 0
+ while ($dst >= 0) { $x->[$dst--] = 0; }
+ # fix spurios last zero element
+ splice @$x,-1 if $x->[-1] == 0;
+ #print "elems: "; my $i = 0;
+ #foreach (reverse @$v) { print "$i $_ "; $i++; } print "\n";
+ }
+ $x;
+ }
+
+##############################################################################
# testing
sub _acmp
@@ -338,15 +450,16 @@ sub _acmp
# ref to array, ref to array, return <0, 0, >0
# arrays must have at least one entry; this is not checked for
- shift @_ if $_[0] eq $class;
- my ($cx, $cy) = @_;
+ my ($c,$cx, $cy) = @_;
#print "$cx $cy\n";
my ($i,$a,$x,$y,$k);
# calculate length based on digits, not parts
- $x = _len($cx); $y = _len($cy);
+ $x = _len('',$cx); $y = _len('',$cy);
# print "length: ",($x-$y),"\n";
- return $x-$y if ($x - $y); # if different in length
+ my $lxy = $x - $y; # if different in length
+ return -1 if $lxy < 0;
+ return 1 if $lxy > 0;
#print "full compare\n";
$i = 0; $a = 0;
# first way takes 5.49 sec instead of 4.87, but has the early out advantage
@@ -359,7 +472,9 @@ sub _acmp
# print "$cx->[$j] $cy->[$j] $a",$cx->[$j]-$cy->[$j],"\n";
last if ($a = $cx->[$j] - $cy->[$j]); $j--;
}
- return $a;
+ return 1 if $a > 0;
+ return -1 if $a < 0;
+ return 0; # equal
# while it early aborts, it is even slower than the manual variant
#grep { return $a if ($a = $_ - $cy->[$i++]); } @$cx;
# grep way, go trough all (bad for early ne)
@@ -372,28 +487,25 @@ sub _len
# computer number of digits in bigint, minus the sign
# int() because add/sub sometimes leaves strings (like '00005') instead of
# int ('5') in this place, causing length to fail
- shift @_ if $_[0] eq $class;
- my $cx = shift;
+ my $cx = $_[1];
- return (@$cx-1)*5+length(int($cx->[-1]));
+ return (@$cx-1)*$BASE_LEN+length(int($cx->[-1]));
}
sub _digit
{
# return the nth digit, negative values count backward
# zero is rightmost, so _digit(123,0) will give 3
- shift @_ if $_[0] eq $class;
- my $x = shift;
- my $n = shift || 0;
+ my ($c,$x,$n) = @_;
- my $len = _len($x);
+ my $len = _len('',$x);
$n = $len+$n if $n < 0; # -1 last, -2 second-to-last
$n = abs($n); # if negative was too big
$len--; $n = $len if $n > $len; # n to big?
- my $elem = int($n / 5); # which array element
- my $digit = $n % 5; # which digit in this element
+ my $elem = int($n / $BASE_LEN); # which array element
+ my $digit = $n % $BASE_LEN; # which digit in this element
$elem = '0000'.@$x[$elem]; # get element padded with 0's
return substr($elem,-$digit-1,1);
}
@@ -403,20 +515,19 @@ sub _zeros
# return amount of trailing zeros in decimal
# check each array elem in _m for having 0 at end as long as elem == 0
# Upon finding a elem != 0, stop
- shift @_ if $_[0] eq $class;
- my $x = shift;
+ my $x = $_[1];
my $zeros = 0; my $elem;
foreach my $e (@$x)
{
if ($e != 0)
{
- $elem = "$e"; # preserve x
- $elem =~ s/.*?(0*$)/$1/; # strip anything not zero
- $zeros *= 5; # elems * 5
- $zeros += CORE::length($elem); # count trailing zeros
- last; # early out
+ $elem = "$e"; # preserve x
+ $elem =~ s/.*?(0*$)/$1/; # strip anything not zero
+ $zeros *= $BASE_LEN; # elems * 5
+ $zeros += CORE::length($elem); # count trailing zeros
+ last; # early out
}
- $zeros ++; # real else branch: 50% slower!
+ $zeros ++; # real else branch: 50% slower!
}
return $zeros;
}
@@ -427,32 +538,28 @@ sub _zeros
sub _is_zero
{
# return true if arg (BINT or num_str) is zero (array '+', '0')
- shift @_ if $_[0] eq $class;
- my ($x) = shift;
+ my $x = $_[1];
return (((scalar @$x == 1) && ($x->[0] == 0))) <=> 0;
}
sub _is_even
{
# return true if arg (BINT or num_str) is even
- shift @_ if $_[0] eq $class;
- my ($x) = shift;
+ my $x = $_[1];
return (!($x->[0] & 1)) <=> 0;
}
sub _is_odd
{
# return true if arg (BINT or num_str) is even
- shift @_ if $_[0] eq $class;
- my ($x) = shift;
+ my $x = $_[1];
return (($x->[0] & 1)) <=> 0;
}
sub _is_one
{
# return true if arg (BINT or num_str) is one (array '+', '1')
- shift @_ if $_[0] eq $class;
- my ($x) = shift;
+ my $x = $_[1];
return (scalar @$x == 1) && ($x->[0] == 1) <=> 0;
}
@@ -460,8 +567,6 @@ sub __strip_zeros
{
# internal normalization function that strips leading zeros from the array
# args: ref to array
- #trace(@_);
- shift @_ if $_[0] eq $class;
my $s = shift;
my $cnt = scalar @$s; # get count of parts
@@ -485,9 +590,8 @@ sub __strip_zeros
sub _check
{
# no checks yet, pull it out from the test suite
- shift @_ if $_[0] eq $class;
+ my $x = $_[1];
- my ($x) = shift;
return "$x is not a reference" if !ref($x);
# are all parts are valid?
@@ -529,7 +633,7 @@ was rewritten to use library modules for core math routines. Any
module which follows the same API as this can be used instead by
using the following call:
- use Math::BigInt Calc => BigNum;
+ use Math::BigInt lib => BigNum;
=head1 EXPORT
@@ -601,8 +705,32 @@ Input strings come in as unsigned but with prefix (i.e. as '123', '0xabc'
or '0b1101').
Testing of input parameter validity is done by the caller, so you need not
-worry about underflow (C<_sub()>, C<_dec()>) nor about division by zero or
-similar cases.
+worry about underflow (f.i. in C<_sub()>, C<_dec()>) nor about division by
+zero or similar cases.
+
+The first parameter can be modified, that includes the possibility that you
+return a reference to a completely different object instead. Although keeping
+the reference the same is prefered.
+
+Return values are always references to objects or strings. Exceptions are
+C<_lsft()> and C<_rsft()>, which return undef if they can not shift the
+argument. This is used to delegate shifting of bases different than 10 back
+to BigInt, which will use some generic code to calculate the result.
+
+=head1 WRAP YOUR OWN
+
+If you want to port your own favourite c-lib for big numbers to the
+Math::BigInt interface, you can take any of the already existing modules as
+a rough guideline. You should really wrap up the latest BigInt and BigFloat
+testsuites with your module, and replace the following line:
+
+ use Math::BigInt;
+
+by
+
+ use Math::BigInt lib => 'yourlib';
+
+This way you ensure that your library really works 100% within Math::BigInt.
=head1 LICENSE
@@ -617,6 +745,7 @@ Seperated from BigInt and shaped API with the help of John Peacock.
=head1 SEE ALSO
-L<Math::BigInt>, L<Math::BigFloat>.
+L<Math::BigInt>, L<Math::BigFloat>, L<Math::BigInt::BitVect> and
+L<Math::BigInt::Pari>.
=cut
diff --git a/lib/Math/BigInt/t/bigfltpm.t b/lib/Math/BigInt/t/bigfltpm.t
index e8a1cc2462..a30563d21e 100755
--- a/lib/Math/BigInt/t/bigfltpm.t
+++ b/lib/Math/BigInt/t/bigfltpm.t
@@ -8,11 +8,11 @@ BEGIN
$| = 1;
unshift @INC, '../lib'; # for running manually
# chdir 't' if -d 't';
- plan tests => 945;
+ plan tests => 1158;
}
-use Math::BigFloat;
use Math::BigInt;
+use Math::BigFloat;
my ($x,$y,$f,@args,$ans,$try,$ans1,$ans1_str,$setup);
while (<DATA>)
@@ -47,10 +47,21 @@ while (<DATA>)
$try .= "\$x;";
} elsif ($f eq "binf") {
$try .= "\$x->binf('$args[1]');";
+ } elsif ($f eq "bnan") {
+ $try .= "\$x->bnan();";
+ } elsif ($f eq "numify") {
+ $try .= "\$x->numify();";
+ } elsif ($f eq "bone") {
+ $try .= "\$x->bone('$args[1]');";
+ } elsif ($f eq "bstr") {
+ $try .= "\$x->accuracy($args[1]); \$x->precision($args[2]);";
+ $try .= '$x->bstr();';
} elsif ($f eq "bsstr") {
- $try .= "\$x->bsstr();";
+ $try .= '$x->bsstr();';
+ } elsif ($f eq "parts") {
+ $try .= '($a,$b) = $x->parts(); "$a $b";';
} elsif ($f eq "fneg") {
- $try .= "-\$x;";
+ $try .= '$x->bneg();';
} elsif ($f eq "bfloor") {
$try .= "\$x->bfloor();";
} elsif ($f eq "bceil") {
@@ -59,6 +70,10 @@ while (<DATA>)
$try .= "\$x->is_zero()+0;";
} elsif ($f eq "is_one") {
$try .= "\$x->is_one()+0;";
+ } elsif ($f eq "is_positive") {
+ $try .= "\$x->is_positive()+0;";
+ } elsif ($f eq "is_negative") {
+ $try .= "\$x->is_negative()+0;";
} elsif ($f eq "is_odd") {
$try .= "\$x->is_odd()+0;";
} elsif ($f eq "is_even") {
@@ -66,7 +81,11 @@ while (<DATA>)
} elsif ($f eq "as_number") {
$try .= "\$x->as_number();";
} elsif ($f eq "fabs") {
- $try .= "abs \$x;";
+ $try .= '$x->babs();';
+ } elsif ($f eq "finc") {
+ $try .= '++$x;';
+ } elsif ($f eq "fdec") {
+ $try .= '--$x;';
}elsif ($f eq "fround") {
$try .= "$setup; \$x->fround($args[1]);";
} elsif ($f eq "ffround") {
@@ -153,15 +172,48 @@ __END__
-123.456:-123
-200:-200
&binf
-1:+:+inf
+1:+:inf
2:-:-inf
-3:abc:+inf
-&bsstr
-+inf:+inf
+3:abc:inf
+&numify
+0:0e+1
++1:1e+0
+1234:1234e+0
+NaN:NaN
++inf:inf
-inf:-inf
+&bnan
abc:NaN
+2:NaN
+-2:NaN
+0:NaN
+&bone
+2:+:1
+-2:-:-1
+-2:+:1
+2:-:-1
+0::1
+-2::1
+abc::1
+2:abc:1
+&bsstr
++inf:inf
+-inf:-inf
+abcbsstr:NaN
+1234.567:1234567e-3
+&bstr
++inf:::inf
+-inf:::-inf
+abcbsstr:::NaN
+1234.567:9::1234.56700
+1234.567::-6:1234.567000
+12345:5::12345
+0.001234:6::0.00123400
+0.001234::-8:0.00123400
+0:4::0
+0::-4:0.0000
&fnorm
-+inf:+inf
++inf:inf
-inf:-inf
+infinity:NaN
+-inf:NaN
@@ -201,6 +253,14 @@ abc:NaN
-123456E-2:-1234.56
1e1:10
2e-11:0.00000000002
+# excercise _split
+ .02e-1:0.002
+ 000001:1
+ -00001:-1
+ -1:-1
+ 000.01:0.01
+ -000.0023:-0.0023
+ 1.1e1:11
-3e111:-3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-4e-1111:-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004
&fpow
@@ -215,12 +275,14 @@ abc:NaN
128:-2:0.00006103515625
abc:123.456:NaN
123.456:abc:NaN
-+inf:123.45:+inf
++inf:123.45:inf
-inf:123.45:-inf
-+inf:-123.45:+inf
++inf:-123.45:inf
-inf:-123.45:-inf
&fneg
-abc:NaN
+fnegNaN:NaN
++inf:-inf
+-inf:inf
+0:0
+1:-1
-1:1
@@ -229,7 +291,9 @@ abc:NaN
+123.456789:-123.456789
-123456.789:123456.789
&fabs
-abc:NaN
+fabsNaN:NaN
++inf:inf
+-inf:inf
+0:0
+1:1
-1:1
@@ -239,6 +303,10 @@ abc:NaN
-123456.789:123456.789
&fround
$rnd_mode = "trunc"
++inf:5:inf
+-inf:5:-inf
+0:5:0
+NaNfround:5:NaN
+10123456789:5:10123000000
-10123456789:5:-10123000000
+10123456789.123:5:10123000000
@@ -294,6 +362,10 @@ $rnd_mode = "even"
-60123456789.0123:5:-60123000000
&ffround
$rnd_mode = "trunc"
++inf:5:inf
+-inf:5:-inf
+0:5:0
+NaNffround:5:NaN
+1.23:-1:1.2
+1.234:-1:1.2
+1.2345:-1:1.2
@@ -424,9 +496,9 @@ $rnd_mode = "even"
0.01234567:-9:0.01234567
0.01234567:-12:0.01234567
&fcmp
-abc:abc:
-abc:+0:
-+0:abc:
+fcmpNaN:fcmpNaN:
+fcmpNaN:+0:
++0:fcmpNaN:
+0:+0:0
-1:+0:-1
+0:-1:1
@@ -482,15 +554,43 @@ abc:+0:
+inf:-54321.12345:1
+inf:+inf:0
-inf:-inf:0
++inf:-inf:1
+-inf:+inf:-1
# return undef
+inf:NaN:
-NaN:+inf:
+NaN:inf:
-inf:NaN:
NaN:-inf:
+&fdec
+fdecNaN:NaN
++inf:inf
+-inf:-inf
++0:-1
++1:0
+-1:-2
+1.23:0.23
+-1.23:-2.23
+&finc
+fincNaN:NaN
++inf:inf
+-inf:-inf
++0:1
++1:2
+-1:0
+1.23:2.23
+-1.23:-0.23
&fadd
abc:abc:NaN
abc:+0:NaN
+0:abc:NaN
++inf:-inf:0
+-inf:+inf:0
++inf:+inf:inf
+-inf:-inf:-inf
+baddNaN:+inf:NaN
+baddNaN:+inf:NaN
++inf:baddNaN:NaN
+-inf:baddNaN:NaN
+0:+0:0
+1:+0:1
+0:+1:1
@@ -530,6 +630,14 @@ abc:+0:NaN
abc:abc:NaN
abc:+0:NaN
+0:abc:NaN
++inf:-inf:inf
+-inf:+inf:-inf
++inf:+inf:0
+-inf:-inf:0
+baddNaN:+inf:NaN
+baddNaN:+inf:NaN
++inf:baddNaN:NaN
+-inf:baddNaN:NaN
+0:+0:0
+1:+0:1
+0:+1:-1
@@ -568,6 +676,22 @@ abc:+0:NaN
abc:abc:NaN
abc:+0:NaN
+0:abc:NaN
++inf:NaNmul:NaN
++inf:NaNmul:NaN
+NaNmul:+inf:NaN
+NaNmul:-inf:NaN
++inf:+inf:inf
++inf:-inf:-inf
++inf:-inf:-inf
++inf:+inf:inf
++inf:123.34:inf
++inf:-123.34:-inf
+-inf:123.34:-inf
+-inf:-123.34:inf
+123.34:+inf:inf
+-123.34:+inf:-inf
+123.34:-inf:-inf
+-123.34:-inf:inf
+0:+0:0
+0:+1:0
+1:+0:0
@@ -604,17 +728,23 @@ $div_scale = 40; $Math::BigFloat::rnd_mode = 'even'
abc:abc:NaN
abc:+1:abc:NaN
+1:abc:NaN
+-1:abc:NaN
+0:abc:NaN
+0:+0:NaN
+0:+1:0
-+1:+0:NaN
++1:+0:inf
++3214:+0:inf
+0:-1:0
--1:+0:NaN
+-1:+0:-inf
+-3214:+0:-inf
+1:+1:1
-1:-1:1
+1:-1:-1
-1:+1:-1
+1:+2:0.5
+2:+1:2
+123:+inf:0
+123:-inf:0
+10:+5:2
+100:+4:25
+1000:+8:125
@@ -683,7 +813,7 @@ $div_scale = 40
-16:NaN
-123.45:NaN
nanfsqrt:NaN
-+inf:+inf
++inf:inf
-inf:NaN
+1:1
+2:1.41421356237309504880168872420969807857
@@ -721,12 +851,39 @@ abc:0
-inf:0
123.456:0
-123.456:0
+&is_positive
+0:1
+1:1
+-1:0
+-123:0
+NaN:0
+-inf:0
++inf:1
+&is_negative
+0:0
+1:0
+-1:1
+-123:1
+NaN:0
+-inf:1
++inf:0
+&parts
+0:0 1
+1:1 0
+123:123 0
+-123:-123 0
+-1200:-12 2
&is_zero
NaNzero:0
++inf:0
+-inf:0
0:1
-1:0
1:0
&is_one
+NaNone:0
++inf:0
+-inf:0
0:0
2:0
1:1
@@ -735,7 +892,7 @@ NaNzero:0
&bfloor
0:0
abc:NaN
-+inf:+inf
++inf:inf
-inf:-inf
1:1
-51:-51
@@ -744,7 +901,7 @@ abc:NaN
&bceil
0:0
abc:NaN
-+inf:+inf
++inf:inf
-inf:-inf
1:1
-51:-51
diff --git a/lib/Math/BigInt/t/bigintc.t b/lib/Math/BigInt/t/bigintc.t
index cb880bab68..9c82d65e0d 100644
--- a/lib/Math/BigInt/t/bigintc.t
+++ b/lib/Math/BigInt/t/bigintc.t
@@ -8,66 +8,121 @@ BEGIN
$| = 1;
# chdir 't' if -d 't';
unshift @INC, '../lib'; # for running manually
- plan tests => 29;
+ plan tests => 52;
}
-# testing of Math::BigInt::Calc, primarily for interface/api and not for the
+# testing of Math::BigInt::BitVect, primarily for interface/api and not for the
# math functionality
use Math::BigInt::Calc;
-my $s123 = \'123'; my $s321 = \'321';
+my $C = 'Math::BigInt::Calc'; # pass classname to sub's
+
# _new and _str
-my $x = _new($s123); my $u = _str($x);
-ok ($$u,123); ok ($x->[0],123); ok (@$x,1);
-my $y = _new($s321);
+my $x = _new($C,\"123"); my $y = _new($C,\"321");
+ok (ref($x),'ARRAY'); ok (${_str($C,$x)},123); ok (${_str($C,$y)},321);
# _add, _sub, _mul, _div
-ok (${_str(_add($x,$y))},444);
-ok (${_str(_sub($x,$y))},123);
-ok (${_str(_mul($x,$y))},39483);
-ok (${_str(_div($x,$y))},123);
-
-# division with reminder
-my $z = _new(\"111");
- _mul($x,$y);
-ok (${_str($x)},39483);
-_add($x,$z);
-ok (${_str($x)},39594);
-my ($re,$rr) = _div($x,$y);
+ok (${_str($C,_add($C,$x,$y))},444);
+ok (${_str($C,_sub($C,$x,$y))},123);
+ok (${_str($C,_mul($C,$x,$y))},39483);
+ok (${_str($C,_div($C,$x,$y))},123);
-ok (${_str($re)},123); ok (${_str($rr)},111);
+ok (${_str($C,_mul($C,$x,$y))},39483);
+ok (${_str($C,$x)},39483);
+ok (${_str($C,$y)},321);
+my $z = _new($C,\"2");
+ok (${_str($C,_add($C,$x,$z))},39485);
+my ($re,$rr) = _div($C,$x,$y);
-# _copy
-$x = _new(\"12356");
-ok (${_str(_copy($x))},12356);
-
-# digit
-$x = _new(\"123456789");
-ok (_digit($x,0),9);
-ok (_digit($x,1),8);
-ok (_digit($x,2),7);
-ok (_digit($x,-1),1);
-ok (_digit($x,-2),2);
-ok (_digit($x,-3),3);
+ok (${_str($C,$re)},123); ok (${_str($C,$rr)},2);
# is_zero, _is_one, _one, _zero
-$x = _new(\"12356");
-ok (_is_zero($x),0);
-ok (_is_one($x),0);
+ok (_is_zero($C,$x),0);
+ok (_is_one($C,$x),0);
-# _zeros
-$x = _new(\"1256000000"); ok (_zeros($x),6);
-$x = _new(\"152"); ok (_zeros($x),0);
-$x = _new(\"123000"); ok (_zeros($x),3);
+ok (_is_one($C,_one()),1); ok (_is_one($C,_zero()),0);
+ok (_is_zero($C,_zero()),1); ok (_is_zero($C,_one()),0);
+
+# is_odd, is_even
+ok (_is_odd($C,_one()),1); ok (_is_odd($C,_zero()),0);
+ok (_is_even($C,_one()),0); ok (_is_even($C,_zero()),1);
-ok (_is_one(_one()),1); ok (_is_one(_zero()),0);
-ok (_is_zero(_zero()),1); ok (_is_zero(_one()),0);
+# _digit
+$x = _new($C,\"123456789");
+ok (_digit($C,$x,0),9);
+ok (_digit($C,$x,1),8);
+ok (_digit($C,$x,2),7);
+ok (_digit($C,$x,-1),1);
+ok (_digit($C,$x,-2),2);
+ok (_digit($C,$x,-3),3);
+
+# _copy
+$x = _new($C,\"12356");
+ok (${_str($C,_copy($C,$x))},12356);
+
+# _zeros
+$x = _new($C,\"1256000000"); ok (_zeros($C,$x),6);
+$x = _new($C,\"152"); ok (_zeros($C,$x),0);
+$x = _new($C,\"123000"); ok (_zeros($C,$x),3);
+
+# _lsft, _rsft
+$x = _new($C,\"10"); $y = _new($C,\"3");
+ok (${_str($C,_lsft($C,$x,$y,10))},10000);
+$x = _new($C,\"20"); $y = _new($C,\"3");
+ok (${_str($C,_lsft($C,$x,$y,10))},20000);
+$x = _new($C,\"128"); $y = _new($C,\"4");
+if (!defined _lsft($C,$x,$y,2))
+ {
+ ok (1,1)
+ }
+else
+ {
+ ok ('_lsft','undef');
+ }
+$x = _new($C,\"1000"); $y = _new($C,\"3");
+ok (${_str($C,_rsft($C,$x,$y,10))},1);
+$x = _new($C,\"20000"); $y = _new($C,\"3");
+ok (${_str($C,_rsft($C,$x,$y,10))},20);
+$x = _new($C,\"256"); $y = _new($C,\"4");
+if (!defined _rsft($C,$x,$y,2))
+ {
+ ok (1,1)
+ }
+else
+ {
+ ok ('_rsft','undef');
+ }
-ok (_check($x),0);
-ok (_check(123),'123 is not a reference');
+# _acmp
+$x = _new($C,\"123456789");
+$y = _new($C,\"987654321");
+ok (_acmp($C,$x,$y),-1);
+ok (_acmp($C,$y,$x),1);
+ok (_acmp($C,$x,$x),0);
+ok (_acmp($C,$y,$y),0);
+
+# _div
+$x = _new($C,\"3333"); $y = _new($C,\"1111");
+ok (${_str($C, scalar _div($C,$x,$y))},3);
+$x = _new($C,\"33333"); $y = _new($C,\"1111"); ($x,$y) = _div($C,$x,$y);
+ok (${_str($C,$x)},30); ok (${_str($C,$y)},3);
+$x = _new($C,\"123"); $y = _new($C,\"1111");
+($x,$y) = _div($C,$x,$y); ok (${_str($C,$x)},0); ok (${_str($C,$y)},123);
+
+# _num
+$x = _new($C,\"12345"); $x = _num($C,$x); ok (ref($x)||'',''); ok ($x,12345);
+
+# should not happen:
+# $x = _new($C,\"-2"); $y = _new($C,\"4"); ok (_acmp($C,$x,$y),-1);
+
+# _check
+$x = _new($C,\"123456789");
+ok (_check($C,$x),0);
+ok (_check($C,123),'123 is not a reference');
# done
1;
+
diff --git a/lib/Math/BigInt/t/bigintpm.t b/lib/Math/BigInt/t/bigintpm.t
index f2663de26d..9e84e20ee6 100755
--- a/lib/Math/BigInt/t/bigintpm.t
+++ b/lib/Math/BigInt/t/bigintpm.t
@@ -8,9 +8,9 @@ BEGIN
$| = 1;
# chdir 't' if -d 't';
unshift @INC, '../lib'; # for running manually
- plan tests => 1222;
+ plan tests => 1424;
}
-my $version = '1.36'; # for $VERSION tests, match current release (by hand!)
+my $version = '1.40'; # for $VERSION tests, match current release (by hand!)
##############################################################################
# for testing inheritance of _swap
@@ -18,6 +18,7 @@ my $version = '1.36'; # for $VERSION tests, match current release (by hand!)
package Math::Foo;
use Math::BigInt;
+#use Math::BigInt lib => 'BitVect'; # for testing
use vars qw/@ISA/;
@ISA = (qw/Math::BigInt/);
@@ -46,9 +47,8 @@ package main;
use Math::BigInt;
#use Math::BigInt lib => 'BitVect'; # for testing
-#use Math::BigInt lib => 'Small'; # for testing
-my $CALC = Math::BigInt::_core_lib();
+my $CALC = Math::BigInt::_core_lib(); ok ($CALC,'Math::BigInt::Calc');
my (@args,$f,$try,$x,$y,$z,$a,$exp,$ans,$ans1,@a,$m,$e,$round_mode);
@@ -81,10 +81,18 @@ while (<DATA>)
$try .= '$x->is_odd()+0;';
} elsif ($f eq "is_even") {
$try .= '$x->is_even()+0;';
+ } elsif ($f eq "is_negative") {
+ $try .= '$x->is_negative()+0;';
+ } elsif ($f eq "is_positive") {
+ $try .= '$x->is_positive()+0;';
} elsif ($f eq "is_inf") {
$try .= "\$x->is_inf('$args[1]')+0;";
} elsif ($f eq "binf") {
$try .= "\$x->binf('$args[1]');";
+ } elsif ($f eq "bone") {
+ $try .= "\$x->bone('$args[1]');";
+ } elsif ($f eq "bnan") {
+ $try .= "\$x->bnan();";
} elsif ($f eq "bfloor") {
$try .= '$x->bfloor();';
} elsif ($f eq "bceil") {
@@ -92,9 +100,9 @@ while (<DATA>)
} elsif ($f eq "bsstr") {
$try .= '$x->bsstr();';
} elsif ($f eq "bneg") {
- $try .= '-$x;';
+ $try .= '$x->bneg();';
} elsif ($f eq "babs") {
- $try .= 'abs $x;';
+ $try .= '$x->babs();';
} elsif ($f eq "binc") {
$try .= '++$x;';
} elsif ($f eq "bdec") {
@@ -130,6 +138,8 @@ while (<DATA>)
$try .= "\$x * \$y;";
}elsif ($f eq "bdiv"){
$try .= "\$x / \$y;";
+ }elsif ($f eq "bdiv-list"){
+ $try .= 'join (",",$x->bdiv($y));';
}elsif ($f eq "bmod"){
$try .= "\$x % \$y;";
}elsif ($f eq "bgcd")
@@ -199,7 +209,7 @@ while (<DATA>)
} # endwhile data tests
close DATA;
-# XXX Tels 06/29/2001 following tests never fail or do not work :(
+# XXX Tels 06/29/2001 following tests never fail or do not work :( !?
# test whether use Math::BigInt qw/version/ works
$try = "use Math::BigInt ($version.'1');";
@@ -214,21 +224,27 @@ $ans1 = eval $try;
ok ( $ans1, "1427247692705959881058285969449495136382746624");
# test wether Math::BigInt::Small via use works (w/ dff. spellings of calc)
-#$try = "use Math::BigInt ($version,'CALC','Small');";
+#$try = "use Math::BigInt ($version,'lib','Small');";
#$try .= ' $x = 2**10; $x = "$x";';
#$ans1 = eval $try;
#ok ( $ans1, "1024");
-#$try = "use Math::BigInt ($version,'cAlC','Math::BigInt::Small');";
+#$try = "use Math::BigInt ($version,'LiB','Math::BigInt::Small');";
#$try .= ' $x = 2**10; $x = "$x";';
#$ans1 = eval $try;
#ok ( $ans1, "1024");
# test wether calc => undef (array element not existing) works
-#$try = "use Math::BigInt ($version,'CALC');";
+#$try = "use Math::BigInt ($version,'LIB');";
#$try = "require Math::BigInt; Math::BigInt::import($version,'CALC');";
#$try .= ' $x = Math::BigInt->new(2)**10; $x = "$x";';
#$ans1 = eval $try;
#ok ( $ans1, 1024);
+# test whether fallback to calc works
+$try = "use Math::BigInt ($version,'lib','foo, bar , ');";
+$try .= ' Math::BigInt::_core_lib();';
+$ans1 = eval $try;
+ok ( $ans1, "Math::BigInt::Calc");
+
# test some more
@a = ();
for (my $i = 1; $i < 10; $i++)
@@ -237,11 +253,16 @@ for (my $i = 1; $i < 10; $i++)
}
ok "@a", "1 2 3 4 5 6 7 8 9";
-# test whether selfmultiplication works correctly (result is 2**64)
+# test whether self-multiplication works correctly (result is 2**64)
$try = '$x = new Math::BigInt "+4294967296";';
$try .= '$a = $x->bmul($x);';
$ans1 = eval $try;
print "# Tried: '$try'\n" if !ok ($ans1, Math::BigInt->new(2) ** 64);
+# test self-pow
+$try = '$x = Math::BigInt->new(10);';
+$try .= '$a = $x->bpow($x);';
+$ans1 = eval $try;
+print "# Tried: '$try'\n" if !ok ($ans1, Math::BigInt->new(10) ** 10);
# test whether op destroys args or not (should better not)
@@ -343,6 +364,9 @@ $ans = eval $try;
print "# For '$try'\n" if (!ok "$ans" , "ok" );
###############################################################################
+# the followin tests only make sense with Math::BigInt::Calc
+
+###############################################################################
# check proper length of internal arrays
$x = Math::BigInt->new(99999); is_valid($x);
@@ -350,8 +374,7 @@ $x += 1; ok ($x,100000); is_valid($x);
$x -= 1; ok ($x,99999); is_valid($x);
###############################################################################
-# check numify, these tests only make sense with Math::BigInt::Calc, since
-# only this uses $BASE
+# check numify
my $BASE = int(1e5); # should access Math::BigInt::Calc::BASE
$x = Math::BigInt->new($BASE-1); ok ($x->numify(),$BASE-1);
@@ -380,6 +403,25 @@ ok ($z, 100000);
ok ($x, 23456);
###############################################################################
+# bug in shortcut in mul()
+
+# construct a number with a zero-hole of BASE_LEN
+my $bl = Math::BigInt::Calc::_base_len();
+$x = '1' x $bl . '0' x $bl . '1' x $bl . '0' x $bl;
+$y = '1' x (2*$bl);
+#print "$x * $y\n";
+$x = Math::BigInt->new($x)->bmul($y);
+# result is 123..$bl . $bl x (3*bl-1) . $bl...321 . '0' x $bl
+$y = ''; my $d = '';
+for (my $i = 1; $i <= $bl; $i++)
+ {
+ $y .= $i; $d = $i.$d;
+ }
+#print "$y $d\n";
+$y .= $bl x (3*$bl-1) . $d . '0' x $bl;
+ok ($x,$y);
+
+###############################################################################
# bug with rest "-0" in div, causing further div()s to fail
$x = Math::BigInt->new('-322056000'); ($x,$y) = $x->bdiv('-12882240');
@@ -477,6 +519,12 @@ ok ($x,-3);
ok (ref($x),'Math::Foo');
###############################################################################
+# test whether +inf eq inf
+
+$y = 1e1000000; # create inf, since bareword inf does not work
+$x = Math::BigInt->new('+inf'); ok ($x,$y);
+
+###############################################################################
# all tests done
###############################################################################
@@ -516,6 +564,20 @@ sub is_valid
}
__END__
+&is_negative
+0:0
+-1:1
+1:0
++inf:0
+-inf:1
+NaNneg:0
+&is_positive
+0:1
+-1:0
+1:1
++inf:1
+-inf:0
+NaNneg:0
&is_odd
abc:0
0:0
@@ -548,6 +610,24 @@ abc:0
+987654321:+123456789:1
-987654321:+123456789:1
-123:+4567889:-1
+# NaNs
+acmpNaN:123:
+123:acmpNaN:
+acmpNaN:acmpNaN:
+# infinity
++inf:+inf:0
+-inf:-inf:0
++inf:-inf:0
+-inf:+inf:0
++inf:123:1
+-inf:123:1
++inf:-123:1
+-inf:-123:1
+# return undef
++inf:NaN:
+NaN:inf:
+-inf:NaN:
+NaN:-inf:
&bnorm
123:123
# binary input
@@ -561,6 +641,8 @@ abc:0
0b011:3
0b101:5
0b1000000000000000000000000000000:1073741824
+0b_101:NaN
+0b1_0_1:5
# hex input
-0x0:0
0xabcdefgh:NaN
@@ -569,8 +651,10 @@ abc:0
-0xABCDEF:-11259375
-0x1234:-4660
0x12345678:305419896
+0x1_2_3_4_56_78:305419896
+0x_123:NaN
# inf input
-+inf:+inf
++inf:inf
-inf:-inf
0inf:NaN
# normal input
@@ -621,10 +705,22 @@ E23:NaN
-1010E-2:NaN
-1.01E+1:NaN
-1.01E-1:NaN
+1234.00:1234
+&bnan
+1:NaN
+2:NaN
+abc:NaN
+&bone
+2:+:+1
+2:-:-1
+boneNaN:-:-1
+boneNaN:+:+1
+2:abc:+1
+3::+1
&binf
-1:+:+inf
+1:+:inf
2:-:-inf
-3:abc:+inf
+3:abc:inf
&is_inf
+inf::1
-inf::1
@@ -677,6 +773,9 @@ abc:abc:NaN
100:1e+2
abc:NaN
&bneg
+bnegNaN:NaN
++inf:-inf
+-inf:inf
abd:NaN
+0:+0
+1:-1
@@ -684,16 +783,18 @@ abd:NaN
+123456789:-123456789
-123456789:+123456789
&babs
-abc:NaN
+babsNaN:NaN
++inf:inf
+-inf:inf
+0:+0
+1:+1
-1:+1
+123456789:+123456789
-123456789:+123456789
&bcmp
-abc:abc:
-abc:+0:
-+0:abc:
+bcmpNaN:bcmpNaN:
+bcmpNaN:+0:
++0:bcmpNaN:
+0:+0:0
-1:+0:-1
+0:-1:1
@@ -723,18 +824,24 @@ abc:+0:
+inf:-5432112345:1
+inf:+inf:0
-inf:-inf:0
++inf:-inf:1
+-inf:+inf:-1
# return undef
+inf:NaN:
-NaN:+inf:
+NaN:inf:
-inf:NaN:
NaN:-inf:
&binc
abc:NaN
++inf:inf
+-inf:-inf
+0:+1
+1:+2
-1:+0
&bdec
abc:NaN
++inf:inf
+-inf:-inf
+0:-1
+1:+0
-1:-2
@@ -742,6 +849,14 @@ abc:NaN
abc:abc:NaN
abc:+0:NaN
+0:abc:NaN
++inf:-inf:0
+-inf:+inf:0
++inf:+inf:inf
+-inf:-inf:-inf
+baddNaN:+inf:NaN
+baddNaN:+inf:NaN
++inf:baddNaN:NaN
+-inf:baddNaN:NaN
+0:+0:+0
+1:+0:+1
+0:+1:+1
@@ -780,6 +895,10 @@ abc:+0:NaN
abc:abc:NaN
abc:+0:NaN
+0:abc:NaN
++inf:-inf:inf
+-inf:+inf:-inf
++inf:+inf:0
+-inf:-inf:0
+0:+0:+0
+1:+0:+1
+0:+1:-1
@@ -818,6 +937,14 @@ abc:+0:NaN
abc:abc:NaN
abc:+0:NaN
+0:abc:NaN
+NaNmul:+inf:NaN
+NaNmul:-inf:NaN
+-inf:NaNmul:NaN
++inf:NaNmul:NaN
++inf:+inf:inf
++inf:-inf:-inf
+-inf:+inf:-inf
+-inf:-inf:inf
+0:+0:+0
+0:+1:+0
+1:+0:+0
@@ -850,18 +977,23 @@ abc:+0:NaN
+25:+25:+625
+12345:+12345:+152399025
+99999:+11111:+1111088889
+&bdiv-list
+100:20:5,0
+4095:4095:1,0
+-4095:-4095:1,0
+4095:-4095:-1,0
+-4095:4095:-1,0
&bdiv
abc:abc:NaN
abc:+1:abc:NaN
-# really?
-#+5:0:+inf
-#-5:0:-inf
+1:abc:NaN
+0:+0:NaN
++5:0:inf
+-5:0:-inf
++1:+0:inf
+0:+1:+0
-+1:+0:NaN
+0:-1:+0
--1:+0:NaN
+-1:+0:-inf
+1:+1:+1
-1:-1:+1
+1:-1:-1
@@ -900,6 +1032,8 @@ abc:+1:abc:NaN
1:-3:-1
-5:3:-2
4:-3:-2
+123:+inf:0
+123:-inf:0
&bmod
abc:abc:NaN
abc:+1:abc:NaN
@@ -948,6 +1082,7 @@ abc:+1:abc:NaN
-2:-3:-2
4:-3:-2
1:-3:-2
+4095:4095:0
&bgcd
abc:abc:NaN
abc:+0:NaN
@@ -983,6 +1118,12 @@ abc:0:NaN
+281474976710656:+0:+0
+281474976710656:+1:+0
+281474976710656:+281474976710656:+281474976710656
+-2:-3:-4
+-1:-1:-1
+-6:-6:-6
+-7:-4:-8
+-7:4:0
+-4:7:4
&bior
abc:abc:NaN
abc:0:NaN
@@ -992,6 +1133,11 @@ abc:0:NaN
+281474976710656:+0:+281474976710656
+281474976710656:+1:+281474976710657
+281474976710656:+281474976710656:+281474976710656
+-2:-3:-1
+-1:-1:-1
+-6:-6:-6
+-7:4:-3
+-4:7:-1
&bxor
abc:abc:NaN
abc:0:NaN
@@ -1001,11 +1147,21 @@ abc:0:NaN
+281474976710656:+0:+281474976710656
+281474976710656:+1:+281474976710657
+281474976710656:+281474976710656:+0
+-2:-3:3
+-1:-1:0
+-6:-6:0
+-7:4:-3
+-4:7:-5
+4:-7:-3
+-4:-7:5
&bnot
abc:NaN
+0:-1
+8:-9
+281474976710656:-281474976710657
+-1:0
+-2:1
+-12:11
&digit
0:0:0
12:0:2
@@ -1075,9 +1231,9 @@ abc:12:NaN
-2:-1:NaN
2:-2:NaN
-2:-2:NaN
-+inf:1234500012:+inf
++inf:1234500012:inf
-inf:1234500012:-inf
-+inf:-12345000123:+inf
++inf:-12345000123:inf
-inf:-12345000123:-inf
# 1 ** -x => 1 / (1 ** x)
-1:0:1
@@ -1124,6 +1280,10 @@ abc:12:NaN
Nan:NaN
&bround
$round_mode('trunc')
+0:12:0
+NaNbround:12:NaN
++inf:12:inf
+-inf:12:-inf
1234:0:1234
1234:2:1200
123456:4:123400
@@ -1201,11 +1361,16 @@ $round_mode('even')
&is_zero
0:1
NaNzero:0
++inf:0
+-inf:0
123:0
-1:0
1:0
&is_one
0:0
+NaNone:0
++inf:0
+-inf:0
1:1
2:0
-1:0
@@ -1213,12 +1378,18 @@ NaNzero:0
# floor and ceil tests are pretty pointless in integer space...but play safe
&bfloor
0:0
+NaNfloor:NaN
++inf:inf
+-inf:-inf
-1:-1
-2:-2
2:2
3:3
abc:NaN
&bceil
+NaNceil:NaN
++inf:inf
+-inf:-inf
0:0
-1:-1
-2:-2
diff --git a/lib/Math/BigInt/t/mbimbf.t b/lib/Math/BigInt/t/mbimbf.t
index 3948102f0e..51cf41b212 100644
--- a/lib/Math/BigInt/t/mbimbf.t
+++ b/lib/Math/BigInt/t/mbimbf.t
@@ -157,7 +157,7 @@ $z = $y - $x; ok ($z,530.9);
$z = $y * $x; ok ($z,80780);
$z = $x ** 2; ok ($z,15241);
$z = $x * $x; ok ($z,15241);
-# not yet: $z = -$x; ok ($z,-123.46); ok ($x,123.456);
+# not: $z = -$x; ok ($z,-123.46); ok ($x,123.456);
$z = $x->copy(); $z->{_a} = 2; $z = $z / 2; ok ($z,62);
$x = Math::BigFloat->new(123456); $x->{_a} = 4;
$z = $x->copy; $z++; ok ($z,123500);