This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Upgrade Math::BigInt from 1.999701 to 1.999704
authorSteve Hay <steve.m.hay@googlemail.com>
Thu, 15 Oct 2015 12:36:38 +0000 (13:36 +0100)
committerSteve Hay <steve.m.hay@googlemail.com>
Thu, 15 Oct 2015 16:44:57 +0000 (17:44 +0100)
This removes the minor blead customizations: I couldn't see any sign of
them having been deliberately added to blead. They looked more like
differences that cropped up because CPAN changes hadn't all been imported
into blead.

23 files changed:
MANIFEST
Porting/Maintainers.pl
cpan/Math-BigInt/lib/Math/BigFloat.pm
cpan/Math-BigInt/lib/Math/BigInt.pm
cpan/Math-BigInt/lib/Math/BigInt/Calc.pm
cpan/Math-BigInt/lib/Math/BigInt/CalcEmu.pm
cpan/Math-BigInt/t/bare_mbf.t
cpan/Math-BigInt/t/bare_mbi.t
cpan/Math-BigInt/t/bigfltpm.inc
cpan/Math-BigInt/t/bigfltpm.t
cpan/Math-BigInt/t/bigintpm.inc
cpan/Math-BigInt/t/bigintpm.t
cpan/Math-BigInt/t/biglog.t
cpan/Math-BigInt/t/bigroot.t
cpan/Math-BigInt/t/blog-mbf.t [new file with mode: 0644]
cpan/Math-BigInt/t/blog-mbi.t [new file with mode: 0644]
cpan/Math-BigInt/t/mbimbf.t
cpan/Math-BigInt/t/objectify_mbf.t [new file with mode: 0644]
cpan/Math-BigInt/t/objectify_mbi.t [new file with mode: 0644]
cpan/Math-BigInt/t/sub_mbf.t
cpan/Math-BigInt/t/sub_mbi.t
cpan/Math-BigInt/t/with_sub.t
t/porting/customized.dat

index fdb316a..f180060 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -1628,6 +1628,8 @@ cpan/Math-BigInt/t/bigints.t              See if BigInt.pm works
 cpan/Math-BigInt/t/biglog.t            Test the log function
 cpan/Math-BigInt/t/big_pi_e.t          test bpi() and bexp()
 cpan/Math-BigInt/t/bigroot.t           Test the broot function
+cpan/Math-BigInt/t/blog-mbf.t          Math::BigInt tests
+cpan/Math-BigInt/t/blog-mbi.t          Math::BigInt tests
 cpan/Math-BigInt/t/calling.t           Test calling conventions
 cpan/Math-BigInt/t/config.t            Test Math::BigInt->config()
 cpan/Math-BigInt/t/constant.t          Test Math::BigInt/BigFloat under :constant
@@ -1648,6 +1650,8 @@ cpan/Math-BigInt/t/mbimbf.t               BigInt/BigFloat accuracy, precision and fallback, r
 cpan/Math-BigInt/t/mbi_rand.t          Test Math::BigInt randomly
 cpan/Math-BigInt/t/nan_cmp.t           overloaded comparison involving *NaN*
 cpan/Math-BigInt/t/new_overloaded.t    test overloaded numbers in BigFloat's new()
+cpan/Math-BigInt/t/objectify_mbf.t     Math::BigInt tests
+cpan/Math-BigInt/t/objectify_mbi.t     Math::BigInt tests
 cpan/Math-BigInt/t/req_mbf0.t          test: require Math::BigFloat; ->bzero();
 cpan/Math-BigInt/t/req_mbf1.t          test: require Math::BigFloat; ->bone();
 cpan/Math-BigInt/t/req_mbfa.t          test: require Math::BigFloat; ->bnan();
index d104609..dc9db30 100755 (executable)
@@ -719,7 +719,7 @@ use File::Glob qw(:case);
     },
 
     'Math::BigInt' => {
-        'DISTRIBUTION' => 'PJACKLAM/Math-BigInt-1.999701.tar.gz',
+        'DISTRIBUTION' => 'PJACKLAM/Math-BigInt-1.999704.tar.gz',
         'FILES'        => q[cpan/Math-BigInt],
         'EXCLUDED'     => [
             qr{^inc/},
@@ -730,13 +730,6 @@ use File::Glob qw(:case);
                 t/03podcov.t
                 ),
         ],
-        'CUSTOMIZED'   => [
-            qw( t/bigfltpm.t
-                t/bigintpm.inc
-                t/bigroot.t
-                t/mbimbf.t
-                ),
-        ],
     },
 
     'Math::BigInt::FastCalc' => {
index a423b35..97e8340 100644 (file)
@@ -12,7 +12,7 @@ package Math::BigFloat;
 #   _a : accuracy
 #   _p : precision
 
-$VERSION = '1.999701';
+$VERSION = '1.999704';
 require 5.006002;
 
 require Exporter;
@@ -860,19 +860,24 @@ sub blog
   {
   my ($self,$x,$base,$a,$p,$r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
 
+  # If called as $x -> blog() or $x -> blog(undef), don't objectify the
+  # undefined base, since undef signals that the base is Euler's number.
+  #unless (ref($x) && !defined($base)) {
+  #    # objectify is costly, so avoid it
+  #    if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) {
+  #        ($self,$x,$base,$a,$p,$r) = objectify(2,@_);
+  #    }
+  #}
+
   return $x if $x->modify('blog');
 
-  # $base > 0, $base != 1; if $base == undef default to $base == e
-  # $x >= 0
+  return $x -> bnan() if $x -> is_nan();
 
   # we need to limit the accuracy to protect against overflow
   my $fallback = 0;
   my ($scale,@params);
   ($x,@params) = $x->_find_round_parameters($a,$p,$r);
 
-  # also takes care of the "error in _find_round_parameters?" case
-  return $x->bnan() if $x->{sign} ne '+' || $x->is_zero();
-
   # no rounding at all, so must use fallback
   if (scalar @params == 0)
     {
@@ -890,28 +895,62 @@ sub blog
     $scale = abs($params[0] || $params[1]) + 4;        # take whatever is defined
     }
 
-  return $x->bzero(@params) if $x->is_one();
-  # base not defined => base == Euler's number e
-  if (defined $base)
-    {
-    # make object, since we don't feed it through objectify() to still get the
-    # case of $base == undef
-    $base = $self->new($base) unless ref($base);
-    # $base > 0; $base != 1
-    return $x->bnan() if $base->is_zero() || $base->is_one() ||
-      $base->{sign} ne '+';
-    # if $x == $base, we know the result must be 1.0
-    if ($x->bcmp($base) == 0)
-      {
-      $x->bone('+',@params);
-      if ($fallback)
-        {
+  my $done = 0;
+  if (defined $base) {
+      $base = $self -> new($base) unless ref $base;
+      if ($base -> is_nan() || $base -> is_one()) {
+          $x -> bnan();
+          $done = 1;
+      } elsif ($base -> is_inf() || $base -> is_zero()) {
+          if ($x -> is_inf() || $x -> is_zero()) {
+              $x -> bnan();
+          } else {
+              $x -> bzero(@params);
+          }
+          $done = 1;
+      } elsif ($base -> is_negative()) {        # -inf < base < 0
+          if ($x -> is_one()) {                 #     x = 1
+              $x -> bzero(@params);
+          } elsif ($x == $base) {
+              $x -> bone('+', @params);         #     x = base
+          } else {
+              $x -> bnan();                     #     otherwise
+          }
+          $done = 1;
+      } elsif ($x == $base) {
+          $x -> bone('+', @params);             # 0 < base && 0 < x < inf
+          $done = 1;
+      }
+  }
+
+  # We now know that the base is either undefined or positive and finite.
+
+  unless ($done) {
+      if ($x -> is_inf()) {             #   x = +/-inf
+          my $sign = defined $base && $base < 1 ? '-' : '+';
+          $x -> binf($sign);
+          $done = 1;
+      } elsif ($x -> is_neg()) {        #   -inf < x < 0
+          $x -> bnan();
+          $done = 1;
+      } elsif ($x -> is_one()) {        #   x = 1
+          $x -> bzero(@params);
+          $done = 1;
+      } elsif ($x -> is_zero()) {       #   x = 0
+          my $sign = defined $base && $base < 1 ? '+' : '-';
+          $x -> binf($sign);
+          $done = 1;
+      }
+  }
+
+  if ($done) {
+      if ($fallback) {
         # clear a/p after round, since user did not request it
-        delete $x->{_a}; delete $x->{_p};
+          delete $x->{_a};
+          delete $x->{_p};
         }
       return $x;
       }
-    }
 
   # when user set globals, they would interfere with our calculation, so
   # disable them and later re-enable them
@@ -933,7 +972,7 @@ sub blog
     $self = ref($x);
     }
   
-  my $done = 0;
+  $done = 0;
 
   # If the base is defined and an integer, try to calculate integer result
   # first. This is very fast, and in case the real result was found, we can
@@ -4396,6 +4435,24 @@ Multiply $x by $y, and then add $z to the result.
 
 This method was added in v1.87 of Math::BigInt (June 2007).
 
+=item as_float()
+
+This method is called when Math::BigFloat encounters an object it doesn't know
+how to handle. For instance, assume $x is a Math::BigFloat, or subclass
+thereof, and $y is defined, but not a Math::BigFloat, or subclass thereof. If
+you do
+
+    $x -> badd($y);
+
+$y needs to be converted into an object that $x can deal with. This is done by
+first checking if $y is something that $x might be upgraded to. If that is the
+case, no further attempts are made. The next is to see if $y supports the
+method C<as_float()>. The method C<as_float()> is expected to return either an
+object that has the same class as $x, a subclass thereof, or a string that
+C<ref($x)-E<gt>new()> can parse to create an object.
+
+In Math::BigFloat, C<as_float()> has the same effect as C<copy()>.
+
 =back
 
 =head1 Autocreating constants
index d990272..e902655 100644 (file)
@@ -18,7 +18,7 @@ package Math::BigInt;
 my $class = "Math::BigInt";
 use 5.006002;
 
-$VERSION = '1.999701';
+$VERSION = '1.999704';
 
 @ISA = qw(Exporter);
 @EXPORT_OK = qw(objectify bgcd blcm); 
@@ -94,7 +94,7 @@ use overload
 #'oct' =>      sub { print "oct"; $_[0]; }, 
 
 # log(N) is log(N, e), where e is Euler's number
-'log'  =>      sub { $_[0]->copy()->blog($_[1], undef); }, 
+'log'  =>      sub { $_[0]->copy()->blog(); }, 
 'exp'  =>      sub { $_[0]->copy()->bexp($_[1]); }, 
 'int'  =>      sub { $_[0]->copy(); }, 
 'neg'  =>      sub { $_[0]->copy()->bneg(); }, 
@@ -1277,27 +1277,52 @@ sub bdec
 
 sub blog
   {
-  # calculate $x = $a ** $base + $b and return $a (e.g. the log() to base
-  # $base of $x)
+  # Return the logarithm of the operand. If a second operand is defined, that
+  # value is used as the base, otherwise the base is assumed to be Euler's
+  # constant.
+
+  # Don't objectify the base, since an undefined base, as in $x->blog() or
+  # $x->blog(undef) signals that the base is Euler's number.
 
   # set up parameters
   my ($self,$x,$base,@r) = (undef,@_);
   # objectify is costly, so avoid it
-  if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
-    {
-    ($self,$x,$base,@r) = objectify(2,@_);
-    }
+  if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) {
+      ($self,$x,$base,@r) = objectify(1,@_);
+  }
 
   return $x if $x->modify('blog');
 
-  $base = $self->new($base) if defined $base && !ref $base;
+  # Handle all exception cases and all trivial cases. I have used Wolfram Alpha
+  # (http://www.wolframalpha.com) as the reference for these cases.
+
+  return $x -> bnan() if $x -> is_nan();
+
+  if (defined $base) {
+      $base = $self -> new($base) unless ref $base;
+      if ($base -> is_nan() || $base -> is_one()) {
+          return $x -> bnan();
+      } elsif ($base -> is_inf() || $base -> is_zero()) {
+          return $x -> bnan() if $x -> is_inf() || $x -> is_zero();
+          return $x -> bzero();
+      } elsif ($base -> is_negative()) {            # -inf < base < 0
+          return $x -> bzero() if $x -> is_one();   #     x = 1
+          return $x -> bone()  if $x == $base;      #     x = base
+          return $x -> bnan();                      #     otherwise
+      }
+      return $x -> bone() if $x == $base;           # 0 < base && 0 < x < inf
+  }
 
-  # inf, -inf, NaN, <0 => NaN
-  return $x->bnan()
-   if $x->{sign} ne '+' || (defined $base && $base->{sign} ne '+');
+  # We now know that the base is either undefined or >= 2 and finite.
 
-  return $upgrade->blog($upgrade->new($x),$base,@r) if 
-    defined $upgrade;
+  return $x -> binf('+') if $x -> is_inf();         #   x = +/-inf
+  return $x -> bnan()    if $x -> is_neg();         #   -inf < x < 0
+  return $x -> bzero()   if $x -> is_one();         #   x = 1
+  return $x -> binf('-') if $x -> is_zero();        #   x = 0
+
+  # At this point we are done handling all exception cases and trivial cases.
+
+  return $upgrade -> blog($upgrade -> new($x), $base, @r) if defined $upgrade;
 
   # fix for bug #24969:
   # the default base is e (Euler's number) which is not an integer
@@ -1312,7 +1337,7 @@ sub blog
     }
 
   my ($rc,$exact) = $CALC->_log_int($x->{value},$base->{value});
-  return $x->bnan() unless defined $rc;                # not possible to take log?
+  return $x->bnan() unless defined $rc;         # not possible to take log?
   $x->{value} = $rc;
   $x->round(@r);
   }
@@ -2801,9 +2826,7 @@ sub objectify {
 
         # If it is an object of the right class, all is fine.
 
-        if ($ref -> isa($a[0])) {
-            next;
-        }
+        next if $ref -> isa($a[0]);
 
         # Upgrading is OK, so skip further tests if the argument is upgraded.
 
@@ -2811,27 +2834,44 @@ sub objectify {
             next;
         }
 
-        # If we want a Math::BigInt, see if the object can become one.
-        # Support the old misnomer as_number().
+        # See if we can call one of the as_xxx() methods. We don't know whether
+        # the as_xxx() method returns an object or a scalar, so re-check
+        # afterwards.
 
-        if ($a[0] eq 'Math::BigInt') {
+        my $recheck = 0;
+
+        if ($a[0] -> isa('Math::BigInt')) {
             if ($a[$i] -> can('as_int')) {
                 $a[$i] = $a[$i] -> as_int();
-                next;
-            }
-            if ($a[$i] -> can('as_number')) {
+                $recheck = 1;
+            } elsif ($a[$i] -> can('as_number')) {
                 $a[$i] = $a[$i] -> as_number();
-                next;
+                $recheck = 1;
             }
         }
 
-        # If we want a Math::BigFloat, see if the object can become one.
-
-        if ($a[0] eq 'Math::BigFloat') {
+        elsif ($a[0] -> isa('Math::BigFloat')) {
             if ($a[$i] -> can('as_float')) {
                 $a[$i] = $a[$i] -> as_float();
+                $recheck = $1;
+            }
+        }
+
+        # If we called one of the as_xxx() methods, recheck.
+
+        if ($recheck) {
+            $ref = ref($a[$i]);
+
+            # Perl scalars are fed to the appropriate constructor.
+
+            unless ($ref) {
+                $a[$i] = $a[0] -> new($a[$i]);
                 next;
             }
+
+            # If it is an object of the right class, all is fine.
+
+            next if $ref -> isa($a[0]);
         }
 
         # Last resort.
@@ -4326,15 +4366,29 @@ Return the signed mantissa of $x as BigInt.
 
     $x->copy();                # make a true copy of $x (unlike $y = $x;)
 
-=item as_int()/as_number()
+=item as_int()
+
+=item as_number()
+
+These methods are called when Math::BigInt encounters an object it doesn't know
+how to handle. For instance, assume $x is a Math::BigInt, or subclass thereof,
+and $y is defined, but not a Math::BigInt, or subclass thereof. If you do
+
+    $x -> badd($y);
 
-    $x->as_int();
+$y needs to be converted into an object that $x can deal with. This is done by
+first checking if $y is something that $x might be upgraded to. If that is the
+case, no further attempts are made. The next is to see if $y supports the
+method C<as_int()>. If it does, C<as_int()> is called, but if it doesn't, the
+next thing is to see if $y supports the method C<as_number()>. If it does,
+C<as_number()> is called. The method C<as_int()> (and C<as_number()>) is
+expected to return either an object that has the same class as $x, a subclass
+thereof, or a string that C<ref($x)-E<gt>new()> can parse to create an object.
 
-Returns $x as a BigInt (truncated towards zero). In BigInt this is the same as
-C<copy()>.
+C<as_number()> is an alias to C<as_int()>. C<as_number> was introduced in
+v1.22, while C<as_int()> was introduced in v1.68.
 
-C<as_number()> is an alias to this method. C<as_number> was introduced in
-v1.22, while C<as_int()> was only introduced in v1.68.
+In Math::BigInt, C<as_int()> has the same effect as C<copy()>.
 
 =item bstr()
 
@@ -4365,7 +4419,7 @@ Returns a normalized string representation of C<$x>.
 This returns a normal Perl scalar from $x. It is used automatically
 whenever a scalar is needed, for instance in array index operations.
 
-This loses precision, to avoid this use L<as_int()|/"as_int()/as_number()"> instead.
+This loses precision, to avoid this use L</as_int()> instead.
 
 =item modify()
 
@@ -5390,43 +5444,34 @@ This makes a copy of $x and takes O(N), but $x->bneg() is O(1).
 
 =item Mixing different object types
 
-In Perl you will get a floating point value if you do one of the following:
-
-       $float = 5.0 + 2;
-       $float = 2 + 5.0;
-       $float = 5 / 2;
-
-With overloaded math, only the first two variants will result in a BigFloat:
+With overloaded operators, it is the first (dominating) operand that determines
+which method is called. Here are some examples showing what actually gets
+called in various cases.
 
        use Math::BigInt;
        use Math::BigFloat;
 
-       $mbf = Math::BigFloat->new(5);
-       $mbi2 = Math::BigInteger->new(5);
-       $mbi = Math::BigInteger->new(2);
-
+       $mbf  = Math::BigFloat->new(5);
+       $mbi2 = Math::BigInt->new(5);
+       $mbi  = Math::BigInt->new(2);
                                        # what actually gets called:
-       $float = $mbf + $mbi;           # $mbf->badd()
-       $float = $mbf / $mbi;           # $mbf->bdiv()
-       $integer = $mbi + $mbf;         # $mbi->badd()
-       $integer = $mbi2 / $mbi;        # $mbi2->bdiv()
-       $integer = $mbi2 / $mbf;        # $mbi2->bdiv()
-
-This is because math with overloaded operators follows the first (dominating)
-operand, and the operation of that is called and returns thus the result. So,
-Math::BigInt::bdiv() will always return a Math::BigInt, regardless whether
-the result should be a Math::BigFloat or the second operant is one.
+        $float = $mbf + $mbi;           # $mbf->badd($mbi)
+        $float = $mbf / $mbi;           # $mbf->bdiv($mbi)
+        $integer = $mbi + $mbf;         # $mbi->badd($mbf)
+        $integer = $mbi2 / $mbi;        # $mbi2->bdiv($mbi)
+        $integer = $mbi2 / $mbf;        # $mbi2->bdiv($mbf)
 
-To get a Math::BigFloat you either need to call the operation manually,
-make sure the operands are already of the proper type or casted to that type
-via Math::BigFloat->new():
+For instance, Math::BigInt->bdiv() will always return a Math::BigInt, regardless of
+whether the second operant is a Math::BigFloat. To get a Math::BigFloat you
+either need to call the operation manually, make sure each operand already is a
+Math::BigFloat, or cast to that type via Math::BigFloat->new():
 
        $float = Math::BigFloat->new($mbi2) / $mbi;     # = 2.5
 
-Beware of simple "casting" the entire expression, this would only convert
-the already computed result:
+Beware of casting the entire expression, as this would cast the
+result, at which point it is too late:
 
-       $float = Math::BigFloat->new($mbi2 / $mbi);     # = 2.0 thus wrong!
+       $float = Math::BigFloat->new($mbi2 / $mbi);     # = 2
 
 Beware also of the order of more complicated expressions like:
 
index ce9bf3a..3776d00 100644 (file)
@@ -4,7 +4,7 @@ use 5.006002;
 use strict;
 # use warnings;        # do not use warnings for older Perls
 
-our $VERSION = '1.999701';
+our $VERSION = '1.999704';
 
 # Package to store unsigned big integers in decimal and do math with them
 
index 0ff9dcc..94cccb5 100644 (file)
@@ -5,7 +5,7 @@ use strict;
 # use warnings;        # do not use warnings for older Perls
 use vars qw/$VERSION/;
 
-$VERSION = '1.999701';
+$VERSION = '1.999704';
 
 package Math::BigInt;
 
index 69dcc80..6eeefa7 100644 (file)
@@ -1,7 +1,7 @@
 #!/usr/bin/perl -w
 
 use strict;
-use Test::More tests => 2340;
+use Test::More tests => 2360;
 
 BEGIN { unshift @INC, 't'; }
 
index 8aedf43..bc22156 100644 (file)
@@ -1,7 +1,7 @@
 #!/usr/bin/perl -w
 
 use strict;
-use Test::More tests => 3649;
+use Test::More tests => 3701;
 
 BEGIN { unshift @INC, 't'; }
 
index 3eb2e21..bbfca4e 100644 (file)
@@ -60,6 +60,9 @@ while (<DATA>)
       # some unary ops (test the fxxx form, since that is done by AUTOLOAD)
       } elsif ($f =~ /^f(nan|sstr|neg|floor|ceil|int|abs)$/) {
         $try .= "\$x->f$1();";
+      # overloaded functions
+      } elsif ($f =~ /^(log|exp|sin|cos|atan2|int|neg|abs|sqrt)$/) {
+        $try .= "\$x = $f(\$x);";
       # some is_xxx test function      
       } elsif ($f =~ /^is_(zero|one|negative|positive|odd|even|nan|int)$/) {
         $try .= "\$x->$f();";
@@ -499,16 +502,16 @@ NaN:1:NaN
 7:0:1
 2:1:2
 &flog
-0::NaN
+0::-inf
 -1::NaN
 -2::NaN
 # base > 0, base != 1
 2:-1:NaN
-2:0:NaN
+2:0:0
 2:1:NaN
-# log(1) is always 1, regardless of $base
+# log(1)
 1::0
-1:1:0
+1:1:NaN
 1:2:0
 2::0.6931471805599453094172321214581765680755
 2.718281828::0.9999999998311266953289851340574956564911
@@ -1834,3 +1837,23 @@ NaN:NaN
 -51.2:-51
 12.2:12
 -0.4:0
+# overloaded functions
+&log
+-1:NaN
+0:-inf
+1:0
+2:0.6931471805599453094172321214581765680755
+3:1.098612288668109691395245236922525704647
+123456789:18.63140176616801803319393334796320420971
+1234567890987654321:41.657252696908474880343847955484513481
+-inf:inf
+inf:inf
+NaN:NaN
+&exp
+&sin
+&cos
+&atan2
+&int
+&neg
+&abs
+&sqrt
index 8653f77..53006e7 100644 (file)
@@ -1,7 +1,7 @@
 #!/usr/bin/perl -w
 
 use strict;
-use Test::More tests => 2340
+use Test::More tests => 2360
     + 5;               # own tests
 
 
@@ -24,6 +24,11 @@ $c = Math::BigFloat->new('0.008'); my $d = Math::BigFloat->new(3);
 my $e = $c->bdiv(Math::BigFloat->new(3),$d);
 
 is ($e,'0.00267'); # '0.008 / 3 => 0.0027');
-is (ref($e->{_e}->[0]), ''); # 'Not a BigInt');
+
+SKIP: {
+    skip("skipping test which is not for this backend", 1)
+      unless $CL eq 'Math::BigInt::Calc';
+    is (ref($e->{_e}->[0]), '');  # 'Not a BigInt');
+}
 
 require 't/bigfltpm.inc';      # all tests here for sharing
index 08a98ac..0b8206e 100644 (file)
@@ -75,6 +75,9 @@ while (<DATA>)
   # some unary ops
    } elsif ($f =~ /^b(nan|floor|ceil|int|sstr|neg|abs|sgn|inc|dec|not|sqrt|fac)$/) {
     $try .= "\$x->$f();";
+  # overloaded functions
+   } elsif ($f =~ /^(log|exp|sin|cos|atan2|int|neg|abs|sqrt)$/) {
+    $try .= "\$x = $f(\$x);";
    } elsif ($f =~ /^(numify|length|stringify|as_hex|as_bin)$/) {
     $try .= "\$x->$f();";
    } elsif ($f eq "exponent"){
@@ -549,140 +552,144 @@ SKIP: {
 # the following tests only make sense with Math::BigInt::Calc or BareCalc or
 # FastCalc
 
-exit if $CALC !~ /^Math::BigInt::(|Bare|Fast)Calc$/; # for Pari et al.
-
-###############################################################################
-# check proper length of internal arrays
-
-my $bl = $CL->_base_len();
-my $BASE = '9' x $bl;
-my $MAX = $BASE;
-$BASE++;
-
-$x = $class->new($MAX); is_valid($x);  # f.i. 9999
-$x += 1; is ($x,$BASE); is_valid($x);  # 10000
-$x -= 1; is ($x,$MAX); is_valid($x);   # 9999 again
-
-###############################################################################
-# check numify
-
-$x = $class->new($BASE-1);     is ($x->numify(),$BASE-1); 
-$x = $class->new(-($BASE-1));  is ($x->numify(),-($BASE-1)); 
-
-# +0 is to protect from 1e15 vs 100000000 (stupid to_string aaaarglburblll...)
-$x = $class->new($BASE);       is ($x->numify()+0,$BASE+0);    
-$x = $class->new(-$BASE);      is ($x->numify(),-$BASE);
-$x = $class->new( -($BASE*$BASE*1+$BASE*1+1) ); 
-is ($x->numify(),-($BASE*$BASE*1+$BASE*1+1));
-
-###############################################################################
-# test bug in _digits with length($c[-1]) where $c[-1] was "00001" instead of 1
+SKIP: {
+    # skip GMP, Pari et al.
+    skip("skipping tests not intended for the backend $CALC", 50)
+      unless $CALC =~ /^Math::BigInt::(Bare|Fast)?Calc$/;
 
-$x = $class->new($BASE-2); $x++; $x++; $x++; $x++;
-if ($x > $BASE) { is (1,1) } else { is ("$x < $BASE","$x > $BASE"); }
+    ###########################################################################
+    # check proper length of internal arrays
 
-$x = $class->new($BASE+3); $x++;
-if ($x > $BASE) { is (1,1) } else { is ("$x > $BASE","$x < $BASE"); }
+    my $bl = $CL->_base_len();
+    my $BASE = '9' x $bl;
+    my $MAX = $BASE;
+    $BASE++;
 
-# test for +0 instead of int(): 
-$x = $class->new($MAX); is ($x->length(), length($MAX));
+    $x = $class->new($MAX); is_valid($x);      # f.i. 9999
+    $x += 1; is ($x,$BASE); is_valid($x);      # 10000
+    $x -= 1; is ($x,$MAX); is_valid($x);       # 9999 again
 
-###############################################################################
-# test bug that $class->digit($string) did not work
+    ###########################################################################
+    # check numify
 
-is ($class->digit(123,2),1);
+    $x = $class->new($BASE-1);     is ($x->numify(),$BASE-1); 
+    $x = $class->new(-($BASE-1));  is ($x->numify(),-($BASE-1)); 
 
-###############################################################################
-# bug in sub where number with at least 6 trailing zeros after any op failed
+    # +0 is to protect from 1e15 vs 100000000 (stupid to_string aaaarglburblll...)
+    $x = $class->new($BASE);       is ($x->numify()+0,$BASE+0);        
+    $x = $class->new(-$BASE);      is ($x->numify(),-$BASE);
+    $x = $class->new( -($BASE*$BASE*1+$BASE*1+1) ); 
+    is ($x->numify(),-($BASE*$BASE*1+$BASE*1+1));
 
-$x = $class->new(123456); $z = $class->new(10000); $z *= 10; $x -= $z;
-is ($z, 100000);
-is ($x, 23456);
+    ###########################################################################
+    # test bug in _digits with length($c[-1]) where $c[-1] was "00001" instead of 1
 
-###############################################################################
-# bug in shortcut in mul()
-
-# construct a number with a zero-hole of BASE_LEN_SMALL
-{
- my @bl = $CL->_base_len(); my $bl = $bl[5];
-
- $x = '1' x $bl . '0' x $bl . '1' x $bl . '0' x $bl;
- $y = '1' x (2*$bl);
- $x = $class->new($x)->bmul($y);
- # result is 123..$bl .  $bl x (3*bl-1) . $bl...321 . '0' x $bl
- $y = ''; my $d = '';
- for (my $i = 1; $i <= $bl; $i++)
-   {
-   $y .= $i; $d = $i.$d;
-   }
- $y .= $bl x (3*$bl-1) . $d . '0' x $bl;
- is ($x,$y);
-
-
-  #############################################################################
-  # see if mul shortcut for small numbers works
-
-  $x = '9' x $bl;
-  $x = $class->new($x); 
-  # 999 * 999 => 998 . 001, 9999*9999 => 9998 . 0001
-  is ($x*$x, '9' x ($bl-1) . '8' . '0' x ($bl-1) . '1');
-}
+    $x = $class->new($BASE-2); $x++; $x++; $x++; $x++;
+    if ($x > $BASE) { is (1,1) } else { is ("$x < $BASE","$x > $BASE"); }
 
-###############################################################################
-# bug with rest "-0" in div, causing further div()s to fail
+    $x = $class->new($BASE+3); $x++;
+    if ($x > $BASE) { is (1,1) } else { is ("$x > $BASE","$x < $BASE"); }
 
-$x = $class->new('-322056000'); ($x,$y) = $x->bdiv('-12882240');
+    # test for +0 instead of int(): 
+    $x = $class->new($MAX); is ($x->length(), length($MAX));
 
-is ($y,'0'); is_valid($y);     # $y not '-0'
+    ###########################################################################
+    # test bug that $class->digit($string) did not work
 
-###############################################################################
-# bug in $x->bmod($y)
+    is ($class->digit(123,2),1);
 
-# if $x < 0 and $y > 0
-$x = $class->new('-629'); is ($x->bmod(5033),4404);
+    ###########################################################################
+    # bug in sub where number with at least 6 trailing zeros after any op failed
 
-###############################################################################
-# bone/binf etc as plain calls (Lite failed them)
-
-is ($class->bzero(),0);
-is ($class->bone(),1);
-is ($class->bone('+'),1);
-is ($class->bone('-'),-1);
-is ($class->bnan(),'NaN');
-is ($class->binf(),'inf');
-is ($class->binf('+'),'inf');
-is ($class->binf('-'),'-inf');
-is ($class->binf('-inf'),'-inf');
+    $x = $class->new(123456); $z = $class->new(10000); $z *= 10; $x -= $z;
+    is ($z, 100000);
+    is ($x, 23456);
 
-###############################################################################
-# is_one('-')
+    ###########################################################################
+    # bug in shortcut in mul()
 
-is ($class->new(1)->is_one('-'),0);
-is ($class->new(-1)->is_one('-'),1);
-is ($class->new(1)->is_one(),1);
-is ($class->new(-1)->is_one(),0);
+    # construct a number with a zero-hole of BASE_LEN_SMALL
+    {
+     my @bl = $CL->_base_len(); my $bl = $bl[5];
+
+     $x = '1' x $bl . '0' x $bl . '1' x $bl . '0' x $bl;
+     $y = '1' x (2*$bl);
+     $x = $class->new($x)->bmul($y);
+     # result is 123..$bl .  $bl x (3*bl-1) . $bl...321 . '0' x $bl
+     $y = ''; my $d = '';
+     for (my $i = 1; $i <= $bl; $i++)
+       {
+       $y .= $i; $d = $i.$d;
+       }
+     $y .= $bl x (3*$bl-1) . $d . '0' x $bl;
+     is ($x,$y);
+
+
+      #########################################################################
+      # see if mul shortcut for small numbers works
+
+      $x = '9' x $bl;
+      $x = $class->new($x); 
+      # 999 * 999 => 998 . 001, 9999*9999 => 9998 . 0001
+      is ($x*$x, '9' x ($bl-1) . '8' . '0' x ($bl-1) . '1');
+    }
 
-###############################################################################
-# [perl #30609] bug with $x -= $x not being 0, but 2*$x
-
-$x = $class->new(3);  $x -= $x; is ($x, 0);
-$x = $class->new(-3); $x -= $x; is ($x, 0);
-$x = $class->new('NaN'); $x -= $x; is ($x->is_nan(), 1);
-$x = $class->new('inf'); $x -= $x; is ($x->is_nan(), 1);
-$x = $class->new('-inf'); $x -= $x; is ($x->is_nan(), 1);
-
-$x = $class->new('NaN'); $x += $x; is ($x->is_nan(), 1);
-$x = $class->new('inf'); $x += $x; is ($x->is_inf(), 1);
-$x = $class->new('-inf'); $x += $x; is ($x->is_inf('-'), 1);
-$x = $class->new(3);  $x += $x; is ($x, 6);
-$x = $class->new(-3); $x += $x; is ($x, -6);
-
-$x = $class->new(3);  $x *= $x; is ($x, 9);
-$x = $class->new(-3); $x *= $x; is ($x, 9);
-$x = $class->new(3);  $x /= $x; is ($x, 1);
-$x = $class->new(-3); $x /= $x; is ($x, 1);
-$x = $class->new(3);  $x %= $x; is ($x, 0);
-$x = $class->new(-3); $x %= $x; is ($x, 0);
+    ###########################################################################
+    # bug with rest "-0" in div, causing further div()s to fail
+
+    $x = $class->new('-322056000'); ($x,$y) = $x->bdiv('-12882240');
+
+    is ($y,'0'); is_valid($y); # $y not '-0'
+
+    ###########################################################################
+    # bug in $x->bmod($y)
+
+    # if $x < 0 and $y > 0
+    $x = $class->new('-629'); is ($x->bmod(5033),4404);
+
+    ###########################################################################
+    # bone/binf etc as plain calls (Lite failed them)
+
+    is ($class->bzero(),0);
+    is ($class->bone(),1);
+    is ($class->bone('+'),1);
+    is ($class->bone('-'),-1);
+    is ($class->bnan(),'NaN');
+    is ($class->binf(),'inf');
+    is ($class->binf('+'),'inf');
+    is ($class->binf('-'),'-inf');
+    is ($class->binf('-inf'),'-inf');
+
+    ###########################################################################
+    # is_one('-')
+
+    is ($class->new(1)->is_one('-'),0);
+    is ($class->new(-1)->is_one('-'),1);
+    is ($class->new(1)->is_one(),1);
+    is ($class->new(-1)->is_one(),0);
+
+    ###########################################################################
+    # [perl #30609] bug with $x -= $x not being 0, but 2*$x
+
+    $x = $class->new(3);  $x -= $x; is ($x, 0);
+    $x = $class->new(-3); $x -= $x; is ($x, 0);
+    $x = $class->new('NaN'); $x -= $x; is ($x->is_nan(), 1);
+    $x = $class->new('inf'); $x -= $x; is ($x->is_nan(), 1);
+    $x = $class->new('-inf'); $x -= $x; is ($x->is_nan(), 1);
+
+    $x = $class->new('NaN'); $x += $x; is ($x->is_nan(), 1);
+    $x = $class->new('inf'); $x += $x; is ($x->is_inf(), 1);
+    $x = $class->new('-inf'); $x += $x; is ($x->is_inf('-'), 1);
+    $x = $class->new(3);  $x += $x; is ($x, 6);
+    $x = $class->new(-3); $x += $x; is ($x, -6);
+
+    $x = $class->new(3);  $x *= $x; is ($x, 9);
+    $x = $class->new(-3); $x *= $x; is ($x, 9);
+    $x = $class->new(3);  $x /= $x; is ($x, 1);
+    $x = $class->new(-3); $x /= $x; is ($x, 1);
+    $x = $class->new(3);  $x %= $x; is ($x, 0);
+    $x = $class->new(-3); $x %= $x; is ($x, 0);
+}
 
 ###############################################################################
 # all tests done
@@ -745,18 +752,40 @@ __DATA__
 &^=
 5:7:2
 &blog
+#
 NaNlog:2:NaN
 122:NaNlog:NaN
 NaNlog1:NaNlog:NaN
-122:inf:NaN
-inf:122:NaN
-122:-inf:NaN
--inf:122:NaN
+#
+122:inf:0
+inf:122:inf
+122:-inf:0
+-inf:122:inf
 -inf:-inf:NaN
-inf:inf:NaN
-0:4:NaN
+0:4:-inf
 -21:4:NaN
 21:-21:NaN
+#
+0:-inf:NaN
+0:-1:NaN
+0:0:NaN
+0:1:NaN
+0:inf:NaN
+#
+1:-inf:0
+1:-1:0
+1:0:0
+1:1:NaN
+1:4:0
+1:inf:0
+#
+inf:-inf:NaN
+inf:-1:NaN
+inf:0:NaN
+inf:1:NaN
+inf:4:inf
+inf:inf:NaN
+#
 # normal results
 1024:2:10
 81:3:4
@@ -764,6 +793,7 @@ inf:inf:NaN
 82:3:4
 # 3.9... truncate
 80:3:3
+4096:2:12
 15625:5:6
 15626:5:6
 15624:5:5
@@ -781,7 +811,6 @@ inf:inf:NaN
 144115188075855872:2:57
 288230376151711744:2:58
 576460752303423488:2:59
-4096:2:12
 1329227995784915872903807060280344576:2:120
 # $x == $base => result 1
 3:3:1
@@ -2705,3 +2734,23 @@ NaNas_hex:NaN
 +inf:inf
 -inf:-inf
 NaNas_bin:NaN
+# overloaded functions
+&log
+-1:NaN
+0:-inf
+1:0
+2:0
+3:1
+123456789:18
+1234567890987654321:41
+-inf:inf
+inf:inf
+NaN:NaN
+&exp
+&sin
+&cos
+&atan2
+&int
+&neg
+&abs
+&sqrt
index a03710e..b641ada 100644 (file)
@@ -1,7 +1,7 @@
 #!/usr/bin/perl -w
 
 use strict;
-use Test::More tests => 3649 + 6;
+use Test::More tests => 3701 + 6;
 
 use Math::BigInt lib => 'Calc';
 
index 7c3b618..94e8f73 100644 (file)
@@ -20,14 +20,14 @@ use Math::BigInt;
 my $cl = "Math::BigInt";
 
 #############################################################################
-# test log($n) in BigInt (broken until 1.80)
+# test $n->blog() in BigInt (broken until 1.80)
 
 is ($cl->new(2)->blog(), '0', "blog(2)");
 is ($cl->new(288)->blog(), '5',"blog(288)");
 is ($cl->new(2000)->blog(), '7', "blog(2000)");
 
 #############################################################################
-# test exp($n) in BigInt
+# test $n->bexp() in BigInt
 
 is ($cl->new(1)->bexp(), '2', "bexp(1)");
 is ($cl->new(2)->bexp(), '7',"bexp(2)");
@@ -38,7 +38,7 @@ is ($cl->new(3)->bexp(), '20', "bexp(3)");
 # BigFloat tests
 
 #############################################################################
-# test log(2, N) where N > 67 (broken until 1.82)
+# test $n->blog(undef, N) where N > 67 (broken until 1.82)
 
 $cl = "Math::BigFloat";
 
index c90d5ae..81532f9 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl -w
+#!perl
 
 # Test broot function (and bsqrt() function, since it is used by broot()).
 
@@ -8,7 +8,9 @@
 # But it is better to test the numerical functionality, instead of not testing
 # it at all.
 
-use strict;
+use strict;             # restrict unsafe constructs
+use warnings;           # enable optional warnings
+
 use Test::More tests => 4 * 2;
 
 use Math::BigFloat;
diff --git a/cpan/Math-BigInt/t/blog-mbf.t b/cpan/Math-BigInt/t/blog-mbf.t
new file mode 100644 (file)
index 0000000..ec9e272
--- /dev/null
@@ -0,0 +1,264 @@
+#!perl
+
+BEGIN {
+    unless ($ENV{AUTHOR_TESTING}) {
+        require Test::More;
+        Test::More::plan(skip_all => 'these tests are for release candidate testing');
+    }
+}
+
+use strict;
+use warnings;
+
+use Test::More tests => 139;
+use Scalar::Util qw< refaddr >;
+
+my $class;
+
+BEGIN { $class = 'Math::BigFloat'; }
+BEGIN { use_ok($class) }
+
+while (<DATA>) {
+    s/\s+\z//;
+    next if /^#/ || ! /\S/;
+
+    # $in0 - the x value
+    # $in1 - the base
+    # $out0 - the wanted output value
+    # $type - the type of the wanted number (real, non-real, ...)
+    # $expr - mathematical expression of the wanted number
+
+    my ($in0, $in1, $out0, $type, $expr) = split /:/;
+
+    # Some of the test data use rational numbers.
+    # - with Math::BigInt, we skip them
+    # - with Math::BigFloat, we convert them to floats
+    # - with Math::BigRat, we use them as they are
+
+    $in0  = eval $in0  if $in0  =~ m|/|;
+    $in1  = eval $in1  if $in1  =~ m|/|;
+    $out0 = eval $out0 if $out0 =~ m|/|;
+
+    my ($x, $y);        # input values as objects
+    my ($yo);           # copy of input value
+    my ($got);          # test output
+
+    my $test = qq|\$x = $class -> new("$in0"); | .
+               qq|\$y = $class -> new("$in1"); | .
+               qq|\$yo = \$y -> copy(); | .
+               qq|\$got = \$x -> blog(\$y);|;
+
+    my $desc = "logarithm of $in0 to base $in1";
+
+    print("#\n",
+          "# Now about to execute the following test.\n",
+          "#\n",
+          "# $test\n",
+          "#\n");
+
+    if ($in0 ne 'NaN' && $in1 ne 'NaN') {
+        print("# Enter log($in1, $in0) into Wolfram Alpha",
+              " (http://www.wolframalpha.com/), and it says that the result",
+              " is ", length($type) ? $type : "real",
+              length($expr) ? ": $expr" : "",
+              ".", "\n",
+              "#\n");
+    }
+
+    eval $test;
+    die $@ if $@;       # this should never happen
+
+    subtest $desc, sub {
+        plan tests => 5,
+
+        # Check output.
+
+        is(ref($got), $class, "output arg is a $class");
+        is($got, $out0, 'output arg has the right value');
+        is(refaddr($got), refaddr($x), 'output arg is the invocand');
+
+        # The second argument (if the invocand is the first) shall *not* be
+        # modified.
+
+        is(ref($y), $class, "second input arg is still a $class");
+        is_deeply($y, $yo, 'second output arg is unmodified');
+
+    };
+
+}
+
+__END__
+
+# base = -inf
+
+-inf:-inf:NaN:undefined:
+-4:-inf:0::
+-2:-inf:0::
+-1:-inf:0::
+-1/2:-inf:0::
+0:-inf:NaN:undefined:
+1/2:-inf:0::
+1:-inf:0::
+2:-inf:0::
+4:-inf:0::
+inf:-inf:NaN:undefined:
+NaN:-inf:NaN:undefined:
+
+# base = -4
+
+-4:-4:1::
+-2:-4:NaN:non-real and finite:(log(2)+i pi)/(log(4)+i pi)
+0:-4:NaN:non-real (directed) infinity:(-sqrt(pi^2+log^2(4))/(log(4)+i pi))infinity
+1/2:-4:NaN:non-real and finite:-(log(2))/(log(4)+i pi)
+1:-4:0::
+2:-4:NaN:non-real and finite:(log(2))/(log(4)+i pi)
+4:-4:NaN:non-real and finite:(log(4))/(log(4)+i pi)
+NaN:-4:NaN:undefined:
+
+# base = -2
+
+-inf:-2:NaN:non-real (directed) infinity:sqrt(pi^2+log^2(2))/(log(2)+i pi)infinity
+-4:-2:NaN:non-real and finite:(log(4)+i pi)/(log(2)+i pi)
+-2:-2:1::
+-1:-2:NaN:non-real and finite:(i pi)/(log(2)+i pi)
+-1/2:-2:NaN:non-real and finite:(-log(2)+i pi)/(log(2)+i pi)
+0:-2:NaN:complex infinity:
+1/2:-2:NaN:non-real and finite:-(log(2))/(log(2)+i pi)
+1:-2:0::
+2:-2:NaN:non-real and finite:(log(2))/(log(2)+i pi)
+4:-2:NaN:non-real and finite:(log(4))/(log(2)+i pi)
+inf:-2:NaN:non-real (directed) infinity:
+NaN:-2:NaN:undefined:
+
+# base = -1
+
+-inf:-1:NaN:non-real (directed) infinity:
+-4:-1:NaN:non-real and finite:-(i (log(4)+i pi))/pi
+-2:-1:NaN:non-real and finite:-(i (log(2)+i pi))/pi
+-1:-1:1::
+-1/2:-1:NaN:non-real and finite:-(i (-log(2)+i pi))/pi
+0:-1:NaN:complex infinity:
+1:-1:0::
+1/2:-1:NaN:non-real and finite:(i log(2))/pi
+2:-1:NaN:non-real and finite:-(i log(2))/pi
+4:-1:NaN:non-real and finite:-(i log(4))/pi
+inf:-1:NaN:non-real (directed) infinity:
+NaN:-1:NaN:undefined:
+
+# base = -1/2
+
+-inf:-1/2:NaN:non-real (directed) infinity:
+-4:-1/2:NaN:non-real and finite:(log(4)+i pi)/(-log(2)+i pi)
+-2:-1/2:NaN:non-real and finite:(log(2)+i pi)/(-log(2)+i pi)
+-1:-1/2:NaN:non-real and finite:(i pi)/(-log(2)+i pi)
+-1/2:-1/2:1::
+0:-1/2:NaN:complex infinity:
+1:-1/2:0::
+1/2:-1/2:NaN:non-real and finite:-(log(2))/(-log(2)+i pi)
+2:-1/2:NaN:non-real and finite:(log(2))/(-log(2)+i pi)
+4:-1/2:NaN:non-real and finite:(log(4))/(-log(2)+i pi)
+inf:-1/2:NaN:non-real (directed) infinity:
+NaN:-1/2:NaN:undefined:
+
+# base = 0
+
+-inf:0:NaN:undefined:
+-4:0:0::
+-2:0:0::
+-1:0:0::
+-1/2:0:0::
+0:0:NaN:undefined:
+1/2:0:0::
+1:0:0::
+2:0:0::
+4:0:0::
+inf:0:NaN:undefined:
+NaN:0:NaN:undefined:
+
+# base = 1/2
+
+-inf:1/2:-inf::
+-2:-1/2:NaN:non-real and finite:(log(2)+i pi)/(-log(2)+i pi)
+-1:1/2:NaN:non-real and finite:-(i pi)/(log(2))
+-1/2:1/2:NaN:non-real and finite:-(-log(2)+i pi)/(log(2))
+0:1/2:inf::
+1/2:1/2:1::
+1:1/2:0::
+2:1/2:-1::
+inf:1/2:-inf::
+NaN:1/2:NaN:undefined:
+
+# base = 1
+
+-inf:1:NaN:complex infinity:
+-4:1:NaN:complex infinity:
+-2:1:NaN:complex infinity:
+-1:1:NaN:complex infinity:
+-1/2:1:NaN:complex infinity:
+0:1:NaN:complex infinity:
+1/2:1:NaN:complex infinity:
+1:1:NaN:undefined:
+2:1:NaN:complex infinity:
+4:1:NaN:complex infinity:
+inf:1:NaN:complex infinity:
+NaN:1:NaN:undefined:
+
+# base = 2
+
+-inf:2:inf::
+-4:2:NaN:non-real and finite:(log(4)+i pi)/(log(2))
+-2:2:NaN:non-real and finite:(log(2)+i pi)/(log(2))
+-1:2:NaN:non-real and finite:(i pi)/(log(2))
+-1/2:2:NaN:non-real and finite:(-log(2)+i pi)/(log(2))
+0:2:-inf::
+1/2:2:-1::
+1:2:0::
+2:2:1::
+4:2:2::
+4:4:1::
+inf:2:inf::
+NaN:2:NaN:undefined:
+
+# base = 4
+
+-inf:4:inf::
+-4:4:NaN:non-real and finite:(log(4)+i pi)/(log(4))
+-2:4:NaN:non-real and finite:(log(2)+i pi)/(log(4))
+-1/2:4:NaN:non-real and finite:(-log(2)+i pi)/(log(4))
+0:4:-inf::
+1:4:0::
+1/2:4:-1/2::
+2:4:1/2::
+4:4:1::
+inf:4:inf::
+NaN:4:NaN:undefined:
+
+# base = inf
+
+-inf:inf:NaN:undefined:
+-4:inf:0::
+-2:inf:0::
+-1:inf:0::
+-1/2:inf:0::
+0:inf:NaN:undefined:
+1:inf:0::
+1/2:inf:0::
+2:inf:0::
+4:inf:0::
+inf:inf:NaN:undefined:
+NaN:inf:NaN:undefined:
+
+# base is NaN
+
+-inf:NaN:NaN:undefined:
+-4:NaN:NaN:undefined:
+-2:NaN:NaN:undefined:
+-1:NaN:NaN:undefined:
+-1/2:NaN:NaN:undefined:
+0:NaN:NaN:undefined:
+1:NaN:NaN:undefined:
+1/2:NaN:NaN:undefined:
+2:NaN:NaN:undefined:
+4:NaN:NaN:undefined:
+inf:NaN:NaN:undefined:
+NaN:NaN:NaN:undefined:
diff --git a/cpan/Math-BigInt/t/blog-mbi.t b/cpan/Math-BigInt/t/blog-mbi.t
new file mode 100644 (file)
index 0000000..5ca48c6
--- /dev/null
@@ -0,0 +1,264 @@
+#!perl
+
+BEGIN {
+    unless ($ENV{AUTHOR_TESTING}) {
+        require Test::More;
+        Test::More::plan(skip_all => 'these tests are for release candidate testing');
+    }
+}
+
+use strict;
+use warnings;
+
+use Test::More tests => 97;
+use Scalar::Util qw< refaddr >;
+
+my $class;
+
+BEGIN { $class = 'Math::BigInt'; }
+BEGIN { use_ok($class) }
+
+while (<DATA>) {
+    s/\s+\z//;
+    next if /^#/ || ! /\S/;
+
+    # $in0 - the x value
+    # $in1 - the base
+    # $out0 - the wanted output value
+    # $type - the type of the wanted number (real, non-real, ...)
+    # $expr - mathematical expression of the wanted number
+
+    my ($in0, $in1, $out0, $type, $expr) = split /:/;
+
+    # Some of the test data use rational numbers.
+    # - with Math::BigInt, we skip them
+    # - with Math::BigFloat, we convert them to floats
+    # - with Math::BigRat, we use them as they are
+
+    next if ($in0  =~ m|/| ||
+             $in1  =~ m|/| ||
+             $out0 =~ m|/|);
+
+    my ($x, $y);        # input values as objects
+    my ($yo);           # copy of input value
+    my ($got);          # test output
+
+    my $test = qq|\$x = $class -> new("$in0"); | .
+               qq|\$y = $class -> new("$in1"); | .
+               qq|\$yo = \$y -> copy(); | .
+               qq|\$got = \$x -> blog(\$y);|;
+
+    my $desc = "logarithm of $in0 to base $in1";
+
+    print("#\n",
+          "# Now about to execute the following test.\n",
+          "#\n",
+          "# $test\n",
+          "#\n");
+
+    if ($in0 ne 'NaN' && $in1 ne 'NaN') {
+        print("# Enter log($in1, $in0) into Wolfram Alpha",
+              " (http://www.wolframalpha.com/), and it says that the result",
+              " is ", length($type) ? $type : "real",
+              length($expr) ? ": $expr" : "",
+              ".", "\n",
+              "#\n");
+    }
+
+    eval $test;
+    die $@ if $@;       # this should never happen
+
+    subtest $desc, sub {
+        plan tests => 5,
+
+        # Check output.
+
+        is(ref($got), $class, "output arg is a $class");
+        is($got, $out0, 'output arg has the right value');
+        is(refaddr($got), refaddr($x), 'output arg is the invocand');
+
+        # The second argument (if the invocand is the first) shall *not* be
+        # modified.
+
+        is(ref($y), $class, "second input arg is still a $class");
+        is_deeply($y, $yo, 'second output arg is unmodified');
+
+    };
+
+}
+
+__END__
+
+# base = -inf
+
+-inf:-inf:NaN:undefined:
+-4:-inf:0::
+-2:-inf:0::
+-1:-inf:0::
+-1/2:-inf:0::
+0:-inf:NaN:undefined:
+1/2:-inf:0::
+1:-inf:0::
+2:-inf:0::
+4:-inf:0::
+inf:-inf:NaN:undefined:
+NaN:-inf:NaN:undefined:
+
+# base = -4
+
+-4:-4:1::
+-2:-4:NaN:non-real and finite:(log(2)+i pi)/(log(4)+i pi)
+0:-4:NaN:non-real (directed) infinity:(-sqrt(pi^2+log^2(4))/(log(4)+i pi))infinity
+1/2:-4:NaN:non-real and finite:-(log(2))/(log(4)+i pi)
+1:-4:0::
+2:-4:NaN:non-real and finite:(log(2))/(log(4)+i pi)
+4:-4:NaN:non-real and finite:(log(4))/(log(4)+i pi)
+NaN:-4:NaN:undefined:
+
+# base = -2
+
+-inf:-2:NaN:non-real (directed) infinity:sqrt(pi^2+log^2(2))/(log(2)+i pi)infinity
+-4:-2:NaN:non-real and finite:(log(4)+i pi)/(log(2)+i pi)
+-2:-2:1::
+-1:-2:NaN:non-real and finite:(i pi)/(log(2)+i pi)
+-1/2:-2:NaN:non-real and finite:(-log(2)+i pi)/(log(2)+i pi)
+0:-2:NaN:complex infinity:
+1/2:-2:NaN:non-real and finite:-(log(2))/(log(2)+i pi)
+1:-2:0::
+2:-2:NaN:non-real and finite:(log(2))/(log(2)+i pi)
+4:-2:NaN:non-real and finite:(log(4))/(log(2)+i pi)
+inf:-2:NaN:non-real (directed) infinity:
+NaN:-2:NaN:undefined:
+
+# base = -1
+
+-inf:-1:NaN:non-real (directed) infinity:
+-4:-1:NaN:non-real and finite:-(i (log(4)+i pi))/pi
+-2:-1:NaN:non-real and finite:-(i (log(2)+i pi))/pi
+-1:-1:1::
+-1/2:-1:NaN:non-real and finite:-(i (-log(2)+i pi))/pi
+0:-1:NaN:complex infinity:
+1:-1:0::
+1/2:-1:NaN:non-real and finite:(i log(2))/pi
+2:-1:NaN:non-real and finite:-(i log(2))/pi
+4:-1:NaN:non-real and finite:-(i log(4))/pi
+inf:-1:NaN:non-real (directed) infinity:
+NaN:-1:NaN:undefined:
+
+# base = -1/2
+
+-inf:-1/2:NaN:non-real (directed) infinity:
+-4:-1/2:NaN:non-real and finite:(log(4)+i pi)/(-log(2)+i pi)
+-2:-1/2:NaN:non-real and finite:(log(2)+i pi)/(-log(2)+i pi)
+-1:-1/2:NaN:non-real and finite:(i pi)/(-log(2)+i pi)
+-1/2:-1/2:1::
+0:-1/2:NaN:complex infinity:
+1:-1/2:0::
+1/2:-1/2:NaN:non-real and finite:-(log(2))/(-log(2)+i pi)
+2:-1/2:NaN:non-real and finite:(log(2))/(-log(2)+i pi)
+4:-1/2:NaN:non-real and finite:(log(4))/(-log(2)+i pi)
+inf:-1/2:NaN:non-real (directed) infinity:
+NaN:-1/2:NaN:undefined:
+
+# base = 0
+
+-inf:0:NaN:undefined:
+-4:0:0::
+-2:0:0::
+-1:0:0::
+-1/2:0:0::
+0:0:NaN:undefined:
+1/2:0:0::
+1:0:0::
+2:0:0::
+4:0:0::
+inf:0:NaN:undefined:
+NaN:0:NaN:undefined:
+
+# base = 1/2
+
+-inf:1/2:-inf::
+-2:-1/2:NaN:non-real and finite:(log(2)+i pi)/(-log(2)+i pi)
+-1:1/2:NaN:non-real and finite:-(i pi)/(log(2))
+-1/2:1/2:NaN:non-real and finite:-(-log(2)+i pi)/(log(2))
+0:1/2:inf::
+1/2:1/2:1::
+1:1/2:0::
+2:1/2:-1::
+inf:1/2:-inf::
+NaN:1/2:NaN:undefined:
+
+# base = 1
+
+-inf:1:NaN:complex infinity:
+-4:1:NaN:complex infinity:
+-2:1:NaN:complex infinity:
+-1:1:NaN:complex infinity:
+-1/2:1:NaN:complex infinity:
+0:1:NaN:complex infinity:
+1/2:1:NaN:complex infinity:
+1:1:NaN:undefined:
+2:1:NaN:complex infinity:
+4:1:NaN:complex infinity:
+inf:1:NaN:complex infinity:
+NaN:1:NaN:undefined:
+
+# base = 2
+
+-inf:2:inf::
+-4:2:NaN:non-real and finite:(log(4)+i pi)/(log(2))
+-2:2:NaN:non-real and finite:(log(2)+i pi)/(log(2))
+-1:2:NaN:non-real and finite:(i pi)/(log(2))
+-1/2:2:NaN:non-real and finite:(-log(2)+i pi)/(log(2))
+0:2:-inf::
+1/2:2:-1::
+1:2:0::
+2:2:1::
+4:2:2::
+4:4:1::
+inf:2:inf::
+NaN:2:NaN:undefined:
+
+# base = 4
+
+-inf:4:inf::
+-4:4:NaN:non-real and finite:(log(4)+i pi)/(log(4))
+-2:4:NaN:non-real and finite:(log(2)+i pi)/(log(4))
+-1/2:4:NaN:non-real and finite:(-log(2)+i pi)/(log(4))
+0:4:-inf::
+1:4:0::
+1/2:4:-1/2::
+2:4:1/2::
+4:4:1::
+inf:4:inf::
+NaN:4:NaN:undefined:
+
+# base = inf
+
+-inf:inf:NaN:undefined:
+-4:inf:0::
+-2:inf:0::
+-1:inf:0::
+-1/2:inf:0::
+0:inf:NaN:undefined:
+1:inf:0::
+1/2:inf:0::
+2:inf:0::
+4:inf:0::
+inf:inf:NaN:undefined:
+NaN:inf:NaN:undefined:
+
+# base is NaN
+
+-inf:NaN:NaN:undefined:
+-4:NaN:NaN:undefined:
+-2:NaN:NaN:undefined:
+-1:NaN:NaN:undefined:
+-1/2:NaN:NaN:undefined:
+0:NaN:NaN:undefined:
+1:NaN:NaN:undefined:
+1/2:NaN:NaN:undefined:
+2:NaN:NaN:undefined:
+4:NaN:NaN:undefined:
+inf:NaN:NaN:undefined:
+NaN:NaN:NaN:undefined:
index 7d8afb0..89559a2 100644 (file)
@@ -7,8 +7,8 @@ use strict;
 use Test::More tests => 684
     + 26;              # own tests
 
-use Math::BigInt 1.70;
-use Math::BigFloat 1.43;
+use Math::BigInt lib => 'Calc';
+use Math::BigFloat;
 
 use vars qw/$mbi $mbf/;
 
diff --git a/cpan/Math-BigInt/t/objectify_mbf.t b/cpan/Math-BigInt/t/objectify_mbf.t
new file mode 100644 (file)
index 0000000..a91ad4b
--- /dev/null
@@ -0,0 +1,90 @@
+#!perl
+#
+# Verify that objectify() is able to convert a "foreign" object into what we
+# want, when what we want is Math::BigFloat or subclass thereof.
+
+use strict;
+use warnings;
+
+package main;
+
+use Test::More tests => 6;
+
+use Math::BigFloat;
+
+###############################################################################
+
+for my $class ('Math::BigFloat', 'Math::BigFloat::Subclass') {
+
+    # This object defines what we want.
+
+    my $float = $class -> new(10);
+
+    # Create various objects that should work with the object above after
+    # objectify() has done its thing.
+
+    my $float_percent1 = My::Percent::Float1 -> new(100);
+    is($float * $float_percent1, 10);
+
+    my $float_percent2 = My::Percent::Float2 -> new(100);
+    is($float * $float_percent2, 10);
+
+    my $float_percent3 = My::Percent::Float3 -> new(100);
+    is($float * $float_percent3, 10);
+}
+
+###############################################################################
+# Class supports as_float(), which returns a Math::BigFloat.
+
+package My::Percent::Float1;
+
+sub new {
+    my $class = shift;
+    my $num = shift;
+    return bless \$num, $class;
+}
+
+sub as_float {
+    my $self = shift;
+    return Math::BigFloat -> new($$self / 100);
+}
+
+###############################################################################
+# Class supports as_float(), which returns a scalar.
+
+package My::Percent::Float2;
+
+sub new {
+    my $class = shift;
+    my $num = shift;
+    return bless \$num, $class;
+}
+
+sub as_float {
+    my $self = shift;
+    return $$self / 100;
+}
+
+###############################################################################
+# Class does not support as_float().
+
+package My::Percent::Float3;
+
+use overload '""' => sub { $_[0] -> as_string(); };
+
+sub new {
+    my $class = shift;
+    my $num = shift;
+    return bless \$num, $class;
+}
+
+sub as_string {
+    my $self = shift;
+    return $$self / 100;
+}
+
+###############################################################################
+
+package Math::BigFloat::Subclass;
+
+use base 'Math::BigFloat';
diff --git a/cpan/Math-BigInt/t/objectify_mbi.t b/cpan/Math-BigInt/t/objectify_mbi.t
new file mode 100644 (file)
index 0000000..155dd52
--- /dev/null
@@ -0,0 +1,130 @@
+#!perl
+#
+# Verify that objectify() is able to convert a "foreign" object into what we
+# want, when what we want is Math::BigInt or subclass thereof.
+
+use strict;
+use warnings;
+
+package main;
+
+use Test::More tests => 10;
+
+use Math::BigInt;
+
+###############################################################################
+
+for my $class ('Math::BigInt', 'Math::BigInt::Subclass') {
+
+    # This object defines what we want.
+
+    my $int = $class -> new(10);
+
+    # Create various objects that should work with the object above after
+    # objectify() has done its thing.
+
+    my $int_percent1 = My::Percent::Int1 -> new(100);
+    is($int * $int_percent1, 10);
+
+    my $int_percent2 = My::Percent::Int2 -> new(100);
+    is($int * $int_percent2, 10);
+
+    my $int_percent3 = My::Percent::Int3 -> new(100);
+    is($int * $int_percent3, 10);
+
+    my $int_percent4 = My::Percent::Int4 -> new(100);
+    is($int * $int_percent4, 10);
+
+    my $int_percent5 = My::Percent::Int5 -> new(100);
+    is($int * $int_percent5, 10);
+}
+
+###############################################################################
+# Class supports as_int(), which returns a Math::BigInt.
+
+package My::Percent::Int1;
+
+sub new {
+    my $class = shift;
+    my $num = shift;
+    return bless \$num, $class;
+}
+
+sub as_int {
+    my $self = shift;
+    return Math::BigInt -> new($$self / 100);
+}
+
+###############################################################################
+# Class supports as_int(), which returns a scalar.
+
+package My::Percent::Int2;
+
+sub new {
+    my $class = shift;
+    my $num = shift;
+    return bless \$num, $class;
+}
+
+sub as_int {
+    my $self = shift;
+    return $$self / 100;
+}
+
+###############################################################################
+# Class does not support as_int(), but supports as_number(), which returns a
+# Math::BigInt.
+
+package My::Percent::Int3;
+
+sub new {
+    my $class = shift;
+    my $num = shift;
+    return bless \$num, $class;
+}
+
+sub as_number {
+    my $self = shift;
+    return Math::BigInt -> new($$self / 100);
+}
+
+###############################################################################
+# Class does  not support as_int(),  but supports as_number(), which  returns a
+# scalar.
+
+package My::Percent::Int4;
+
+sub new {
+    my $class = shift;
+    my $num = shift;
+    return bless \$num, $class;
+}
+
+sub as_number {
+    my $self = shift;
+    return $$self / 100;
+}
+
+###############################################################################
+# Class supports neither as_int() or as_number().
+
+package My::Percent::Int5;
+
+use overload '""' => sub { $_[0] -> as_string(); };
+
+sub new {
+    my $class = shift;
+    my $num = shift;
+    return bless \$num, $class;
+}
+
+sub as_string {
+    my $self = shift;
+    return $$self / 100;
+}
+
+###############################################################################
+
+package Math::BigInt::Subclass;
+
+use base 'Math::BigInt';
index fec4d07..035b129 100644 (file)
@@ -1,7 +1,7 @@
 #!/usr/bin/perl -w
 
 use strict;
-use Test::More tests => 2340
+use Test::More tests => 2360
     + 6;       # + our own tests
 
 
index b8e0a02..1af9f1c 100644 (file)
@@ -1,7 +1,7 @@
 #!/usr/bin/perl -w
 
 use strict;
-use Test::More tests => 3649
+use Test::More tests => 3701
     + 5;       # +5 own tests
 
 BEGIN { unshift @INC, 't'; }
index d90bbbc..86c7684 100644 (file)
@@ -3,7 +3,7 @@
 # Test use Math::BigFloat with => 'Math::BigInt::SomeSubclass';
 
 use strict;
-use Test::More tests => 2340 + 1;
+use Test::More tests => 2360 + 1;
 
 use Math::BigFloat with => 'Math::BigInt::Subclass', lib => 'Calc';
 
index fc58ce2..06246c9 100644 (file)
@@ -6,10 +6,6 @@ ExtUtils::MakeMaker cpan/ExtUtils-MakeMaker/lib/ExtUtils/MakeMaker.pm fd048a43fc
 ExtUtils::MakeMaker cpan/ExtUtils-MakeMaker/lib/ExtUtils/MM_VMS.pm 0c78ba02d6249dfcca12ac9886a7c7cfb60e77fe
 ExtUtils::MakeMaker cpan/ExtUtils-MakeMaker/t/prereq.t 53bda2c549fd13a6b6c13a070ca6bc79883081c0
 ExtUtils::MakeMaker cpan/ExtUtils-MakeMaker/t/vstrings.t 90035a2bdbf45f15b9c3196d072d7cba7e662871
-Math::BigInt cpan/Math-BigInt/t/bigfltpm.t 9b96649cc37c42003830957dcc9b3d62e4511b87
-Math::BigInt cpan/Math-BigInt/t/bigintpm.inc bb1d4d5029dbb74a52bf59cff53bf3ad1652e428
-Math::BigInt cpan/Math-BigInt/t/bigroot.t da260b6e02b220868fc7b4c0f87569299402fbf7
-Math::BigInt cpan/Math-BigInt/t/mbimbf.t 2709f7d1acdb39aab910d3ba4c88191b28cc3cfc
 Math::BigInt::FastCalc cpan/Math-BigInt-FastCalc/lib/Math/BigInt/FastCalc.pm 3f92fc3b8735055d1ea496c3c44d82ea3819c306
 Math::BigRat cpan/Math-BigRat/lib/Math/BigRat.pm 682352dde33638125ce12ca44990bd1cd44af4f8
 Pod::Perldoc cpan/Pod-Perldoc/lib/Pod/Perldoc.pm dcd53fba13060dbb71b1b5861fbc5c0881c8625a