1#!/usr/bin/perl -w 2 3use strict; 4use Test::More tests => 359; 5 6use Math::BigInt::FastCalc; 7 8my ($BASE_LEN, undef, $AND_BITS, $XOR_BITS, $OR_BITS, $BASE_LEN_SMALL, $MAX_VAL) = 9 Math::BigInt::FastCalc->_base_len(); 10 11print "# BASE_LEN = $BASE_LEN\n"; 12print "# MAX_VAL = $MAX_VAL\n"; 13print "# AND_BITS = $AND_BITS\n"; 14print "# XOR_BITS = $XOR_BITS\n"; 15print "# IOR_BITS = $OR_BITS\n"; 16 17# testing of Math::BigInt::FastCalc 18 19my $C = 'Math::BigInt::FastCalc'; # pass classname to sub's 20 21# _new and _str 22my $x = $C->_new("123"); my $y = $C->_new("321"); 23is (ref($x),'ARRAY'); is ($C->_str($x),123); is ($C->_str($y),321); 24 25############################################################################### 26# _add, _sub, _mul, _div 27is ($C->_str($C->_add($x,$y)),444); 28is ($C->_str($C->_sub($x,$y)),123); 29is ($C->_str($C->_mul($x,$y)),39483); 30is ($C->_str($C->_div($x,$y)),123); 31 32############################################################################### 33# check that mul/div doesn't change $y 34# and returns the same reference, not something new 35is ($C->_str($C->_mul($x,$y)),39483); 36is ($C->_str($x),39483); is ($C->_str($y),321); 37 38is ($C->_str($C->_div($x,$y)),123); 39is ($C->_str($x),123); is ($C->_str($y),321); 40 41$x = $C->_new("39483"); 42my ($x1,$r1) = $C->_div($x,$y); 43is ("$x1","$x"); 44$C->_inc($x1); 45is ("$x1","$x"); 46is ($C->_str($r1),'0'); 47 48$x = $C->_new("39483"); # reset 49 50############################################################################### 51my $z = $C->_new("2"); 52is ($C->_str($C->_add($x,$z)),39485); 53my ($re,$rr) = $C->_div($x,$y); 54 55is ($C->_str($re),123); is ($C->_str($rr),2); 56 57# is_zero, _is_one, _one, _zero 58is ($C->_is_zero($x),''); 59is ($C->_is_one($x),''); 60 61is ($C->_str($C->_zero()),"0"); 62is ($C->_str($C->_one()),"1"); 63 64# _two() and _ten() 65is ($C->_str($C->_two()),"2"); 66is ($C->_str($C->_ten()),"10"); 67is ($C->_is_ten($C->_two()),''); 68is ($C->_is_two($C->_two()),1); 69is ($C->_is_ten($C->_ten()),1); 70is ($C->_is_two($C->_ten()),''); 71 72is ($C->_is_one($C->_one()),1); 73is ($C->_is_one($C->_two()), ''); 74is ($C->_is_one($C->_ten()), ''); 75 76is ($C->_is_one($C->_zero()), ''); 77 78is ($C->_is_zero($C->_zero()),1); 79 80is ($C->_is_zero($C->_one()), ''); 81 82# is_odd, is_even 83is ($C->_is_odd($C->_one()),1); is ($C->_is_odd($C->_zero()),''); 84is ($C->_is_even($C->_one()), ''); is ($C->_is_even($C->_zero()),1); 85 86# _len 87for my $method (qw/_alen _len/) 88 { 89 $x = $C->_new("1"); is ($C->$method($x),1); 90 $x = $C->_new("12"); is ($C->$method($x),2); 91 $x = $C->_new("123"); is ($C->$method($x),3); 92 $x = $C->_new("1234"); is ($C->$method($x),4); 93 $x = $C->_new("12345"); is ($C->$method($x),5); 94 $x = $C->_new("123456"); is ($C->$method($x),6); 95 $x = $C->_new("1234567"); is ($C->$method($x),7); 96 $x = $C->_new("12345678"); is ($C->$method($x),8); 97 $x = $C->_new("123456789"); is ($C->$method($x),9); 98 99 $x = $C->_new("8"); is ($C->$method($x),1); 100 $x = $C->_new("21"); is ($C->$method($x),2); 101 $x = $C->_new("321"); is ($C->$method($x),3); 102 $x = $C->_new("4321"); is ($C->$method($x),4); 103 $x = $C->_new("54321"); is ($C->$method($x),5); 104 $x = $C->_new("654321"); is ($C->$method($x),6); 105 $x = $C->_new("7654321"); is ($C->$method($x),7); 106 $x = $C->_new("87654321"); is ($C->$method($x),8); 107 $x = $C->_new("987654321"); is ($C->$method($x),9); 108 109 $x = $C->_new("0"); is ($C->$method($x),1); 110 $x = $C->_new("20"); is ($C->$method($x),2); 111 $x = $C->_new("320"); is ($C->$method($x),3); 112 $x = $C->_new("4320"); is ($C->$method($x),4); 113 $x = $C->_new("54320"); is ($C->$method($x),5); 114 $x = $C->_new("654320"); is ($C->$method($x),6); 115 $x = $C->_new("7654320"); is ($C->$method($x),7); 116 $x = $C->_new("87654320"); is ($C->$method($x),8); 117 $x = $C->_new("987654320"); is ($C->$method($x),9); 118 119 for (my $i = 1; $i < 9; $i++) 120 { 121 my $a = "$i" . '0' x ($i-1); 122 $x = $C->_new($a); 123 print "# Tried len '$a'\n" unless is ($C->_len($x),$i); 124 } 125 } 126 127# _digit 128$x = $C->_new("123456789"); 129is ($C->_digit($x,0),9); 130is ($C->_digit($x,1),8); 131is ($C->_digit($x,2),7); 132is ($C->_digit($x,-1),1); 133is ($C->_digit($x,-2),2); 134is ($C->_digit($x,-3),3); 135 136# _copy 137foreach (qw/ 1 12 123 1234 12345 123456 1234567 12345678 123456789/) 138 { 139 $x = $C->_new("$_"); 140 is ($C->_str($C->_copy($x)),"$_"); 141 is ($C->_str($x),"$_"); # did _copy destroy original x? 142 } 143 144# _zeros 145$x = $C->_new("1256000000"); is ($C->_zeros($x),6); 146$x = $C->_new("152"); is ($C->_zeros($x),0); 147$x = $C->_new("123000"); is ($C->_zeros($x),3); 148$x = $C->_new("0"); is ($C->_zeros($x),0); 149 150# _lsft, _rsft 151$x = $C->_new("10"); $y = $C->_new("3"); 152is ($C->_str($C->_lsft($x,$y,10)),10000); 153$x = $C->_new("20"); $y = $C->_new("3"); 154is ($C->_str($C->_lsft($x,$y,10)),20000); 155 156$x = $C->_new("128"); $y = $C->_new("4"); 157is ($C->_str($C->_lsft($x,$y,2)), 128 << 4); 158 159$x = $C->_new("1000"); $y = $C->_new("3"); 160is ($C->_str($C->_rsft($x,$y,10)),1); 161$x = $C->_new("20000"); $y = $C->_new("3"); 162is ($C->_str($C->_rsft($x,$y,10)),20); 163$x = $C->_new("256"); $y = $C->_new("4"); 164is ($C->_str($C->_rsft($x,$y,2)),256 >> 4); 165 166$x = $C->_new("6411906467305339182857313397200584952398"); 167$y = $C->_new("45"); 168is ($C->_str($C->_rsft($x,$y,10)),0); 169 170# _acmp 171$x = $C->_new("123456789"); 172$y = $C->_new("987654321"); 173is ($C->_acmp($x,$y),-1); 174is ($C->_acmp($y,$x),1); 175is ($C->_acmp($x,$x),0); 176is ($C->_acmp($y,$y),0); 177$x = $C->_new("12"); 178$y = $C->_new("12"); 179is ($C->_acmp($x,$y),0); 180$x = $C->_new("21"); 181is ($C->_acmp($x,$y),1); 182is ($C->_acmp($y,$x),-1); 183$x = $C->_new("123456789"); 184$y = $C->_new("1987654321"); 185is ($C->_acmp($x,$y),-1); 186is ($C->_acmp($y,$x),+1); 187 188$x = $C->_new("1234567890123456789"); 189$y = $C->_new("987654321012345678"); 190is ($C->_acmp($x,$y),1); 191is ($C->_acmp($y,$x),-1); 192is ($C->_acmp($x,$x),0); 193is ($C->_acmp($y,$y),0); 194 195$x = $C->_new("1234"); 196$y = $C->_new("987654321012345678"); 197is ($C->_acmp($x,$y),-1); 198is ($C->_acmp($y,$x),1); 199is ($C->_acmp($x,$x),0); 200is ($C->_acmp($y,$y),0); 201 202# _modinv 203$x = $C->_new("8"); 204$y = $C->_new("5033"); 205my ($xmod,$sign) = $C->_modinv($x,$y); 206is ($C->_str($xmod),'629'); # -629 % 5033 == 4404 207is ($sign, '-'); 208 209# _div 210$x = $C->_new("3333"); $y = $C->_new("1111"); 211is ($C->_str(scalar $C->_div($x,$y)),3); 212$x = $C->_new("33333"); $y = $C->_new("1111"); ($x,$y) = $C->_div($x,$y); 213is ($C->_str($x),30); is ($C->_str($y),3); 214$x = $C->_new("123"); $y = $C->_new("1111"); 215($x,$y) = $C->_div($x,$y); is ($C->_str($x),0); is ($C->_str($y),123); 216 217# _num 218foreach (qw/1 12 123 1234 12345 1234567 12345678 123456789 1234567890/) 219 { 220 $x = $C->_new("$_"); 221 is (ref($x),'ARRAY'); is ($C->_str($x),"$_"); 222 $x = $C->_num($x); is (ref($x),''); is ($x,$_); 223 } 224 225# _sqrt 226$x = $C->_new("144"); is ($C->_str($C->_sqrt($x)),'12'); 227$x = $C->_new("144000000000000"); is ($C->_str($C->_sqrt($x)),'12000000'); 228 229# _root 230$x = $C->_new("81"); my $n = $C->_new("3"); # 4*4*4 = 64, 5*5*5 = 125 231is ($C->_str($C->_root($x,$n)),'4'); # 4.xx => 4.0 232$x = $C->_new("81"); $n = $C->_new("4"); # 3*3*3*3 == 81 233is ($C->_str($C->_root($x,$n)),'3'); 234 235# _pow (and _root) 236$x = $C->_new("0"); $n = $C->_new("3"); # 0 ** y => 0 237is ($C->_str($C->_pow($x,$n)), 0); 238$x = $C->_new("3"); $n = $C->_new("0"); # x ** 0 => 1 239is ($C->_str($C->_pow($x,$n)), 1); 240$x = $C->_new("1"); $n = $C->_new("3"); # 1 ** y => 1 241is ($C->_str($C->_pow($x,$n)), 1); 242$x = $C->_new("5"); $n = $C->_new("1"); # x ** 1 => x 243is ($C->_str($C->_pow($x,$n)), 5); 244 245$x = $C->_new("81"); $n = $C->_new("3"); # 81 ** 3 == 531441 246is ($C->_str($C->_pow($x,$n)),81 ** 3); 247 248is ($C->_str($C->_root($x,$n)),81); 249 250$x = $C->_new("81"); 251is ($C->_str($C->_pow($x,$n)),81 ** 3); 252is ($C->_str($C->_pow($x,$n)),'150094635296999121'); # 531441 ** 3 == 253 254is ($C->_str($C->_root($x,$n)),'531441'); 255is ($C->_str($C->_root($x,$n)),'81'); 256 257$x = $C->_new("81"); $n = $C->_new("14"); 258is ($C->_str($C->_pow($x,$n)),'523347633027360537213511521'); 259is ($C->_str($C->_root($x,$n)),'81'); 260 261$x = $C->_new("523347633027360537213511520"); 262is ($C->_str($C->_root($x,$n)),'80'); 263 264$x = $C->_new("523347633027360537213511522"); 265is ($C->_str($C->_root($x,$n)),'81'); 266 267my $res = [ qw/ 9 31 99 316 999 3162 9999/ ]; 268 269# 99 ** 2 = 9801, 999 ** 2 = 998001 etc 270for my $i (2 .. 9) 271 { 272 $x = '9' x $i; $x = $C->_new($x); 273 $n = $C->_new("2"); 274 my $rc = '9' x ($i-1). '8' . '0' x ($i-1) . '1'; 275 print "# _pow( ", '9' x $i, ", 2) \n" unless 276 is ($C->_str($C->_pow($x,$n)),$rc); 277 278 if ($i <= 7) 279 { 280 $x = '9' x $i; $x = $C->_new($x); 281 $n = '9' x $i; $n = $C->_new($n); 282 print "# _root( ", '9' x $i, ", ", 9 x $i, ") \n" unless 283 is ($C->_str($C->_root($x,$n)),'1'); 284 285 $x = '9' x $i; $x = $C->_new($x); 286 $n = $C->_new("2"); 287 print "# _root( ", '9' x $i, ", ", 9 x $i, ") \n" unless 288 is ($C->_str($C->_root($x,$n)), $res->[$i-2]); 289 } 290 } 291 292############################################################################## 293# _fac 294$x = $C->_new("0"); is ($C->_str($C->_fac($x)),'1'); 295$x = $C->_new("1"); is ($C->_str($C->_fac($x)),'1'); 296$x = $C->_new("2"); is ($C->_str($C->_fac($x)),'2'); 297$x = $C->_new("3"); is ($C->_str($C->_fac($x)),'6'); 298$x = $C->_new("4"); is ($C->_str($C->_fac($x)),'24'); 299$x = $C->_new("5"); is ($C->_str($C->_fac($x)),'120'); 300$x = $C->_new("10"); is ($C->_str($C->_fac($x)),'3628800'); 301$x = $C->_new("11"); is ($C->_str($C->_fac($x)),'39916800'); 302$x = $C->_new("12"); is ($C->_str($C->_fac($x)),'479001600'); 303$x = $C->_new("13"); is ($C->_str($C->_fac($x)),'6227020800'); 304 305# test that _fac modifies $x in place for small arguments 306$x = $C->_new("3"); $C->_fac($x); is ($C->_str($x),'6'); 307$x = $C->_new("13"); $C->_fac($x); is ($C->_str($x),'6227020800'); 308 309############################################################################## 310# _inc and _dec 311foreach (qw/1 11 121 1231 12341 1234561 12345671 123456781 1234567891/) 312 { 313 $x = $C->_new("$_"); $C->_inc($x); 314 print "# \$x = ",$C->_str($x),"\n" 315 unless is ($C->_str($x),substr($_,0,length($_)-1) . '2'); 316 $C->_dec($x); is ($C->_str($x),$_); 317 } 318foreach (qw/19 119 1219 12319 1234519 12345619 123456719 1234567819/) 319 { 320 $x = $C->_new("$_"); $C->_inc($x); 321 print "# \$x = ",$C->_str($x),"\n" 322 unless is ($C->_str($x),substr($_,0,length($_)-2) . '20'); 323 $C->_dec($x); is ($C->_str($x),$_); 324 } 325foreach (qw/999 9999 99999 9999999 99999999 999999999 9999999999 99999999999/) 326 { 327 $x = $C->_new("$_"); $C->_inc($x); 328 print "# \$x = ",$C->_str($x),"\n" 329 unless is ($C->_str($x), '1' . '0' x (length($_))); 330 $C->_dec($x); is ($C->_str($x),$_); 331 } 332 333$x = $C->_new("1000"); $C->_inc($x); is ($C->_str($x),'1001'); 334$C->_dec($x); is ($C->_str($x),'1000'); 335 336my $BL = $C -> _base_len(); 337 338$x = '1' . '0' x $BL; 339$z = '1' . '0' x ($BL-1); $z .= '1'; 340$x = $C->_new($x); $C->_inc($x); is ($C->_str($x),$z); 341 342$x = '1' . '0' x $BL; $z = '9' x $BL; 343$x = $C->_new($x); $C->_dec($x); is ($C->_str($x),$z); 344 345# should not happen: 346# $x = $C->_new("-2"); $y = $C->_new("4"); is ($C->_acmp($x,$y),-1); 347 348############################################################################### 349# _mod 350$x = $C->_new("1000"); $y = $C->_new("3"); 351is ($C->_str(scalar $C->_mod($x,$y)),1); 352$x = $C->_new("1000"); $y = $C->_new("2"); 353is ($C->_str(scalar $C->_mod($x,$y)),0); 354 355# _and, _or, _xor 356$x = $C->_new("5"); $y = $C->_new("2"); 357is ($C->_str(scalar $C->_xor($x,$y)),7); 358$x = $C->_new("5"); $y = $C->_new("2"); 359is ($C->_str(scalar $C->_or($x,$y)),7); 360$x = $C->_new("5"); $y = $C->_new("3"); 361is ($C->_str(scalar $C->_and($x,$y)),1); 362 363# _from_hex, _from_bin, _from_oct 364is ($C->_str( $C->_from_hex("0xFf")),255); 365is ($C->_str( $C->_from_bin("0b10101011")),160+11); 366is ($C->_str( $C->_from_oct("0100")), 8*8); 367is ($C->_str( $C->_from_oct("01000")), 8*8*8); 368is ($C->_str( $C->_from_oct("010001")), 8*8*8*8+1); 369is ($C->_str( $C->_from_oct("010007")), 8*8*8*8+7); 370 371# _as_hex, _as_bin, as_oct 372is ($C->_str( $C->_from_hex( $C->_as_hex( $C->_new("128")))), 128); 373is ($C->_str( $C->_from_bin( $C->_as_bin( $C->_new("128")))), 128); 374is ($C->_str( $C->_from_oct( $C->_as_oct( $C->_new("128")))), 128); 375 376is ($C->_str( $C->_from_oct( $C->_as_oct( $C->_new("123456")))), 123456); 377is ($C->_str( $C->_from_oct( $C->_as_oct( $C->_new("123456789")))), "123456789"); 378is ($C->_str( $C->_from_oct( $C->_as_oct( $C->_new("1234567890123")))), "1234567890123"); 379 380# _1ex 381is ($C->_str($C->_1ex(0)), "1"); 382is ($C->_str($C->_1ex(1)), "10"); 383is ($C->_str($C->_1ex(2)), "100"); 384is ($C->_str($C->_1ex(12)), "1000000000000"); 385is ($C->_str($C->_1ex(16)), "10000000000000000"); 386 387# _check 388$x = $C->_new("123456789"); 389is ($C->_check($x),0); 390is ($C->_check(123),'123 is not a reference'); 391 392############################################################################### 393# __strip_zeros 394 395{ 396 no strict 'refs'; 397 # correct empty arrays 398 $x = &{$C."::__strip_zeros"}([]); is (@$x,1); is ($x->[0],0); 399 # don't strip single elements 400 $x = &{$C."::__strip_zeros"}([0]); is (@$x,1); is ($x->[0],0); 401 $x = &{$C."::__strip_zeros"}([1]); is (@$x,1); is ($x->[0],1); 402 # don't strip non-zero elements 403 $x = &{$C."::__strip_zeros"}([0,1]); 404 is (@$x,2); is ($x->[0],0); is ($x->[1],1); 405 $x = &{$C."::__strip_zeros"}([0,1,2]); 406 is (@$x,3); is ($x->[0],0); is ($x->[1],1); is ($x->[2],2); 407 408 # but strip leading zeros 409 $x = &{$C."::__strip_zeros"}([0,1,2,0]); 410 is (@$x,3); is ($x->[0],0); is ($x->[1],1); is ($x->[2],2); 411 412 $x = &{$C."::__strip_zeros"}([0,1,2,0,0]); 413 is (@$x,3); is ($x->[0],0); is ($x->[1],1); is ($x->[2],2); 414 415 $x = &{$C."::__strip_zeros"}([0,1,2,0,0,0]); 416 is (@$x,3); is ($x->[0],0); is ($x->[1],1); is ($x->[2],2); 417 418 # collapse multiple zeros 419 $x = &{$C."::__strip_zeros"}([0,0,0,0]); 420 is (@$x,1); is ($x->[0],0); 421} 422 423# done 424 4251; 426