Upgrade BigInt and BigRat
Tels [Sun, 6 Jul 2003 15:41:36 +0000 (17:41 +0200)]
Subject: BigInt v1.65, Bigrat v0.10 - reloaded
Message-Id: <200307061158.23576@bloodgate.com>

p4raw-id: //depot/perl@20041

lib/Math/BigFloat.pm
lib/Math/BigInt.pm
lib/Math/BigInt/Calc.pm
lib/Math/BigInt/t/biglog.t
lib/Math/BigInt/t/mbimbf.t
lib/Math/BigRat.pm
lib/Math/BigRat/t/bigrat.t
lib/Math/BigRat/t/bigratpm.inc
lib/Math/BigRat/t/bigratpm.t

index 4a5a74e..9dd4c1c 100644 (file)
@@ -712,6 +712,7 @@ sub blog
   delete $x->{_a}; delete $x->{_p};
   # need to disable $upgrade in BigInt, to avoid deep recursion
   local $Math::BigInt::upgrade = undef;
+  local $Math::BigFloat::downgrade = undef;
 
   # upgrade $x if $x is not a BigFloat (handle BigInt input)
   if (!$x->isa('Math::BigFloat'))
@@ -725,6 +726,7 @@ sub blog
   # and if a different base was requested, convert it
   if (defined $base)
     {
+    $base = Math::BigFloat->new($base) unless $base->isa('Math::BigFloat');
     # not ln, but some other base
     $x->bdiv( $base->copy()->blog(undef,$scale), $scale );
     }
index fba83e2..dd9fda8 100644 (file)
@@ -2197,7 +2197,7 @@ sub broot
     $x->badd($org / ($x ** 2)); 
     $x->bdiv($divider);
     }
-    #print $x ** $y," org ",$org,"\n";
+  #print $x ** $y," org ",$org,"\n";
   # correct overshot
   while ($x ** $y < $org)
     {
@@ -3119,8 +3119,14 @@ appropriate information.
        div_scale       Fallback acccuracy for div
                        40
 
-It is currently not supported to set the configuration parameters by passing
-a hash ref to C<config()>.
+The following values can be set by passing config a reference to a hash:
+
+       trap_inf trap_nan
+        upgrade downgrade precision accuracy round_mode div_scale
+
+Example:
+       
+       $new_cfg = Math::BigInt->config( { trap_inf => 1, precision => 5 } );
 
 =head2 accuracy
 
index b1d88fa..a3091c7 100644 (file)
@@ -8,7 +8,7 @@ require Exporter;
 use vars qw/@ISA $VERSION/;
 @ISA = qw(Exporter);
 
-$VERSION = '0.34';
+$VERSION = '0.35';
 
 # Package to store unsigned big integers in decimal and do math with them
 
@@ -27,7 +27,7 @@ $VERSION = '0.34';
 
 # Beware of things like:
 # $i = $i * $y + $car; $car = int($i / $MBASE); $i = $i % $MBASE;
-# This works on x86, but fails on ARM (SA1100, iPAQ) due to whoeknows what
+# This works on x86, but fails on ARM (SA1100, iPAQ) due to whoknows what
 # reasons. So, use this instead (slower, but correct):
 # $i = $i * $y + $car; $car = int($i / $MBASE); $i -= $MBASE * $car;
 
index e79a5d2..c7c07c1 100644 (file)
@@ -96,9 +96,7 @@ ok ($cl->new('1.2')->bpow('0.3',10),  '1.056219968');
 ok ($cl->new('10')->bpow('0.6',10),   '3.981071706');
 
 # blog should handle bigint input
-# TODO: should be 2
-#ok (Math::BigFloat::blog(Math::BigInt->new(100),10), 2);
-ok (Math::BigFloat::blog(Math::BigInt->new(100),10), 'NaN');
+ok (Math::BigFloat::blog(Math::BigInt->new(100),10), 2);
 ok (Math::BigInt->new(100)->blog(10), 'NaN');
 
 # test for bug in bsqrt() not taking negative _e into account
index bada2aa..17cd712 100644 (file)
@@ -32,7 +32,7 @@ BEGIN
   print "# INC = @INC\n";
 
   plan tests => 679 
-    + 22;              # own tests
+    + 23;              # own tests
   }
 
 use Math::BigInt 1.63;
@@ -92,4 +92,12 @@ foreach my $class (qw/Math::BigInt Math::BigFloat/)
                                # so the return value of that operation should
                                # be 42, not undef
   ok ($x->accuracy(),42);      # so $x should still have A = 42
+  $class->accuracy(undef);     # reset for further tests
+  $class->precision(undef);
   }
+
+# bug with flog(Math::BigFloat,Math::BigInt)
+$x = Math::BigFloat->new(100);
+$x = $x->blog(Math::BigInt->new(10));
+
+ok ($x,2);
index b00aed4..993c2a4 100644 (file)
@@ -168,7 +168,7 @@ sub new
       $self->{sign} = '+';
       return $self->bnan() if $self->{_n}->{sign} eq $nan ||
                               $self->{_d}->{sign} eq $nan;
-      # inf handling is missing here
+      # handle inf and NAN cases:
       if ($self->{_n}->is_inf() || $self->{_d}->is_inf())
         {
         # inf/inf => NaN
@@ -570,12 +570,13 @@ sub bmod
 
   # compute $x - $y * floor($x/$y), keeping the sign of $x
 
+  # locally disable these, since they would interfere
   local $Math::BigInt::upgrade = undef;
   local $Math::BigInt::accuracy = undef;
   local $Math::BigInt::precision = undef;
 
   my $u = $x->copy()->babs();
-  # do a "normal" division ($x/$y)
+  # first, do a "normal" division ($x/$y)
   $u->{_d}->bmul($y->{_n});
   $u->{_n}->bmul($y->{_d});
 
@@ -597,7 +598,6 @@ sub bmod
   $x->{sign} = $xsign;                         # put sign back
 
   $x->bnorm()->round(@r);
-  $x;
   }
 
 ##############################################################################
@@ -908,8 +908,8 @@ sub bsqrt
   local $Math::BigInt::upgrade = undef;
   local $Math::BigInt::precision = undef;
   local $Math::BigInt::accuracy = undef;
-  $x->{_d} = Math::BigFloat->new($x->{_d})->bsqrt(@r);
-  $x->{_n} = Math::BigFloat->new($x->{_n})->bsqrt(@r);
+  $x->{_d} = Math::BigFloat->new($x->{_d})->bsqrt();
+  $x->{_n} = Math::BigFloat->new($x->{_n})->bsqrt();
 
   # if sqrt(D) was not integer
   if ($x->{_d}->{_e}->{sign} ne '+')
@@ -921,7 +921,7 @@ sub bsqrt
   if ($x->{_n}->{_e}->{sign} ne '+')
     {
     $x->{_d}->blsft($x->{_n}->{_e}->babs(),10);                # 71/45.1 => 710/45.1
-    $x->{_n} = $x->{_n}->{_n};                         # 710/45.1 => 710/451
+    $x->{_n} = $x->{_n}->{_m};                         # 710/45.1 => 710/451
     }
  
   # convert parts to $MBI again 
@@ -1024,10 +1024,12 @@ sub numify
  
   return $x->bstr() if $x->{sign} !~ /^[+-]$/; # inf, NaN, etc
 
-  my $t = Math::BigFloat->new($x->{_n});
-  $t->bneg() if $x->is_negative();
-  $t->bdiv($x->{_d});
-  $t->numify();  
+  # N/1 => N
+  return $x->{_n}->numify() if $x->{_d}->is_one();
+
+  # N/D
+  my $neg = 1; $neg = -1 if $x->{sign} ne '+';
+  $neg * $x->{_n}->numify() / $x->{_d}->numify();      # return sign * N/D
   }
 
 sub as_number
@@ -1113,7 +1115,10 @@ sub import
       eval $rc;
       }
     }
-  die ("Couldn't load $MBI: $! $@") if $@;
+  if ($@)
+    {
+    require Carp; Carp::croak ("Couldn't load $MBI: $! $@");
+    }
 
   # any non :constant stuff is handled by our parent, Exporter
   # even if @_ is empty, to give it a chance
index dd6f8ad..ae38555 100755 (executable)
@@ -8,7 +8,7 @@ BEGIN
   $| = 1;
   chdir 't' if -d 't';
   unshift @INC, '../lib'; # for running manually
-  plan tests => 159;
+  plan tests => 164;
   }
 
 # testing of Math::BigRat
@@ -162,8 +162,20 @@ ok ($x*$y,'3/7');
 $x = $cr->new('3/5');          $y = $cr->new('5/7');
 ok ($x/$y,'21/25');
 
+$x = $cr->new('7/4');          $y = $cr->new('1');
+ok ($x % $y,'3/4');
+
+$x = $cr->new('7/4');          $y = $cr->new('5/13');
+ok ($x % $y,'11/52');
+
+$x = $cr->new('7/4');          $y = $cr->new('5/9');
+ok ($x % $y,'1/12');
+
 $x = $cr->new('-144/9')->bsqrt();      ok ($x,'NaN');
 $x = $cr->new('144/9')->bsqrt();       ok ($x,'4');
+$x = $cr->new('3/4')->bsqrt();         ok ($x,
+  '1732050807568877293527446341505872366943/'
+ .'2000000000000000000000000000000000000000');
 
 ##############################################################################
 # bpow
@@ -222,6 +234,8 @@ $x = $cr->new('inf'); ok ($x->numify(), 'inf');
 $x = $cr->new('-inf'); ok ($x->numify(), '-inf');
 $x = $cr->new('NaN'); ok ($x->numify(), 'NaN');
 
+$x = $cr->new('4/3'); ok ($x->numify(), 4/3);
+
 ##############################################################################
 # done
 
index 8b706be..4e63220 100644 (file)
@@ -214,12 +214,16 @@ NaN:NaN
 2:-:-inf
 3:abc:inf
 &numify
-#0:0e+1
-#+1:1e+0
-#1234:1234e+0
+0:0
++1:1
+1234:1234
+3/4:0.75
+5/2:2.5
+3/2:1.5
+5/4:1.25
 NaN:NaN
-#+inf:inf
-#-inf:-inf
++inf:inf
+-inf:-inf
 &fnan
 abc:NaN
 2:NaN
index befed73..7994332 100755 (executable)
@@ -26,7 +26,7 @@ BEGIN
     }
   print "# INC = @INC\n";
 
-  plan tests => 525;
+  plan tests => 534;
   }
 
 use Math::BigRat;