Upgrade to Math::BigInt 1.55, from Tels.
Jarkko Hietaniemi [Sat, 23 Mar 2002 20:34:43 +0000 (20:34 +0000)]
p4raw-id: //depot/perl@15447

21 files changed:
MANIFEST
lib/Math/BigFloat.pm
lib/Math/BigInt.pm
lib/Math/BigInt/Calc.pm
lib/Math/BigInt/t/bare_mbf.t
lib/Math/BigInt/t/bare_mbi.t
lib/Math/BigInt/t/bigfltpm.inc
lib/Math/BigInt/t/bigfltpm.t
lib/Math/BigInt/t/bigintpm.inc
lib/Math/BigInt/t/bigintpm.t
lib/Math/BigInt/t/config.t
lib/Math/BigInt/t/constant.t
lib/Math/BigInt/t/mbi_rand.t [new file with mode: 0644]
lib/Math/BigInt/t/sub_mbf.t
lib/Math/BigInt/t/sub_mbi.t
lib/Math/BigInt/t/upgrade.inc
lib/Math/BigInt/t/upgrade.t
lib/Math/BigInt/t/use_lib1.t [new file with mode: 0644]
lib/Math/BigInt/t/use_lib2.t [new file with mode: 0644]
lib/Math/BigInt/t/use_lib3.t [new file with mode: 0644]
lib/Math/BigInt/t/use_lib4.t [new file with mode: 0644]

index dd32c99..1b168a3 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -1160,6 +1160,11 @@ lib/look.pl                      A "look" equivalent
 lib/Math/BigFloat.pm           An arbitrary precision floating-point arithmetic package
 lib/Math/BigInt.pm             An arbitrary precision integer arithmetic package
 lib/Math/BigInt/Calc.pm                Pure Perl module to support Math::BigInt
+lib/Math/BigInt/t/mbi_rand.t   Test Math::BigInt randomly
+lib/Math/BigInt/t/use_lib1.t   Test combinations of Math::BigInt and BigFloat
+lib/Math/BigInt/t/use_lib2.t   Test combinations of Math::BigInt and BigFloat
+lib/Math/BigInt/t/use_lib3.t   Test combinations of Math::BigInt and BigFloat
+lib/Math/BigInt/t/use_lib4.t   Test combinations of Math::BigInt and BigFloat
 lib/Math/BigInt/t/bare_mbf.t   Test MBF under Math::BigInt::BareCalc
 lib/Math/BigInt/t/bare_mbi.t   Test MBI under Math::BigInt::BareCalc
 lib/Math/BigInt/t/bigfltpm.inc Shared tests for bigfltpm.t and sub_mbf.t
index ad6588e..d47b5f1 100644 (file)
@@ -12,15 +12,16 @@ package Math::BigFloat;
 #   _p: precision
 #   _f: flags, used to signal MBI not to touch our private parts
 
-$VERSION = '1.30';
+$VERSION = '1.31';
 require 5.005;
 use Exporter;
-use Math::BigInt qw/objectify/;
+use File::Spec;
+# use Math::BigInt;
 @ISA =       qw( Exporter Math::BigInt);
 
 use strict;
 use vars qw/$AUTOLOAD $accuracy $precision $div_scale $round_mode $rnd_mode/;
-use vars qw/$upgrade $downgrade/;
+use vars qw/$upgrade $downgrade $MBI/;
 my $class = "Math::BigFloat";
 
 use overload
@@ -48,16 +49,21 @@ $div_scale  = 40;
 
 $upgrade = undef;
 $downgrade = undef;
+$MBI = 'Math::BigInt'; # the package we are using for our private parts
+                       # changable by use Math::BigFloat with => 'package'
 
 ##############################################################################
 # the old code had $rnd_mode, so we need to support it, too
 
-$rnd_mode   = 'even';
 sub TIESCALAR   { my ($class) = @_; bless \$round_mode, $class; }
 sub FETCH       { return $round_mode; }
 sub STORE       { $rnd_mode = $_[0]->round_mode($_[1]); }
 
-BEGIN { tie $rnd_mode, 'Math::BigFloat'; }
+BEGIN
+  { 
+  $rnd_mode   = 'even';
+  tie $rnd_mode, 'Math::BigFloat'; 
+  }
  
 ##############################################################################
 
@@ -104,7 +110,7 @@ sub new
   if ((ref($wanted)) && (ref($wanted) ne $class))
     {
     $self->{_m} = $wanted->as_number();                # get us a bigint copy
-    $self->{_e} = Math::BigInt->bzero();
+    $self->{_e} = $MBI->bzero();
     $self->{_m}->babs();
     $self->{sign} = $wanted->sign();
     return $self->bnorm();
@@ -115,8 +121,8 @@ sub new
     {
     return $downgrade->new($wanted) if $downgrade;
 
-    $self->{_e} = Math::BigInt->bzero();
-    $self->{_m} = Math::BigInt->bzero();
+    $self->{_e} = $MBI->bzero();
+    $self->{_m} = $MBI->bzero();
     $self->{sign} = $wanted;
     $self->{sign} = '+inf' if $self->{sign} eq 'inf';
     return $self->bnorm();
@@ -129,16 +135,16 @@ sub new
     
     return $downgrade->bnan() if $downgrade;
     
-    $self->{_e} = Math::BigInt->bzero();
-    $self->{_m} = Math::BigInt->bzero();
+    $self->{_e} = $MBI->bzero();
+    $self->{_m} = $MBI->bzero();
     $self->{sign} = $nan;
     }
   else
     {
     # make integer from mantissa by adjusting exp, then convert to bigint
     # undef,undef to signal MBI that we don't need no bloody rounding
-    $self->{_e} = Math::BigInt->new("$$es$$ev",undef,undef);   # exponent
-    $self->{_m} = Math::BigInt->new("$$miv$$mfv",undef,undef);         # create mant.
+    $self->{_e} = $MBI->new("$$es$$ev",undef,undef);   # exponent
+    $self->{_m} = $MBI->new("$$miv$$mfv",undef,undef);         # create mant.
     # 3.123E0 = 3123E-3, and 3.123E-2 => 3123E-5
     $self->{_e} -= CORE::length($$mfv) if CORE::length($$mfv) != 0;            
     $self->{sign} = $$mis;
@@ -163,39 +169,39 @@ sub _bnan
   {
   # used by parent class bone() to initialize number to 1
   my $self = shift;
-  $self->{_m} = Math::BigInt->bzero();
-  $self->{_e} = Math::BigInt->bzero();
+  $self->{_m} = $MBI->bzero();
+  $self->{_e} = $MBI->bzero();
   }
 
 sub _binf
   {
   # used by parent class bone() to initialize number to 1
   my $self = shift;
-  $self->{_m} = Math::BigInt->bzero();
-  $self->{_e} = Math::BigInt->bzero();
+  $self->{_m} = $MBI->bzero();
+  $self->{_e} = $MBI->bzero();
   }
 
 sub _bone
   {
   # used by parent class bone() to initialize number to 1
   my $self = shift;
-  $self->{_m} = Math::BigInt->bone();
-  $self->{_e} = Math::BigInt->bzero();
+  $self->{_m} = $MBI->bone();
+  $self->{_e} = $MBI->bzero();
   }
 
 sub _bzero
   {
   # used by parent class bone() to initialize number to 1
   my $self = shift;
-  $self->{_m} = Math::BigInt->bzero();
-  $self->{_e} = Math::BigInt->bone();
+  $self->{_m} = $MBI->bzero();
+  $self->{_e} = $MBI->bone();
   }
 
 sub isa
   {
   my ($self,$class) = @_;
-  return if $class eq 'Math::BigInt';          # we aren't
-  return UNIVERSAL::isa($self,$class);
+  return if $class =~ /^Math::BigInt/;         # we aren't one of these
+  UNIVERSAL::isa($self,$class);
   }
 
 ##############################################################################
@@ -264,7 +270,7 @@ sub bstr
     my $zeros = -$x->{_p} + $cad;
     $es .= $dot.'0' x $zeros if $zeros > 0;
     }
-  return $es;
+  $es;
   }
 
 sub bsstr
@@ -285,7 +291,7 @@ sub bsstr
     }
   my $sign = $x->{_e}->{sign}; $sign = '' if $sign eq '-';
   my $sep = 'e'.$sign;
-  return $x->{_m}->bstr().$sep.$x->{_e}->bstr();
+  $x->{_m}->bstr().$sep.$x->{_e}->bstr();
   }
     
 sub numify 
@@ -293,7 +299,7 @@ sub numify
   # Make a number from a BigFloat object
   # simple return string and let Perl's atoi()/atof() handle the rest
   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
-  return $x->bsstr(); 
+  $x->bsstr(); 
   }
 
 ##############################################################################
@@ -429,8 +435,7 @@ sub badd
       return $x if $x->{sign} eq $y->{sign};
       return $x->bnan();
       }
-    # +-inf + something => +inf
-    # something +-inf => +-inf
+    # +-inf + something => +inf; something +-inf => +-inf
     $x->{sign} = $y->{sign}, return $x if $y->{sign} =~ /^[+-]inf$/;
     return $x;
     }
@@ -448,11 +453,10 @@ sub badd
  
   # take lower of the two e's and adapt m1 to it to match m2
   my $e = $y->{_e};
-  $e = Math::BigInt::bzero() if !defined $e;   # if no BFLOAT ?
-  $e = $e->copy();                             # make copy (didn't do it yet)
+  $e = $MBI->bzero() if !defined $e;   # if no BFLOAT ?
+  $e = $e->copy();                     # make copy (didn't do it yet)
   $e->bsub($x->{_e});
   my $add = $y->{_m}->copy();
-#  if ($e < 0)                         # < 0
   if ($e->{sign} eq '-')               # < 0
     {
     my $e1 = $e->copy()->babs();
@@ -460,7 +464,6 @@ sub badd
     $x->{_m}->blsft($e1,10);
     $x->{_e} += $e;                    # need the sign of e
     }
-#  if ($e > 0)                         # > 0
   elsif (!$e->is_zero())               # > 0
     {
     #$add *= (10 ** $e);
@@ -947,13 +950,12 @@ sub bmod
     {
     $x->{_m}->blsft($x->{_e},10);
     }
-  $x->{_e} = Math::BigInt->bzero() unless $x->{_e}->is_zero();
+  $x->{_e} = $MBI->bzero() unless $x->{_e}->is_zero();
   
   $x->{_e}->bsub($shiftx) if $shiftx != 0;
   $x->{_e}->bsub($shifty) if $shifty != 0;
   
   # now mantissas are equalized, exponent of $x is adjusted, so calc result
-#  $ym->{sign} = '-' if $neg; # bmod() will make the correction for us
 
   $x->{_m}->bmod($ym);
 
@@ -1023,7 +1025,7 @@ sub bsqrt
    && ($xas->bacmp($gs * $gs) == 0))   # guess hit the nail on the head?
     {
     # exact result
-    $x->{_m} = $gs; $x->{_e} = Math::BigInt->bzero(); $x->bnorm();
+    $x->{_m} = $gs; $x->{_e} = $MBI->bzero(); $x->bnorm();
     # shortcut to not run trough _find_round_parameters again
     if (defined $params[1])
       {
@@ -1104,6 +1106,108 @@ sub bfac
   $x->bnorm()->round(@r);
   }
 
+sub _pow2
+  {
+  # Calculate a power where $y is a non-integer, like 2 ** 0.5
+  my ($x,$y,$a,$p,$r) = @_;
+  my $self = ref($x);
+  
+  # we need to limit the accuracy to protect against overflow
+  my $fallback = 0;
+  my $scale = 0;
+  my @params = $x->_find_round_parameters($a,$p,$r);
+
+  # no rounding at all, so must use fallback
+  if (scalar @params == 1)
+    {
+    # simulate old behaviour
+    $params[1] = $self->div_scale();   # and round to it as accuracy
+    $scale = $params[1]+4;             # at least four more for proper round
+    $params[3] = $r;                   # round mode by caller or undef
+    $fallback = 1;                     # to clear a/p afterwards
+    }
+  else
+    {
+    # the 4 below is empirical, and there might be cases where it is not
+    # enough...
+    $scale = abs($params[1] || $params[2]) + 4;        # take whatever is defined
+    }
+
+  # when user set globals, they would interfere with our calculation, so
+  # disable then and later re-enable them
+  no strict 'refs';
+  my $abr = "$self\::accuracy"; my $ab = $$abr; $$abr = undef;
+  my $pbr = "$self\::precision"; my $pb = $$pbr; $$pbr = undef;
+  # we also need to disable any set A or P on $x (_find_round_parameters took
+  # them already into account), since these would interfere, too
+  delete $x->{_a}; delete $x->{_p};
+  # need to disable $upgrade in BigInt, to avoid deep recursion
+  local $Math::BigInt::upgrade = undef;
+  # split the second argument into its integer and fraction part
+  # we calculate the result then from these two parts, like in
+  # 2 ** 2.4 == (2 ** 2) * (2 ** 0.4)
+  my $c = $self->new($y->as_number()); # integer part
+  my $d = $y-$c;                       # fractional part
+  my $xc = $x->copy();                 # a temp. copy
+  
+  # now calculate binary fraction from the decimal fraction on the fly
+  # f.i. 0.654:
+  # 0.654 * 2 = 1.308 > 1 => 0.1       ( 1.308 - 1 = 0.308)
+  # 0.308 * 2 = 0.616 < 1 => 0.10
+  # 0.616 * 2 = 1.232 > 1 => 0.101     ( 1.232 - 1 = 0.232)
+  # and so on...
+  # The process stops when the result is exactly one, or when we have
+  # enough accuracy
+
+  # From the binary fraction we calculate the result as follows:
+  # we assume the fraction ends in 1, and we remove this one first.
+  # For each digit after the dot, assume 1 eq R and 0 eq XR, where R means
+  # take square root and X multiply with the original X. 
+  
+  my $i = 0;
+  while ($i++ < 50)
+    {
+    $d->badd($d);                                              # * 2
+    last if $d->is_one();                                      # == 1
+    $x->bsqrt();                                               # 0
+    if ($d > 1)
+      {
+      $x->bsqrt(); $x->bmul($xc); $d->bdec();                  # 1
+      }
+    print "at $x\n";
+    }
+  # assume fraction ends in 1
+  $x->bsqrt();                                                 # 1
+  if (!$c->is_one())
+    {
+    $x->bmul( $xc->bpow($c) );
+    }
+  elsif (!$c->is_zero())
+    {
+    $x->bmul( $xc );
+    }
+  # done
+
+  # shortcut to not run trough _find_round_parameters again
+  if (defined $params[1])
+    {
+    $x->bround($params[1],$params[3]);         # then round accordingly
+    }
+  else
+    {
+    $x->bfround($params[2],$params[3]);                # then round accordingly
+    }
+  if ($fallback)
+    {
+    # clear a/p after round, since user did not request it
+    $x->{_a} = undef; $x->{_p} = undef;
+    }
+  # restore globals
+  $$abr = $ab; $$pbr = $pb;
+  $x;
+  }
+
 sub _pow
   {
   # Calculate a power where $y is a non-integer, like 2 ** 0.5
@@ -1209,7 +1313,7 @@ sub bpow
   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
+  return $x->_pow2($y,$a,$p,$r) if !$y->is_int();      # non-integer power
 
   my $y1 = $y->as_number();            # make bigint
   # if ($x == -1)
@@ -1494,7 +1598,7 @@ sub AUTOLOAD
       }
     # try one level up, but subst. bxxx() for fxxx() since MBI only got bxxx()
     $name =~ s/^f/b/;
-    return &{'Math::BigInt'."::$name"}(@_);
+    return &{"$MBI"."::$name"}(@_);
     }
   my $bname = $name; $bname =~ s/^f/b/;
   *{$class."::$name"} = \&$bname;
@@ -1552,6 +1656,7 @@ sub import
   {
   my $self = shift;
   my $l = scalar @_; my $j = 0; my @a = @_;
+  my $lib = '';
   for ( my $i = 0; $i < $l ; $i++, $j++)
     {
     if ( $_[$i] eq ':constant' )
@@ -1575,7 +1680,28 @@ sub import
       my $s = 2; $s = 1 if @a-$j < 2;   # avoid "can not modify non-existant..."
       splice @a, $j, $s; $j -= $s;
       }
+    elsif ($_[$i] eq 'lib')
+      {
+      $lib = $_[$i+1] || '';           # default Calc
+      my $s = 2; $s = 1 if @a-$j < 2;   # avoid "can not modify non-existant..."
+      splice @a, $j, $s; $j -= $s;
+      }
+    elsif ($_[$i] eq 'with')
+      {
+      $MBI = $_[$i+1] || 'Math::BigInt';       # default Math::BigInt
+      my $s = 2; $s = 1 if @a-$j < 2;   # avoid "can not modify non-existant..."
+      splice @a, $j, $s; $j -= $s;
+      }
     }
+  my @parts = split /::/, $MBI;                        # Math::BigInt => Math BigInt
+  my $file = pop @parts; $file .= '.pm';       # BigInt => BigInt.pm
+  $file = File::Spec->catdir (@parts, $file);
+  # let use Math::BigInt lib => 'GMP'; use Math::BigFloat; still work
+  my $mbilib = eval { Math::BigInt->config()->{lib} };
+  $lib .= ",$mbilib" if defined $mbilib;
+  require $file;
+  $MBI->import ( lib => $lib, 'objectify' );
+
   # any non :constant stuff is handled by our parent, Exporter
   # even if @_ is empty, to give it a chance
   $self->SUPER::import(@a);            # for subclasses
@@ -1643,7 +1769,7 @@ sub length
   $len += $x->{_e} if $x->{_e}->sign() eq '+';
   if (wantarray())
     {
-    my $t = Math::BigInt::bzero();
+    my $t = $MBI->bzero();
     $t = $x->{_e}->copy()->babs() if $x->{_e}->sign() eq '-';
     return ($len,$t);
     }
@@ -1922,10 +2048,100 @@ In particular
 
   perl -MMath::BigFloat=:constant -e 'print 2E-100,"\n"'
 
-prints the value of C<2E-100>.  Note that without conversion of 
+prints the value of C<2E-100>. Note that without conversion of 
 constants the expression 2E-100 will be calculated as normal floating point 
 number.
 
+Please note that ':constant' does not affect integer constants, nor binary 
+nor hexadecimal constants. Use L<bignum> or L<Math::BigInt> to get this to
+work.
+
+=head2 Math library
+
+Math with the numbers is done (by default) by a module called
+Math::BigInt::Calc. This is equivalent to saying:
+
+       use Math::BigFloat lib => 'Calc';
+
+You can change this by using:
+
+       use Math::BigFloat lib => 'BitVect';
+
+The following would first try to find Math::BigInt::Foo, then
+Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
+
+       use Math::BigFloat lib => 'Foo,Math::BigInt::Bar';
+
+Calc.pm uses as internal format an array of elements of some decimal base
+(usually 1e7, but this might be differen for some systems) with the least
+significant digit first, while BitVect.pm uses a bit vector of base 2, most
+significant bit first. Other modules might use even different means of
+representing the numbers. See the respective module documentation for further
+details.
+
+Please note that Math::BigFloat does B<not> use the denoted library itself,
+but it merely passes the lib argument to Math::BigInt. So, instead of the need
+to do:
+
+       use Math::BigInt lib => 'GMP';
+       use Math::BigFloat;
+
+you can roll it all into one line:
+
+       use Math::BigFloat lib => 'GMP';
+
+Use the lib, Luke! And see L<Using Math::BigInt::Lite> for more details.
+
+=head2 Using Math::BigInt::Lite
+
+It is possible to use L<Math::BigInt::Lite> with Math::BigFloat:
+
+        # 1
+        use Math::BigFloat with => 'Math::BigInt::Lite';
+
+There is no need to "use Math::BigInt" or "use Math::BigInt::Lite", but you
+can combine these if you want. For instance, you may want to use
+Math::BigInt objects in your main script, too.
+
+        # 2
+        use Math::BigInt;
+        use Math::BigFloat with => 'Math::BigInt::Lite';
+
+Of course, you can combine this with the C<lib> parameter.
+
+        # 3
+        use Math::BigFloat with => 'Math::BigInt::Lite', lib => 'GMP,Pari';
+
+If you want to use Math::BigInt's, too, simple add a Math::BigInt B<before>:
+
+        # 4
+        use Math::BigInt;
+        use Math::BigFloat with => 'Math::BigInt::Lite', lib => 'GMP,Pari';
+
+Notice that the module with the last C<lib> will "win" and thus
+it's lib will be used if the lib is available:
+
+        # 5
+        use Math::BigInt lib => 'Bar,Baz';
+        use Math::BigFloat with => 'Math::BigInt::Lite', lib => 'Foo';
+
+That would try to load Foo, Bar, Baz and Calc (in that order). Or in other
+words, Math::BigFloat will try to retain previously loaded libs when you
+don't specify it one.
+
+Actually, the lib loading order would be "Bar,Baz,Calc", and then
+"Foo,Bar,Baz,Calc", but independend of which lib exists, the result is the
+same as trying the latter load alone, except for the fact that Bar or Baz
+might be loaded needlessly in an intermidiate step
+
+The old way still works though:
+
+        # 6
+        use Math::BigInt lib => 'Bar,Baz';
+        use Math::BigFloat;
+
+But B<examples #3 and #4 are recommended> for usage.
+
 =head1 BUGS
 
 =over 2
index abe2c82..3c142f2 100644 (file)
@@ -18,7 +18,7 @@ package Math::BigInt;
 my $class = "Math::BigInt";
 require 5.005;
 
-$VERSION = '1.54';
+$VERSION = '1.55';
 use Exporter;
 @ISA =       qw( Exporter );
 @EXPORT_OK = qw( objectify _swap bgcd blcm); 
@@ -535,7 +535,7 @@ sub binf
   # create a bigint '+-inf', if given a BigInt, set it to '+-inf'
   # the sign is either '+', or if given, used from there
   my $self = shift;
-  my $sign = shift; $sign = '+' if !defined $sign || $sign ne '-';
+  my $sign = shift; $sign = '+' if !defined $sign || $sign !~ /^-(inf)?$/;
   $self = $class if !defined $self;
   if (!ref($self))
     {
@@ -554,7 +554,8 @@ sub binf
     # otherwise do our own thing
     $self->{value} = $CALC->_zero();
     }
-  $self->{sign} = $sign.'inf';
+  $sign = $sign . 'inf' if $sign !~ /inf$/;    # - => -inf
+  $self->{sign} = $sign;
   ($self->{_a},$self->{_p}) = @_;              # take over requested rounding
   return $self;
   }
@@ -657,7 +658,7 @@ sub bstr
   # make a string from bigint object
   my $x = shift; $class = ref($x) || $x; $x = $class->new(shift) if !ref($x); 
   # my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_); 
+
   if ($x->{sign} !~ /^[+-]$/)
     {
     return $x->{sign} unless $x->{sign} eq '+inf';     # -inf, NaN
@@ -870,12 +871,11 @@ sub bcmp
   # post-normalized compare for internal use (honors signs)
   if ($x->{sign} eq '+') 
     {
-    return 1 if $y->{sign} eq '-'; # 0 check handled above
+    # $x and $y both > 0
     return $CALC->_acmp($x->{value},$y->{value});
     }
 
-  # $x->{sign} eq '-'
-  return -1 if $y->{sign} eq '+';
+  # $x && $y both < 0
   $CALC->_acmp($y->{value},$x->{value});       # swaped (lib does only 0,1,-1)
   }
 
@@ -906,8 +906,8 @@ sub badd
 #  print "mbi badd ",join(' ',caller()),"\n";
 #  print "upgrade => ",$upgrade||'undef',
 #    " \$x (",ref($x),") \$y (",ref($y),")\n";
-#  return $upgrade->badd($x,$y,@r) if defined $upgrade &&
-#    ((ref($x) eq $upgrade) || (ref($y) eq $upgrade));
+  return $upgrade->badd($x,$y,@r) if defined $upgrade &&
+    ((ref($x) eq $upgrade) || (ref($y) eq $upgrade));
 #  print "still badd\n";
 
   $r[3] = $y;                          # no push!
@@ -1487,7 +1487,7 @@ sub bpow
     $x->bmul($x);
     }
   $x->bmul($pow2) unless $pow2->is_one();
-  return $x->round(@r);
+  $x->round(@r);
   }
 
 sub blsft 
@@ -1716,10 +1716,10 @@ sub length
 sub digit
   {
   # return the nth decimal digit, negative values count backward, 0 is right
-  my $x = shift;
-  my $n = shift || 0; 
+  my ($self,$x,$n) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
+  $n = 0 if !defined $n;
 
-  return $CALC->_digit($x->{value},$n);
+  $CALC->_digit($x->{value},$n);
   }
 
 sub _trailing_zeros
@@ -1789,7 +1789,7 @@ sub exponent
   my $e = $class->bzero();
   return $e->binc() if $x->is_zero();
   $e += $x->_trailing_zeros();
-  return $e;
+  $e;
   }
 
 sub mantissa
@@ -1804,8 +1804,9 @@ sub mantissa
   my $m = $x->copy();
   # that's inefficient
   my $zeros = $m->_trailing_zeros();
-  $m /= 10 ** $zeros if $zeros != 0;
-  return $m;
+  $m->brsft($zeros,10) if $zeros != 0;
+#  $m /= 10 ** $zeros if $zeros != 0;
+  $m;
   }
 
 sub parts
@@ -2153,6 +2154,7 @@ sub import
       {
       # this causes overlord er load to step in
       overload::constant integer => sub { $self->new(shift) };
+      overload::constant binary => sub { $self->new(shift) };
       splice @a, $j, 1; $j --;
       }
     elsif ($_[$i] eq 'upgrade')
@@ -2711,35 +2713,60 @@ If used on an object, it will set it to one:
        $x->bone();             # +1
        $x->bone('-');          # -1
 
-=head2 is_one() / is_zero() / is_nan() / is_positive() / is_negative() /
-is_inf() / is_odd() / is_even() / is_int()
+=head2 is_one()/is_zero()/is_nan()/is_inf()
+
   
        $x->is_zero();                  # true if arg is +0
        $x->is_nan();                   # true if arg is NaN
        $x->is_one();                   # true if arg is +1
        $x->is_one('-');                # true if arg is -1
-       $x->is_odd();                   # true if odd, false for even
-       $x->is_even();                  # true if even, false for odd
-       $x->is_positive();              # true if >= 0
-       $x->is_negative();              # true if <  0
        $x->is_inf();                   # true if +inf
        $x->is_inf('-');                # true if -inf (sign is default '+')
+
+These methods all test the BigInt for beeing one specific value and return
+true or false depending on the input. These are faster than doing something
+like:
+
+       if ($x == 0)
+
+=head2 is_positive()/is_negative()
+       
+       $x->is_positive();              # true if >= 0
+       $x->is_negative();              # true if <  0
+
+The methods return true if the argument is positive or negative, respectively.
+C<NaN> is neither positive nor negative, while C<+inf> counts as positive, and
+C<-inf> is negative. A C<zero> is positive.
+
+These methods are only testing the sign, and not the value.
+
+=head2 is_odd()/is_even()/is_int()
+
+       $x->is_odd();                   # true if odd, false for even
+       $x->is_even();                  # true if even, false for odd
        $x->is_int();                   # true if $x is an integer
 
-These methods all test the BigInt for one condition and return true or false
-depending on the input.
+The return true when the argument satisfies the condition. C<NaN>, C<+inf>,
+C<-inf> are not integers and are neither odd nor even.
 
 =head2 bcmp
 
-  $x->bcmp($y);                        # compare numbers (undef,<0,=0,>0)
+       $x->bcmp($y);
+
+Compares $x with $y and takes the sign into account.
+Returns -1, 0, 1 or undef.
 
 =head2 bacmp
 
-  $x->bacmp($y);               # compare absolutely (undef,<0,=0,>0)
+       $x->bacmp($y);
+
+Compares $x with $y while ignoring their. Returns -1, 0, 1 or undef.
 
 =head2 sign
 
-  $x->sign();                  # return the sign, either +,- or NaN
+       $x->sign();
+
+Return the sign, of $x, meaning either C<+>, C<->, C<-inf>, C<+inf> or NaN.
 
 =head2 bcmp
 
@@ -3381,15 +3408,15 @@ Examples for converting:
 
 =head1 Autocreating constants
 
-After C<use Math::BigInt ':constant'> all the B<integer> decimal constants
-in the given scope are converted to C<Math::BigInt>. This conversion
-happens at compile time.
+After C<use Math::BigInt ':constant'> all the B<integer> decimal, hexadecimal
+and binary constants in the given scope are converted to C<Math::BigInt>.
+This conversion happens at compile time. 
 
 In particular,
 
   perl -MMath::BigInt=:constant -e 'print 2**100,"\n"'
 
-prints the integer value of C<2**100>.  Note that without conversion of 
+prints the integer value of C<2**100>. Note that without conversion of 
 constants the expression 2**100 will be calculated as perl scalar.
 
 Please note that strings and floating point constants are not affected,
@@ -3413,6 +3440,16 @@ Without the quotes Perl would convert the large number to a floating point
 constant at compile time and then hand the result to BigInt, which results in
 an truncated result or a NaN.
 
+This also applies to integers that look like floating point constants:
+
+       use Math::BigInt ':constant';
+
+       print ref(123e2),"\n";
+       print ref(123.2e2),"\n";
+
+will print nothing but newlines. Use either L<bignum> or L<Math::BigFloat>
+to get this to work.
+
 =head1 PERFORMANCE
 
 Using the form $x += $y; etc over $x = $x + $y is faster, since a copy of $x
index de4f46e..a7110c9 100644 (file)
@@ -8,7 +8,7 @@ require Exporter;
 use vars qw/@ISA $VERSION/;
 @ISA = qw(Exporter);
 
-$VERSION = '0.25';
+$VERSION = '0.26';
 
 # Package to store unsigned big integers in decimal and do math with them
 
@@ -392,7 +392,7 @@ sub _sub
   {
   # (ref to int_num_array, ref to int_num_array, swap)
   # subtract base 1eX numbers -- stolen from Knuth Vol 2 pg 232, $x > $y
-  # subtract Y from X (X is always greater/equal!) by modifying x in place
+  # subtract Y from X by modifying x in place
   my ($c,$sx,$sy,$s) = @_;
  
   my $car = 0; my $i; my $j = 0;
@@ -410,7 +410,9 @@ sub _sub
   #print "case 1 (swap)\n";
   for $i (@$sx)
     {
-    last unless defined $sy->[$j] || $car;
+    # we can't do an early out if $x is than $y, since we
+    # need to copy the high chunks from $y. Found by Bob Mathews.
+    #last unless defined $sy->[$j] || $car;
     $sy->[$j] += $BASE
      if $car = (($sy->[$j] = $i-($sy->[$j]||0) - $car) < 0);
     $j++;
@@ -1174,7 +1176,7 @@ sub _rsft
       $dst++;
       }
     splice (@$x,$dst) if $dst > 0;             # kill left-over array elems
-    pop @$x if $x->[-1] == 0;                  # kill last element if 0
+    pop @$x if $x->[-1] == 0 && @$x > 1;       # kill last element if 0
     } # else rem == 0
   $x;
   }
index 8288d2b..abeb8c2 100644 (file)
@@ -26,11 +26,14 @@ BEGIN
     }
   print "# INC = @INC\n";
 
-  plan tests => 1592;
+  plan tests => 1601;
   }
 
-use Math::BigInt lib => 'BareCalc';
-use Math::BigFloat;
+#use Math::BigInt lib => 'BareCalc';
+#use Math::BigFloat;
+
+# use Math::BigInt; use Math::BigFloat lib => 'BareCalc';
+use Math::BigFloat lib => 'BareCalc';
 
 use vars qw ($class $try $x $y $f @args $ans $ans1 $ans1_str $setup $CL);
 $class = "Math::BigFloat";
index d480062..5899dfe 100644 (file)
@@ -26,7 +26,7 @@ BEGIN
     }
   print "# INC = @INC\n";
 
-  plan tests => 2147;
+  plan tests => 2237;
   }
 
 use Math::BigInt lib => 'BareCalc';
index 8748d23..734b935 100644 (file)
@@ -153,6 +153,19 @@ $x = $class->new(2); $x->fzero(); ok_undef ($x->{_a}); ok_undef ($x->{_p});
 $x = $class->new(2); $x->finf();  ok_undef ($x->{_a}); ok_undef ($x->{_p});
 $x = $class->new(2); $x->fone();  ok_undef ($x->{_a}); ok_undef ($x->{_p});
 $x = $class->new(2); $x->fnan();  ok_undef ($x->{_a}); ok_undef ($x->{_p});
+
+###############################################################################
+# bone/binf etc as plain calls (Lite failed them)
+
+ok ($class->fzero(),0);
+ok ($class->fone(),1);
+ok ($class->fone('+'),1);
+ok ($class->fone('-'),-1);
+ok ($class->fnan(),'NaN');
+ok ($class->finf(),'inf');
+ok ($class->finf('+'),'inf');
+ok ($class->finf('-'),'-inf');
+ok ($class->finf('-inf'),'-inf');
         
 ###############################################################################
 # fsqrt() with set global A/P or A/P enabled on $x, also a test whether fsqrt()
@@ -370,7 +383,11 @@ abc:123.456:NaN
 # 2 ** 0.5 == sqrt(2)
 #     1.41..7 and not 1.4170 since fallback (bsqrt(9) is '3', not 3.0...0)
 2:0.5:1.41421356237309504880168872420969807857
-2:0.2:1.148698354997035006798626946777927589444
+#2:0.2:1.148698354997035006798626946777927589444
+6:1.5:14.6969384566990685891837044482353483518
+$div_scale = 20;
+#62.5:12.5:26447206647554886213592.3959144
+$div_scale = 40;
 &fneg
 fnegNaN:NaN
 +inf:-inf
index 2b4f83a..a3c0131 100755 (executable)
@@ -26,7 +26,7 @@ BEGIN
     }
   print "# INC = @INC\n";
 
-  plan tests => 1592;
+  plan tests => 1601;
   }
 
 use Math::BigInt;
index 39f4c77..2bcf346 100644 (file)
@@ -164,7 +164,7 @@ while (<DATA>)
       }elsif ($f eq "bpow"){
         $try .= "\$x ** \$y;";
       }elsif ($f eq "digit"){
-        $try = "\$x = $class->new('$args[0]'); \$x->digit($args[1]);";
+        $try .= "\$x->digit(\$y);";
       } else { warn "Unknown op '$f'"; }
     } # end else all other ops
 
@@ -311,25 +311,25 @@ $x = Math::BigInt->new(0); if (!$x) { ok (1,1); } else { ok($x,'to be false') }
 
 @args = Math::BigInt::objectify(2,4,5);
 ok (scalar @args,3);           # $class, 4, 5
-ok ($args[0],$class);
+ok ($args[0] =~ /^Math::BigInt/);
 ok ($args[1],4);
 ok ($args[2],5);
 
 @args = Math::BigInt::objectify(0,4,5);
 ok (scalar @args,3);           # $class, 4, 5
-ok ($args[0],$class);
+ok ($args[0] =~ /^Math::BigInt/);
 ok ($args[1],4);
 ok ($args[2],5);
 
 @args = Math::BigInt::objectify(2,4,5);
 ok (scalar @args,3);           # $class, 4, 5
-ok ($args[0],$class);
+ok ($args[0] =~ /^Math::BigInt/);
 ok ($args[1],4);
 ok ($args[2],5);
 
 @args = Math::BigInt::objectify(2,4,5,6,7);
 ok (scalar @args,5);           # $class, 4, 5, 6, 7
-ok ($args[0],$class);
+ok ($args[0] =~ /^Math::BigInt/);
 ok ($args[1],4); ok (ref($args[1]),$args[0]);
 ok ($args[2],5); ok (ref($args[2]),$args[0]);
 ok ($args[3],6); ok (ref($args[3]),'');
@@ -446,6 +446,11 @@ if ($x > $BASE) { ok (1,1) } else { ok ("$x > $BASE","$x < $BASE"); }
 $x = $class->new($MAX); ok ($x->length(), length($MAX));
 
 ###############################################################################
+# test bug that $class->digit($string) did not work
+
+ok ($class->digit(123,2),1);
+
+###############################################################################
 # bug in sub where number with at least 6 trailing zeros after any op failed
 
 $x = $class->new(123456); $z = $class->new(10000); $z *= 10; $x -= $z;
@@ -490,6 +495,19 @@ $x = $class->new('-322056000'); ($x,$y) = $x->bdiv('-12882240');
 ok ($y,'0'); is_valid($y);     # $y not '-0'
 
 ###############################################################################
+# bone/binf etc as plain calls (Lite failed them)
+
+ok ($class->bzero(),0);
+ok ($class->bone(),1);
+ok ($class->bone('+'),1);
+ok ($class->bone('-'),-1);
+ok ($class->bnan(),'NaN');
+ok ($class->binf(),'inf');
+ok ($class->binf('+'),'inf');
+ok ($class->binf('-'),'-inf');
+ok ($class->binf('-inf'),'-inf');
+
+###############################################################################
 # all tests done
 
 1;
@@ -515,15 +533,20 @@ sub is_valid
   my ($x,$f) = @_;
 
   my $e = 0;                   # error?
-  # ok as reference? 
-  $e = 'Not a reference to Math::BigInt' if !ref($x);
 
-  # has ok sign?
-  $e = "Illegal sign $x->{sign} (expected: '+', '-', '-inf', '+inf' or 'NaN'"
-   if $e eq '0' && $x->{sign} !~ /^(\+|-|\+inf|-inf|NaN)$/;
+  # allow the check to pass for all Lite, and all MBI and subclasses
+  # ok as reference? 
+  $e = 'Not a reference to Math::BigInt' if ref($x) !~ /^Math::BigInt/;
 
-  $e = "-0 is invalid!" if $e ne '0' && $x->{sign} eq '-' && $x == 0;
-  $e = $CALC->_check($x->{value}) if $e eq '0';
+  if (ref($x) ne 'Math::BigInt::Lite')
+    {
+    # has ok sign?
+    $e = "Illegal sign $x->{sign} (expected: '+', '-', '-inf', '+inf' or 'NaN'"
+     if $e eq '0' && $x->{sign} !~ /^(\+|-|\+inf|-inf|NaN)$/;
+  
+    $e = "-0 is invalid!" if $e ne '0' && $x->{sign} eq '-' && $x == 0;
+    $e = $CALC->_check($x->{value}) if $e eq '0';
+    }
 
   # test done, see if error did crop up
   ok (1,1), return if ($e eq '0');
@@ -1029,6 +1052,26 @@ baddNaN:+inf:NaN
 -123456789:987654321:864197532
 -123456789:-987654321:-1111111110
 +123456789:-987654321:-864197532
+-1:10001:10000
+-1:100001:100000
+-1:1000001:1000000
+-1:10000001:10000000
+-1:100000001:100000000
+-1:1000000001:1000000000
+-1:10000000001:10000000000
+-1:100000000001:100000000000
+-1:1000000000001:1000000000000
+-1:10000000000001:10000000000000
+-1:-10001:-10002
+-1:-100001:-100002
+-1:-1000001:-1000002
+-1:-10000001:-10000002
+-1:-100000001:-100000002
+-1:-1000000001:-1000000002
+-1:-10000000001:-10000000002
+-1:-100000000001:-100000000002
+-1:-1000000000001:-1000000000002
+-1:-10000000000001:-10000000000002
 &bsub
 abc:abc:NaN
 abc:+0:NaN
@@ -1071,6 +1114,26 @@ abc:+0:NaN
 -123456789:+987654321:-1111111110
 -123456789:-987654321:864197532
 +123456789:-987654321:1111111110
+10001:1:10000
+100001:1:100000
+1000001:1:1000000
+10000001:1:10000000
+100000001:1:100000000
+1000000001:1:1000000000
+10000000001:1:10000000000
+100000000001:1:100000000000
+1000000000001:1:1000000000000
+10000000000001:1:10000000000000
+10001:-1:10002
+100001:-1:100002
+1000001:-1:1000002
+10000001:-1:10000002
+100000001:-1:100000002
+1000000001:-1:1000000002
+10000000001:-1:10000000002
+100000000001:-1:100000000002
+1000000000001:-1:1000000000002
+10000000000001:-1:10000000000002
 &bmul
 abc:abc:NaN
 abc:+0:NaN
index eca2d29..c14d441 100755 (executable)
@@ -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 => 2147;
+  plan tests => 2237;
   }
 
 use Math::BigInt;
index fc3e52f..db0c27e 100644 (file)
@@ -22,7 +22,7 @@ my $cfg = Math::BigInt->config();
 ok (ref($cfg),'HASH');
 
 ok ($cfg->{lib},'Math::BigInt::Calc');
-ok ($cfg->{lib_version},'0.25');
+ok ($cfg->{lib_version},'0.26');
 ok ($cfg->{class},'Math::BigInt');
 ok ($cfg->{upgrade}||'','');
 ok ($cfg->{div_scale},40);
index ef3e223..3c9b13f 100644 (file)
@@ -8,13 +8,24 @@ BEGIN
   $| = 1;
   chdir 't' if -d 't';
   unshift @INC, '../lib'; # for running manually
-  plan tests => 5;
+  plan tests => 7;
   } 
 
 use Math::BigInt ':constant';
 
 ok (2 ** 255,'57896044618658097711785492504343953926634992332820282019728792003956564819968');
 
+{
+    no warnings 'portable';
+    # hexadecimal constants
+    ok (0x123456789012345678901234567890,
+      Math::BigInt->new('0x123456789012345678901234567890'));
+    # binary constants
+    ok (0b01010100011001010110110001110011010010010110000101101101,
+      Math::BigInt->new(
+     '0b01010100011001010110110001110011010010010110000101101101'));
+}
+
 use Math::BigFloat ':constant';
 ok (1.0 / 3.0, '0.3333333333333333333333333333333333333333');
 
diff --git a/lib/Math/BigInt/t/mbi_rand.t b/lib/Math/BigInt/t/mbi_rand.t
new file mode 100644 (file)
index 0000000..1f19c6b
--- /dev/null
@@ -0,0 +1,56 @@
+#!/usr/bin/perl -w
+
+use Test;
+use strict;
+
+my $count;
+  
+BEGIN
+  {
+  $| = 1;
+  unshift @INC, '../lib'; # for running manually
+  my $location = $0; $location =~ s/mbi_rand.t//;
+  unshift @INC, $location; # to locate the testing files
+  chdir 't' if -d 't';
+  $count = 500;
+  plan tests => $count*2;
+  }
+
+use Math::BigInt;
+my $c = 'Math::BigInt';
+
+my $length = 200;
+
+# If you get a failure here, please re-run the test with the printed seed
+# value as input: perl t/mbi_rand.t seed
+
+my $seed = int(rand(65537)); print "# seed: $seed\n"; srand($seed);
+
+my ($A,$B,$ADB,$AMB,$la,$lb);
+for (my $i = 0; $i < $count; $i++)
+  {
+  # length of A and B
+  $la = int(rand($length)+1); $lb = int(rand($length)+1);
+  $A = ''; $B = '';
+  # we create the numbers from "patterns", e.g. get a random number and a
+  # random count and string them together. This means things like
+  # "100000999999999999911122222222" are much more likely. If we just strung
+  # together digits, we would end up with "1272398823211223" etc.
+  while (length($A) < $la) { $A .= int(rand(100)) x int(rand(16)); }
+  while (length($B) < $lb) { $B .= int(rand(100)) x int(rand(16)); }
+  $A = $c->new($A); $B = $c->new($B);
+  print "# A $A\n# B $B\n";
+  if ($A->is_zero() || $B->is_zero())
+    {
+    ok (1,1); ok (1,1); next;
+    }
+  # check that int(A/B)*B + A % B == A holds for all inputs
+  # $X = ($A/$B)*$B + 2 * ($A % $B) - ($A % $B);
+  ($ADB,$AMB) = $A->copy()->bdiv($B);
+  ok ($A,$ADB*$B+2*$AMB-$AMB);
+  # swap 'em and try this, too
+  # $X = ($B/$A)*$A + $B % $A;
+  ($ADB,$AMB) = $B->copy()->bdiv($A);
+  ok ($B,$ADB*$A+2*$AMB-$AMB);
+  }
+
index 3df9ce4..69a1ab9 100755 (executable)
@@ -26,7 +26,7 @@ BEGIN
     }
   print "# INC = @INC\n"; 
   
-  plan tests => 1592
+  plan tests => 1601
     + 6;       # + our own tests
   }
 
index c492592..95a0dae 100755 (executable)
@@ -26,7 +26,7 @@ BEGIN
     }
   print "# INC = @INC\n";
 
-  plan tests => 2147
+  plan tests => 2237
     + 5;       # +4 own tests
   }
 
index 26b3a65..bf35261 100644 (file)
@@ -725,9 +725,9 @@ baddNaN:+inf:NaN
 -123456789:987654321:864197532
 -123456789:-987654321:-1111111110
 +123456789:-987654321:-864197532
-#2:2.5:4.5^
-#-123:-1.5:-124.5^
-#-1.2:1:-0.2^
+2:2.5:4.5^
+-123:-1.5:-124.5^
+-1.2:1:-0.2^
 &bsub
 abc:abc:NaN
 abc:+0:NaN
index 534c99b..5c8cf5f 100644 (file)
@@ -10,7 +10,7 @@ BEGIN
   my $location = $0; $location =~ s/upgrade.t//;
   unshift @INC, $location; # to locate the testing files
   chdir 't' if -d 't';
-  plan tests => 2056
+  plan tests => 2068
    + 2;                        # our own tests
   }
 
diff --git a/lib/Math/BigInt/t/use_lib1.t b/lib/Math/BigInt/t/use_lib1.t
new file mode 100644 (file)
index 0000000..d737081
--- /dev/null
@@ -0,0 +1,24 @@
+#!/usr/bin/perl -w
+
+# see if using Math::BigInt and Math::BigFloat works together nicely.
+# all use_lib*.t should be equivalent
+
+use strict;
+use Test;
+
+BEGIN
+  {
+  $| = 1;
+  chdir 't' if -d 't';
+  unshift @INC, '../lib'; # for running manually
+  unshift @INC, 'lib';
+  print "# INC = @INC\n";
+  plan tests => 2;
+  } 
+
+use Math::BigFloat lib => 'BareCalc';
+
+ok (Math::BigInt->config()->{lib},'Math::BigInt::BareCalc');
+
+ok (Math::BigFloat->new(123)->badd(123),246);
+
diff --git a/lib/Math/BigInt/t/use_lib2.t b/lib/Math/BigInt/t/use_lib2.t
new file mode 100644 (file)
index 0000000..6dd744f
--- /dev/null
@@ -0,0 +1,24 @@
+#!/usr/bin/perl -w
+
+# see if using Math::BigInt and Math::BigFloat works together nicely.
+# all use_lib*.t should be equivalent
+
+use strict;
+use Test;
+
+BEGIN
+  {
+  $| = 1;
+  chdir 't' if -d 't';
+  unshift @INC, '../lib'; # for running manually
+  unshift @INC, 'lib';
+  plan tests => 2;
+  } 
+
+use Math::BigInt;
+use Math::BigFloat lib => 'BareCalc';
+
+ok (Math::BigInt->config()->{lib},'Math::BigInt::BareCalc');
+
+ok (Math::BigFloat->new(123)->badd(123),246);
+
diff --git a/lib/Math/BigInt/t/use_lib3.t b/lib/Math/BigInt/t/use_lib3.t
new file mode 100644 (file)
index 0000000..3b43544
--- /dev/null
@@ -0,0 +1,24 @@
+#!/usr/bin/perl -w
+
+# see if using Math::BigInt and Math::BigFloat works together nicely.
+# all use_lib*.t should be equivalent
+
+use strict;
+use Test;
+
+BEGIN
+  {
+  $| = 1;
+  chdir 't' if -d 't';
+  unshift @INC, '../lib'; # for running manually
+  unshift @INC, 'lib';
+  plan tests => 2;
+  } 
+
+use Math::BigInt lib => 'BareCalc';
+use Math::BigFloat;
+
+ok (Math::BigInt->config()->{lib},'Math::BigInt::BareCalc');
+
+ok (Math::BigFloat->new(123)->badd(123),246);
+
diff --git a/lib/Math/BigInt/t/use_lib4.t b/lib/Math/BigInt/t/use_lib4.t
new file mode 100644 (file)
index 0000000..079ba6d
--- /dev/null
@@ -0,0 +1,25 @@
+#!/usr/bin/perl -w
+
+# see if using Math::BigInt and Math::BigFloat works together nicely.
+# all use_lib*.t should be equivalent, except this, since the later overrides
+# the former lib statement
+
+use strict;
+use Test;
+
+BEGIN
+  {
+  $| = 1;
+  chdir 't' if -d 't';
+  unshift @INC, '../lib'; # for running manually
+  unshift @INC, 'lib';
+  plan tests => 2;
+  } 
+
+use Math::BigInt lib => 'BareCalc';
+use Math::BigFloat lib => 'Calc';
+
+ok (Math::BigInt->config()->{lib},'Math::BigInt::Calc');
+
+ok (Math::BigFloat->new(123)->badd(123),246);
+