ANNOUNCE: Math-BigInt v1.62
[p5sagit/p5-mst-13.2.git] / lib / Math / BigInt / t / bigintc.t
index 9c82d65..22e64c5 100644 (file)
@@ -6,121 +6,340 @@ use Test;
 BEGIN 
   {
   $| = 1;
-  # chdir 't' if -d 't';
-  unshift @INC, '../lib'; # for running manually
-  plan tests => 52;
+  chdir 't' if -d 't';
+  unshift @INC, '../lib';              # for running manually
   }
 
-# testing of Math::BigInt::BitVect, primarily for interface/api and not for the
-# math functionality
-
 use Math::BigInt::Calc;
 
-my $C = 'Math::BigInt::Calc';  # pass classname to sub's
+BEGIN
+  {
+  plan tests => 276;
+  }
+
+# testing of Math::BigInt::Calc
+
+my $C = 'Math::BigInt::Calc';          # pass classname to sub's
 
 # _new and _str
-my $x = _new($C,\"123"); my $y = _new($C,\"321");
-ok (ref($x),'ARRAY'); ok (${_str($C,$x)},123); ok (${_str($C,$y)},321);
+my $x = $C->_new(\"123"); my $y = $C->_new(\"321");
+ok (ref($x),'ARRAY'); ok (${$C->_str($x)},123); ok (${$C->_str($y)},321);
 
+###############################################################################
 # _add, _sub, _mul, _div
+ok (${$C->_str($C->_add($x,$y))},444);
+ok (${$C->_str($C->_sub($x,$y))},123);
+ok (${$C->_str($C->_mul($x,$y))},39483);
+ok (${$C->_str($C->_div($x,$y))},123);
+
+###############################################################################
+# check that mul/div doesn't change $y
+# and returns the same reference, not something new
+ok (${$C->_str($C->_mul($x,$y))},39483);
+ok (${$C->_str($x)},39483); ok (${$C->_str($y)},321);
+
+ok (${$C->_str($C->_div($x,$y))},123);
+ok (${$C->_str($x)},123); ok (${$C->_str($y)},321);
 
-ok (${_str($C,_add($C,$x,$y))},444);
-ok (${_str($C,_sub($C,$x,$y))},123);
-ok (${_str($C,_mul($C,$x,$y))},39483);
-ok (${_str($C,_div($C,$x,$y))},123);
+$x = $C->_new(\"39483");
+my ($x1,$r1) = $C->_div($x,$y);
+ok ("$x1","$x");
+$C->_inc($x1);
+ok ("$x1","$x");
+ok (${$C->_str($r1)},'0');
 
-ok (${_str($C,_mul($C,$x,$y))},39483);
-ok (${_str($C,$x)},39483);
-ok (${_str($C,$y)},321);
-my $z = _new($C,\"2");
-ok (${_str($C,_add($C,$x,$z))},39485);
-my ($re,$rr) = _div($C,$x,$y);
+$x = $C->_new(\"39483");       # reset
 
-ok (${_str($C,$re)},123); ok (${_str($C,$rr)},2);
+###############################################################################
+my $z = $C->_new(\"2");
+ok (${$C->_str($C->_add($x,$z))},39485);
+my ($re,$rr) = $C->_div($x,$y);
+
+ok (${$C->_str($re)},123); ok (${$C->_str($rr)},2);
 
 # is_zero, _is_one, _one, _zero
-ok (_is_zero($C,$x),0);
-ok (_is_one($C,$x),0);
+ok ($C->_is_zero($x)||0,0);
+ok ($C->_is_one($x)||0,0);
+
+ok (${$C->_str($C->_zero())},"0");
+ok (${$C->_str($C->_one())},"1");
+
+# _two() (only used internally)
+ok (${$C->_str($C->_two())},"2");
+
+ok ($C->_is_one($C->_one()),1);
 
-ok (_is_one($C,_one()),1); ok (_is_one($C,_zero()),0);
-ok (_is_zero($C,_zero()),1); ok (_is_zero($C,_one()),0);
+ok ($C->_is_one($C->_zero()) || 0,0);
+
+ok ($C->_is_zero($C->_zero()),1);
+
+ok ($C->_is_zero($C->_one()) || 0,0);
 
 # is_odd, is_even
-ok (_is_odd($C,_one()),1); ok (_is_odd($C,_zero()),0);
-ok (_is_even($C,_one()),0); ok (_is_even($C,_zero()),1);
+ok ($C->_is_odd($C->_one()),1); ok ($C->_is_odd($C->_zero())||0,0);
+ok ($C->_is_even($C->_one()) || 0,0); ok ($C->_is_even($C->_zero()),1);
+
+# _len
+$x = $C->_new(\"1"); ok ($C->_len($x),1);
+$x = $C->_new(\"12"); ok ($C->_len($x),2);
+$x = $C->_new(\"123"); ok ($C->_len($x),3);
+$x = $C->_new(\"1234"); ok ($C->_len($x),4);
+$x = $C->_new(\"12345"); ok ($C->_len($x),5);
+$x = $C->_new(\"123456"); ok ($C->_len($x),6);
+$x = $C->_new(\"1234567"); ok ($C->_len($x),7);
+$x = $C->_new(\"12345678"); ok ($C->_len($x),8);
+$x = $C->_new(\"123456789"); ok ($C->_len($x),9);
+
+$x = $C->_new(\"8"); ok ($C->_len($x),1);
+$x = $C->_new(\"21"); ok ($C->_len($x),2);
+$x = $C->_new(\"321"); ok ($C->_len($x),3);
+$x = $C->_new(\"4321"); ok ($C->_len($x),4);
+$x = $C->_new(\"54321"); ok ($C->_len($x),5);
+$x = $C->_new(\"654321"); ok ($C->_len($x),6);
+$x = $C->_new(\"7654321"); ok ($C->_len($x),7);
+$x = $C->_new(\"87654321"); ok ($C->_len($x),8);
+$x = $C->_new(\"987654321"); ok ($C->_len($x),9);
+
+for (my $i = 1; $i < 9; $i++)
+  {
+  my $a = "$i" . '0' x ($i-1);
+  $x = $C->_new(\$a); 
+  print "# Tried len '$a'\n" unless ok ($C->_len($x),$i);
+  }
 
 # _digit
-$x = _new($C,\"123456789");
-ok (_digit($C,$x,0),9);
-ok (_digit($C,$x,1),8);
-ok (_digit($C,$x,2),7);
-ok (_digit($C,$x,-1),1);
-ok (_digit($C,$x,-2),2);
-ok (_digit($C,$x,-3),3);
+$x = $C->_new(\"123456789");
+ok ($C->_digit($x,0),9);
+ok ($C->_digit($x,1),8);
+ok ($C->_digit($x,2),7);
+ok ($C->_digit($x,-1),1);
+ok ($C->_digit($x,-2),2);
+ok ($C->_digit($x,-3),3);
 
 # _copy
-$x = _new($C,\"12356");
-ok (${_str($C,_copy($C,$x))},12356);
+foreach (qw/ 1 12 123 1234 12345 123456 1234567 12345678 123456789/)
+  {
+  $x = $C->_new(\"$_");
+  ok (${$C->_str($C->_copy($x))},"$_");
+  ok (${$C->_str($x)},"$_");           # did _copy destroy original x?
+  }
 
 # _zeros
-$x = _new($C,\"1256000000"); ok (_zeros($C,$x),6);
-$x = _new($C,\"152"); ok (_zeros($C,$x),0);
-$x = _new($C,\"123000"); ok (_zeros($C,$x),3); 
+$x = $C->_new(\"1256000000"); ok ($C->_zeros($x),6);
+$x = $C->_new(\"152"); ok ($C->_zeros($x),0);
+$x = $C->_new(\"123000"); ok ($C->_zeros($x),3); 
 
 # _lsft, _rsft
-$x = _new($C,\"10"); $y = _new($C,\"3"); 
-ok (${_str($C,_lsft($C,$x,$y,10))},10000);
-$x = _new($C,\"20"); $y = _new($C,\"3"); 
-ok (${_str($C,_lsft($C,$x,$y,10))},20000);
-$x = _new($C,\"128"); $y = _new($C,\"4");
-if (!defined _lsft($C,$x,$y,2)) 
+$x = $C->_new(\"10"); $y = $C->_new(\"3"); 
+ok (${$C->_str($C->_lsft($x,$y,10))},10000);
+$x = $C->_new(\"20"); $y = $C->_new(\"3"); 
+ok (${$C->_str($C->_lsft($x,$y,10))},20000);
+
+$x = $C->_new(\"128"); $y = $C->_new(\"4");
+ok (${$C->_str($C->_lsft($x,$y,2))}, 128 << 4);
+
+$x = $C->_new(\"1000"); $y = $C->_new(\"3"); 
+ok (${$C->_str($C->_rsft($x,$y,10))},1);
+$x = $C->_new(\"20000"); $y = $C->_new(\"3"); 
+ok (${$C->_str($C->_rsft($x,$y,10))},20);
+$x = $C->_new(\"256"); $y = $C->_new(\"4");
+ok (${$C->_str($C->_rsft($x,$y,2))},256 >> 4);
+
+$x = $C->_new(\"6411906467305339182857313397200584952398");
+$y = $C->_new(\"45");
+ok (${$C->_str($C->_rsft($x,$y,10))},0);
+
+# _acmp
+$x = $C->_new(\"123456789");
+$y = $C->_new(\"987654321");
+ok ($C->_acmp($x,$y),-1);
+ok ($C->_acmp($y,$x),1);
+ok ($C->_acmp($x,$x),0);
+ok ($C->_acmp($y,$y),0);
+
+$x = $C->_new(\"1234567890123456789");
+$y = $C->_new(\"987654321012345678");
+ok ($C->_acmp($x,$y),1);
+ok ($C->_acmp($y,$x),-1);
+ok ($C->_acmp($x,$x),0);
+ok ($C->_acmp($y,$y),0);
+
+$x = $C->_new(\"1234");
+$y = $C->_new(\"987654321012345678");
+ok ($C->_acmp($x,$y),-1);
+ok ($C->_acmp($y,$x),1);
+ok ($C->_acmp($x,$x),0);
+ok ($C->_acmp($y,$y),0);
+
+# _modinv
+$x = $C->_new(\"8");
+$y = $C->_new(\"5033");
+my ($xmod,$sign) = $C->_modinv($x,$y);
+ok (${$C->_str($xmod)},'629');         # -629 % 5033 == 4404
+ok ($sign, '-');
+
+# _div
+$x = $C->_new(\"3333"); $y = $C->_new(\"1111");
+ok (${$C->_str(scalar $C->_div($x,$y))},3);
+$x = $C->_new(\"33333"); $y = $C->_new(\"1111"); ($x,$y) = $C->_div($x,$y);
+ok (${$C->_str($x)},30); ok (${$C->_str($y)},3);
+$x = $C->_new(\"123"); $y = $C->_new(\"1111"); 
+($x,$y) = $C->_div($x,$y); ok (${$C->_str($x)},0); ok (${$C->_str($y)},123);
+
+# _num
+foreach (qw/1 12 123 1234 12345 1234567 12345678 123456789 1234567890/)
   {
-  ok (1,1) 
+  $x = $C->_new(\"$_"); 
+  ok (ref($x)||'','ARRAY'); ok (${$C->_str($x)},"$_");
+  $x = $C->_num($x); ok (ref($x)||'',''); ok ($x,$_);
   }
-else
+
+# _sqrt
+$x = $C->_new(\"144"); ok (${$C->_str($C->_sqrt($x))},'12');
+
+# _fac
+$x = $C->_new(\"0"); ok (${$C->_str($C->_fac($x))},'1');
+$x = $C->_new(\"1"); ok (${$C->_str($C->_fac($x))},'1');
+$x = $C->_new(\"2"); ok (${$C->_str($C->_fac($x))},'2');
+$x = $C->_new(\"3"); ok (${$C->_str($C->_fac($x))},'6');
+$x = $C->_new(\"4"); ok (${$C->_str($C->_fac($x))},'24');
+$x = $C->_new(\"5"); ok (${$C->_str($C->_fac($x))},'120');
+$x = $C->_new(\"10"); ok (${$C->_str($C->_fac($x))},'3628800');
+$x = $C->_new(\"11"); ok (${$C->_str($C->_fac($x))},'39916800');
+$x = $C->_new(\"12"); ok (${$C->_str($C->_fac($x))},'479001600');
+
+##############################################################################
+# _inc and _dec
+foreach (qw/1 11 121 1231 12341 1234561 12345671 123456781 1234567891/)
   {
-  ok ('_lsft','undef');
+  $x = $C->_new(\"$_"); $C->_inc($x);
+  print "# \$x = ",${$C->_str($x)},"\n"
+   unless ok (${$C->_str($x)},substr($_,0,length($_)-1) . '2');
+  $C->_dec($x); ok (${$C->_str($x)},$_);
   }
-$x = _new($C,\"1000"); $y = _new($C,\"3"); 
-ok (${_str($C,_rsft($C,$x,$y,10))},1);
-$x = _new($C,\"20000"); $y = _new($C,\"3"); 
-ok (${_str($C,_rsft($C,$x,$y,10))},20);
-$x = _new($C,\"256"); $y = _new($C,\"4");
-if (!defined _rsft($C,$x,$y,2)) 
+foreach (qw/19 119 1219 12319 1234519 12345619 123456719 1234567819/)
   {
-  ok (1,1) 
+  $x = $C->_new(\"$_"); $C->_inc($x);
+  print "# \$x = ",${$C->_str($x)},"\n"
+   unless ok (${$C->_str($x)},substr($_,0,length($_)-2) . '20');
+  $C->_dec($x); ok (${$C->_str($x)},$_);
   }
-else
+foreach (qw/999 9999 99999 9999999 99999999 999999999 9999999999 99999999999/)
   {
-  ok ('_rsft','undef');
+  $x = $C->_new(\"$_"); $C->_inc($x);
+  print "# \$x = ",${$C->_str($x)},"\n"
+   unless ok (${$C->_str($x)}, '1' . '0' x (length($_)));
+  $C->_dec($x); ok (${$C->_str($x)},$_);
   }
 
-# _acmp
-$x = _new($C,\"123456789");
-$y = _new($C,\"987654321");
-ok (_acmp($C,$x,$y),-1);
-ok (_acmp($C,$y,$x),1);
-ok (_acmp($C,$x,$x),0);
-ok (_acmp($C,$y,$y),0);
+$x = $C->_new(\"1000"); $C->_inc($x); ok (${$C->_str($x)},'1001');
+$C->_dec($x); ok (${$C->_str($x)},'1000');
 
-# _div
-$x = _new($C,\"3333"); $y = _new($C,\"1111");
-ok (${_str($C, scalar _div($C,$x,$y))},3);
-$x = _new($C,\"33333"); $y = _new($C,\"1111"); ($x,$y) = _div($C,$x,$y);
-ok (${_str($C,$x)},30); ok (${_str($C,$y)},3);
-$x = _new($C,\"123"); $y = _new($C,\"1111"); 
-($x,$y) = _div($C,$x,$y); ok (${_str($C,$x)},0); ok (${_str($C,$y)},123);
+my $BL;
+{
+  no strict 'refs';
+  $BL = &{"$C"."::_base_len"}();
+}
 
-# _num
-$x = _new($C,\"12345"); $x = _num($C,$x); ok (ref($x)||'',''); ok ($x,12345);
+$x = '1' . '0' x $BL;
+$z = '1' . '0' x ($BL-1); $z .= '1';
+$x = $C->_new(\$x); $C->_inc($x); ok (${$C->_str($x)},$z);
+
+$x = '1' . '0' x $BL; $z = '9' x $BL;
+$x = $C->_new(\$x); $C->_dec($x); ok (${$C->_str($x)},$z);
 
 # should not happen:
-# $x = _new($C,\"-2"); $y = _new($C,\"4"); ok (_acmp($C,$x,$y),-1);
+# $x = $C->_new(\"-2"); $y = $C->_new(\"4"); ok ($C->_acmp($x,$y),-1);
+
+###############################################################################
+# _mod
+$x = $C->_new(\"1000"); $y = $C->_new(\"3");
+ok (${$C->_str(scalar $C->_mod($x,$y))},1);
+$x = $C->_new(\"1000"); $y = $C->_new(\"2");
+ok (${$C->_str(scalar $C->_mod($x,$y))},0);
+
+# _and, _or, _xor
+$x = $C->_new(\"5"); $y = $C->_new(\"2");
+ok (${$C->_str(scalar $C->_xor($x,$y))},7);
+$x = $C->_new(\"5"); $y = $C->_new(\"2");
+ok (${$C->_str(scalar $C->_or($x,$y))},7);
+$x = $C->_new(\"5"); $y = $C->_new(\"3");
+ok (${$C->_str(scalar $C->_and($x,$y))},1);
+
+# _from_hex, _from_bin
+ok (${$C->_str(scalar $C->_from_hex(\"0xFf"))},255);
+ok (${$C->_str(scalar $C->_from_bin(\"0b10101011"))},160+11);
+
+# _as_hex, _as_bin
+ok (${$C->_str(scalar $C->_from_hex( $C->_as_hex( $C->_new(\"128"))))}, 128);
+ok (${$C->_str(scalar $C->_from_bin( $C->_as_bin( $C->_new(\"128"))))}, 128);
 
 # _check
-$x = _new($C,\"123456789");
-ok (_check($C,$x),0);
-ok (_check($C,123),'123 is not a reference');
+$x = $C->_new(\"123456789");
+ok ($C->_check($x),0);
+ok ($C->_check(123),'123 is not a reference');
+
+###############################################################################
+# __strip_zeros
+
+{
+  no strict 'refs';
+  # correct empty arrays
+  $x = &{$C."::__strip_zeros"}([]); ok (@$x,1); ok ($x->[0],0);
+  # don't strip single elements
+  $x = &{$C."::__strip_zeros"}([0]); ok (@$x,1); ok ($x->[0],0);
+  $x = &{$C."::__strip_zeros"}([1]); ok (@$x,1); ok ($x->[0],1);
+  # don't strip non-zero elements
+  $x = &{$C."::__strip_zeros"}([0,1]);
+  ok (@$x,2); ok ($x->[0],0); ok ($x->[1],1);
+  $x = &{$C."::__strip_zeros"}([0,1,2]);
+  ok (@$x,3); ok ($x->[0],0); ok ($x->[1],1); ok ($x->[2],2);
+
+  # but strip leading zeros
+  $x = &{$C."::__strip_zeros"}([0,1,2,0]);
+  ok (@$x,3); ok ($x->[0],0); ok ($x->[1],1); ok ($x->[2],2);
+
+  $x = &{$C."::__strip_zeros"}([0,1,2,0,0]);
+  ok (@$x,3); ok ($x->[0],0); ok ($x->[1],1); ok ($x->[2],2);
+
+  $x = &{$C."::__strip_zeros"}([0,1,2,0,0,0]);
+  ok (@$x,3); ok ($x->[0],0); ok ($x->[1],1); ok ($x->[2],2);
+
+  # collapse multiple zeros
+  $x = &{$C."::__strip_zeros"}([0,0,0,0]);
+  ok (@$x,1); ok ($x->[0],0);
+}
+
+###############################################################################
+# _to_large and _to_small (last since they toy with BASE_LEN etc)
+
+$C->_base_len(5,7); $x = [ qw/67890 12345 67890 12345/ ]; $C->_to_large($x);
+ok (@$x,3);
+ok ($x->[0], '4567890'); ok ($x->[1], '7890123'); ok ($x->[2], '123456');
+
+$C->_base_len(5,7); $x = [ qw/54321 54321 54321 54321/ ]; $C->_to_large($x);
+ok (@$x,3);
+ok ($x->[0], '2154321'); ok ($x->[1], '4321543'); ok ($x->[2], '543215');
+
+$C->_base_len(6,7); $x = [ qw/654321 654321 654321 654321/ ];
+$C->_to_large($x); ok (@$x,4);
+ok ($x->[0], '1654321'); ok ($x->[1], '2165432');
+ok ($x->[2], '3216543'); ok ($x->[3], '654');
+
+$C->_base_len(5,7); $C->_to_small($x); ok (@$x,5);
+ok ($x->[0], '54321'); ok ($x->[1], '43216');
+ok ($x->[2], '32165'); ok ($x->[3], '21654');
+ok ($x->[4], '6543');
+
+$C->_base_len(7,10); $x = [ qw/0000000 0000000 9999990 9999999/ ];
+$C->_to_large($x); ok (@$x,3);
+ok ($x->[0], '0000000000'); ok ($x->[1], '9999900000');
+ok ($x->[2], '99999999');
+
+$C->_base_len(7,10); $x = [ qw/0000000 0000000 9999990 9999999 99/ ];
+$C->_to_large($x); ok (@$x,3);
+ok ($x->[0], '0000000000'); ok ($x->[1], '9999900000');
+ok ($x->[2], '9999999999');
 
 # done