From: Tels Date: Fri, 12 Dec 2003 18:47:43 +0000 (+0100) Subject: Math::BigInt v1.67 released X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=8df1e0a2b21ea34567b1f903327ae2a11bb9b86e;p=p5sagit%2Fp5-mst-13.2.git Math::BigInt v1.67 released Message-Id: <200312121847.49039@bloodgate.com> p4raw-id: //depot/perl@21882 --- diff --git a/lib/Math/BigFloat.pm b/lib/Math/BigFloat.pm index dfb2671..3b8d5a6 100644 --- a/lib/Math/BigFloat.pm +++ b/lib/Math/BigFloat.pm @@ -172,8 +172,9 @@ sub new # undef,undef to signal MBI that we don't need no bloody rounding $self->{_e} = $MBI->new("$$es$$ev",undef,undef); # exponent $self->{_m} = $MBI->new("$$miv$$mfv",undef,undef); # create mant. + # print $self->{_e}, " ", $self->{_m},"\n"; # 3.123E0 = 3123E-3, and 3.123E-2 => 3123E-5 - $self->{_e} -= CORE::length($$mfv) if CORE::length($$mfv) != 0; + $self->{_e} -= CORE::length($$mfv) if CORE::length($$mfv) != 0; $self->{sign} = $$mis; } # if downgrade, inf, NaN or integers go down @@ -186,7 +187,7 @@ sub new $self->{_m}->{sign} = $$mis; # negative if wanted return $downgrade->new($self->{_m}); } - return $downgrade->new("$$mis$$miv$$mfv"."E$$es$$ev"); + return $downgrade->new($self->bsstr()); } #print "mbf new $self->{sign} $self->{_m} e $self->{_e} ",ref($self),"\n"; $self->bnorm()->round(@r); # first normalize, then round diff --git a/lib/Math/BigInt.pm b/lib/Math/BigInt.pm index 0e4ae68..1b16600 100644 --- a/lib/Math/BigInt.pm +++ b/lib/Math/BigInt.pm @@ -1250,7 +1250,7 @@ sub blog if ($CAN{log_int}) { - my $rc = $CALC->_log_int($x->{value},$base->{value}); + my ($rc,$exact) = $CALC->_log_int($x->{value},$base->{value}); return $x->bnan() unless defined $rc; $x->{value} = $rc; return $x->round(@r); @@ -3093,7 +3093,7 @@ sub _split # valid mantissa? return if $m eq '.' || $m eq ''; my ($mi,$mf,$lastf) = split /\./,$m; - return if defined $lastf; # last defined => 1.2.3 or others + return if defined $lastf; # lastf defined => 1.2.3 or others $mi = '0' if !defined $mi; $mi .= '0' if $mi =~ /^[\-\+]?$/; $mf = '0' if !defined $mf || $mf eq ''; diff --git a/lib/Math/BigInt/Calc.pm b/lib/Math/BigInt/Calc.pm index 6db1a62..02770e2 100644 --- a/lib/Math/BigInt/Calc.pm +++ b/lib/Math/BigInt/Calc.pm @@ -1351,38 +1351,48 @@ sub _log_int if ($cmp == 0) { splice (@$x,1); $x->[0] = 1; - return $x; + return ($x,1) } # X < BASE if ($cmp < 0) { splice (@$x,1); $x->[0] = 0; - return $x; + return ($x,undef); } # this trial multiplication is very fast, even for large counts (like for # 2 ** 1024, since this still requires only 1024 very fast steps # (multiplication of a large number by a very small number is very fast)) my $x_org = _copy($c,$x); # preserve x - splice(@$x,1); $x->[0] = 0; # keep ref to $x + splice(@$x,1); $x->[0] = 1; # keep ref to $x + + # simple loop that increments $x by two in each step, possible overstepping + # the real result by one # use a loop that keeps $x as scalar as long as possible (this is faster) - my $trial = _copy($c,$base); my $count = 0; my $a; - while (($a = _acmp($x,$trial,$x_org) <= 0) && $count < $BASE) + my $trial = _copy($c,$base); my $a; + my $base_mul = _mul($c, _copy($c,$base), $base); + + while (($a = _acmp($x,$trial,$x_org)) < 0) { - _mul($c,$trial,$base); $count++; + _mul($c,$trial,$base_mul); _add($c, $x, [2]); } - if ($a <= 0) + + my $exact = 1; + if ($a > 0) { - # not done yet? - $x->[0] = $count; - while (_acmp($x,$trial,$x_org) <= 0) + # overstepped the result + _dec($c, $x); + _div($c,$trial,$base); + $a = _acmp($x,$trial,$x_org); + if ($a > 0) { - _mul($c,$trial,$base); _inc($c,$x); + _dec($c, $x); } + $exact = 0 if $a != 0; } - $x; # return result + ($x,$exact); # return result } # for debugging: @@ -1978,6 +1988,10 @@ slow) fallback routines to emulate these: _modpow return modulus of power ($x ** $y) % $z _log_int(X,N) calculate integer log() of X in base N X >= 0, N >= 0 (return undef for NaN) + returns (RESULT, EXACT) where EXACT is: + 1 : result is exactly RESULT + 0 : result was truncated to RESULT + undef : unknown whether result is exactly RESULT Input strings come in as unsigned but with prefix (i.e. as '123', '0xabc' or '0b1101'). diff --git a/lib/Math/BigInt/t/bare_mbi.t b/lib/Math/BigInt/t/bare_mbi.t index 6bcc6bd..0af4c42 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 => 2728; + plan tests => 2760; } use Math::BigInt lib => 'BareCalc'; diff --git a/lib/Math/BigInt/t/bigintpm.inc b/lib/Math/BigInt/t/bigintpm.inc index 332f575..db52553 100644 --- a/lib/Math/BigInt/t/bigintpm.inc +++ b/lib/Math/BigInt/t/bigintpm.inc @@ -718,6 +718,22 @@ inf:inf:NaN 15625:5:6 15626:5:6 15624:5:5 +1000:10:3 +10000:10:4 +100000:10:5 +1000000:10:6 +10000000:10:7 +100000000:10:8 +8916100448256:12:12 +8916100448257:12:12 +8916100448255:12:11 +2251799813685248:8:17 +72057594037927936:2:56 +144115188075855872:2:57 +288230376151711744:2:58 +576460752303423488:2:59 +4096:2:12 +1329227995784915872903807060280344576:2:120 # $x == $base => result 1 3:3:1 # $x < $base => result 0 ($base ** 0 <= $x) diff --git a/lib/Math/BigInt/t/bigintpm.t b/lib/Math/BigInt/t/bigintpm.t index b541aae..d4e0772 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 => 2728; + plan tests => 2760; } use Math::BigInt; diff --git a/lib/Math/BigInt/t/downgrade.t b/lib/Math/BigInt/t/downgrade.t index 0208a56..25d672c 100644 --- a/lib/Math/BigInt/t/downgrade.t +++ b/lib/Math/BigInt/t/downgrade.t @@ -10,7 +10,7 @@ BEGIN my $location = $0; $location =~ s/downgrade.t//; unshift @INC, $location; # to locate the testing files chdir 't' if -d 't'; - plan tests => 12; + plan tests => 15; } use Math::BigInt upgrade => 'Math::BigFloat'; @@ -36,6 +36,12 @@ ok (ref(Math::BigFloat->new('10')),'Math::BigInt'); ok (ref(Math::BigFloat->new('-10')),'Math::BigInt'); ok (ref(Math::BigFloat->new('-10.0E1')),'Math::BigInt'); +# bug until v1.67: +ok (Math::BigFloat->new('0.2E0'), '0.2'); +ok (Math::BigFloat->new('0.2E1'), '2'); +# until v1.67 resulted in 200: +ok (Math::BigFloat->new('0.2E2'), '20'); + # disable, otherwise it screws calculations Math::BigFloat->upgrade(undef); ok (Math::BigFloat->upgrade()||'',''); diff --git a/lib/Math/BigInt/t/fallback.t b/lib/Math/BigInt/t/fallback.t index c09a201..e348d92 100644 --- a/lib/Math/BigInt/t/fallback.t +++ b/lib/Math/BigInt/t/fallback.t @@ -31,6 +31,10 @@ BEGIN plan tests => 8; } +# 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) +# should calculate the result to X digits accuracy. For now, this is better +# than die()ing... use Math::BigInt; use Math::BigFloat; diff --git a/lib/Math/BigInt/t/sub_mbi.t b/lib/Math/BigInt/t/sub_mbi.t index 65c6d0b..3b3c6e6 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 => 2728 + plan tests => 2760 + 5; # +5 own tests }