Upgrade to Math::BigInt v1.71.
Rafael Garcia-Suarez [Fri, 30 Jul 2004 14:24:08 +0000 (14:24 +0000)]
p4raw-id: //depot/perl@23171

lib/Math/BigFloat.pm
lib/Math/BigInt.pm
lib/Math/BigInt/Calc.pm
lib/Math/BigInt/t/bare_mbf.t
lib/Math/BigInt/t/bigfltpm.inc
lib/Math/BigInt/t/bigfltpm.t
lib/Math/BigInt/t/sub_mbf.t
lib/Math/BigInt/t/with_sub.t

index 846f5f0..dcd0d35 100644 (file)
@@ -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
index af361b4..25fb8f8 100644 (file)
@@ -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)
index c90d61b..f2bcc92 100644 (file)
@@ -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;
   }                                                                             
 
index 336ca01..999604c 100644 (file)
@@ -27,7 +27,7 @@ BEGIN
     }
   print "# INC = @INC\n";
 
-  plan tests => 1835;
+  plan tests => 1837;
   }
 
 use Math::BigFloat lib => 'BareCalc';
index 4e38e5b..8a621f7 100644 (file)
@@ -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
 
 ###############################################################################
index b81114c..dbad294 100755 (executable)
@@ -26,7 +26,7 @@ BEGIN
     }
   print "# INC = @INC\n";
 
-  plan tests => 1835
+  plan tests => 1837
        + 2;            # own tests
   }
 
index e72506c..bdae6a5 100755 (executable)
@@ -26,7 +26,7 @@ BEGIN
     }
   print "# INC = @INC\n"; 
   
-  plan tests => 1835
+  plan tests => 1837
     + 6;       # + our own tests
   }
 
index be6efa0..af00563 100644 (file)
@@ -28,7 +28,7 @@ BEGIN
     }
   print "# INC = @INC\n";
 
-  plan tests => 1835
+  plan tests => 1837
        + 1;
   }