From: Rafael Garcia-Suarez Date: Fri, 30 Jul 2004 14:24:08 +0000 (+0000) Subject: Upgrade to Math::BigInt v1.71. X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=ae161977d1005f6fda2476d87af33f49d164cb96;p=p5sagit%2Fp5-mst-13.2.git Upgrade to Math::BigInt v1.71. p4raw-id: //depot/perl@23171 --- diff --git a/lib/Math/BigFloat.pm b/lib/Math/BigFloat.pm index 846f5f0..dcd0d35 100644 --- a/lib/Math/BigFloat.pm +++ b/lib/Math/BigFloat.pm @@ -1283,7 +1283,8 @@ sub bdiv # cases like $x /= $x (but not $x /= $y!) were wrong due to modifying $x # twice below) - if (overload::StrVal($x) eq overload::StrVal($y)) + require Scalar::Util; + if (Scalar::Util::refaddr($x) == Scalar::Util::refaddr($y)) { $x->bone(); # x/x => 1, rem 0 } @@ -1825,7 +1826,7 @@ sub _pow $below = $v->copy(); $over = $u->copy(); - + $limit = $self->new("1E-". ($scale-1)); #my $steps = 0; while (3 < 5) @@ -1879,12 +1880,16 @@ sub bpow return $x if $x->{sign} =~ /^[+-]inf$/; return $x->bnan() if $x->{sign} eq $nan || $y->{sign} eq $nan; - return $x->bone() if $y->is_zero(); + + # cache the result of is_zero + my $y_is_zero = $y->is_zero(); + return $x->bone() if $y_is_zero; return $x if $x->is_one() || $y->is_one(); - return $x->_pow($y,$a,$p,$r) if !$y->is_int(); # non-integer power + my $x_is_zero = $x->is_zero(); + return $x->_pow($y,$a,$p,$r) if !$x_is_zero && !$y->is_int(); # non-integer power - my $y1 = $y->as_number()->{value}; # make CALC + my $y1 = $y->as_number()->{value}; # make MBI part # if ($x == -1) if ($x->{sign} eq '-' && $MBI->_is_one($x->{_m}) && $MBI->_is_zero($x->{_e})) @@ -1892,27 +1897,27 @@ sub bpow # if $x == -1 and odd/even y => +1/-1 because +-1 ^ (+-1) => +-1 return $MBI->_is_odd($y1) ? $x : $x->babs(1); } - if ($x->is_zero()) + if ($x_is_zero) { - return $x->bone() if $y->is_zero(); + return $x->bone() if $y_is_zero; return $x if $y->{sign} eq '+'; # 0**y => 0 (if not y <= 0) # 0 ** -y => 1 / (0 ** y) => 1 / 0! (1 / 0 => +inf) return $x->binf(); } my $new_sign = '+'; - $new_sign = $y->is_odd() ? '-' : '+' if ($x->{sign} ne '+'); + $new_sign = $MBI->_is_odd($y1) ? '-' : '+' if $x->{sign} ne '+'; # calculate $x->{_m} ** $y and $x->{_e} * $y separately (faster) $x->{_m} = $MBI->_pow( $x->{_m}, $y1); - $MBI->_mul ($x->{_e}, $y1); + $x->{_e} = $MBI->_mul ($x->{_e}, $y1); $x->{sign} = $new_sign; $x->bnorm(); if ($y->{sign} eq '-') { # modify $x in place! - my $z = $x->copy(); $x->bzero()->binc(); + my $z = $x->copy(); $x->bone(); return $x->bdiv($z,$a,$p,$r); # round in one go (might ignore y's A!) } $x->round($a,$p,$r,$y); @@ -2025,7 +2030,7 @@ sub bfround } } # pass sign to bround for rounding modes '+inf' and '-inf' - my $m = Math::BigInt->new( $x->{sign} . $MBI->_str($x->{_m})); + my $m = bless { sign => $x->{sign}, value => $x->{_m} }, 'Math::BigInt'; $m->bround($scale,$mode); $x->{_m} = $m->{value}; # get our mantissa back $x->bnorm(); @@ -2066,7 +2071,7 @@ sub bround } # pass sign to bround for '+inf' and '-inf' rounding modes - my $m = Math::BigInt->new( $x->{sign} . $MBI->_str($x->{_m})); + my $m = bless { sign => $x->{sign}, value => $x->{_m} }, 'Math::BigInt'; $m->bround($scale,$mode); # round mantissa $x->{_m} = $m->{value}; # get our mantissa back diff --git a/lib/Math/BigInt.pm b/lib/Math/BigInt.pm index af361b4..25fb8f8 100644 --- a/lib/Math/BigInt.pm +++ b/lib/Math/BigInt.pm @@ -1140,7 +1140,8 @@ sub bsub return $x; } - if (overload::StrVal($x) eq overload::StrVal($y)) + require Scalar::Util; + if (Scalar::Util::refaddr($x) == Scalar::Util::refaddr($y)) { # if we get the same variable twice, the result must be zero (the code # below fails in that case) @@ -2034,17 +2035,15 @@ sub bfround sub _scan_for_nonzero { - # internal, used by bround() - my ($x,$pad,$xs) = @_; + # internal, used by bround() to scan for non-zeros after a '5' + my ($x,$pad,$xs,$len) = @_; - my $len = $x->length(); - return 0 if $len == 1; # '5' is trailed by invisible zeros + return 0 if $len == 1; # "5" is trailed by invisible zeros my $follow = $pad - 1; return 0 if $follow > $len || $follow < 1; - # since we do not know underlying represention of $x, use decimal string - my $r = substr ("$x",-$follow); - $r =~ /[^0]/ ? 1 : 0; + # use the string form to check whether only '0's follow or not + substr ($xs,-$follow) =~ /[^0]/ ? 1 : 0; } sub fround @@ -2094,8 +2093,8 @@ sub bround $pad = $len - $scale; $pad = abs($scale-1) if $scale < 0; - # do not use digit(), it is costly for binary => decimal - + # do not use digit(), it is very costly for binary => decimal + # getting the entire string is also costly, but we need to do it only once my $xs = $CALC->_str($x->{value}); my $pl = -$pad-1; @@ -2113,7 +2112,7 @@ sub bround ($digit_after =~ /[01234]/) || # round down anyway, # 6789 => round up ($digit_after eq '5') && # not 5000...0000 - ($x->_scan_for_nonzero($pad,$xs) == 0) && + ($x->_scan_for_nonzero($pad,$xs,$len) == 0) && ( ($mode eq 'even') && ($digit_round =~ /[24680]/) || ($mode eq 'odd') && ($digit_round =~ /[13579]/) || @@ -2125,8 +2124,8 @@ sub bround if (($pad > 0) && ($pad <= $len)) { - substr($xs,-$pad,$pad) = '0' x $pad; - $put_back = 1; + substr($xs,-$pad,$pad) = '0' x $pad; # replace with '00...' + $put_back = 1; # need to put back } elsif ($pad > $len) { @@ -2135,7 +2134,7 @@ sub bround if ($round_up) # what gave test above? { - $put_back = 1; + $put_back = 1; # need to put back $pad = $len, $xs = '0' x $pad if $scale < 0; # tlr: whack 0.51=>1.0 # we modify directly the string variant instead of creating a number and @@ -2150,7 +2149,7 @@ sub bround $xs = '1'.$xs if $c == 0; } - $x->{value} = $CALC->_new($xs) if $put_back == 1; # put back in if needed + $x->{value} = $CALC->_new($xs) if $put_back == 1; # put back, if needed $x->{_a} = $scale if $scale >= 0; if ($scale < 0) diff --git a/lib/Math/BigInt/Calc.pm b/lib/Math/BigInt/Calc.pm index c90d61b..f2bcc92 100644 --- a/lib/Math/BigInt/Calc.pm +++ b/lib/Math/BigInt/Calc.pm @@ -303,7 +303,7 @@ sub _inc return $x if (($i += 1) < $BASE); # early out $i = 0; # overflow, next } - push @$x,1 if ($x->[-1] == 0); # last overflowed, so extend + push @$x,1 if (($x->[-1] || 0) == 0); # last overflowed, so extend $x; } diff --git a/lib/Math/BigInt/t/bare_mbf.t b/lib/Math/BigInt/t/bare_mbf.t index 336ca01..999604c 100644 --- a/lib/Math/BigInt/t/bare_mbf.t +++ b/lib/Math/BigInt/t/bare_mbf.t @@ -27,7 +27,7 @@ BEGIN } print "# INC = @INC\n"; - plan tests => 1835; + plan tests => 1837; } use Math::BigFloat lib => 'BareCalc'; diff --git a/lib/Math/BigInt/t/bigfltpm.inc b/lib/Math/BigInt/t/bigfltpm.inc index 4e38e5b..8a621f7 100644 --- a/lib/Math/BigInt/t/bigfltpm.inc +++ b/lib/Math/BigInt/t/bigfltpm.inc @@ -285,6 +285,21 @@ $x = $class->new('-3.14'); $x /= $x; ok ($x, '1'); $x = $class->new('3.14'); $x %= $x; ok ($x, '0'); $x = $class->new('-3.14'); $x %= $x; ok ($x, '0'); +############################################################################### +# the following two were reported by "kenny" via hotmail.com: + +#perl -MMath::BigFloat -wle 'print Math::BigFloat->new(0)->bpow(".1")' +#Use of uninitialized value in numeric le (<=) at BigFloat.pm line 1851. + +$x = $class->new(0); $y = $class->new('0.1'); +ok ($x ** $y, 0, 'no warnings and zero result'); + +#perl -MMath::BigFloat -lwe 'print Math::BigFloat->new(".222222222222222222222222222222222222222222")->bceil()' +#Use of uninitialized value in numeric le (<=) at BigFloat.pm line 1851. + +$x = $class->new(".222222222222222222222222222222222222222222"); +ok ($x->bceil(), 1, 'no warnings and one as result'); + 1; # all done ############################################################################### diff --git a/lib/Math/BigInt/t/bigfltpm.t b/lib/Math/BigInt/t/bigfltpm.t index b81114c..dbad294 100755 --- a/lib/Math/BigInt/t/bigfltpm.t +++ b/lib/Math/BigInt/t/bigfltpm.t @@ -26,7 +26,7 @@ BEGIN } print "# INC = @INC\n"; - plan tests => 1835 + plan tests => 1837 + 2; # own tests } diff --git a/lib/Math/BigInt/t/sub_mbf.t b/lib/Math/BigInt/t/sub_mbf.t index e72506c..bdae6a5 100755 --- a/lib/Math/BigInt/t/sub_mbf.t +++ b/lib/Math/BigInt/t/sub_mbf.t @@ -26,7 +26,7 @@ BEGIN } print "# INC = @INC\n"; - plan tests => 1835 + plan tests => 1837 + 6; # + our own tests } diff --git a/lib/Math/BigInt/t/with_sub.t b/lib/Math/BigInt/t/with_sub.t index be6efa0..af00563 100644 --- a/lib/Math/BigInt/t/with_sub.t +++ b/lib/Math/BigInt/t/with_sub.t @@ -28,7 +28,7 @@ BEGIN } print "# INC = @INC\n"; - plan tests => 1835 + plan tests => 1837 + 1; }