Update Math-BigInt to CPAN version 1.999816
authorChris 'BinGOs' Williams <chris@bingosnet.co.uk>
Fri, 18 Jan 2019 19:28:07 +0000 (19:28 +0000)
committerChris 'BinGOs' Williams <chris@bingosnet.co.uk>
Fri, 18 Jan 2019 19:28:07 +0000 (19:28 +0000)
  [DELTA]

1.999816 2018-10-26

 * bnok() for Math::BigInt and Math::BigFloat now support the full Kronenburg
   extension. The behaviour is identical to the behaviour of the Maple and
   Mathematica function for negative integers n, k. Add tests. This closes CPAN
   RT #95628.

 * Fix POD errors. This closes CPAN RT #125141.

1.999815 2018-10-19

 * Move bitwise operators signed and, signed or, and signed xor from
   lib/Math/BigInt/CalcEmu.pm into lib/Math/BigInt/Lib.pm. The file
   lib/Math/BigInt/CalcEmu.pm is no longer needed and thus removed.

1.999814 2018-10-01

 * Add to_base() and from_base() to Math::BigInt and corresponding library
   methods _to_base() and _from_base() to Math::BigInt::Lib. This was inspired
   by CPAN RT #122681.

 * Fix Makefile.PL to reflect that Test::More is only needed for testing, not
   for building.

 * In the documentation for each of the to_(bin|hex|oct|bytes) methods, add a
   reference to the corresponding from_(bin|hex|oct|bytes) method.

13 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 [deleted file]
cpan/Math-BigInt/lib/Math/BigInt/Lib.pm
cpan/Math-BigInt/t/Math/BigInt/Lib/Minimal.pm
cpan/Math-BigInt/t/bnok-mbf.t [new file with mode: 0644]
cpan/Math-BigInt/t/bnok-mbi.t [new file with mode: 0644]
cpan/Math-BigInt/t/calling.t
cpan/Math-BigInt/t/from_base-mbi.t [new file with mode: 0644]
cpan/Math-BigInt/t/to_base-mbi.t [new file with mode: 0644]

index 4ffedad..6ea2457 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -1284,7 +1284,6 @@ cpan/Locale-Maketext-Simple/t/po_without_i_default/fr.po  Locale::Simple tests
 cpan/Math-BigInt/lib/Math/BigFloat.pm          An arbitrary precision floating-point arithmetic package
 cpan/Math-BigInt/lib/Math/BigInt.pm    An arbitrary precision integer arithmetic package
 cpan/Math-BigInt/lib/Math/BigInt/Calc.pm       Pure Perl module to support Math::BigInt
-cpan/Math-BigInt/lib/Math/BigInt/CalcEmu.pm    Pure Perl module to support Math::BigInt
 cpan/Math-BigInt/lib/Math/BigInt/Lib.pm
 cpan/Math-BigInt/t/_e_math.t           Helper routine in BigFloat for _e math
 cpan/Math-BigInt/t/alias.inc           Support for BigInt tests
@@ -1306,6 +1305,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/bigroot.t           Test the broot function
 cpan/Math-BigInt/t/blucas-mbi.t
+cpan/Math-BigInt/t/bnok-mbf.t
+cpan/Math-BigInt/t/bnok-mbi.t
 cpan/Math-BigInt/t/bnstr-mbf.t         Test Math::BigInt
 cpan/Math-BigInt/t/bnstr-mbi.t         Test Math::BigInt
 cpan/Math-BigInt/t/bsstr-mbf.t         Test Math::BigInt
@@ -1321,6 +1322,7 @@ cpan/Math-BigInt/t/dparts-mbf.t           Test Math::BigInt
 cpan/Math-BigInt/t/dparts-mbi.t                Test Math::BigInt
 cpan/Math-BigInt/t/eparts-mbf.t                Test Math::BigInt
 cpan/Math-BigInt/t/eparts-mbi.t                Test Math::BigInt
+cpan/Math-BigInt/t/from_base-mbi.t
 cpan/Math-BigInt/t/from_bin-mbf.t      Test Math::BigInt
 cpan/Math-BigInt/t/from_bin-mbi.t
 cpan/Math-BigInt/t/from_hex-mbf.t      Test Math::BigInt
@@ -1363,6 +1365,7 @@ cpan/Math-BigInt/t/sub_ali.t              Tests for aliases in BigInt subclasses
 cpan/Math-BigInt/t/sub_mbf.t           Empty subclass test of BigFloat
 cpan/Math-BigInt/t/sub_mbi.t           Empty subclass test of BigInt
 cpan/Math-BigInt/t/sub_mif.t           Test A & P with subclasses using mbimbf.inc
+cpan/Math-BigInt/t/to_base-mbi.t
 cpan/Math-BigInt/t/trap.t              Test whether trap_nan and trap_inf work
 cpan/Math-BigInt/t/upgrade.inc         Actual tests for upgrade.t
 cpan/Math-BigInt/t/upgrade.t           Test if use Math::BigInt(); under upgrade works
index c32e698..6b71c81 100755 (executable)
@@ -706,7 +706,7 @@ use File::Glob qw(:case);
     },
 
     'Math::BigInt' => {
-        'DISTRIBUTION' => 'PJACKLAM/Math-BigInt-1.999813.tar.gz',
+        'DISTRIBUTION' => 'PJACKLAM/Math-BigInt-1.999816.tar.gz',
         'FILES'        => q[cpan/Math-BigInt],
         'EXCLUDED'     => [
             qr{^examples/},
index b8a9637..8a92b58 100644 (file)
@@ -19,7 +19,7 @@ use warnings;
 use Carp qw< carp croak >;
 use Math::BigInt ();
 
-our $VERSION = '1.999813';
+our $VERSION = '1.999816';
 
 our @ISA        = qw/Math::BigInt/;
 our @EXPORT_OK  = qw/bpi/;
@@ -2569,16 +2569,20 @@ sub bnok {
     return $x if $x->modify('bnok');
 
     return $x->bnan() if $x->is_nan() || $y->is_nan();
-    return $x->binf() if $x->is_inf();
+    return $x->bnan() if (($x->is_finite() && !$x->is_int()) ||
+                          ($y->is_finite() && !$y->is_int()));
 
-    my $u = $x->as_int();
-    $u->bnok($y->as_int());
+    my $xint = Math::BigInt -> new($x -> bsstr());
+    my $yint = Math::BigInt -> new($y -> bsstr());
+    $xint -> bnok($yint);
+    my $xflt = Math::BigFloat -> new($xint);
 
-    $x->{_m} = $u->{value};
-    $x->{_e} = $LIB->_zero();
-    $x->{_es} = '+';
-    $x->{sign} = '+';
-    $x->bnorm(@r);
+    $x->{_m}   = $xflt->{_m};
+    $x->{_e}   = $xflt->{_e};
+    $x->{_es}  = $xflt->{_es};
+    $x->{sign} = $xflt->{sign};
+
+    return $x;
 }
 
 sub bsin {
@@ -5133,7 +5137,7 @@ This method was added in v1.87 of Math::BigInt (June 2007).
 In scalar context, divides $x by $y and returns the result to the given or
 default accuracy/precision. In list context, does floored division
 (F-division), returning an integer $q and a remainder $r so that $x = $q * $y +
-$r. The remainer (modulo) is equal to what is returned by C<$x->bmod($y)>.
+$r. The remainer (modulo) is equal to what is returned by C<< $x->bmod($y) >>.
 
 =item bmod()
 
index 67a59f2..a443cd4 100644 (file)
@@ -20,7 +20,7 @@ use warnings;
 
 use Carp qw< carp croak >;
 
-our $VERSION = '1.999813';
+our $VERSION = '1.999816';
 
 require Exporter;
 our @ISA = qw(Exporter);
@@ -233,7 +233,6 @@ my $LIB = 'Math::BigInt::Calc';        # module to do the low level math
 my $IMPORT = 0;                         # was import() called yet?
                                         # used to make require work
 my %WARN;                               # warn only once for low-level libs
-my %CAN;                                # cache for $LIB->can(...)
 my %CALLBACKS;                          # callbacks to notify on lib loads
 my $EMU_LIB = 'Math/BigInt/CalcEmu.pm'; # emulate low-level math
 
@@ -904,6 +903,50 @@ sub from_bytes {
     return $self;
 }
 
+sub from_base {
+    my $self    = shift;
+    my $selfref = ref $self;
+    my $class   = $selfref || $self;
+
+    # Don't modify constant (read-only) objects.
+
+    return if $selfref && $self->modify('from_base');
+
+    my $str = shift;
+
+    my $base = shift;
+    $base = $class->new($base) unless ref($base);
+
+    croak("the base must be a finite integer >= 2")
+      if $base < 2 || ! $base -> is_int();
+
+    # If called as a class method, initialize a new object.
+
+    $self = $class -> bzero() unless $selfref;
+
+    # If no collating sequence is given, pass some of the conversions to
+    # methods optimized for those cases.
+
+    if (! @_) {
+        return $self -> from_bin($str) if $base == 2;
+        return $self -> from_oct($str) if $base == 8;
+        return $self -> from_hex($str) if $base == 16;
+        if ($base == 10) {
+            my $tmp = $class -> new($str);
+            $self -> {value} = $tmp -> {value};
+            $self -> {sign}  = '+';
+        }
+    }
+
+    croak("from_base() requires a newer version of the $LIB library.")
+      unless $LIB->can('_from_base');
+
+    $self -> {sign}  = '+';
+    $self -> {value}
+      = $LIB->_from_base($str, $base -> {value}, @_ ? shift() : ());
+    return $self
+}
+
 sub bzero {
     # create/assign '+0'
 
@@ -2478,74 +2521,85 @@ sub bexp {
 }
 
 sub bnok {
-    # Calculate n over k (binomial coefficient or "choose" function) as integer.
-    # set up parameters
-    my ($class, $x, $y, @r) = (ref($_[0]), @_);
+    # Calculate n over k (binomial coefficient or "choose" function) as
+    # integer.
 
-    # objectify is costly, so avoid it
+    # Set up parameters.
+    my ($self, $n, $k, @r) = (ref($_[0]), @_);
+
+    # Objectify is costly, so avoid it.
     if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) {
-        ($class, $x, $y, @r) = objectify(2, @_);
+        ($self, $n, $k, @r) = objectify(2, @_);
     }
 
-    return $x if $x->modify('bnok');
-    return $x->bnan() if $x->{sign} eq 'NaN' || $y->{sign} eq 'NaN';
-    return $x->binf() if $x->{sign} eq '+inf';
-
-    # k > n or k < 0 => 0
-    my $cmp = $x->bacmp($y);
-    return $x->bzero() if $cmp < 0 || substr($y->{sign}, 0, 1) eq "-";
+    return $n if $n->modify('bnok');
 
-    if ($LIB->can('_nok')) {
-        $x->{value} = $LIB->_nok($x->{value}, $y->{value});
-    } else {
-        # ( 7 )       7!       1*2*3*4 * 5*6*7   5 * 6 * 7       6   7
-        # ( - ) = --------- =  --------------- = --------- = 5 * - * -
-        # ( 3 )   (7-3)! 3!    1*2*3*4 * 1*2*3   1 * 2 * 3       2   3
+    # All cases where at least one argument is NaN.
 
-        my $n = $x -> {value};
-        my $k = $y -> {value};
+    return $n->bnan() if $n->{sign} eq 'NaN' || $k->{sign} eq 'NaN';
 
-        # If k > n/2, or, equivalently, 2*k > n, compute nok(n, k) as
-        # nok(n, n-k) to minimize the number if iterations in the loop.
+    # All cases where at least one argument is +/-inf.
 
-        {
-            my $twok = $LIB->_mul($LIB->_two(), $LIB->_copy($k));
-            if ($LIB->_acmp($twok, $n) > 0) {
-                $k = $LIB->_sub($LIB->_copy($n), $k);
+    if ($n -> is_inf()) {
+        if ($k -> is_inf()) {                   # bnok(+/-inf,+/-inf)
+            return $n -> bnan();
+        } elsif ($k -> is_neg()) {              # bnok(+/-inf,k), k < 0
+            return $n -> bzero();
+        } elsif ($k -> is_zero()) {             # bnok(+/-inf,k), k = 0
+            return $n -> bone();
+        } else {
+            if ($n -> is_inf("+")) {            # bnok(+inf,k), 0 < k < +inf
+                return $n -> binf("+");
+            } else {                            # bnok(-inf,k), k > 0
+                my $sign = $k -> is_even() ? "+" : "-";
+                return $n -> binf($sign);
             }
         }
+    }
 
-        if ($LIB->_is_zero($k)) {
-            $n = $LIB->_one();
-        } else {
+    elsif ($k -> is_inf()) {            # bnok(n,+/-inf), -inf <= n <= inf
+        return $n -> bnan();
+    }
+
+    # At this point, both n and k are real numbers.
 
-            # Make a copy of the original n, since we'll be modifying n
-            # in-place.
+    my $sign = 1;
 
-            my $n_orig = $LIB->_copy($n);
+    if ($n >= 0) {
+        if ($k < 0 || $k > $n) {
+            return $n -> bzero();
+        }
+    } else {
 
-            $LIB->_sub($n, $k);
-            $LIB->_inc($n);
+        if ($k >= 0) {
 
-            my $f = $LIB->_copy($n);
-            $LIB->_inc($f);
+            # n < 0 and k >= 0: bnok(n,k) = (-1)^k * bnok(-n+k-1,k)
 
-            my $d = $LIB->_two();
+            $sign = (-1) ** $k;
+            $n -> bneg() -> badd($k) -> bdec();
 
-            # while f <= n (the original n, that is) ...
+        } elsif ($k <= $n) {
 
-            while ($LIB->_acmp($f, $n_orig) <= 0) {
-                $LIB->_mul($n, $f);
-                $LIB->_div($n, $d);
-                $LIB->_inc($f);
-                $LIB->_inc($d);
-            }
-        }
+            # n < 0 and k <= n: bnok(n,k) = (-1)^(n-k) * bnok(-k-1,n-k)
 
-        $x -> {value} = $n;
+            $sign = (-1) ** ($n - $k);
+            my $x0 = $n -> copy();
+            $n -> bone() -> badd($k) -> bneg();
+            $k = $k -> copy();
+            $k -> bneg() -> badd($x0);
+
+        } else {
+
+            # n < 0 and n < k < 0:
+
+            return $n -> bzero();
+        }
     }
 
-    $x->round(@r);
+    $n->{value} = $LIB->_nok($n->{value}, $k->{value});
+    $n -> bneg() if $sign == -1;
+
+    $n->round(@r);
 }
 
 sub bsin {
@@ -2947,21 +3001,13 @@ sub band {
 
     return $x->bnan() if ($x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/);
 
-    my $sx = $x->{sign} eq '+' ? 1 : -1;
-    my $sy = $y->{sign} eq '+' ? 1 : -1;
-
-    if ($sx == 1 && $sy == 1) {
+    if ($x->{sign} eq '+' && $y->{sign} eq '+') {
         $x->{value} = $LIB->_and($x->{value}, $y->{value});
-        return $x->round(@r);
-    }
-
-    if ($CAN{signed_and}) {
-        $x->{value} = $LIB->_signed_and($x->{value}, $y->{value}, $sx, $sy);
-        return $x->round(@r);
+    } else {
+        ($x->{value}, $x->{sign}) = $LIB->_sand($x->{value}, $x->{sign},
+                                                $y->{value}, $y->{sign});
     }
-
-    require $EMU_LIB;
-    __emu_band($class, $x, $y, $sx, $sy, @r);
+    return $x->round(@r);
 }
 
 sub bior {
@@ -2976,29 +3022,18 @@ sub bior {
     }
 
     return $x if $x->modify('bior');
+
     $r[3] = $y;                 # no push!
 
     return $x->bnan() if ($x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/);
 
-    my $sx = $x->{sign} eq '+' ? 1 : -1;
-    my $sy = $y->{sign} eq '+' ? 1 : -1;
-
-    # the sign of X follows the sign of X, e.g. sign of Y irrelevant for bior()
-
-    # don't use lib for negative values
-    if ($sx == 1 && $sy == 1) {
+    if ($x->{sign} eq '+' && $y->{sign} eq '+') {
         $x->{value} = $LIB->_or($x->{value}, $y->{value});
-        return $x->round(@r);
-    }
-
-    # if lib can do negative values, let it handle this
-    if ($CAN{signed_or}) {
-        $x->{value} = $LIB->_signed_or($x->{value}, $y->{value}, $sx, $sy);
-        return $x->round(@r);
+    } else {
+        ($x->{value}, $x->{sign}) = $LIB->_sor($x->{value}, $x->{sign},
+                                               $y->{value}, $y->{sign});
     }
-
-    require $EMU_LIB;
-    __emu_bior($class, $x, $y, $sx, $sy, @r);
+    return $x->round(@r);
 }
 
 sub bxor {
@@ -3013,27 +3048,18 @@ sub bxor {
     }
 
     return $x if $x->modify('bxor');
+
     $r[3] = $y;                 # no push!
 
     return $x->bnan() if ($x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/);
 
-    my $sx = $x->{sign} eq '+' ? 1 : -1;
-    my $sy = $y->{sign} eq '+' ? 1 : -1;
-
-    # don't use lib for negative values
-    if ($sx == 1 && $sy == 1) {
+    if ($x->{sign} eq '+' && $y->{sign} eq '+') {
         $x->{value} = $LIB->_xor($x->{value}, $y->{value});
-        return $x->round(@r);
-    }
-
-    # if lib can do negative values, let it handle this
-    if ($CAN{signed_xor}) {
-        $x->{value} = $LIB->_signed_xor($x->{value}, $y->{value}, $sx, $sy);
-        return $x->round(@r);
+    } else {
+        ($x->{value}, $x->{sign}) = $LIB->_sxor($x->{value}, $x->{sign},
+                                               $y->{value}, $y->{sign});
     }
-
-    require $EMU_LIB;
-    __emu_bxor($class, $x, $y, $sx, $sy, @r);
+    return $x->round(@r);
 }
 
 sub bnot {
@@ -3670,6 +3696,36 @@ sub to_bytes {
     return $LIB->_to_bytes($x->{value});
 }
 
+sub to_base {
+    # return a base anything string
+    my $x = shift;
+    $x = $class->new($x) if !ref($x);
+
+    croak("the value to convert must be a finite, non-negative integer")
+      if $x -> is_neg() || !$x -> is_int();
+
+    my $base = shift;
+    $base = $class->new($base) unless ref($base);
+
+    croak("the base must be a finite integer >= 2")
+      if $base < 2 || ! $base -> is_int();
+
+    # If no collating sequence is given, pass some of the conversions to
+    # methods optimized for those cases.
+
+    if (! @_) {
+        return    $x -> to_bin() if $base == 2;
+        return    $x -> to_oct() if $base == 8;
+        return uc $x -> to_hex() if $base == 16;
+        return    $x -> bstr()   if $base == 10;
+    }
+
+    croak("to_base() requires a newer version of the $LIB library.")
+      unless $LIB->can('_to_base');
+
+    return $LIB->_to_base($x->{value}, $base -> {value}, @_ ? shift() : ());
+}
+
 sub as_hex {
     # return as hex string, with prefixed 0x
     my $x = shift;
@@ -3999,14 +4055,6 @@ sub import {
         &{$CALLBACKS{$class}}($LIB);
     }
 
-    # Fill $CAN with the results of $LIB->can(...) for emulating lower math lib
-    # functions
-
-    %CAN = ();
-    for my $method (qw/ signed_and signed_or signed_xor /) {
-        $CAN{$method} = $LIB->can("_$method") ? 1 : 0;
-    }
-
     # import done
 }
 
@@ -4301,19 +4349,20 @@ Math::BigInt - Arbitrary size integer/float math package
   # Constructor methods (when the class methods below are used as instance
   # methods, the value is assigned the invocand)
 
-  $x = Math::BigInt->new($str);         # defaults to 0
-  $x = Math::BigInt->new('0x123');      # from hexadecimal
-  $x = Math::BigInt->new('0b101');      # from binary
-  $x = Math::BigInt->from_hex('cafe');  # from hexadecimal
-  $x = Math::BigInt->from_oct('377');   # from octal
-  $x = Math::BigInt->from_bin('1101');  # from binary
-  $x = Math::BigInt->bzero();           # create a +0
-  $x = Math::BigInt->bone();            # create a +1
-  $x = Math::BigInt->bone('-');         # create a -1
-  $x = Math::BigInt->binf();            # create a +inf
-  $x = Math::BigInt->binf('-');         # create a -inf
-  $x = Math::BigInt->bnan();            # create a Not-A-Number
-  $x = Math::BigInt->bpi();             # returns pi
+  $x = Math::BigInt->new($str);             # defaults to 0
+  $x = Math::BigInt->new('0x123');          # from hexadecimal
+  $x = Math::BigInt->new('0b101');          # from binary
+  $x = Math::BigInt->from_hex('cafe');      # from hexadecimal
+  $x = Math::BigInt->from_oct('377');       # from octal
+  $x = Math::BigInt->from_bin('1101');      # from binary
+  $x = Math::BigInt->from_base('why', 36);  # from any base
+  $x = Math::BigInt->bzero();               # create a +0
+  $x = Math::BigInt->bone();                # create a +1
+  $x = Math::BigInt->bone('-');             # create a -1
+  $x = Math::BigInt->binf();                # create a +inf
+  $x = Math::BigInt->binf('-');             # create a -inf
+  $x = Math::BigInt->bnan();                # create a Not-A-Number
+  $x = Math::BigInt->bpi();                 # returns pi
 
   $y = $x->copy();         # make a copy (unlike $y = $x)
   $y = $x->as_int();       # return as a Math::BigInt
@@ -4440,6 +4489,7 @@ Math::BigInt - Arbitrary size integer/float math package
   $x->to_bin();       # as signed binary string
   $x->to_oct();       # as signed octal string
   $x->to_bytes();     # as byte string
+  $x->to_base($b);    # as string in any base
 
   $x->as_hex();       # as signed hexadecimal string with prefixed 0x
   $x->as_bin();       # as signed binary string with prefixed 0b
@@ -4747,6 +4797,49 @@ In some special cases, from_bytes() matches the conversion done by unpack():
     $x = Math::BigInt->from_bytes($b);       # = 3305723134637787565
     $y = unpack "Q>", $b;                    # ditto, but scalar
 
+=item from_base()
+
+Given a string, a base, and an optional collation sequence, interpret the
+string as a number in the given base. The collation sequence describes the
+value of each character in the string.
+
+If a collation sequence is not given, a default collation sequence is used. If
+the base is less than or equal to 36, the collation sequence is the string
+consisting of the 36 characters "0" to "9" and "A" to "Z". In this case, the
+letter case in the input is ignored. If the base is greater than 36, and
+smaller than or equal to 62, the collation sequence is the string consisting of
+the 62 characters "0" to "9", "A" to "Z", and "a" to "z". A base larger than 62
+requires the collation sequence to be specified explicitly.
+
+These examples show standard binary, octal, and hexadecimal conversion. All
+cases return 250.
+
+    $x = Math::BigInt->from_base("11111010", 2);
+    $x = Math::BigInt->from_base("372", 8);
+    $x = Math::BigInt->from_base("fa", 16);
+
+When the base is less than or equal to 36, and no collation sequence is given,
+the letter case is ignored, so both of these also return 250:
+
+    $x = Math::BigInt->from_base("6Y", 16);
+    $x = Math::BigInt->from_base("6y", 16);
+
+When the base greater than 36, and no collation sequence is given, the default
+collation sequence contains both uppercase and lowercase letters, so
+the letter case in the input is not ignored:
+
+    $x = Math::BigInt->from_base("6S", 37);         # $x is 250
+    $x = Math::BigInt->from_base("6s", 37);         # $x is 276
+    $x = Math::BigInt->from_base("121", 3);         # $x is 16
+    $x = Math::BigInt->from_base("XYZ", 36);        # $x is 44027
+    $x = Math::BigInt->from_base("Why", 42);        # $x is 58314
+
+The collation sequence can be any set of unique characters. These two cases
+are equivalent
+
+    $x = Math::BigInt->from_base("100", 2, "01");   # $x is 4
+    $x = Math::BigInt->from_base("|--", 2, "-|");   # $x is 4
+
 =item bzero()
 
     $x = Math::BigInt->bzero();
@@ -5176,13 +5269,28 @@ See also L</blog()>.
     $x->bnok($y);               # x over y (binomial coefficient n over k)
 
 Calculates the binomial coefficient n over k, also called the "choose"
-function. The result is equivalent to:
+function, which is
 
-    ( n )      n!
-    | - |  = -------
+    ( n )       n!
+    |   |  = --------
     ( k )    k!(n-k)!
 
-This method was added in v1.84 of Math::BigInt (April 2007).
+when n and k are non-negative. This method implements the full Kronenburg
+extension (Kronenburg, M.J. "The Binomial Coefficient for Negative Arguments."
+18 May 2011. http://arxiv.org/abs/1105.3689/) illustrated by the following
+pseudo-code:
+
+    if n >= 0 and k >= 0:
+        return binomial(n, k)
+    if k >= 0:
+        return (-1)^k*binomial(-n+k-1, k)
+    if k <= n:
+        return (-1)^(n-k)*binomial(-k-1, n-k)
+    else
+        return 0
+
+The behaviour is identical to the behaviour of the Maple and Mathematica
+function for negative integers n, k.
 
 =item bsin()
 
@@ -5619,19 +5727,19 @@ corresponds to the output from C<dparts()>.
 
     $x->to_hex();
 
-Returns a hexadecimal string representation of the number.
+Returns a hexadecimal string representation of the number. See also from_hex().
 
 =item to_bin()
 
     $x->to_bin();
 
-Returns a binary string representation of the number.
+Returns a binary string representation of the number. See also from_bin().
 
 =item to_oct()
 
     $x->to_oct();
 
-Returns an octal string representation of the number.
+Returns an octal string representation of the number. See also from_oct().
 
 =item to_bytes()
 
@@ -5639,7 +5747,27 @@ Returns an octal string representation of the number.
     $s = $x->to_bytes();                    # $s = "cafe"
 
 Returns a byte string representation of the number using big endian byte
-order. The invocand must be a non-negative, finite integer.
+order. The invocand must be a non-negative, finite integer. See also from_bytes().
+
+=item to_base()
+
+    $x = Math::BigInt->new("250");
+    $x->to_base(2);     # returns "11111010"
+    $x->to_base(8);     # returns "372"
+    $x->to_base(16);    # returns "fa"
+
+Returns a string representation of the number in the given base. If a collation
+sequence is given, the collation sequence determines which characters are used
+in the output.
+
+Here are some more examples
+
+    $x = Math::BigInt->new("16")->to_base(3);       # returns "121"
+    $x = Math::BigInt->new("44027")->to_base(36);   # returns "XYZ"
+    $x = Math::BigInt->new("58314")->to_base(42);   # returns "Why"
+    $x = Math::BigInt->new("4")->to_base(2, "-|");  # returns "|--"
+
+See from_base() for information and examples.
 
 =item as_hex()
 
index 6f38f3c..2bb06a0 100644 (file)
@@ -7,7 +7,7 @@ use warnings;
 use Carp qw< carp croak >;
 use Math::BigInt::Lib;
 
-our $VERSION = '1.999813';
+our $VERSION = '1.999816';
 
 our @ISA = ('Math::BigInt::Lib');
 
diff --git a/cpan/Math-BigInt/lib/Math/BigInt/CalcEmu.pm b/cpan/Math-BigInt/lib/Math/BigInt/CalcEmu.pm
deleted file mode 100644 (file)
index b716a6d..0000000
+++ /dev/null
@@ -1,394 +0,0 @@
-package Math::BigInt::CalcEmu;
-
-use 5.006001;
-use strict;
-use warnings;
-
-our $VERSION = '1.999813';
-
-package Math::BigInt;
-
-# See SYNOPSIS below.
-
-my $CALC_EMU;
-
-BEGIN
-  {
-  $CALC_EMU = Math::BigInt->config('lib');
-  # register us with MBI to get notified of future lib changes
-  Math::BigInt::_register_callback( __PACKAGE__, sub { $CALC_EMU = $_[0]; } );
-  }
-
-sub __emu_band
-  {
-  my ($self,$x,$y,$sx,$sy,@r) = @_;
-
-  return $x->bzero(@r) if $y->is_zero() || $x->is_zero();
-
-  my $sign = 0;                                 # sign of result
-  $sign = 1 if $sx == -1 && $sy == -1;
-
-  my ($bx,$by);
-
-  if ($sx == -1)                                # if x is negative
-    {
-    # two's complement: inc and flip all "bits" in $bx
-    $bx = $x->binc()->as_hex();                 # -1 => 0, -2 => 1, -3 => 2 etc
-    $bx =~ s/-?0x//;
-    $bx =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
-    }
-  else
-    {
-    $bx = $x->as_hex();                         # get binary representation
-    $bx =~ s/-?0x//;
-    $bx =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
-    }
-  if ($sy == -1)                                # if y is negative
-    {
-    # two's complement: inc and flip all "bits" in $by
-    $by = $y->copy()->binc()->as_hex();         # -1 => 0, -2 => 1, -3 => 2 etc
-    $by =~ s/-?0x//;
-    $by =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
-    }
-  else
-    {
-    $by = $y->as_hex();                         # get binary representation
-    $by =~ s/-?0x//;
-    $by =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
-    }
-  # now we have bit-strings from X and Y, reverse them for padding
-  $bx = reverse $bx;
-  $by = reverse $by;
-
-  # padd the shorter string
-  my $xx = "\x00"; $xx = "\x0f" if $sx == -1;
-  my $yy = "\x00"; $yy = "\x0f" if $sy == -1;
-  my $diff = CORE::length($bx) - CORE::length($by);
-  if ($diff > 0)
-    {
-    # if $yy eq "\x00", we can cut $bx, otherwise we need to padd $by
-    $by .= $yy x $diff;
-    }
-  elsif ($diff < 0)
-    {
-    # if $xx eq "\x00", we can cut $by, otherwise we need to padd $bx
-    $bx .= $xx x abs($diff);
-    }
-
-  # and the strings together
-  my $r = $bx & $by;
-
-  # and reverse the result again
-  $bx = reverse $r;
-
-  # One of $x or $y was negative, so need to flip bits in the result.
-  # In both cases (one or two of them negative, or both positive) we need
-  # to get the characters back.
-  if ($sign == 1)
-    {
-    $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/0123456789abcdef/;
-    }
-  else
-    {
-    $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/fedcba9876543210/;
-    }
-
-  # leading zeros will be stripped by _from_hex()
-  $bx = '0x' . $bx;
-  $x->{value} = $CALC_EMU->_from_hex( $bx );
-
-  # calculate sign of result
-  $x->{sign} = '+';
-  $x->{sign} = '-' if $sign == 1 && !$x->is_zero();
-
-  $x->bdec() if $sign == 1;
-
-  $x->round(@r);
-  }
-
-sub __emu_bior
-  {
-  my ($self,$x,$y,$sx,$sy,@r) = @_;
-
-  return $x->round(@r) if $y->is_zero();
-
-  my $sign = 0;                                 # sign of result
-  $sign = 1 if ($sx == -1) || ($sy == -1);
-
-  my ($bx,$by);
-
-  if ($sx == -1)                                # if x is negative
-    {
-    # two's complement: inc and flip all "bits" in $bx
-    $bx = $x->binc()->as_hex();                 # -1 => 0, -2 => 1, -3 => 2 etc
-    $bx =~ s/-?0x//;
-    $bx =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
-    }
-  else
-    {
-    $bx = $x->as_hex();                         # get binary representation
-    $bx =~ s/-?0x//;
-    $bx =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
-    }
-  if ($sy == -1)                                # if y is negative
-    {
-    # two's complement: inc and flip all "bits" in $by
-    $by = $y->copy()->binc()->as_hex();         # -1 => 0, -2 => 1, -3 => 2 etc
-    $by =~ s/-?0x//;
-    $by =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
-    }
-  else
-    {
-    $by = $y->as_hex();                         # get binary representation
-    $by =~ s/-?0x//;
-    $by =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
-    }
-  # now we have bit-strings from X and Y, reverse them for padding
-  $bx = reverse $bx;
-  $by = reverse $by;
-
-  # padd the shorter string
-  my $xx = "\x00"; $xx = "\x0f" if $sx == -1;
-  my $yy = "\x00"; $yy = "\x0f" if $sy == -1;
-  my $diff = CORE::length($bx) - CORE::length($by);
-  if ($diff > 0)
-    {
-    $by .= $yy x $diff;
-    }
-  elsif ($diff < 0)
-    {
-    $bx .= $xx x abs($diff);
-    }
-
-  # or the strings together
-  my $r = $bx | $by;
-
-  # and reverse the result again
-  $bx = reverse $r;
-
-  # one of $x or $y was negative, so need to flip bits in the result
-  # in both cases (one or two of them negative, or both positive) we need
-  # to get the characters back.
-  if ($sign == 1)
-    {
-    $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/0123456789abcdef/;
-    }
-  else
-    {
-    $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/fedcba9876543210/;
-    }
-
-  # leading zeros will be stripped by _from_hex()
-  $bx = '0x' . $bx;
-  $x->{value} = $CALC_EMU->_from_hex( $bx );
-
-  # calculate sign of result
-  $x->{sign} = '+';
-  $x->{sign} = '-' if $sign == 1 && !$x->is_zero();
-
-  # if one of X or Y was negative, we need to decrement result
-  $x->bdec() if $sign == 1;
-
-  $x->round(@r);
-  }
-
-sub __emu_bxor
-  {
-  my ($self,$x,$y,$sx,$sy,@r) = @_;
-
-  return $x->round(@r) if $y->is_zero();
-
-  my $sign = 0;                                 # sign of result
-  $sign = 1 if $x->{sign} ne $y->{sign};
-
-  my ($bx,$by);
-
-  if ($sx == -1)                                # if x is negative
-    {
-    # two's complement: inc and flip all "bits" in $bx
-    $bx = $x->binc()->as_hex();                 # -1 => 0, -2 => 1, -3 => 2 etc
-    $bx =~ s/-?0x//;
-    $bx =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
-    }
-  else
-    {
-    $bx = $x->as_hex();                         # get binary representation
-    $bx =~ s/-?0x//;
-    $bx =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
-    }
-  if ($sy == -1)                                # if y is negative
-    {
-    # two's complement: inc and flip all "bits" in $by
-    $by = $y->copy()->binc()->as_hex();         # -1 => 0, -2 => 1, -3 => 2 etc
-    $by =~ s/-?0x//;
-    $by =~ tr/0123456789abcdef/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
-    }
-  else
-    {
-    $by = $y->as_hex();                         # get binary representation
-    $by =~ s/-?0x//;
-    $by =~ tr/fedcba9876543210/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/;
-    }
-  # now we have bit-strings from X and Y, reverse them for padding
-  $bx = reverse $bx;
-  $by = reverse $by;
-
-  # padd the shorter string
-  my $xx = "\x00"; $xx = "\x0f" if $sx == -1;
-  my $yy = "\x00"; $yy = "\x0f" if $sy == -1;
-  my $diff = CORE::length($bx) - CORE::length($by);
-  if ($diff > 0)
-    {
-    $by .= $yy x $diff;
-    }
-  elsif ($diff < 0)
-    {
-    $bx .= $xx x abs($diff);
-    }
-
-  # xor the strings together
-  my $r = $bx ^ $by;
-
-  # and reverse the result again
-  $bx = reverse $r;
-
-  # one of $x or $y was negative, so need to flip bits in the result
-  # in both cases (one or two of them negative, or both positive) we need
-  # to get the characters back.
-  if ($sign == 1)
-    {
-    $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/0123456789abcdef/;
-    }
-  else
-    {
-    $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/fedcba9876543210/;
-    }
-
-  # leading zeros will be stripped by _from_hex()
-  $bx = '0x' . $bx;
-  $x->{value} = $CALC_EMU->_from_hex( $bx );
-
-  # calculate sign of result
-  $x->{sign} = '+';
-  $x->{sign} = '-' if $sx != $sy && !$x->is_zero();
-
-  $x->bdec() if $sign == 1;
-
-  $x->round(@r);
-  }
-
-##############################################################################
-##############################################################################
-
-1;
-
-__END__
-
-=pod
-
-=head1 NAME
-
-Math::BigInt::CalcEmu - Emulate low-level math with BigInt code
-
-=head1 SYNOPSIS
-
-        use Math::BigInt::CalcEmu;
-
-=head1 DESCRIPTION
-
-Contains routines that emulate low-level math functions in BigInt, e.g.
-optional routines the low-level math package does not provide on its own.
-
-Will be loaded on demand and called automatically by BigInt.
-
-Stuff here is really low-priority to optimize, since it is far better to
-implement the operation in the low-level math library directly, possible even
-using a call to the native lib.
-
-=head1 METHODS
-
-=over
-
-=item __emu_bxor
-
-=item __emu_band
-
-=item __emu_bior
-
-=back
-
-=head1 BUGS
-
-Please report any bugs or feature requests to
-C<bug-math-bigint at rt.cpan.org>, or through the web interface at
-L<https://rt.cpan.org/Ticket/Create.html?Queue=Math-BigInt>
-(requires login).
-We will be notified, and then you'll automatically be notified of progress on
-your bug as I make changes.
-
-=head1 SUPPORT
-
-You can find documentation for this module with the perldoc command.
-
-    perldoc Math::BigInt::CalcEmu
-
-You can also look for information at:
-
-=over 4
-
-=item * RT: CPAN's request tracker
-
-L<https://rt.cpan.org/Public/Dist/Display.html?Name=Math-BigInt>
-
-=item * AnnoCPAN: Annotated CPAN documentation
-
-L<http://annocpan.org/dist/Math-BigInt>
-
-=item * CPAN Ratings
-
-L<http://cpanratings.perl.org/dist/Math-BigInt>
-
-=item * Search CPAN
-
-L<http://search.cpan.org/dist/Math-BigInt/>
-
-=item * CPAN Testers Matrix
-
-L<http://matrix.cpantesters.org/?dist=Math-BigInt>
-
-=item * The Bignum mailing list
-
-=over 4
-
-=item * Post to mailing list
-
-C<bignum at lists.scsys.co.uk>
-
-=item * View mailing list
-
-L<http://lists.scsys.co.uk/pipermail/bignum/>
-
-=item * Subscribe/Unsubscribe
-
-L<http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/bignum>
-
-=back
-
-=back
-
-=head1 LICENSE
-
-This program is free software; you may redistribute it and/or modify it under
-the same terms as Perl itself.
-
-=head1 AUTHORS
-
-(c) Tels http://bloodgate.com 2003, 2004 - based on BigInt code by
-Tels from 2001-2003.
-
-=head1 SEE ALSO
-
-L<Math::BigInt>, L<Math::BigFloat>,
-L<Math::BigInt::GMP> and L<Math::BigInt::Pari>.
-
-=cut
index 024b934..883f31f 100644 (file)
@@ -4,7 +4,7 @@ use 5.006001;
 use strict;
 use warnings;
 
-our $VERSION = '1.999813';
+our $VERSION = '1.999816';
 
 use Carp;
 
@@ -1076,6 +1076,261 @@ sub _or {
     return $z;
 }
 
+sub _sand {
+    my ($class, $x, $sx, $y, $sy) = @_;
+
+    return ($class -> _zero(), '+')
+      if $class -> _is_zero($x) || $class -> _is_zero($y);
+
+    my $sign = $sx eq '-' && $sy eq '-' ? '-' : '+';
+
+    my ($bx, $by);
+
+    if ($sx eq '-') {                   # if x is negative
+        # two's complement: inc (dec unsigned value) and flip all "bits" in $bx
+        $bx = $class -> _copy($x);
+        $bx = $class -> _dec($bx);
+        $bx = $class -> _as_hex($bx);
+        $bx =~ s/^-?0x//;
+        $bx =~ tr<0123456789abcdef>
+                <\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00>;
+    } else {                            # if x is positive
+        $bx = $class -> _as_hex($x);    # get binary representation
+        $bx =~ s/^-?0x//;
+        $bx =~ tr<fedcba9876543210>
+                 <\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00>;
+    }
+
+    if ($sy eq '-') {                   # if y is negative
+        # two's complement: inc (dec unsigned value) and flip all "bits" in $by
+        $by = $class -> _copy($y);
+        $by = $class -> _dec($by);
+        $by = $class -> _as_hex($by);
+        $by =~ s/^-?0x//;
+        $by =~ tr<0123456789abcdef>
+                <\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00>;
+    } else {
+        $by = $class -> _as_hex($y);    # get binary representation
+        $by =~ s/^-?0x//;
+        $by =~ tr<fedcba9876543210>
+                <\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00>;
+    }
+
+    # now we have bit-strings from X and Y, reverse them for padding
+    $bx = reverse $bx;
+    $by = reverse $by;
+
+    # padd the shorter string
+    my $xx = "\x00"; $xx = "\x0f" if $sx eq '-';
+    my $yy = "\x00"; $yy = "\x0f" if $sy eq '-';
+    my $diff = CORE::length($bx) - CORE::length($by);
+    if ($diff > 0) {
+        # if $yy eq "\x00", we can cut $bx, otherwise we need to padd $by
+        $by .= $yy x $diff;
+    } elsif ($diff < 0) {
+        # if $xx eq "\x00", we can cut $by, otherwise we need to padd $bx
+        $bx .= $xx x abs($diff);
+    }
+
+    # and the strings together
+    my $r = $bx & $by;
+
+    # and reverse the result again
+    $bx = reverse $r;
+
+    # One of $bx or $by was negative, so need to flip bits in the result. In both
+    # cases (one or two of them negative, or both positive) we need to get the
+    # characters back.
+    if ($sign eq '-') {
+        $bx =~ tr<\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00>
+                 <0123456789abcdef>;
+    } else {
+        $bx =~ tr<\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00>
+                 <fedcba9876543210>;
+    }
+
+    # leading zeros will be stripped by _from_hex()
+    $bx = '0x' . $bx;
+    $bx = $class -> _from_hex($bx);
+
+    $bx = $class -> _inc($bx) if $sign eq '-';
+
+    # avoid negative zero
+    $sign = '+' if $class -> _is_zero($bx);
+
+    return $bx, $sign;
+}
+
+sub _sxor {
+    my ($class, $x, $sx, $y, $sy) = @_;
+
+    return ($class -> _zero(), '+')
+      if $class -> _is_zero($x) && $class -> _is_zero($y);
+
+    my $sign = $sx ne $sy ? '-' : '+';
+
+    my ($bx, $by);
+
+    if ($sx eq '-') {                   # if x is negative
+        # two's complement: inc (dec unsigned value) and flip all "bits" in $bx
+        $bx = $class -> _copy($x);
+        $bx = $class -> _dec($bx);
+        $bx = $class -> _as_hex($bx);
+        $bx =~ s/^-?0x//;
+        $bx =~ tr<0123456789abcdef>
+                <\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00>;
+    } else {                            # if x is positive
+        $bx = $class -> _as_hex($x);    # get binary representation
+        $bx =~ s/^-?0x//;
+        $bx =~ tr<fedcba9876543210>
+                 <\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00>;
+    }
+
+    if ($sy eq '-') {                   # if y is negative
+        # two's complement: inc (dec unsigned value) and flip all "bits" in $by
+        $by = $class -> _copy($y);
+        $by = $class -> _dec($by);
+        $by = $class -> _as_hex($by);
+        $by =~ s/^-?0x//;
+        $by =~ tr<0123456789abcdef>
+                <\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00>;
+    } else {
+        $by = $class -> _as_hex($y);    # get binary representation
+        $by =~ s/^-?0x//;
+        $by =~ tr<fedcba9876543210>
+                <\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00>;
+    }
+
+    # now we have bit-strings from X and Y, reverse them for padding
+    $bx = reverse $bx;
+    $by = reverse $by;
+
+    # padd the shorter string
+    my $xx = "\x00"; $xx = "\x0f" if $sx eq '-';
+    my $yy = "\x00"; $yy = "\x0f" if $sy eq '-';
+    my $diff = CORE::length($bx) - CORE::length($by);
+    if ($diff > 0) {
+        # if $yy eq "\x00", we can cut $bx, otherwise we need to padd $by
+        $by .= $yy x $diff;
+    } elsif ($diff < 0) {
+        # if $xx eq "\x00", we can cut $by, otherwise we need to padd $bx
+        $bx .= $xx x abs($diff);
+    }
+
+    # xor the strings together
+    my $r = $bx ^ $by;
+
+    # and reverse the result again
+    $bx = reverse $r;
+
+    # One of $bx or $by was negative, so need to flip bits in the result. In both
+    # cases (one or two of them negative, or both positive) we need to get the
+    # characters back.
+    if ($sign eq '-') {
+        $bx =~ tr<\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00>
+                 <0123456789abcdef>;
+    } else {
+        $bx =~ tr<\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00>
+                 <fedcba9876543210>;
+    }
+
+    # leading zeros will be stripped by _from_hex()
+    $bx = '0x' . $bx;
+    $bx = $class -> _from_hex($bx);
+
+    $bx = $class -> _inc($bx) if $sign eq '-';
+
+    # avoid negative zero
+    $sign = '+' if $class -> _is_zero($bx);
+
+    return $bx, $sign;
+}
+
+sub _sor {
+    my ($class, $x, $sx, $y, $sy) = @_;
+
+    return ($class -> _zero(), '+')
+      if $class -> _is_zero($x) && $class -> _is_zero($y);
+
+    my $sign = $sx eq '-' || $sy eq '-' ? '-' : '+';
+
+    my ($bx, $by);
+
+    if ($sx eq '-') {                   # if x is negative
+        # two's complement: inc (dec unsigned value) and flip all "bits" in $bx
+        $bx = $class -> _copy($x);
+        $bx = $class -> _dec($bx);
+        $bx = $class -> _as_hex($bx);
+        $bx =~ s/^-?0x//;
+        $bx =~ tr<0123456789abcdef>
+                <\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00>;
+    } else {                            # if x is positive
+        $bx = $class -> _as_hex($x);     # get binary representation
+        $bx =~ s/^-?0x//;
+        $bx =~ tr<fedcba9876543210>
+                 <\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00>;
+    }
+
+    if ($sy eq '-') {                   # if y is negative
+        # two's complement: inc (dec unsigned value) and flip all "bits" in $by
+        $by = $class -> _copy($y);
+        $by = $class -> _dec($by);
+        $by = $class -> _as_hex($by);
+        $by =~ s/^-?0x//;
+        $by =~ tr<0123456789abcdef>
+                <\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00>;
+    } else {
+        $by = $class -> _as_hex($y);     # get binary representation
+        $by =~ s/^-?0x//;
+        $by =~ tr<fedcba9876543210>
+                <\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00>;
+    }
+
+    # now we have bit-strings from X and Y, reverse them for padding
+    $bx = reverse $bx;
+    $by = reverse $by;
+
+    # padd the shorter string
+    my $xx = "\x00"; $xx = "\x0f" if $sx eq '-';
+    my $yy = "\x00"; $yy = "\x0f" if $sy eq '-';
+    my $diff = CORE::length($bx) - CORE::length($by);
+    if ($diff > 0) {
+        # if $yy eq "\x00", we can cut $bx, otherwise we need to padd $by
+        $by .= $yy x $diff;
+    } elsif ($diff < 0) {
+        # if $xx eq "\x00", we can cut $by, otherwise we need to padd $bx
+        $bx .= $xx x abs($diff);
+    }
+
+    # or the strings together
+    my $r = $bx | $by;
+
+    # and reverse the result again
+    $bx = reverse $r;
+
+    # One of $bx or $by was negative, so need to flip bits in the result. In both
+    # cases (one or two of them negative, or both positive) we need to get the
+    # characters back.
+    if ($sign eq '-') {
+        $bx =~ tr<\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00>
+                 <0123456789abcdef>;
+    } else {
+        $bx =~ tr<\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00>
+                 <fedcba9876543210>;
+    }
+
+    # leading zeros will be stripped by _from_hex()
+    $bx = '0x' . $bx;
+    $bx = $class -> _from_hex($bx);
+
+    $bx = $class -> _inc($bx) if $sign eq '-';
+
+    # avoid negative zero
+    $sign = '+' if $class -> _is_zero($bx);
+
+    return $bx, $sign;
+}
+
 sub _to_bin {
     # convert the number to a string of binary digits without prefix
     my ($class, $x) = @_;
@@ -1162,6 +1417,43 @@ sub _to_bytes {
 
 *_as_bytes = \&_to_bytes;
 
+sub _to_base {
+    # convert the number to a string of digits in various bases
+    my $class = shift;
+    my $x     = shift;
+    my $base  = shift;
+    $base = $class -> _new($base) unless ref($base);
+
+    my $collseq;
+    if (@_) {
+        $collseq = shift();
+    } else {
+        if ($class -> _acmp($base, $class -> _new("62")) <= 0) {
+            $collseq = '0123456789' . 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+                                    . 'abcdefghijklmnopqrstuvwxyz';
+        } else {
+            croak "When base > 62, a collation sequence must be given";
+        }
+    }
+
+    my @collseq = split '', $collseq;
+    my %collseq = map { $_ => $collseq[$_] } 0 .. $#collseq;
+
+    my $str   = '';
+    my $tmp   = $class -> _copy($x);
+    my $rem;
+    until ($class -> _is_zero($tmp)) {
+        ($tmp, $rem) = $class -> _div($tmp, $base);
+        my $num = $class -> _num($rem);
+        croak "no character to represent '$num' in collation sequence",
+          " (collation sequence is too short)" if $num > $#collseq;
+        my $chr = $collseq[$num];
+        $str = $chr . $str;
+    }
+    return "0" unless length $str;
+    return $str;
+}
+
 sub _from_hex {
     # Convert a string of hexadecimal digits to a number.
 
@@ -1264,6 +1556,56 @@ sub _from_bytes {
     return $x;
 }
 
+sub _from_base {
+    # convert a string to a decimal number
+    my $class = shift;
+    my $str   = shift;
+    my $base  = shift;
+    $base = $class -> _new($base) unless ref($base);
+
+    my $n = length($str);
+    my $x = $class -> _zero();
+
+    my $collseq;
+    if (@_) {
+        $collseq = shift();
+    } else {
+        if ($class -> _acmp($base, $class -> _new("36")) <= 0) {
+            $str = uc $str;
+            $collseq = '0123456789' . 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
+        } elsif ($class -> _acmp($base, $class -> _new("62")) <= 0) {
+            $collseq = '0123456789' . 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+                                    . 'abcdefghijklmnopqrstuvwxyz';
+        } else {
+            croak "When base > 62, a collation sequence must be given";
+        }
+        $collseq = substr $collseq, 0, $class -> _num($base);
+    }
+
+    # Create a mapping from each character in the collation sequence to the
+    # corresponding integer. Check for duplicates in the collation sequence.
+
+    my @collseq = split '', $collseq;
+    my %collseq;
+    for my $num (0 .. $#collseq) {
+        my $chr = $collseq[$num];
+        die "duplicate character '$chr' in collation sequence"
+          if exists $collseq{$chr};
+        $collseq{$chr} = $num;
+    }
+
+    for (my $i = 0 ; $i < $n ; ++$i) {
+        my $chr = substr($str, $i, 1);
+        die "input character '$chr' does not exist in collation sequence"
+          unless exists $collseq{$chr};
+        $x = $class -> _mul($x, $base);
+        my $num = $class -> _new($collseq{$chr});
+        $x = $class -> _add($x, $num);
+    }
+
+    return $x;
+}
+
 ##############################################################################
 # special modulus functions
 
@@ -1637,6 +1979,37 @@ Returns an object given a byte string representing the number. The byte string
 is in big endian byte order, so the two-byte input string "\x01\x00" should
 give an output value representing the number 256.
 
+=item CLASS-E<gt>_from_base(STR, BASE, COLLSEQ)
+
+Returns an object given a string STR, a base BASE, and a collation sequence
+COLLSEQ. Each character in STR represents a numerical value identical to the
+character's position in COLLSEQ. All characters in STR must be present in
+COLLSEQ.
+
+If BASE is less than or equal to 62, and a collation sequence is not specified,
+a default collation sequence consisting of the 62 characters 0..9, A..Z, and
+a..z is used. If the default collation sequence is used, and the BASE is less
+than or equal to 36, the letter case in STR is ignored.
+
+For instance, with base 3 and collation sequence "-/|", the character "-"
+represents 0, "/" represents 1, and "|" represents 2. So if STR is "/|-", the
+output is 1 * 3**2 + 2 * 3**1 + 0 * 3**0 = 15.
+
+The following examples show standard binary, octal, decimal, and hexadecimal
+conversion. All examples return 250.
+
+    $x = $class -> _from_base("11111010", 2)
+    $x = $class -> _from_base("372", 8)
+    $x = $class -> _from_base("250", 10)
+    $x = $class -> _from_base("FA", 16)
+
+Some more examples, all returning 250:
+
+    $x = $class -> _from_base("100021", 3, "012")
+    $x = $class -> _from_base("3322", 4, "0123")
+    $x = $class -> _from_base("2000", 5, "01234")
+    $x = $class -> _from_base("caaa", 5, "abcde")
+
 =back
 
 =head3 Mathematical functions
@@ -1775,11 +2148,23 @@ Returns bitwise and.
 
 =item CLASS-E<gt>_or(OBJ1, OBJ2)
 
-Return bitwise or.
+Returns bitwise or.
 
 =item CLASS-E<gt>_xor(OBJ1, OBJ2)
 
-Return bitwise exclusive or.
+Returns bitwise exclusive or.
+
+=item CLASS-E<gt>_sand(OBJ1, OBJ2, SIGN1, SIGN2)
+
+Returns bitwise signed and.
+
+=item CLASS-E<gt>_sor(OBJ1, OBJ2, SIGN1, SIGN2)
+
+Returns bitwise signed or.
+
+=item CLASS-E<gt>_sxor(OBJ1, OBJ2, SIGN1, SIGN2)
+
+Returns bitwise signed exclusive or.
 
 =back
 
@@ -1845,6 +2230,19 @@ Returns a byte string representation of OBJ. The byte string is in big endian
 byte order, so if OBJ represents the number 256, the output should be the
 two-byte string "\x01\x00".
 
+=item CLASS-E<gt>_to_base(OBJ, BASE, COLLSEQ)
+
+Returns a string representation of OBJ in base BASE with collation sequence
+COLLSEQ.
+
+    $val = $class -> _new("210");
+    $str = $class -> _to_base($val, 10, "xyz")  # $str is "zyx"
+
+    $val = $class -> _new("32");
+    $str = $class -> _to_base($val, 2, "-|")  # $str is "|-----"
+
+See _from_base() for more information.
+
 =item CLASS-E<gt>_as_bin(OBJ)
 
 Like C<_to_bin()> but with a '0b' prefix.
@@ -1951,30 +2349,6 @@ Perl scalar.
 
 =back
 
-=head2 API optional methods
-
-The following methods are optional, and can be defined if the underlying lib
-has a fast way to do them. If undefined, Math::BigInt will use pure Perl (hence
-slow) fallback routines to emulate these:
-
-=head3 Signed bitwise operators.
-
-=over 4
-
-=item CLASS-E<gt>_signed_or(OBJ1, OBJ2, SIGN1, SIGN2)
-
-Return the signed bitwise or.
-
-=item CLASS-E<gt>_signed_and(OBJ1, OBJ2, SIGN1, SIGN2)
-
-Return the signed bitwise and.
-
-=item CLASS-E<gt>_signed_xor(OBJ1, OBJ2, SIGN1, SIGN2)
-
-Return the signed bitwise exclusive or.
-
-=back
-
 =head1 WRAP YOUR OWN
 
 If you want to port your own favourite C library for big numbers to the
index f613482..73b79d9 100644 (file)
@@ -692,8 +692,8 @@ except that it might be much faster, depending on how the number is represented
 internally.
 
 For instance, if the object $obj represents the hexadecimal number 0xabcde,
-then C<$obj->_rsft(2, 16)> returns an object representing the number 0xabc. The
-"remainer", 0xde, is discarded and not returned.
+then C<< $obj->_rsft(2, 16) >> returns an object representing the number 0xabc.
+The "remainer", 0xde, is discarded and not returned.
 
 =item I<_lsft(OBJ, N, B)>
 
diff --git a/cpan/Math-BigInt/t/bnok-mbf.t b/cpan/Math-BigInt/t/bnok-mbf.t
new file mode 100644 (file)
index 0000000..edeaad8
--- /dev/null
@@ -0,0 +1,1451 @@
+#!perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 4957;
+
+my $class;
+
+BEGIN {
+    $class = 'Math::BigFloat';
+    use_ok($class);
+}
+
+while (<DATA>) {
+    s/#.*$//;                   # remove comments
+    s/\s+$//;                   # remove trailing whitespace
+    next unless length;         # skip empty lines
+
+    my ($nval, $kval, $nokval) = split /:/;
+    my ($n, $k, $got, @got);
+
+    for my $context_is_scalar (0, 1) {
+        for my $k_is_scalar (0, 1) {
+
+            my $test = qq|\$n = $class -> new("$nval");|;
+
+            $test .= $k_is_scalar
+                     ? qq| \$k = "$kval";|
+                     : qq| \$k = $class -> new("$kval");|;
+
+            $test .= $context_is_scalar
+                     ? qq| \$got = \$n -> bnok(\$k);|
+                     : qq| \@got = \$n -> bnok(\$k);|;
+
+            my $desc = "bnok() in ";
+            $desc .= $context_is_scalar ? "scalar context" : "list context";
+            $desc .= $k_is_scalar ? " with k as scalar" : " with k as object";
+
+            subtest $desc,
+              sub {
+                  plan tests => $context_is_scalar ? 7 : 8;
+
+                  eval $test;
+                  is($@, "", "'$test' gives emtpy \$\@");
+
+                  if ($context_is_scalar) {
+
+                      # Check output.
+
+                      is(ref($got), $class,
+                         "'$test' output arg is a $class");
+
+                      is($got -> bstr(), $nokval,
+                         "'$test' output arg has the right value");
+
+                  } else {
+
+                      # Check number of output arguments.
+
+                      cmp_ok(scalar @got, '==', 1,
+                             "'$test' gives one output arg");
+
+                      # Check output.
+
+                      is(ref($got[0]), $class,
+                         "'$test' output arg is a $class");
+
+                      is($got[0] -> bstr(), $nokval,
+                         "'$test' output arg has the right value");
+                  }
+
+                  # Check the invocand.
+
+                  is(ref($n), $class,
+                     "'$test' invocand is still a $class");
+
+                  is($n -> bstr(), $nokval,
+                     "'$test' invocand has the right value");
+
+                  # Check the input argument.
+
+                  if ($k_is_scalar) {
+
+                      is(ref($k), '',
+                         "'$test' second input arg is still a scalar");
+
+                      is($k, $kval,
+                         "'$test' second input arg is unmodified");
+
+                  } else {
+
+                      is(ref($k), $class,
+                         "'$test' second input arg is still a $class");
+
+                      is($k -> bstr(), $kval,
+                         "'$test' second input arg is unmodified");
+                  }
+              };
+        }
+    }
+}
+
+__DATA__
+
+# n and/or k is NaN
+
+NaN:NaN:NaN
+NaN:0:NaN
+NaN:3:NaN
+3:NaN:NaN
+NaN:-3:NaN
+-3:NaN:NaN
+
+# n = inf
+
+inf:-inf:NaN
+inf:-3:0
+inf:-2:0
+inf:-1:0
+inf:0:1
+inf:1:inf
+inf:2:inf
+inf:3:inf
+inf:inf:NaN
+
+# n = -inf
+
+-inf:-inf:NaN
+-inf:-3:0
+-inf:-2:0
+-inf:-1:0
+-inf:0:1
+-inf:1:-inf
+-inf:2:inf
+-inf:3:-inf
+-inf:inf:NaN
+
+# k = inf
+
+-3:inf:NaN
+-2:inf:NaN
+-1:inf:NaN
+0:inf:NaN
+1:inf:NaN
+2:inf:NaN
+3:inf:NaN
+
+# k = -inf
+
+-3:-inf:NaN
+-2:-inf:NaN
+-1:-inf:NaN
+0:-inf:NaN
+1:-inf:NaN
+2:-inf:NaN
+3:-inf:NaN
+
+# n = -15, k = n - 15 ... n + 15
+
+-15:-30:-77558760
+-15:-29:40116600
+-15:-28:-20058300
+-15:-27:9657700
+-15:-26:-4457400
+-15:-25:1961256
+-15:-24:-817190
+-15:-23:319770
+-15:-22:-116280
+-15:-21:38760
+-15:-20:-11628
+-15:-19:3060
+-15:-18:-680
+-15:-17:120
+-15:-16:-15
+-15:-15:1
+-15:-14:0
+-15:-13:0
+-15:-12:0
+-15:-11:0
+-15:-10:0
+-15:-9:0
+-15:-8:0
+-15:-7:0
+-15:-6:0
+-15:-5:0
+-15:-4:0
+-15:-3:0
+-15:-2:0
+-15:-1:0
+-15:0:1
+-15:1:-15
+-15:2:120
+-15:3:-680
+-15:4:3060
+-15:5:-11628
+-15:6:38760
+-15:7:-116280
+-15:8:319770
+-15:9:-817190
+-15:10:1961256
+-15:11:-4457400
+-15:12:9657700
+-15:13:-20058300
+-15:14:40116600
+-15:15:-77558760
+
+# n = -14, k = n - 15 ... n + 15
+
+-14:-29:-37442160
+-14:-28:20058300
+-14:-27:-10400600
+-14:-26:5200300
+-14:-25:-2496144
+-14:-24:1144066
+-14:-23:-497420
+-14:-22:203490
+-14:-21:-77520
+-14:-20:27132
+-14:-19:-8568
+-14:-18:2380
+-14:-17:-560
+-14:-16:105
+-14:-15:-14
+-14:-14:1
+-14:-13:0
+-14:-12:0
+-14:-11:0
+-14:-10:0
+-14:-9:0
+-14:-8:0
+-14:-7:0
+-14:-6:0
+-14:-5:0
+-14:-4:0
+-14:-3:0
+-14:-2:0
+-14:-1:0
+-14:0:1
+-14:1:-14
+-14:2:105
+-14:3:-560
+-14:4:2380
+-14:5:-8568
+-14:6:27132
+-14:7:-77520
+-14:8:203490
+-14:9:-497420
+-14:10:1144066
+-14:11:-2496144
+-14:12:5200300
+-14:13:-10400600
+-14:14:20058300
+-14:15:-37442160
+
+# n = -13, k = n - 15 ... n + 15
+
+-13:-28:-17383860
+-13:-27:9657700
+-13:-26:-5200300
+-13:-25:2704156
+-13:-24:-1352078
+-13:-23:646646
+-13:-22:-293930
+-13:-21:125970
+-13:-20:-50388
+-13:-19:18564
+-13:-18:-6188
+-13:-17:1820
+-13:-16:-455
+-13:-15:91
+-13:-14:-13
+-13:-13:1
+-13:-12:0
+-13:-11:0
+-13:-10:0
+-13:-9:0
+-13:-8:0
+-13:-7:0
+-13:-6:0
+-13:-5:0
+-13:-4:0
+-13:-3:0
+-13:-2:0
+-13:-1:0
+-13:0:1
+-13:1:-13
+-13:2:91
+-13:3:-455
+-13:4:1820
+-13:5:-6188
+-13:6:18564
+-13:7:-50388
+-13:8:125970
+-13:9:-293930
+-13:10:646646
+-13:11:-1352078
+-13:12:2704156
+-13:13:-5200300
+-13:14:9657700
+-13:15:-17383860
+
+# n = -12, k = n - 15 ... n + 15
+
+-12:-27:-7726160
+-12:-26:4457400
+-12:-25:-2496144
+-12:-24:1352078
+-12:-23:-705432
+-12:-22:352716
+-12:-21:-167960
+-12:-20:75582
+-12:-19:-31824
+-12:-18:12376
+-12:-17:-4368
+-12:-16:1365
+-12:-15:-364
+-12:-14:78
+-12:-13:-12
+-12:-12:1
+-12:-11:0
+-12:-10:0
+-12:-9:0
+-12:-8:0
+-12:-7:0
+-12:-6:0
+-12:-5:0
+-12:-4:0
+-12:-3:0
+-12:-2:0
+-12:-1:0
+-12:0:1
+-12:1:-12
+-12:2:78
+-12:3:-364
+-12:4:1365
+-12:5:-4368
+-12:6:12376
+-12:7:-31824
+-12:8:75582
+-12:9:-167960
+-12:10:352716
+-12:11:-705432
+-12:12:1352078
+-12:13:-2496144
+-12:14:4457400
+-12:15:-7726160
+
+# n = -11, k = n - 15 ... n + 15
+
+-11:-26:-3268760
+-11:-25:1961256
+-11:-24:-1144066
+-11:-23:646646
+-11:-22:-352716
+-11:-21:184756
+-11:-20:-92378
+-11:-19:43758
+-11:-18:-19448
+-11:-17:8008
+-11:-16:-3003
+-11:-15:1001
+-11:-14:-286
+-11:-13:66
+-11:-12:-11
+-11:-11:1
+-11:-10:0
+-11:-9:0
+-11:-8:0
+-11:-7:0
+-11:-6:0
+-11:-5:0
+-11:-4:0
+-11:-3:0
+-11:-2:0
+-11:-1:0
+-11:0:1
+-11:1:-11
+-11:2:66
+-11:3:-286
+-11:4:1001
+-11:5:-3003
+-11:6:8008
+-11:7:-19448
+-11:8:43758
+-11:9:-92378
+-11:10:184756
+-11:11:-352716
+-11:12:646646
+-11:13:-1144066
+-11:14:1961256
+-11:15:-3268760
+
+# n = -10, k = n - 15 ... n + 15
+
+-10:-25:-1307504
+-10:-24:817190
+-10:-23:-497420
+-10:-22:293930
+-10:-21:-167960
+-10:-20:92378
+-10:-19:-48620
+-10:-18:24310
+-10:-17:-11440
+-10:-16:5005
+-10:-15:-2002
+-10:-14:715
+-10:-13:-220
+-10:-12:55
+-10:-11:-10
+-10:-10:1
+-10:-9:0
+-10:-8:0
+-10:-7:0
+-10:-6:0
+-10:-5:0
+-10:-4:0
+-10:-3:0
+-10:-2:0
+-10:-1:0
+-10:0:1
+-10:1:-10
+-10:2:55
+-10:3:-220
+-10:4:715
+-10:5:-2002
+-10:6:5005
+-10:7:-11440
+-10:8:24310
+-10:9:-48620
+-10:10:92378
+-10:11:-167960
+-10:12:293930
+-10:13:-497420
+-10:14:817190
+-10:15:-1307504
+
+# n = -9, k = n - 15 ... n + 15
+
+-9:-24:-490314
+-9:-23:319770
+-9:-22:-203490
+-9:-21:125970
+-9:-20:-75582
+-9:-19:43758
+-9:-18:-24310
+-9:-17:12870
+-9:-16:-6435
+-9:-15:3003
+-9:-14:-1287
+-9:-13:495
+-9:-12:-165
+-9:-11:45
+-9:-10:-9
+-9:-9:1
+-9:-8:0
+-9:-7:0
+-9:-6:0
+-9:-5:0
+-9:-4:0
+-9:-3:0
+-9:-2:0
+-9:-1:0
+-9:0:1
+-9:1:-9
+-9:2:45
+-9:3:-165
+-9:4:495
+-9:5:-1287
+-9:6:3003
+-9:7:-6435
+-9:8:12870
+-9:9:-24310
+-9:10:43758
+-9:11:-75582
+-9:12:125970
+-9:13:-203490
+-9:14:319770
+-9:15:-490314
+
+# n = -8, k = n - 15 ... n + 15
+
+-8:-23:-170544
+-8:-22:116280
+-8:-21:-77520
+-8:-20:50388
+-8:-19:-31824
+-8:-18:19448
+-8:-17:-11440
+-8:-16:6435
+-8:-15:-3432
+-8:-14:1716
+-8:-13:-792
+-8:-12:330
+-8:-11:-120
+-8:-10:36
+-8:-9:-8
+-8:-8:1
+-8:-7:0
+-8:-6:0
+-8:-5:0
+-8:-4:0
+-8:-3:0
+-8:-2:0
+-8:-1:0
+-8:0:1
+-8:1:-8
+-8:2:36
+-8:3:-120
+-8:4:330
+-8:5:-792
+-8:6:1716
+-8:7:-3432
+-8:8:6435
+-8:9:-11440
+-8:10:19448
+-8:11:-31824
+-8:12:50388
+-8:13:-77520
+-8:14:116280
+-8:15:-170544
+
+# n = -7, k = n - 15 ... n + 15
+
+-7:-22:-54264
+-7:-21:38760
+-7:-20:-27132
+-7:-19:18564
+-7:-18:-12376
+-7:-17:8008
+-7:-16:-5005
+-7:-15:3003
+-7:-14:-1716
+-7:-13:924
+-7:-12:-462
+-7:-11:210
+-7:-10:-84
+-7:-9:28
+-7:-8:-7
+-7:-7:1
+-7:-6:0
+-7:-5:0
+-7:-4:0
+-7:-3:0
+-7:-2:0
+-7:-1:0
+-7:0:1
+-7:1:-7
+-7:2:28
+-7:3:-84
+-7:4:210
+-7:5:-462
+-7:6:924
+-7:7:-1716
+-7:8:3003
+-7:9:-5005
+-7:10:8008
+-7:11:-12376
+-7:12:18564
+-7:13:-27132
+-7:14:38760
+-7:15:-54264
+
+# n = -6, k = n - 15 ... n + 15
+
+-6:-21:-15504
+-6:-20:11628
+-6:-19:-8568
+-6:-18:6188
+-6:-17:-4368
+-6:-16:3003
+-6:-15:-2002
+-6:-14:1287
+-6:-13:-792
+-6:-12:462
+-6:-11:-252
+-6:-10:126
+-6:-9:-56
+-6:-8:21
+-6:-7:-6
+-6:-6:1
+-6:-5:0
+-6:-4:0
+-6:-3:0
+-6:-2:0
+-6:-1:0
+-6:0:1
+-6:1:-6
+-6:2:21
+-6:3:-56
+-6:4:126
+-6:5:-252
+-6:6:462
+-6:7:-792
+-6:8:1287
+-6:9:-2002
+-6:10:3003
+-6:11:-4368
+-6:12:6188
+-6:13:-8568
+-6:14:11628
+-6:15:-15504
+
+# n = -5, k = n - 15 ... n + 15
+
+-5:-20:-3876
+-5:-19:3060
+-5:-18:-2380
+-5:-17:1820
+-5:-16:-1365
+-5:-15:1001
+-5:-14:-715
+-5:-13:495
+-5:-12:-330
+-5:-11:210
+-5:-10:-126
+-5:-9:70
+-5:-8:-35
+-5:-7:15
+-5:-6:-5
+-5:-5:1
+-5:-4:0
+-5:-3:0
+-5:-2:0
+-5:-1:0
+-5:0:1
+-5:1:-5
+-5:2:15
+-5:3:-35
+-5:4:70
+-5:5:-126
+-5:6:210
+-5:7:-330
+-5:8:495
+-5:9:-715
+-5:10:1001
+-5:11:-1365
+-5:12:1820
+-5:13:-2380
+-5:14:3060
+-5:15:-3876
+
+# n = -4, k = n - 15 ... n + 15
+
+-4:-19:-816
+-4:-18:680
+-4:-17:-560
+-4:-16:455
+-4:-15:-364
+-4:-14:286
+-4:-13:-220
+-4:-12:165
+-4:-11:-120
+-4:-10:84
+-4:-9:-56
+-4:-8:35
+-4:-7:-20
+-4:-6:10
+-4:-5:-4
+-4:-4:1
+-4:-3:0
+-4:-2:0
+-4:-1:0
+-4:0:1
+-4:1:-4
+-4:2:10
+-4:3:-20
+-4:4:35
+-4:5:-56
+-4:6:84
+-4:7:-120
+-4:8:165
+-4:9:-220
+-4:10:286
+-4:11:-364
+-4:12:455
+-4:13:-560
+-4:14:680
+-4:15:-816
+
+# n = -3, k = n - 15 ... n + 15
+
+-3:-18:-136
+-3:-17:120
+-3:-16:-105
+-3:-15:91
+-3:-14:-78
+-3:-13:66
+-3:-12:-55
+-3:-11:45
+-3:-10:-36
+-3:-9:28
+-3:-8:-21
+-3:-7:15
+-3:-6:-10
+-3:-5:6
+-3:-4:-3
+-3:-3:1
+-3:-2:0
+-3:-1:0
+-3:0:1
+-3:1:-3
+-3:2:6
+-3:3:-10
+-3:4:15
+-3:5:-21
+-3:6:28
+-3:7:-36
+-3:8:45
+-3:9:-55
+-3:10:66
+-3:11:-78
+-3:12:91
+-3:13:-105
+-3:14:120
+-3:15:-136
+
+# n = -2, k = n - 15 ... n + 15
+
+-2:-17:-16
+-2:-16:15
+-2:-15:-14
+-2:-14:13
+-2:-13:-12
+-2:-12:11
+-2:-11:-10
+-2:-10:9
+-2:-9:-8
+-2:-8:7
+-2:-7:-6
+-2:-6:5
+-2:-5:-4
+-2:-4:3
+-2:-3:-2
+-2:-2:1
+-2:-1:0
+-2:0:1
+-2:1:-2
+-2:2:3
+-2:3:-4
+-2:4:5
+-2:5:-6
+-2:6:7
+-2:7:-8
+-2:8:9
+-2:9:-10
+-2:10:11
+-2:11:-12
+-2:12:13
+-2:13:-14
+-2:14:15
+-2:15:-16
+
+# n = -1, k = n - 15 ... n + 15
+
+-1:-16:-1
+-1:-15:1
+-1:-14:-1
+-1:-13:1
+-1:-12:-1
+-1:-11:1
+-1:-10:-1
+-1:-9:1
+-1:-8:-1
+-1:-7:1
+-1:-6:-1
+-1:-5:1
+-1:-4:-1
+-1:-3:1
+-1:-2:-1
+-1:-1:1
+-1:0:1
+-1:1:-1
+-1:2:1
+-1:3:-1
+-1:4:1
+-1:5:-1
+-1:6:1
+-1:7:-1
+-1:8:1
+-1:9:-1
+-1:10:1
+-1:11:-1
+-1:12:1
+-1:13:-1
+-1:14:1
+-1:15:-1
+
+# n = 0, k = n - 15 ... n + 15
+
+0:-15:0
+0:-14:0
+0:-13:0
+0:-12:0
+0:-11:0
+0:-10:0
+0:-9:0
+0:-8:0
+0:-7:0
+0:-6:0
+0:-5:0
+0:-4:0
+0:-3:0
+0:-2:0
+0:-1:0
+0:0:1
+0:1:0
+0:2:0
+0:3:0
+0:4:0
+0:5:0
+0:6:0
+0:7:0
+0:8:0
+0:9:0
+0:10:0
+0:11:0
+0:12:0
+0:13:0
+0:14:0
+0:15:0
+
+# n = 1, k = n - 15 ... n + 15
+
+1:-15:0
+1:-14:0
+1:-13:0
+1:-12:0
+1:-11:0
+1:-10:0
+1:-9:0
+1:-8:0
+1:-7:0
+1:-6:0
+1:-5:0
+1:-4:0
+1:-3:0
+1:-2:0
+1:-1:0
+1:0:1
+1:1:1
+1:2:0
+1:3:0
+1:4:0
+1:5:0
+1:6:0
+1:7:0
+1:8:0
+1:9:0
+1:10:0
+1:11:0
+1:12:0
+1:13:0
+1:14:0
+1:15:0
+1:16:0
+
+# n = 2, k = n - 15 ... n + 15
+
+2:-15:0
+2:-14:0
+2:-13:0
+2:-12:0
+2:-11:0
+2:-10:0
+2:-9:0
+2:-8:0
+2:-7:0
+2:-6:0
+2:-5:0
+2:-4:0
+2:-3:0
+2:-2:0
+2:-1:0
+2:0:1
+2:1:2
+2:2:1
+2:3:0
+2:4:0
+2:5:0
+2:6:0
+2:7:0
+2:8:0
+2:9:0
+2:10:0
+2:11:0
+2:12:0
+2:13:0
+2:14:0
+2:15:0
+2:16:0
+2:17:0
+
+# n = 3, k = n - 15 ... n + 15
+
+3:-15:0
+3:-14:0
+3:-13:0
+3:-12:0
+3:-11:0
+3:-10:0
+3:-9:0
+3:-8:0
+3:-7:0
+3:-6:0
+3:-5:0
+3:-4:0
+3:-3:0
+3:-2:0
+3:-1:0
+3:0:1
+3:1:3
+3:2:3
+3:3:1
+3:4:0
+3:5:0
+3:6:0
+3:7:0
+3:8:0
+3:9:0
+3:10:0
+3:11:0
+3:12:0
+3:13:0
+3:14:0
+3:15:0
+3:16:0
+3:17:0
+3:18:0
+
+# n = 4, k = n - 15 ... n + 15
+
+4:-15:0
+4:-14:0
+4:-13:0
+4:-12:0
+4:-11:0
+4:-10:0
+4:-9:0
+4:-8:0
+4:-7:0
+4:-6:0
+4:-5:0
+4:-4:0
+4:-3:0
+4:-2:0
+4:-1:0
+4:0:1
+4:1:4
+4:2:6
+4:3:4
+4:4:1
+4:5:0
+4:6:0
+4:7:0
+4:8:0
+4:9:0
+4:10:0
+4:11:0
+4:12:0
+4:13:0
+4:14:0
+4:15:0
+4:16:0
+4:17:0
+4:18:0
+4:19:0
+
+# n = 5, k = n - 15 ... n + 15
+
+5:-15:0
+5:-14:0
+5:-13:0
+5:-12:0
+5:-11:0
+5:-10:0
+5:-9:0
+5:-8:0
+5:-7:0
+5:-6:0
+5:-5:0
+5:-4:0
+5:-3:0
+5:-2:0
+5:-1:0
+5:0:1
+5:1:5
+5:2:10
+5:3:10
+5:4:5
+5:5:1
+5:6:0
+5:7:0
+5:8:0
+5:9:0
+5:10:0
+5:11:0
+5:12:0
+5:13:0
+5:14:0
+5:15:0
+5:16:0
+5:17:0
+5:18:0
+5:19:0
+5:20:0
+
+# n = 6, k = n - 15 ... n + 15
+
+6:-15:0
+6:-14:0
+6:-13:0
+6:-12:0
+6:-11:0
+6:-10:0
+6:-9:0
+6:-8:0
+6:-7:0
+6:-6:0
+6:-5:0
+6:-4:0
+6:-3:0
+6:-2:0
+6:-1:0
+6:0:1
+6:1:6
+6:2:15
+6:3:20
+6:4:15
+6:5:6
+6:6:1
+6:7:0
+6:8:0
+6:9:0
+6:10:0
+6:11:0
+6:12:0
+6:13:0
+6:14:0
+6:15:0
+6:16:0
+6:17:0
+6:18:0
+6:19:0
+6:20:0
+6:21:0
+
+# n = 7, k = n - 15 ... n + 15
+
+7:-15:0
+7:-14:0
+7:-13:0
+7:-12:0
+7:-11:0
+7:-10:0
+7:-9:0
+7:-8:0
+7:-7:0
+7:-6:0
+7:-5:0
+7:-4:0
+7:-3:0
+7:-2:0
+7:-1:0
+7:0:1
+7:1:7
+7:2:21
+7:3:35
+7:4:35
+7:5:21
+7:6:7
+7:7:1
+7:8:0
+7:9:0
+7:10:0
+7:11:0
+7:12:0
+7:13:0
+7:14:0
+7:15:0
+7:16:0
+7:17:0
+7:18:0
+7:19:0
+7:20:0
+7:21:0
+7:22:0
+
+# n = 8, k = n - 15 ... n + 15
+
+8:-15:0
+8:-14:0
+8:-13:0
+8:-12:0
+8:-11:0
+8:-10:0
+8:-9:0
+8:-8:0
+8:-7:0
+8:-6:0
+8:-5:0
+8:-4:0
+8:-3:0
+8:-2:0
+8:-1:0
+8:0:1
+8:1:8
+8:2:28
+8:3:56
+8:4:70
+8:5:56
+8:6:28
+8:7:8
+8:8:1
+8:9:0
+8:10:0
+8:11:0
+8:12:0
+8:13:0
+8:14:0
+8:15:0
+8:16:0
+8:17:0
+8:18:0
+8:19:0
+8:20:0
+8:21:0
+8:22:0
+8:23:0
+
+# n = 9, k = n - 15 ... n + 15
+
+9:-15:0
+9:-14:0
+9:-13:0
+9:-12:0
+9:-11:0
+9:-10:0
+9:-9:0
+9:-8:0
+9:-7:0
+9:-6:0
+9:-5:0
+9:-4:0
+9:-3:0
+9:-2:0
+9:-1:0
+9:0:1
+9:1:9
+9:2:36
+9:3:84
+9:4:126
+9:5:126
+9:6:84
+9:7:36
+9:8:9
+9:9:1
+9:10:0
+9:11:0
+9:12:0
+9:13:0
+9:14:0
+9:15:0
+9:16:0
+9:17:0
+9:18:0
+9:19:0
+9:20:0
+9:21:0
+9:22:0
+9:23:0
+9:24:0
+
+# n = 10, k = n - 15 ... n + 15
+
+10:-15:0
+10:-14:0
+10:-13:0
+10:-12:0
+10:-11:0
+10:-10:0
+10:-9:0
+10:-8:0
+10:-7:0
+10:-6:0
+10:-5:0
+10:-4:0
+10:-3:0
+10:-2:0
+10:-1:0
+10:0:1
+10:1:10
+10:2:45
+10:3:120
+10:4:210
+10:5:252
+10:6:210
+10:7:120
+10:8:45
+10:9:10
+10:10:1
+10:11:0
+10:12:0
+10:13:0
+10:14:0
+10:15:0
+10:16:0
+10:17:0
+10:18:0
+10:19:0
+10:20:0
+10:21:0
+10:22:0
+10:23:0
+10:24:0
+10:25:0
+
+# n = 11, k = n - 15 ... n + 15
+
+11:-15:0
+11:-14:0
+11:-13:0
+11:-12:0
+11:-11:0
+11:-10:0
+11:-9:0
+11:-8:0
+11:-7:0
+11:-6:0
+11:-5:0
+11:-4:0
+11:-3:0
+11:-2:0
+11:-1:0
+11:0:1
+11:1:11
+11:2:55
+11:3:165
+11:4:330
+11:5:462
+11:6:462
+11:7:330
+11:8:165
+11:9:55
+11:10:11
+11:11:1
+11:12:0
+11:13:0
+11:14:0
+11:15:0
+11:16:0
+11:17:0
+11:18:0
+11:19:0
+11:20:0
+11:21:0
+11:22:0
+11:23:0
+11:24:0
+11:25:0
+11:26:0
+
+# n = 12, k = n - 15 ... n + 15
+
+12:-15:0
+12:-14:0
+12:-13:0
+12:-12:0
+12:-11:0
+12:-10:0
+12:-9:0
+12:-8:0
+12:-7:0
+12:-6:0
+12:-5:0
+12:-4:0
+12:-3:0
+12:-2:0
+12:-1:0
+12:0:1
+12:1:12
+12:2:66
+12:3:220
+12:4:495
+12:5:792
+12:6:924
+12:7:792
+12:8:495
+12:9:220
+12:10:66
+12:11:12
+12:12:1
+12:13:0
+12:14:0
+12:15:0
+12:16:0
+12:17:0
+12:18:0
+12:19:0
+12:20:0
+12:21:0
+12:22:0
+12:23:0
+12:24:0
+12:25:0
+12:26:0
+12:27:0
+
+# n = 13, k = n - 15 ... n + 15
+
+13:-15:0
+13:-14:0
+13:-13:0
+13:-12:0
+13:-11:0
+13:-10:0
+13:-9:0
+13:-8:0
+13:-7:0
+13:-6:0
+13:-5:0
+13:-4:0
+13:-3:0
+13:-2:0
+13:-1:0
+13:0:1
+13:1:13
+13:2:78
+13:3:286
+13:4:715
+13:5:1287
+13:6:1716
+13:7:1716
+13:8:1287
+13:9:715
+13:10:286
+13:11:78
+13:12:13
+13:13:1
+13:14:0
+13:15:0
+13:16:0
+13:17:0
+13:18:0
+13:19:0
+13:20:0
+13:21:0
+13:22:0
+13:23:0
+13:24:0
+13:25:0
+13:26:0
+13:27:0
+13:28:0
+
+# n = 14, k = n - 15 ... n + 15
+
+14:-15:0
+14:-14:0
+14:-13:0
+14:-12:0
+14:-11:0
+14:-10:0
+14:-9:0
+14:-8:0
+14:-7:0
+14:-6:0
+14:-5:0
+14:-4:0
+14:-3:0
+14:-2:0
+14:-1:0
+14:0:1
+14:1:14
+14:2:91
+14:3:364
+14:4:1001
+14:5:2002
+14:6:3003
+14:7:3432
+14:8:3003
+14:9:2002
+14:10:1001
+14:11:364
+14:12:91
+14:13:14
+14:14:1
+14:15:0
+14:16:0
+14:17:0
+14:18:0
+14:19:0
+14:20:0
+14:21:0
+14:22:0
+14:23:0
+14:24:0
+14:25:0
+14:26:0
+14:27:0
+14:28:0
+14:29:0
+
+# n = 15, k = n - 15 ... n + 15
+
+15:-15:0
+15:-14:0
+15:-13:0
+15:-12:0
+15:-11:0
+15:-10:0
+15:-9:0
+15:-8:0
+15:-7:0
+15:-6:0
+15:-5:0
+15:-4:0
+15:-3:0
+15:-2:0
+15:-1:0
+15:0:1
+15:1:15
+15:2:105
+15:3:455
+15:4:1365
+15:5:3003
+15:6:5005
+15:7:6435
+15:8:6435
+15:9:5005
+15:10:3003
+15:11:1365
+15:12:455
+15:13:105
+15:14:15
+15:15:1
+15:16:0
+15:17:0
+15:18:0
+15:19:0
+15:20:0
+15:21:0
+15:22:0
+15:23:0
+15:24:0
+15:25:0
+15:26:0
+15:27:0
+15:28:0
+15:29:0
+15:30:0
diff --git a/cpan/Math-BigInt/t/bnok-mbi.t b/cpan/Math-BigInt/t/bnok-mbi.t
new file mode 100644 (file)
index 0000000..9fd3ab2
--- /dev/null
@@ -0,0 +1,1451 @@
+#!perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 4957;
+
+my $class;
+
+BEGIN {
+    $class = 'Math::BigInt';
+    use_ok($class);
+}
+
+while (<DATA>) {
+    s/#.*$//;                   # remove comments
+    s/\s+$//;                   # remove trailing whitespace
+    next unless length;         # skip empty lines
+
+    my ($nval, $kval, $nokval) = split /:/;
+    my ($n, $k, $got, @got);
+
+    for my $context_is_scalar (0, 1) {
+        for my $k_is_scalar (0, 1) {
+
+            my $test = qq|\$n = $class -> new("$nval");|;
+
+            $test .= $k_is_scalar
+                     ? qq| \$k = "$kval";|
+                     : qq| \$k = $class -> new("$kval");|;
+
+            $test .= $context_is_scalar
+                     ? qq| \$got = \$n -> bnok(\$k);|
+                     : qq| \@got = \$n -> bnok(\$k);|;
+
+            my $desc = "bnok() in ";
+            $desc .= $context_is_scalar ? "scalar context" : "list context";
+            $desc .= $k_is_scalar ? " with k as scalar" : " with k as object";
+
+            subtest $desc,
+              sub {
+                  plan tests => $context_is_scalar ? 7 : 8;
+
+                  eval $test;
+                  is($@, "", "'$test' gives emtpy \$\@");
+
+                  if ($context_is_scalar) {
+
+                      # Check output.
+
+                      is(ref($got), $class,
+                         "'$test' output arg is a $class");
+
+                      is($got -> bstr(), $nokval,
+                         "'$test' output arg has the right value");
+
+                  } else {
+
+                      # Check number of output arguments.
+
+                      cmp_ok(scalar @got, '==', 1,
+                             "'$test' gives one output arg");
+
+                      # Check output.
+
+                      is(ref($got[0]), $class,
+                         "'$test' output arg is a $class");
+
+                      is($got[0] -> bstr(), $nokval,
+                         "'$test' output arg has the right value");
+                  }
+
+                  # Check the invocand.
+
+                  is(ref($n), $class,
+                     "'$test' invocand is still a $class");
+
+                  is($n -> bstr(), $nokval,
+                     "'$test' invocand has the right value");
+
+                  # Check the input argument.
+
+                  if ($k_is_scalar) {
+
+                      is(ref($k), '',
+                         "'$test' second input arg is still a scalar");
+
+                      is($k, $kval,
+                         "'$test' second input arg is unmodified");
+
+                  } else {
+
+                      is(ref($k), $class,
+                         "'$test' second input arg is still a $class");
+
+                      is($k -> bstr(), $kval,
+                         "'$test' second input arg is unmodified");
+                  }
+              };
+        }
+    }
+}
+
+__DATA__
+
+# n and/or k is NaN
+
+NaN:NaN:NaN
+NaN:0:NaN
+NaN:3:NaN
+3:NaN:NaN
+NaN:-3:NaN
+-3:NaN:NaN
+
+# n = inf
+
+inf:-inf:NaN
+inf:-3:0
+inf:-2:0
+inf:-1:0
+inf:0:1
+inf:1:inf
+inf:2:inf
+inf:3:inf
+inf:inf:NaN
+
+# n = -inf
+
+-inf:-inf:NaN
+-inf:-3:0
+-inf:-2:0
+-inf:-1:0
+-inf:0:1
+-inf:1:-inf
+-inf:2:inf
+-inf:3:-inf
+-inf:inf:NaN
+
+# k = inf
+
+-3:inf:NaN
+-2:inf:NaN
+-1:inf:NaN
+0:inf:NaN
+1:inf:NaN
+2:inf:NaN
+3:inf:NaN
+
+# k = -inf
+
+-3:-inf:NaN
+-2:-inf:NaN
+-1:-inf:NaN
+0:-inf:NaN
+1:-inf:NaN
+2:-inf:NaN
+3:-inf:NaN
+
+# n = -15, k = n - 15 ... n + 15
+
+-15:-30:-77558760
+-15:-29:40116600
+-15:-28:-20058300
+-15:-27:9657700
+-15:-26:-4457400
+-15:-25:1961256
+-15:-24:-817190
+-15:-23:319770
+-15:-22:-116280
+-15:-21:38760
+-15:-20:-11628
+-15:-19:3060
+-15:-18:-680
+-15:-17:120
+-15:-16:-15
+-15:-15:1
+-15:-14:0
+-15:-13:0
+-15:-12:0
+-15:-11:0
+-15:-10:0
+-15:-9:0
+-15:-8:0
+-15:-7:0
+-15:-6:0
+-15:-5:0
+-15:-4:0
+-15:-3:0
+-15:-2:0
+-15:-1:0
+-15:0:1
+-15:1:-15
+-15:2:120
+-15:3:-680
+-15:4:3060
+-15:5:-11628
+-15:6:38760
+-15:7:-116280
+-15:8:319770
+-15:9:-817190
+-15:10:1961256
+-15:11:-4457400
+-15:12:9657700
+-15:13:-20058300
+-15:14:40116600
+-15:15:-77558760
+
+# n = -14, k = n - 15 ... n + 15
+
+-14:-29:-37442160
+-14:-28:20058300
+-14:-27:-10400600
+-14:-26:5200300
+-14:-25:-2496144
+-14:-24:1144066
+-14:-23:-497420
+-14:-22:203490
+-14:-21:-77520
+-14:-20:27132
+-14:-19:-8568
+-14:-18:2380
+-14:-17:-560
+-14:-16:105
+-14:-15:-14
+-14:-14:1
+-14:-13:0
+-14:-12:0
+-14:-11:0
+-14:-10:0
+-14:-9:0
+-14:-8:0
+-14:-7:0
+-14:-6:0
+-14:-5:0
+-14:-4:0
+-14:-3:0
+-14:-2:0
+-14:-1:0
+-14:0:1
+-14:1:-14
+-14:2:105
+-14:3:-560
+-14:4:2380
+-14:5:-8568
+-14:6:27132
+-14:7:-77520
+-14:8:203490
+-14:9:-497420
+-14:10:1144066
+-14:11:-2496144
+-14:12:5200300
+-14:13:-10400600
+-14:14:20058300
+-14:15:-37442160
+
+# n = -13, k = n - 15 ... n + 15
+
+-13:-28:-17383860
+-13:-27:9657700
+-13:-26:-5200300
+-13:-25:2704156
+-13:-24:-1352078
+-13:-23:646646
+-13:-22:-293930
+-13:-21:125970
+-13:-20:-50388
+-13:-19:18564
+-13:-18:-6188
+-13:-17:1820
+-13:-16:-455
+-13:-15:91
+-13:-14:-13
+-13:-13:1
+-13:-12:0
+-13:-11:0
+-13:-10:0
+-13:-9:0
+-13:-8:0
+-13:-7:0
+-13:-6:0
+-13:-5:0
+-13:-4:0
+-13:-3:0
+-13:-2:0
+-13:-1:0
+-13:0:1
+-13:1:-13
+-13:2:91
+-13:3:-455
+-13:4:1820
+-13:5:-6188
+-13:6:18564
+-13:7:-50388
+-13:8:125970
+-13:9:-293930
+-13:10:646646
+-13:11:-1352078
+-13:12:2704156
+-13:13:-5200300
+-13:14:9657700
+-13:15:-17383860
+
+# n = -12, k = n - 15 ... n + 15
+
+-12:-27:-7726160
+-12:-26:4457400
+-12:-25:-2496144
+-12:-24:1352078
+-12:-23:-705432
+-12:-22:352716
+-12:-21:-167960
+-12:-20:75582
+-12:-19:-31824
+-12:-18:12376
+-12:-17:-4368
+-12:-16:1365
+-12:-15:-364
+-12:-14:78
+-12:-13:-12
+-12:-12:1
+-12:-11:0
+-12:-10:0
+-12:-9:0
+-12:-8:0
+-12:-7:0
+-12:-6:0
+-12:-5:0
+-12:-4:0
+-12:-3:0
+-12:-2:0
+-12:-1:0
+-12:0:1
+-12:1:-12
+-12:2:78
+-12:3:-364
+-12:4:1365
+-12:5:-4368
+-12:6:12376
+-12:7:-31824
+-12:8:75582
+-12:9:-167960
+-12:10:352716
+-12:11:-705432
+-12:12:1352078
+-12:13:-2496144
+-12:14:4457400
+-12:15:-7726160
+
+# n = -11, k = n - 15 ... n + 15
+
+-11:-26:-3268760
+-11:-25:1961256
+-11:-24:-1144066
+-11:-23:646646
+-11:-22:-352716
+-11:-21:184756
+-11:-20:-92378
+-11:-19:43758
+-11:-18:-19448
+-11:-17:8008
+-11:-16:-3003
+-11:-15:1001
+-11:-14:-286
+-11:-13:66
+-11:-12:-11
+-11:-11:1
+-11:-10:0
+-11:-9:0
+-11:-8:0
+-11:-7:0
+-11:-6:0
+-11:-5:0
+-11:-4:0
+-11:-3:0
+-11:-2:0
+-11:-1:0
+-11:0:1
+-11:1:-11
+-11:2:66
+-11:3:-286
+-11:4:1001
+-11:5:-3003
+-11:6:8008
+-11:7:-19448
+-11:8:43758
+-11:9:-92378
+-11:10:184756
+-11:11:-352716
+-11:12:646646
+-11:13:-1144066
+-11:14:1961256
+-11:15:-3268760
+
+# n = -10, k = n - 15 ... n + 15
+
+-10:-25:-1307504
+-10:-24:817190
+-10:-23:-497420
+-10:-22:293930
+-10:-21:-167960
+-10:-20:92378
+-10:-19:-48620
+-10:-18:24310
+-10:-17:-11440
+-10:-16:5005
+-10:-15:-2002
+-10:-14:715
+-10:-13:-220
+-10:-12:55
+-10:-11:-10
+-10:-10:1
+-10:-9:0
+-10:-8:0
+-10:-7:0
+-10:-6:0
+-10:-5:0
+-10:-4:0
+-10:-3:0
+-10:-2:0
+-10:-1:0
+-10:0:1
+-10:1:-10
+-10:2:55
+-10:3:-220
+-10:4:715
+-10:5:-2002
+-10:6:5005
+-10:7:-11440
+-10:8:24310
+-10:9:-48620
+-10:10:92378
+-10:11:-167960
+-10:12:293930
+-10:13:-497420
+-10:14:817190
+-10:15:-1307504
+
+# n = -9, k = n - 15 ... n + 15
+
+-9:-24:-490314
+-9:-23:319770
+-9:-22:-203490
+-9:-21:125970
+-9:-20:-75582
+-9:-19:43758
+-9:-18:-24310
+-9:-17:12870
+-9:-16:-6435
+-9:-15:3003
+-9:-14:-1287
+-9:-13:495
+-9:-12:-165
+-9:-11:45
+-9:-10:-9
+-9:-9:1
+-9:-8:0
+-9:-7:0
+-9:-6:0
+-9:-5:0
+-9:-4:0
+-9:-3:0
+-9:-2:0
+-9:-1:0
+-9:0:1
+-9:1:-9
+-9:2:45
+-9:3:-165
+-9:4:495
+-9:5:-1287
+-9:6:3003
+-9:7:-6435
+-9:8:12870
+-9:9:-24310
+-9:10:43758
+-9:11:-75582
+-9:12:125970
+-9:13:-203490
+-9:14:319770
+-9:15:-490314
+
+# n = -8, k = n - 15 ... n + 15
+
+-8:-23:-170544
+-8:-22:116280
+-8:-21:-77520
+-8:-20:50388
+-8:-19:-31824
+-8:-18:19448
+-8:-17:-11440
+-8:-16:6435
+-8:-15:-3432
+-8:-14:1716
+-8:-13:-792
+-8:-12:330
+-8:-11:-120
+-8:-10:36
+-8:-9:-8
+-8:-8:1
+-8:-7:0
+-8:-6:0
+-8:-5:0
+-8:-4:0
+-8:-3:0
+-8:-2:0
+-8:-1:0
+-8:0:1
+-8:1:-8
+-8:2:36
+-8:3:-120
+-8:4:330
+-8:5:-792
+-8:6:1716
+-8:7:-3432
+-8:8:6435
+-8:9:-11440
+-8:10:19448
+-8:11:-31824
+-8:12:50388
+-8:13:-77520
+-8:14:116280
+-8:15:-170544
+
+# n = -7, k = n - 15 ... n + 15
+
+-7:-22:-54264
+-7:-21:38760
+-7:-20:-27132
+-7:-19:18564
+-7:-18:-12376
+-7:-17:8008
+-7:-16:-5005
+-7:-15:3003
+-7:-14:-1716
+-7:-13:924
+-7:-12:-462
+-7:-11:210
+-7:-10:-84
+-7:-9:28
+-7:-8:-7
+-7:-7:1
+-7:-6:0
+-7:-5:0
+-7:-4:0
+-7:-3:0
+-7:-2:0
+-7:-1:0
+-7:0:1
+-7:1:-7
+-7:2:28
+-7:3:-84
+-7:4:210
+-7:5:-462
+-7:6:924
+-7:7:-1716
+-7:8:3003
+-7:9:-5005
+-7:10:8008
+-7:11:-12376
+-7:12:18564
+-7:13:-27132
+-7:14:38760
+-7:15:-54264
+
+# n = -6, k = n - 15 ... n + 15
+
+-6:-21:-15504
+-6:-20:11628
+-6:-19:-8568
+-6:-18:6188
+-6:-17:-4368
+-6:-16:3003
+-6:-15:-2002
+-6:-14:1287
+-6:-13:-792
+-6:-12:462
+-6:-11:-252
+-6:-10:126
+-6:-9:-56
+-6:-8:21
+-6:-7:-6
+-6:-6:1
+-6:-5:0
+-6:-4:0
+-6:-3:0
+-6:-2:0
+-6:-1:0
+-6:0:1
+-6:1:-6
+-6:2:21
+-6:3:-56
+-6:4:126
+-6:5:-252
+-6:6:462
+-6:7:-792
+-6:8:1287
+-6:9:-2002
+-6:10:3003
+-6:11:-4368
+-6:12:6188
+-6:13:-8568
+-6:14:11628
+-6:15:-15504
+
+# n = -5, k = n - 15 ... n + 15
+
+-5:-20:-3876
+-5:-19:3060
+-5:-18:-2380
+-5:-17:1820
+-5:-16:-1365
+-5:-15:1001
+-5:-14:-715
+-5:-13:495
+-5:-12:-330
+-5:-11:210
+-5:-10:-126
+-5:-9:70
+-5:-8:-35
+-5:-7:15
+-5:-6:-5
+-5:-5:1
+-5:-4:0
+-5:-3:0
+-5:-2:0
+-5:-1:0
+-5:0:1
+-5:1:-5
+-5:2:15
+-5:3:-35
+-5:4:70
+-5:5:-126
+-5:6:210
+-5:7:-330
+-5:8:495
+-5:9:-715
+-5:10:1001
+-5:11:-1365
+-5:12:1820
+-5:13:-2380
+-5:14:3060
+-5:15:-3876
+
+# n = -4, k = n - 15 ... n + 15
+
+-4:-19:-816
+-4:-18:680
+-4:-17:-560
+-4:-16:455
+-4:-15:-364
+-4:-14:286
+-4:-13:-220
+-4:-12:165
+-4:-11:-120
+-4:-10:84
+-4:-9:-56
+-4:-8:35
+-4:-7:-20
+-4:-6:10
+-4:-5:-4
+-4:-4:1
+-4:-3:0
+-4:-2:0
+-4:-1:0
+-4:0:1
+-4:1:-4
+-4:2:10
+-4:3:-20
+-4:4:35
+-4:5:-56
+-4:6:84
+-4:7:-120
+-4:8:165
+-4:9:-220
+-4:10:286
+-4:11:-364
+-4:12:455
+-4:13:-560
+-4:14:680
+-4:15:-816
+
+# n = -3, k = n - 15 ... n + 15
+
+-3:-18:-136
+-3:-17:120
+-3:-16:-105
+-3:-15:91
+-3:-14:-78
+-3:-13:66
+-3:-12:-55
+-3:-11:45
+-3:-10:-36
+-3:-9:28
+-3:-8:-21
+-3:-7:15
+-3:-6:-10
+-3:-5:6
+-3:-4:-3
+-3:-3:1
+-3:-2:0
+-3:-1:0
+-3:0:1
+-3:1:-3
+-3:2:6
+-3:3:-10
+-3:4:15
+-3:5:-21
+-3:6:28
+-3:7:-36
+-3:8:45
+-3:9:-55
+-3:10:66
+-3:11:-78
+-3:12:91
+-3:13:-105
+-3:14:120
+-3:15:-136
+
+# n = -2, k = n - 15 ... n + 15
+
+-2:-17:-16
+-2:-16:15
+-2:-15:-14
+-2:-14:13
+-2:-13:-12
+-2:-12:11
+-2:-11:-10
+-2:-10:9
+-2:-9:-8
+-2:-8:7
+-2:-7:-6
+-2:-6:5
+-2:-5:-4
+-2:-4:3
+-2:-3:-2
+-2:-2:1
+-2:-1:0
+-2:0:1
+-2:1:-2
+-2:2:3
+-2:3:-4
+-2:4:5
+-2:5:-6
+-2:6:7
+-2:7:-8
+-2:8:9
+-2:9:-10
+-2:10:11
+-2:11:-12
+-2:12:13
+-2:13:-14
+-2:14:15
+-2:15:-16
+
+# n = -1, k = n - 15 ... n + 15
+
+-1:-16:-1
+-1:-15:1
+-1:-14:-1
+-1:-13:1
+-1:-12:-1
+-1:-11:1
+-1:-10:-1
+-1:-9:1
+-1:-8:-1
+-1:-7:1
+-1:-6:-1
+-1:-5:1
+-1:-4:-1
+-1:-3:1
+-1:-2:-1
+-1:-1:1
+-1:0:1
+-1:1:-1
+-1:2:1
+-1:3:-1
+-1:4:1
+-1:5:-1
+-1:6:1
+-1:7:-1
+-1:8:1
+-1:9:-1
+-1:10:1
+-1:11:-1
+-1:12:1
+-1:13:-1
+-1:14:1
+-1:15:-1
+
+# n = 0, k = n - 15 ... n + 15
+
+0:-15:0
+0:-14:0
+0:-13:0
+0:-12:0
+0:-11:0
+0:-10:0
+0:-9:0
+0:-8:0
+0:-7:0
+0:-6:0
+0:-5:0
+0:-4:0
+0:-3:0
+0:-2:0
+0:-1:0
+0:0:1
+0:1:0
+0:2:0
+0:3:0
+0:4:0
+0:5:0
+0:6:0
+0:7:0
+0:8:0
+0:9:0
+0:10:0
+0:11:0
+0:12:0
+0:13:0
+0:14:0
+0:15:0
+
+# n = 1, k = n - 15 ... n + 15
+
+1:-15:0
+1:-14:0
+1:-13:0
+1:-12:0
+1:-11:0
+1:-10:0
+1:-9:0
+1:-8:0
+1:-7:0
+1:-6:0
+1:-5:0
+1:-4:0
+1:-3:0
+1:-2:0
+1:-1:0
+1:0:1
+1:1:1
+1:2:0
+1:3:0
+1:4:0
+1:5:0
+1:6:0
+1:7:0
+1:8:0
+1:9:0
+1:10:0
+1:11:0
+1:12:0
+1:13:0
+1:14:0
+1:15:0
+1:16:0
+
+# n = 2, k = n - 15 ... n + 15
+
+2:-15:0
+2:-14:0
+2:-13:0
+2:-12:0
+2:-11:0
+2:-10:0
+2:-9:0
+2:-8:0
+2:-7:0
+2:-6:0
+2:-5:0
+2:-4:0
+2:-3:0
+2:-2:0
+2:-1:0
+2:0:1
+2:1:2
+2:2:1
+2:3:0
+2:4:0
+2:5:0
+2:6:0
+2:7:0
+2:8:0
+2:9:0
+2:10:0
+2:11:0
+2:12:0
+2:13:0
+2:14:0
+2:15:0
+2:16:0
+2:17:0
+
+# n = 3, k = n - 15 ... n + 15
+
+3:-15:0
+3:-14:0
+3:-13:0
+3:-12:0
+3:-11:0
+3:-10:0
+3:-9:0
+3:-8:0
+3:-7:0
+3:-6:0
+3:-5:0
+3:-4:0
+3:-3:0
+3:-2:0
+3:-1:0
+3:0:1
+3:1:3
+3:2:3
+3:3:1
+3:4:0
+3:5:0
+3:6:0
+3:7:0
+3:8:0
+3:9:0
+3:10:0
+3:11:0
+3:12:0
+3:13:0
+3:14:0
+3:15:0
+3:16:0
+3:17:0
+3:18:0
+
+# n = 4, k = n - 15 ... n + 15
+
+4:-15:0
+4:-14:0
+4:-13:0
+4:-12:0
+4:-11:0
+4:-10:0
+4:-9:0
+4:-8:0
+4:-7:0
+4:-6:0
+4:-5:0
+4:-4:0
+4:-3:0
+4:-2:0
+4:-1:0
+4:0:1
+4:1:4
+4:2:6
+4:3:4
+4:4:1
+4:5:0
+4:6:0
+4:7:0
+4:8:0
+4:9:0
+4:10:0
+4:11:0
+4:12:0
+4:13:0
+4:14:0
+4:15:0
+4:16:0
+4:17:0
+4:18:0
+4:19:0
+
+# n = 5, k = n - 15 ... n + 15
+
+5:-15:0
+5:-14:0
+5:-13:0
+5:-12:0
+5:-11:0
+5:-10:0
+5:-9:0
+5:-8:0
+5:-7:0
+5:-6:0
+5:-5:0
+5:-4:0
+5:-3:0
+5:-2:0
+5:-1:0
+5:0:1
+5:1:5
+5:2:10
+5:3:10
+5:4:5
+5:5:1
+5:6:0
+5:7:0
+5:8:0
+5:9:0
+5:10:0
+5:11:0
+5:12:0
+5:13:0
+5:14:0
+5:15:0
+5:16:0
+5:17:0
+5:18:0
+5:19:0
+5:20:0
+
+# n = 6, k = n - 15 ... n + 15
+
+6:-15:0
+6:-14:0
+6:-13:0
+6:-12:0
+6:-11:0
+6:-10:0
+6:-9:0
+6:-8:0
+6:-7:0
+6:-6:0
+6:-5:0
+6:-4:0
+6:-3:0
+6:-2:0
+6:-1:0
+6:0:1
+6:1:6
+6:2:15
+6:3:20
+6:4:15
+6:5:6
+6:6:1
+6:7:0
+6:8:0
+6:9:0
+6:10:0
+6:11:0
+6:12:0
+6:13:0
+6:14:0
+6:15:0
+6:16:0
+6:17:0
+6:18:0
+6:19:0
+6:20:0
+6:21:0
+
+# n = 7, k = n - 15 ... n + 15
+
+7:-15:0
+7:-14:0
+7:-13:0
+7:-12:0
+7:-11:0
+7:-10:0
+7:-9:0
+7:-8:0
+7:-7:0
+7:-6:0
+7:-5:0
+7:-4:0
+7:-3:0
+7:-2:0
+7:-1:0
+7:0:1
+7:1:7
+7:2:21
+7:3:35
+7:4:35
+7:5:21
+7:6:7
+7:7:1
+7:8:0
+7:9:0
+7:10:0
+7:11:0
+7:12:0
+7:13:0
+7:14:0
+7:15:0
+7:16:0
+7:17:0
+7:18:0
+7:19:0
+7:20:0
+7:21:0
+7:22:0
+
+# n = 8, k = n - 15 ... n + 15
+
+8:-15:0
+8:-14:0
+8:-13:0
+8:-12:0
+8:-11:0
+8:-10:0
+8:-9:0
+8:-8:0
+8:-7:0
+8:-6:0
+8:-5:0
+8:-4:0
+8:-3:0
+8:-2:0
+8:-1:0
+8:0:1
+8:1:8
+8:2:28
+8:3:56
+8:4:70
+8:5:56
+8:6:28
+8:7:8
+8:8:1
+8:9:0
+8:10:0
+8:11:0
+8:12:0
+8:13:0
+8:14:0
+8:15:0
+8:16:0
+8:17:0
+8:18:0
+8:19:0
+8:20:0
+8:21:0
+8:22:0
+8:23:0
+
+# n = 9, k = n - 15 ... n + 15
+
+9:-15:0
+9:-14:0
+9:-13:0
+9:-12:0
+9:-11:0
+9:-10:0
+9:-9:0
+9:-8:0
+9:-7:0
+9:-6:0
+9:-5:0
+9:-4:0
+9:-3:0
+9:-2:0
+9:-1:0
+9:0:1
+9:1:9
+9:2:36
+9:3:84
+9:4:126
+9:5:126
+9:6:84
+9:7:36
+9:8:9
+9:9:1
+9:10:0
+9:11:0
+9:12:0
+9:13:0
+9:14:0
+9:15:0
+9:16:0
+9:17:0
+9:18:0
+9:19:0
+9:20:0
+9:21:0
+9:22:0
+9:23:0
+9:24:0
+
+# n = 10, k = n - 15 ... n + 15
+
+10:-15:0
+10:-14:0
+10:-13:0
+10:-12:0
+10:-11:0
+10:-10:0
+10:-9:0
+10:-8:0
+10:-7:0
+10:-6:0
+10:-5:0
+10:-4:0
+10:-3:0
+10:-2:0
+10:-1:0
+10:0:1
+10:1:10
+10:2:45
+10:3:120
+10:4:210
+10:5:252
+10:6:210
+10:7:120
+10:8:45
+10:9:10
+10:10:1
+10:11:0
+10:12:0
+10:13:0
+10:14:0
+10:15:0
+10:16:0
+10:17:0
+10:18:0
+10:19:0
+10:20:0
+10:21:0
+10:22:0
+10:23:0
+10:24:0
+10:25:0
+
+# n = 11, k = n - 15 ... n + 15
+
+11:-15:0
+11:-14:0
+11:-13:0
+11:-12:0
+11:-11:0
+11:-10:0
+11:-9:0
+11:-8:0
+11:-7:0
+11:-6:0
+11:-5:0
+11:-4:0
+11:-3:0
+11:-2:0
+11:-1:0
+11:0:1
+11:1:11
+11:2:55
+11:3:165
+11:4:330
+11:5:462
+11:6:462
+11:7:330
+11:8:165
+11:9:55
+11:10:11
+11:11:1
+11:12:0
+11:13:0
+11:14:0
+11:15:0
+11:16:0
+11:17:0
+11:18:0
+11:19:0
+11:20:0
+11:21:0
+11:22:0
+11:23:0
+11:24:0
+11:25:0
+11:26:0
+
+# n = 12, k = n - 15 ... n + 15
+
+12:-15:0
+12:-14:0
+12:-13:0
+12:-12:0
+12:-11:0
+12:-10:0
+12:-9:0
+12:-8:0
+12:-7:0
+12:-6:0
+12:-5:0
+12:-4:0
+12:-3:0
+12:-2:0
+12:-1:0
+12:0:1
+12:1:12
+12:2:66
+12:3:220
+12:4:495
+12:5:792
+12:6:924
+12:7:792
+12:8:495
+12:9:220
+12:10:66
+12:11:12
+12:12:1
+12:13:0
+12:14:0
+12:15:0
+12:16:0
+12:17:0
+12:18:0
+12:19:0
+12:20:0
+12:21:0
+12:22:0
+12:23:0
+12:24:0
+12:25:0
+12:26:0
+12:27:0
+
+# n = 13, k = n - 15 ... n + 15
+
+13:-15:0
+13:-14:0
+13:-13:0
+13:-12:0
+13:-11:0
+13:-10:0
+13:-9:0
+13:-8:0
+13:-7:0
+13:-6:0
+13:-5:0
+13:-4:0
+13:-3:0
+13:-2:0
+13:-1:0
+13:0:1
+13:1:13
+13:2:78
+13:3:286
+13:4:715
+13:5:1287
+13:6:1716
+13:7:1716
+13:8:1287
+13:9:715
+13:10:286
+13:11:78
+13:12:13
+13:13:1
+13:14:0
+13:15:0
+13:16:0
+13:17:0
+13:18:0
+13:19:0
+13:20:0
+13:21:0
+13:22:0
+13:23:0
+13:24:0
+13:25:0
+13:26:0
+13:27:0
+13:28:0
+
+# n = 14, k = n - 15 ... n + 15
+
+14:-15:0
+14:-14:0
+14:-13:0
+14:-12:0
+14:-11:0
+14:-10:0
+14:-9:0
+14:-8:0
+14:-7:0
+14:-6:0
+14:-5:0
+14:-4:0
+14:-3:0
+14:-2:0
+14:-1:0
+14:0:1
+14:1:14
+14:2:91
+14:3:364
+14:4:1001
+14:5:2002
+14:6:3003
+14:7:3432
+14:8:3003
+14:9:2002
+14:10:1001
+14:11:364
+14:12:91
+14:13:14
+14:14:1
+14:15:0
+14:16:0
+14:17:0
+14:18:0
+14:19:0
+14:20:0
+14:21:0
+14:22:0
+14:23:0
+14:24:0
+14:25:0
+14:26:0
+14:27:0
+14:28:0
+14:29:0
+
+# n = 15, k = n - 15 ... n + 15
+
+15:-15:0
+15:-14:0
+15:-13:0
+15:-12:0
+15:-11:0
+15:-10:0
+15:-9:0
+15:-8:0
+15:-7:0
+15:-6:0
+15:-5:0
+15:-4:0
+15:-3:0
+15:-2:0
+15:-1:0
+15:0:1
+15:1:15
+15:2:105
+15:3:455
+15:4:1365
+15:5:3003
+15:6:5005
+15:7:6435
+15:8:6435
+15:9:5005
+15:10:3003
+15:11:1365
+15:12:455
+15:13:105
+15:14:15
+15:15:1
+15:16:0
+15:17:0
+15:18:0
+15:19:0
+15:20:0
+15:21:0
+15:22:0
+15:23:0
+15:24:0
+15:25:0
+15:26:0
+15:27:0
+15:28:0
+15:29:0
+15:30:0
index 4241cc6..be72db4 100644 (file)
@@ -6,7 +6,7 @@ use strict;
 use warnings;
 use lib 't';
 
-my $VERSION = '1.999813';       # adjust manually to match latest release
+my $VERSION = '1.999816';       # adjust manually to match latest release
 
 use Test::More tests => 5;
 
diff --git a/cpan/Math-BigInt/t/from_base-mbi.t b/cpan/Math-BigInt/t/from_base-mbi.t
new file mode 100644 (file)
index 0000000..88912cb
--- /dev/null
@@ -0,0 +1,126 @@
+#!perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 176;
+
+my $class;
+
+BEGIN { $class = 'Math::BigInt'; }
+BEGIN { use_ok($class); }
+
+my @data;
+
+while (<DATA>) {
+    s/#.*$//;           # remove comments
+    s/\s+$//;           # remove trailing whitespace
+    next unless length; # skip empty lines
+
+    my @in = split /:/;
+    my $out = pop @in;
+
+    # As class method.
+
+    {
+        my $x;
+        my $test = qq|\$x = $class -> from_base("$in[0]", $in[1]|;
+        $test .= qq|, "$in[2]"| if @in == 3;
+        $test .= qq|);|;
+
+        eval $test;
+        #die $@ if $@;           # this should never happen
+        die "\nThe following test died when eval()'ed. This indicates a ",
+          "broken test\n\n    $test\n\nThe error message was\n\n    $@\n"
+          if $@;
+
+        subtest $test, sub {
+            plan tests => 2,
+
+            is(ref($x), $class, "output arg is a $class");
+            is($x, $out, 'output arg has the right value');
+        };
+    }
+
+    # As instance method.
+
+    {
+        for my $str ("-1", "0", "1", "-inf", "+inf", "NaN") {
+            my $x;
+            my $test = qq|\$x = $class -> new("$str");|;
+            $test .= qq| \$x -> from_base("$in[0]", $in[1]|;
+            $test .= qq|, "$in[2]"| if @in == 3;
+            $test .= qq|);|;
+
+            eval $test;
+            #die $@ if $@;       # this should never happen
+            die "\nThe following test died when eval()'ed. This indicates a ",
+              "broken test\n\n    $test\n\nThe error message was\n\n    $@\n"
+              if $@;
+
+            subtest $test, sub {
+                plan tests => 2,
+
+                is(ref($x), $class, "output arg is a $class");
+                is($x, $out, 'output arg has the right value');
+            };
+        }
+    }
+}
+
+__END__
+
+# Base 2
+
+11111010:2:250
+11111010:2:01:250
+
+# Base 8
+
+372:8:250
+372:8:01234567:250
+
+# Base 10 (in the last case, use a truncted collation sequence that does not
+# include unused characters)
+
+250:10:250
+250:10:0123456789:250
+250:10:012345:250
+
+# Base 16
+
+fa:16:250
+FA:16:250
+fa:16:0123456789abcdef:250
+
+# Base 3
+
+100021:3:250
+100021:3:012:250
+
+/|-:3:-/|:15
+
+# Base 4
+
+3322:4:250
+3322:4:0123:250
+
+# Base 5
+
+2000:5:250
+2000:5:01234:250
+caaa:5:abcde:250
+
+# when base is less than or equal to 36, case is ignored
+
+6Y:36:250
+6y:36:250
+
+6S:37:250
+7H:37:276
+
+121:3:16
+
+XYZ:36:44027
+
+Why:62:125734
diff --git a/cpan/Math-BigInt/t/to_base-mbi.t b/cpan/Math-BigInt/t/to_base-mbi.t
new file mode 100644 (file)
index 0000000..6ffee61
--- /dev/null
@@ -0,0 +1,93 @@
+#!perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 24;
+
+my $class;
+
+BEGIN { $class = 'Math::BigInt'; }
+BEGIN { use_ok($class); }
+
+while (<DATA>) {
+    s/#.*$//;           # remove comments
+    s/\s+$//;           # remove trailing whitespace
+    next unless length; # skip empty lines
+
+    my @in = split /:/;
+    my $out = pop @in;
+
+    my ($x, $xo, $y);
+    my $test = qq|\$x = $class -> new("$in[0]");|;
+    $test .= qq| \$xo = \$x -> copy();|;
+    $test .= qq| \$y = \$x -> to_base($in[1]|;
+    $test .= qq|, "$in[2]"| if @in == 3;
+    $test .= qq|);|;
+
+    eval $test;
+    #die $@ if $@;       # this should never happen
+    die "\nThe following test died when eval()'ed. This indicates a ",
+      "broken test\n\n    $test\n\nThe error message was\n\n    $@\n"
+      if $@;
+
+    subtest $test, sub {
+        plan tests => 2,
+
+        is($x, $xo, "invocand object was not changed");
+        is($y, $out, 'output arg has the right value');
+    };
+}
+
+__END__
+
+# Base 2
+
+250:2:11111010
+250:2:01:11111010
+
+# Base 8
+
+250:8:372
+250:8:01234567:372
+
+# Base 10 (in the last case, use a truncted collation sequence that does not
+# include unused characters)
+
+250:10:250
+250:10:0123456789:250
+250:10:012345:250
+
+# Base 16
+
+250:16:FA
+250:16:0123456789abcdef:fa
+250:16:0123456789abcdef:fa
+
+# Base 3
+
+250:3:100021
+250:3:012:100021
+
+15:3:-/|:/|-
+
+# Base 4
+
+250:4:3322
+250:4:0123:3322
+
+# Base 5
+
+250:5:2000
+250:5:01234:2000
+250:5:abcde:caaa
+
+# Other bases
+
+250:36:6Y
+
+250:37:6S
+
+16:3:121
+44027:36:XYZ
+125734:62:Why