summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael Garcia-Suarez <rgarciasuarez@gmail.com>2005-03-20 21:20:50 +0000
committerRafael Garcia-Suarez <rgarciasuarez@gmail.com>2005-03-20 21:20:50 +0000
commita87115f0a1b74f765307464de281024d76c71ad6 (patch)
tree51f85b871e1453b41fd88749d09bfb38f8c94f96
parentfdac53cdf7b8b7030448d0e63e6537e85a7a19df (diff)
downloadperl-a87115f0a1b74f765307464de281024d76c71ad6.tar.gz
Upgrade to Math::BigInt 1.75, by Tels
p4raw-id: //depot/perl@24048
-rw-r--r--lib/Math/BigFloat.pm59
-rw-r--r--lib/Math/BigInt.pm26
-rw-r--r--lib/Math/BigInt/Calc.pm2
-rw-r--r--lib/Math/BigInt/t/bare_mbi.t2
-rw-r--r--lib/Math/BigInt/t/bigintpm.inc2
-rwxr-xr-xlib/Math/BigInt/t/bigintpm.t2
-rw-r--r--lib/Math/BigInt/t/fallback.t20
-rw-r--r--lib/Math/BigInt/t/mbi_rand.t28
-rwxr-xr-xlib/Math/BigInt/t/sub_mbi.t2
9 files changed, 97 insertions, 46 deletions
diff --git a/lib/Math/BigFloat.pm b/lib/Math/BigFloat.pm
index 7466472ee6..8143175870 100644
--- a/lib/Math/BigFloat.pm
+++ b/lib/Math/BigFloat.pm
@@ -12,7 +12,7 @@ package Math::BigFloat;
# _a : accuracy
# _p : precision
-$VERSION = '1.48';
+$VERSION = '1.49';
require 5.005;
require Exporter;
@@ -1340,19 +1340,25 @@ sub bdiv
$scale = $ly if $ly > $scale;
my $diff = $ly - $lx;
$scale += $diff if $diff > 0; # if lx << ly, but not if ly << lx!
-
- # cases like $x /= $x (but not $x /= $y!) were wrong due to modifying $x
- # twice below)
- require Scalar::Util;
- if (Scalar::Util::refaddr($x) == Scalar::Util::refaddr($y))
+
+ # already handled inf/NaN/-inf above:
+
+ my $xsign = $x->{sign};
+ $y->{sign} =~ tr/+-/-+/;
+ my $y_not_one = !$y->is_one(); # cache this result
+ if ($xsign ne $x->{sign})
{
- $x->bone(); # x/x => 1, rem 0
+ # special case of $x /= $x results in 1
+ $x->bone();
}
else
{
-
+ # correct $y's sign again
+ $y->{sign} =~ tr/+-/-+/;
+ # continue with normal div code:
+
# make copy of $x in case of list context for later reminder calculation
- if (wantarray && !$y->is_one())
+ if (wantarray && $y_not_one)
{
$rem = $x->copy();
}
@@ -1360,7 +1366,7 @@ sub bdiv
$x->{sign} = $x->{sign} ne $y->sign() ? '-' : '+';
# check for / +-1 ( +/- 1E0)
- if (!$y->is_one())
+ if ($y_not_one)
{
# promote BigInts and it's subclasses (except when already a BigFloat)
$y = $self->new($y) unless $y->isa('Math::BigFloat');
@@ -1397,7 +1403,7 @@ sub bdiv
if (wantarray)
{
- if (!$y->is_one())
+ if ($y_not_one)
{
$rem->bmod($y,@params); # copy already done
}
@@ -2736,12 +2742,33 @@ it is rounded. The rounding mode taken is either the default mode, or the one
supplied to the operation after the I<scale>:
$x = Math::BigFloat->new(2);
- Math::BigFloat->precision(5); # 5 digits max
- $y = $x->copy()->bdiv(3); # will give 0.66666
- $y = $x->copy()->bdiv(3,6); # will give 0.666666
- $y = $x->copy()->bdiv(3,6,'odd'); # will give 0.666667
+ Math::BigFloat->accuracy(5); # 5 digits max
+ $y = $x->copy()->bdiv(3); # will give 0.66667
+ $y = $x->copy()->bdiv(3,6); # will give 0.666667
+ $y = $x->copy()->bdiv(3,6,undef,'odd'); # will give 0.666667
Math::BigFloat->round_mode('zero');
- $y = $x->copy()->bdiv(3,6); # will give 0.666666
+ $y = $x->copy()->bdiv(3,6); # will also give 0.666667
+
+Note that C<< Math::BigFloat->accuracy() >> and C<< Math::BigFloat->precision() >>
+set the global variables, and thus B<any> newly created number will be subject
+to the global rounding. This means that in the examples above, the C<3>
+as argument to C<bdiv()> will also get an accuracy of B<5>.
+
+It is less confusing to either calculate the result fully, and afterwards
+round it explicitely, or use the additional parameters to the math
+functions like so:
+
+ use Math::BigFloat;
+ $x = Math::BigFloat->new(2);
+ $y = $x->copy()->bdiv(3);
+ print $y->bround(5),"\n"; # will give 0.66667
+
+ or
+
+ use Math::BigFloat;
+ $x = Math::BigFloat->new(2);
+ $y = $x->copy()->bdiv(3,5); # will give 0.66667
+ print "$y\n";
=head2 Rounding
diff --git a/lib/Math/BigInt.pm b/lib/Math/BigInt.pm
index f7ff61278c..1d31534dca 100644
--- a/lib/Math/BigInt.pm
+++ b/lib/Math/BigInt.pm
@@ -18,7 +18,7 @@ package Math::BigInt;
my $class = "Math::BigInt";
require 5.005;
-$VERSION = '1.74';
+$VERSION = '1.75';
@ISA = qw( Exporter );
@EXPORT_OK = qw( objectify bgcd blcm);
@@ -75,7 +75,9 @@ use overload
'cos' => sub { cos($_[0]->numify()) },
'sin' => sub { sin($_[0]->numify()) },
'exp' => sub { exp($_[0]->numify()) },
-'atan2' => sub { atan2($_[0]->numify(),$_[1]) },
+'atan2' => sub { $_[2] ?
+ atan2($_[1],$_[0]->numify()) :
+ atan2($_[0]->numify(),$_[1]) },
# are not yet overloadable
#'hex' => sub { print "hex"; $_[0]; },
@@ -90,8 +92,8 @@ use overload
# for subtract it's a bit tricky to not modify b: b-a => -a+b
'-' => sub { my $c = $_[0]->copy; $_[2] ?
- $c->bneg()->badd( $_[1]) :
- $c->bsub( $_[1]) },
+ $c->bneg()->badd( $_[1]) :
+ $c->bsub( $_[1]) },
'+' => sub { $_[0]->copy()->badd($_[1]); },
'*' => sub { $_[0]->copy()->bmul($_[1]); },
@@ -1146,15 +1148,17 @@ sub bsub
return $x->round(@r) if $y->is_zero();
- require Scalar::Util;
- if (Scalar::Util::refaddr($x) == Scalar::Util::refaddr($y))
+ # To correctly handle the lone special case $x->bsub($x), we note the sign
+ # of $x, then flip the sign from $y, and if the sign of $x did change, too,
+ # then we caught the special case:
+ my $xsign = $x->{sign};
+ $y->{sign} =~ tr/+\-/-+/; # does nothing for NaN
+ if ($xsign ne $x->{sign})
{
- # if we get the same variable twice, the result must be zero (the code
- # below fails in that case)
- return $x->bzero(@r) if $x->{sign} =~ /^[+-]$/;
+ # special case of $x->bsub($x) results in 0
+ return $x->bzero(@r) if $xsign =~ /^[+-]$/;
return $x->bnan(); # NaN, -inf, +inf
}
- $y->{sign} =~ tr/+\-/-+/; # does nothing for NaN
$x->badd($y,@r); # badd does not leave internal zeros
$y->{sign} =~ tr/+\-/-+/; # refix $y (does nothing for NaN)
$x; # already rounded by badd() or no round necc.
@@ -2471,7 +2475,7 @@ sub import
{
if (($WARN{$lib}||0) < 2)
{
- my $ver = eval "\$$lib\::VERSION";
+ my $ver = eval "\$$lib\::VERSION" || 'unknown';
require Carp;
Carp::carp ("Cannot load outdated $lib v$ver, please upgrade");
$WARN{$lib} = 2; # never warn again
diff --git a/lib/Math/BigInt/Calc.pm b/lib/Math/BigInt/Calc.pm
index 39a0435746..eb5ba98a67 100644
--- a/lib/Math/BigInt/Calc.pm
+++ b/lib/Math/BigInt/Calc.pm
@@ -15,7 +15,7 @@ $VERSION = '0.45';
# automatically at loading time to be the maximum possible value
# todo:
-# - fully remove funky $# stuff (maybe)
+# - fully remove funky $# stuff in div() (maybe - that code scares me...)
# USE_MUL: due to problems on certain os (os390, posix-bc) "* 1e-5" is used
# instead of "/ 1e5" at some places, (marked with USE_MUL). Other platforms
diff --git a/lib/Math/BigInt/t/bare_mbi.t b/lib/Math/BigInt/t/bare_mbi.t
index bf08a90f34..b171e9382f 100644
--- a/lib/Math/BigInt/t/bare_mbi.t
+++ b/lib/Math/BigInt/t/bare_mbi.t
@@ -26,7 +26,7 @@ BEGIN
}
print "# INC = @INC\n";
- plan tests => 3012;
+ plan tests => 3014;
}
use Math::BigInt lib => 'BareCalc';
diff --git a/lib/Math/BigInt/t/bigintpm.inc b/lib/Math/BigInt/t/bigintpm.inc
index 2a2bfe11e9..82d0cb2484 100644
--- a/lib/Math/BigInt/t/bigintpm.inc
+++ b/lib/Math/BigInt/t/bigintpm.inc
@@ -1633,6 +1633,8 @@ inf:0:inf
9999999_9999999_9999999_9999999:100_0000000_0000000_0000000:99999
9999999_9999999_9999999_9999999:10_0000000_0000000_0000000:999999
9999999_9999999_9999999_9999999:1_0000000_0000000_0000000:9999999
+# bug with shortcut in Calc 0.44
+949418181818187070707070707070707070:181818181853535353535353535353535353:5
&bmodinv
# format: number:modulus:result
# bmodinv Data errors
diff --git a/lib/Math/BigInt/t/bigintpm.t b/lib/Math/BigInt/t/bigintpm.t
index 16f4d32a30..9923256a89 100755
--- a/lib/Math/BigInt/t/bigintpm.t
+++ b/lib/Math/BigInt/t/bigintpm.t
@@ -10,7 +10,7 @@ BEGIN
my $location = $0; $location =~ s/bigintpm.t//;
unshift @INC, $location; # to locate the testing files
chdir 't' if -d 't';
- plan tests => 3012;
+ plan tests => 3014;
}
use Math::BigInt;
diff --git a/lib/Math/BigInt/t/fallback.t b/lib/Math/BigInt/t/fallback.t
index e348d9240d..00f1dfd74b 100644
--- a/lib/Math/BigInt/t/fallback.t
+++ b/lib/Math/BigInt/t/fallback.t
@@ -28,11 +28,11 @@ BEGIN
}
print "# INC = @INC\n";
- plan tests => 8;
+ plan tests => 12;
}
# The tests below test that cos(BigInt) = cos(Scalar) which is DWIM, but not
-# exactly right, ideally cos(BigInt) should truncate to int() and cos(BigFLoat)
+# exactly right, ideally cos(BigInt) should truncate to int() and cos(BigFloat)
# should calculate the result to X digits accuracy. For now, this is better
# than die()ing...
@@ -46,10 +46,16 @@ ok (sin($bi), sin(1));
ok (exp($bi), exp(1));
ok (atan2($bi,$bi), atan2(1,1));
-my $bf = Math::BigInt->new(1);
+my $bf = Math::BigInt->new(0);
-ok (cos($bf), cos(1));
-ok (sin($bf), sin(1));
-ok (exp($bf), exp(1));
-ok (atan2($bf,$bf), atan2(1,1));
+ok (cos($bf), cos(0));
+ok (sin($bf), sin(0));
+ok (exp($bf), exp(0));
+ok (atan2($bi,$bf), atan2(1,0));
+ok (atan2($bf,$bi), atan2(0,1));
+
+my $bone = Math::BigInt->new(1);
+ok (cos($bone), cos(1));
+ok (sin($bone), sin(1));
+ok (exp($bone), exp(1));
diff --git a/lib/Math/BigInt/t/mbi_rand.t b/lib/Math/BigInt/t/mbi_rand.t
index dd280515f9..d24920f68b 100644
--- a/lib/Math/BigInt/t/mbi_rand.t
+++ b/lib/Math/BigInt/t/mbi_rand.t
@@ -28,6 +28,12 @@ my $length = 128;
my $seed = ($#ARGV == 0) ? $ARGV[0] : int(rand(1165537));
print "# seed: $seed\n"; srand($seed);
+print "# lib: ", Math::BigInt->config()->{lib},"\n";
+if (Math::BigInt->config()->{lib} =~ /::Calc/)
+ {
+ print "# base len: ", scalar Math::BigInt::Calc->_base_len(),"\n";
+ }
+
my ($A,$B,$As,$Bs,$ADB,$AMB,$la,$lb);
my $two = Math::BigInt->new(2);
for (my $i = 0; $i < $count; $i++)
@@ -46,9 +52,9 @@ for (my $i = 0; $i < $count; $i++)
$As =~ s/^0+//; $Bs =~ s/^0+//;
$As = $As || '0'; $Bs = $Bs || '0';
- # print "# As $As\n# Bs $Bs\n";
+# print "# As $As\n# Bs $Bs\n";
$A = $c->new($As); $B = $c->new($Bs);
- # print "# A $A\n# B $B\n";
+ print "# A $A\n# B $B\n";
if ($A->is_zero() || $B->is_zero())
{
for (1..4) { ok (1,1); } next;
@@ -59,22 +65,28 @@ for (my $i = 0; $i < $count; $i++)
# $X = ($A/$B)*$B + 2 * ($A % $B) - ($A % $B);
($ADB,$AMB) = $A->copy()->bdiv($B);
-# print "# ($A / $B, $A % $B ) = $ADB $AMB\n";
+ print "# ($A / $B, $A % $B ) = $ADB $AMB\n";
print "# seed $seed, ". join(' ',Math::BigInt::Calc->_base_len()),"\n".
"# tried $ADB * $B + $two*$AMB - $AMB\n"
unless ok ($ADB*$B+$two*$AMB-$AMB,$As);
- print "# seed: $seed, \$ADB * \$B / \$B = ", $ADB * $B / $B, " != $ADB (\$B=$B)\n"
- unless ok ($ADB*$B/$B,$ADB);
+ if (ok ($ADB*$B/$B,$ADB))
+ {
+ print "# seed: $seed, \$ADB * \$B / \$B = ", $ADB * $B / $B, " != $ADB (\$B=$B)\n";
+ if (Math::BigInt->config()->{lib} =~ /::Calc/)
+ {
+ print "# ADB->[-1]: ", $ADB->{value}->[-1], " B->[-1]: ", $B->{value}->[-1],"\n";
+ }
+ }
# swap 'em and try this, too
# $X = ($B/$A)*$A + $B % $A;
($ADB,$AMB) = $B->copy()->bdiv($A);
- #print "check: $ADB $AMB";
+ # print "check: $ADB $AMB";
print "# seed $seed, ". join(' ',Math::BigInt::Calc->_base_len()),"\n".
"# tried $ADB * $A + $two*$AMB - $AMB\n"
unless ok ($ADB*$A+$two*$AMB-$AMB,$Bs);
-# print " +$two * $AMB = ",$ADB * $A + $two * $AMB,"\n";
-# print " -$AMB = ",$ADB * $A + $two * $AMB - $AMB,"\n";
+ print "# +$two * $AMB = ",$ADB * $A + $two * $AMB,"\n";
+ print "# -$AMB = ",$ADB * $A + $two * $AMB - $AMB,"\n";
print "# seed $seed, \$ADB * \$A / \$A = ", $ADB * $A / $A, " != $ADB (\$A=$A)\n"
unless ok ($ADB*$A/$A,$ADB);
}
diff --git a/lib/Math/BigInt/t/sub_mbi.t b/lib/Math/BigInt/t/sub_mbi.t
index 4d4fc4eada..9346dcd337 100755
--- a/lib/Math/BigInt/t/sub_mbi.t
+++ b/lib/Math/BigInt/t/sub_mbi.t
@@ -26,7 +26,7 @@ BEGIN
}
print "# INC = @INC\n";
- plan tests => 3012
+ plan tests => 3014
+ 5; # +5 own tests
}