1# -*- mode: perl; -*- 2 3use strict; 4use warnings; 5 6use Test::More tests => 356;; 7 8use Math::BigInt::GMP; 9 10# testing of Math::BigInt::GMP 11 12my $LIB = 'Math::BigInt::GMP'; # pass classname to sub's 13 14# _new and _str 15my $x = $LIB->_new("123"); 16my $y = $LIB->_new("321"); 17is(ref($x), 'Math::BigInt::GMP'); 18is($LIB->_str($x), 123); 19is($LIB->_str($y), 321); 20 21############################################################################### 22 23note "_set()"; 24 25my $b = $LIB->_new("123"); 26$LIB->_set($b, 12); 27is($LIB->_str($b), 12); 28 29############################################################################### 30 31note "_add(), _sub(), _mul(), _div()"; 32 33is($LIB->_str($LIB->_add($x, $y)), 444); 34is($LIB->_str($LIB->_sub($x, $y)), 123); 35is($LIB->_str($x), 123); 36is($LIB->_str($y), 321); 37is($LIB->_str($LIB->_mul($x, $y)), 39483); 38is($LIB->_str(scalar $LIB->_div($x, $y)), 123); 39 40# check that mul/div doesn't change $y 41# and returns the same reference, not something new 42 43is($LIB->_str($LIB->_mul($x, $y)), 39483); 44is($LIB->_str($x), 39483); 45is($LIB->_str($y), 321); 46 47is($LIB->_str(scalar $LIB->_div($x, $y)), 123); 48is($LIB->_str($x), 123); 49is($LIB->_str($y), 321); 50 51$x = $LIB->_new("39483"); 52my ($x1, $r1) = $LIB->_div($x, $y); 53is("$x1", "$x"); 54$LIB->_inc($x1); 55is("$x1", "$x"); 56is($LIB->_str($r1), '0'); 57 58# check that sub modifies the right argument: 59 60$x = $LIB->_new("221"); 61$y = $LIB->_new("444"); 62 63$x = $LIB->_sub($y, $x, 1); # 444 - 221 => 223 64 65is($LIB->_str($x), 223); 66is($LIB->_str($y), 444); 67 68$x = $LIB->_new("444"); 69$y = $LIB->_new("221"); 70 71is($LIB->_str($LIB->_sub($x, $y)), 223); # 444 - 221 => 223 72 73is($LIB->_str($x), 223); 74is($LIB->_str($y), 221); 75 76############################################################################### 77 78$x = $LIB->_new("39483"); # reset 79$y = $LIB->_new("321"); # reset 80 81my $z = $LIB->_new("2"); 82is($LIB->_str($LIB->_add($x, $z)), 39485); 83my ($re, $rr) = $LIB->_div($x, $y); 84 85is($LIB->_str($re), 123); 86is($LIB->_str($rr), 2); 87 88############################################################################## 89 90note "is_zero()"; 91 92is($LIB->_is_zero($x) || 0, 0); 93 94note "_is_one()"; 95 96is($LIB->_is_one($x) || 0, 0); 97 98note "_one()"; 99 100is($LIB->_str($LIB->_zero()), "0"); 101 102note "_zero()"; 103 104is($LIB->_str($LIB->_one()), "1"); 105 106############################################################################## 107 108note "_two()"; 109 110is($LIB->_str($LIB->_two()), "2"); 111is($LIB->_is_ten($LIB->_two()), 0); 112is($LIB->_is_two($LIB->_two()), 1); 113 114note "_ten()"; 115 116is($LIB->_str($LIB->_ten()), "10"); 117is($LIB->_is_ten($LIB->_ten()), 1); 118is($LIB->_is_two($LIB->_ten()), 0); 119 120is($LIB->_is_one($LIB->_one()), 1); 121is($LIB->_is_one($LIB->_two()), 0); 122is($LIB->_is_one($LIB->_ten()), 0); 123 124is($LIB->_is_one($LIB->_zero()) || 0, 0); 125 126is($LIB->_is_zero($LIB->_zero()), 1); 127 128is($LIB->_is_zero($LIB->_one()) || 0, 0); 129 130############################################################################### 131 132note "is_odd()"; 133 134is($LIB->_is_odd($LIB->_one()), 1); 135is($LIB->_is_odd($LIB->_zero()) || 0, 0); 136 137note "is_even()"; 138 139is($LIB->_is_even($LIB->_one()) || 0, 0); 140is($LIB->_is_even($LIB->_zero()), 1); 141 142############################################################################### 143 144note "_len() and _alen()"; 145 146sub _check_len { 147 my ($str, $method) = @_; 148 149 my $n = length($str); 150 my $x = $LIB->_new($str); 151 152 # _len() is exact 153 is($LIB->_len($x), $n); 154 155 # _alen() is equal or at most one bigger 156 my $alen = $LIB->_alen($x); 157 ok($n -1 <= $alen && $alen <= $n + 1, 158 qq|\$x = $LIB->_new("$str"); $LIB->_alen(\$x)|) 159 or diag sprintf <<"EOF", $alen, $n - 1, $n, $n + 1; 160 got: '%d' 161 expected: '%d', '%d' or '%d' 162EOF 163} 164 165_check_len("1"); 166_check_len("12"); 167_check_len("123"); 168_check_len("1234"); 169_check_len("12345"); 170_check_len("123456"); 171_check_len("1234567"); 172_check_len("12345678"); 173_check_len("123456789"); 174_check_len("1234567890"); 175_check_len("7"); 176_check_len("8"); 177_check_len("9"); 178_check_len("10"); 179_check_len("11"); 180_check_len("21"); 181_check_len("321"); 182_check_len("320"); 183_check_len("4321"); 184_check_len("54321"); 185_check_len("654321"); 186_check_len("7654321"); 187_check_len("7654321"); 188_check_len("87654321"); 189_check_len("987654321"); 190_check_len("9876543219876543210"); 191_check_len("1234567890" x 10); 192_check_len("1234567890" x 100); 193 194for (my $i = 1; $i < 9; $i++) { 195 my $a = "$i" . '0' x ($i-1); 196 _check_len($a); 197} 198 199############################################################################### 200 201note "_digit()"; 202 203$x = $LIB->_new("123456789"); 204is($LIB->_digit($x, 0), 9); 205is($LIB->_digit($x, 1), 8); 206is($LIB->_digit($x, 2), 7); 207is($LIB->_digit($x, -1), 1); 208is($LIB->_digit($x, -2), 2); 209is($LIB->_digit($x, -3), 3); 210 211############################################################################### 212 213note "_copy()"; 214 215foreach (qw/ 1 12 123 1234 12345 123456 1234567 12345678 123456789/) { 216 $x = $LIB->_new("$_"); 217 is($LIB->_str($LIB->_copy($x)), "$_"); 218 is($LIB->_str($x), "$_"); # did _copy destroy original x? 219} 220 221############################################################################### 222 223note "_zeros()"; 224 225$x = $LIB->_new("1256000000"); 226is($LIB->_zeros($x), 6); 227 228$x = $LIB->_new("152"); 229is($LIB->_zeros($x), 0); 230 231$x = $LIB->_new("123000"); 232is($LIB->_zeros($x), 3); 233 234$x = $LIB->_new("123001"); 235is($LIB->_zeros($x), 0); 236 237$x = $LIB->_new("1"); 238is($LIB->_zeros($x), 0); 239 240$x = $LIB->_new("8"); 241is($LIB->_zeros($x), 0); 242 243$x = $LIB->_new("10"); 244is($LIB->_zeros($x), 1); 245 246$x = $LIB->_new("11"); 247is($LIB->_zeros($x), 0); 248 249$x = $LIB->_new("0"); 250is($LIB->_zeros($x), 0); 251 252############################################################################### 253 254note "_lsft()"; 255 256$x = $LIB->_new("10"); 257$y = $LIB->_new("3"); 258is($LIB->_str($LIB->_lsft($x, $y, 10)), 10000); 259 260$x = $LIB->_new("20"); 261$y = $LIB->_new("3"); 262is($LIB->_str($LIB->_lsft($x, $y, 10)), 20000); 263 264$x = $LIB->_new("128"); 265$y = $LIB->_new("4"); 266is($LIB->_str($LIB->_lsft($x, $y, 2)), 128 << 4); 267 268note "_rsft()"; 269 270$x = $LIB->_new("1000"); 271$y = $LIB->_new("3"); 272is($LIB->_str($LIB->_rsft($x, $y, 10)), 1); 273 274$x = $LIB->_new("20000"); 275$y = $LIB->_new("3"); 276is($LIB->_str($LIB->_rsft($x, $y, 10)), 20); 277 278$x = $LIB->_new("256"); 279$y = $LIB->_new("4"); 280is($LIB->_str($LIB->_rsft($x, $y, 2)), 256 >> 4); 281 282$x = $LIB->_new("6411906467305339182857313397200584952398"); 283$y = $LIB->_new("45"); 284is($LIB->_str($LIB->_rsft($x, $y, 10)), 0); 285 286############################################################################### 287 288note "_acmp()"; 289 290$x = $LIB->_new("123456789"); 291$y = $LIB->_new("987654321"); 292is($LIB->_acmp($x, $y), -1); 293is($LIB->_acmp($y, $x), 1); 294is($LIB->_acmp($x, $x), 0); 295is($LIB->_acmp($y, $y), 0); 296$x = $LIB->_new("12"); 297$y = $LIB->_new("12"); 298is($LIB->_acmp($x, $y), 0); 299$x = $LIB->_new("21"); 300is($LIB->_acmp($x, $y), 1); 301is($LIB->_acmp($y, $x), -1); 302$x = $LIB->_new("123456789"); 303$y = $LIB->_new("1987654321"); 304is($LIB->_acmp($x, $y), -1); 305is($LIB->_acmp($y, $x), +1); 306 307$x = $LIB->_new("1234567890123456789"); 308$y = $LIB->_new("987654321012345678"); 309is($LIB->_acmp($x, $y), 1); 310is($LIB->_acmp($y, $x), -1); 311is($LIB->_acmp($x, $x), 0); 312is($LIB->_acmp($y, $y), 0); 313 314$x = $LIB->_new("1234"); 315$y = $LIB->_new("987654321012345678"); 316is($LIB->_acmp($x, $y), -1); 317is($LIB->_acmp($y, $x), 1); 318is($LIB->_acmp($x, $x), 0); 319is($LIB->_acmp($y, $y), 0); 320 321############################################################################### 322 323note "_modinv()"; 324 325$x = $LIB->_new("8"); 326$y = $LIB->_new("5033"); 327my ($xmod, $sign) = $LIB->_modinv($x, $y); 328is($LIB->_str($xmod), '4404'); 329 # (4404 * 8) % 5033 = 1 330is($sign, '+'); 331 332############################################################################### 333 334note "_div()"; 335 336$x = $LIB->_new("3333"); 337$y = $LIB->_new("1111"); 338is($LIB->_str(scalar $LIB->_div($x, $y)), 3); 339$x = $LIB->_new("33333"); 340$y = $LIB->_new("1111"); 341($x, $y) = $LIB->_div($x, $y); 342is($LIB->_str($x), 30); 343is($LIB->_str($y), 3); 344$x = $LIB->_new("123"); 345$y = $LIB->_new("1111"); 346($x, $y) = $LIB->_div($x, $y); 347is($LIB->_str($x), 0); 348is($LIB->_str($y), 123); 349 350############################################################################### 351 352note "_num()"; 353 354foreach (qw/1 12 123 1234 12345 1234567 12345678 123456789 1234567890/) { 355 $x = $LIB->_new("$_"); 356 is(ref($x) || '', 'Math::BigInt::GMP'); 357 is($LIB->_str($x), "$_"); 358 $x = $LIB->_num($x); 359 is(ref($x) || '', ''); 360 is($x, $_); 361} 362 363############################################################################### 364 365note "_sqrt()"; 366 367$x = $LIB->_new("144"); 368is($LIB->_str($LIB->_sqrt($x)), '12'); 369$x = $LIB->_new("144000000000000"); 370is($LIB->_str($LIB->_sqrt($x)), '12000000'); 371 372############################################################################### 373 374note "_root()"; 375 376$x = $LIB->_new("81"); 377my $n = $LIB->_new("3"); 378is($LIB->_str($LIB->_root($x, $n)), '4'); # 4*4*4 = 64, 5*5*5 = 125 379 380$x = $LIB->_new("81"); 381$n = $LIB->_new("4"); 382is($LIB->_str($LIB->_root($x, $n)), '3'); # 3*3*3*3 == 81 383 384############################################################################### 385 386note "_pow() (and _root())"; 387 388$x = $LIB->_new("0"); 389$n = $LIB->_new("3"); 390is($LIB->_str($LIB->_pow($x, $n)), 0); # 0 ** y => 0 391 392$x = $LIB->_new("3"); 393$n = $LIB->_new("0"); 394is($LIB->_str($LIB->_pow($x, $n)), 1); # x ** 0 => 1 395 396$x = $LIB->_new("1"); 397$n = $LIB->_new("3"); 398is($LIB->_str($LIB->_pow($x, $n)), 1); # 1 ** y => 1 399 400$x = $LIB->_new("5"); 401$n = $LIB->_new("1"); 402is($LIB->_str($LIB->_pow($x, $n)), 5); # x ** 1 => x 403 404$x = $LIB->_new("81"); 405$n = $LIB->_new("3"); 406 407is($LIB->_str($LIB->_pow($x, $n)), 81 ** 3); # 81 ** 3 == 531441 408 409is($LIB->_str($LIB->_root($x, $n)), 81); 410 411$x = $LIB->_new("81"); 412is($LIB->_str($LIB->_pow($x, $n)), 81 ** 3); 413is($LIB->_str($LIB->_pow($x, $n)), '150094635296999121'); # 531441 ** 3 == 414 415is($LIB->_str($LIB->_root($x, $n)), '531441'); 416is($LIB->_str($LIB->_root($x, $n)), '81'); 417 418$x = $LIB->_new("81"); 419$n = $LIB->_new("14"); 420is($LIB->_str($LIB->_pow($x, $n)), '523347633027360537213511521'); 421is($LIB->_str($LIB->_root($x, $n)), '81'); 422 423$x = $LIB->_new("523347633027360537213511520"); 424is($LIB->_str($LIB->_root($x, $n)), '80'); 425 426$x = $LIB->_new("523347633027360537213511522"); 427is($LIB->_str($LIB->_root($x, $n)), '81'); 428 429my $res = [ qw/ 9 31 99 316 999 3162 9999/ ]; 430 431# 99 ** 2 = 9801, 999 ** 2 = 998001 etc 432for my $i (2 .. 9) { 433 $x = '9' x $i; 434 $x = $LIB->_new($x); 435 $n = $LIB->_new("2"); 436 my $rc = '9' x ($i-1). '8' . '0' x ($i-1) . '1'; 437 is($LIB->_str($LIB->_pow($x, $n)), $rc, 438 "_pow(" . ('9' x $i) . ", 2)"); 439 440 if ($i <= 7) { 441 $x = '9' x $i; 442 $x = $LIB->_new($x); 443 $n = '9' x $i; 444 $n = $LIB->_new($n); 445 is($LIB->_str($LIB->_root($x, $n)), '1', 446 "_root(" . ('9' x $i) . ", " . (9 x $i) . ")"); 447 448 449 $x = '9' x $i; 450 $x = $LIB->_new($x); 451 $n = $LIB->_new("2"); 452 is($LIB->_str($LIB->_root($x, $n)), $res->[$i-2], 453 "_root(" . ('9' x $i) . ", " . (9 x $i) . ")"); 454 } 455} 456 457############################################################################## 458# _fac 459 460$x = $LIB->_new("0"); 461is($LIB->_str($LIB->_fac($x)), '1'); 462 463$x = $LIB->_new("1"); 464is($LIB->_str($LIB->_fac($x)), '1'); 465 466$x = $LIB->_new("2"); 467is($LIB->_str($LIB->_fac($x)), '2'); 468 469$x = $LIB->_new("3"); 470is($LIB->_str($LIB->_fac($x)), '6'); 471 472$x = $LIB->_new("4"); 473is($LIB->_str($LIB->_fac($x)), '24'); 474 475$x = $LIB->_new("5"); 476is($LIB->_str($LIB->_fac($x)), '120'); 477 478$x = $LIB->_new("10"); 479is($LIB->_str($LIB->_fac($x)), '3628800'); 480 481$x = $LIB->_new("11"); 482is($LIB->_str($LIB->_fac($x)), '39916800'); 483 484$x = $LIB->_new("12"); 485is($LIB->_str($LIB->_fac($x)), '479001600'); 486 487$x = $LIB->_new("13"); 488is($LIB->_str($LIB->_fac($x)), '6227020800'); 489 490# test that _fac modifes $x in place for small arguments 491 492$x = $LIB->_new("3"); $LIB->_fac($x); is($LIB->_str($x), '6'); 493$x = $LIB->_new("13"); $LIB->_fac($x); is($LIB->_str($x), '6227020800'); 494 495############################################################################## 496 497note "_inc() and _dec()"; 498 499foreach (qw/1 11 121 1231 12341 1234561 12345671 123456781 1234567891/) { 500 $x = $LIB->_new("$_"); 501 $LIB->_inc($x); 502 print "# \$x = ", $LIB->_str($x), "\n" 503 unless is($LIB->_str($x), substr($_, 0, length($_)-1) . '2'); 504 $LIB->_dec($x); 505 is($LIB->_str($x), $_); 506} 507 508foreach (qw/19 119 1219 12319 1234519 12345619 123456719 1234567819/) { 509 $x = $LIB->_new("$_"); 510 $LIB->_inc($x); 511 print "# \$x = ", $LIB->_str($x), "\n" 512 unless is($LIB->_str($x), substr($_, 0, length($_)-2) . '20'); 513 $LIB->_dec($x); 514 is($LIB->_str($x), $_); 515} 516 517foreach (qw/999 9999 99999 9999999 99999999 999999999 9999999999 99999999999/) { 518 $x = $LIB->_new("$_"); 519 $LIB->_inc($x); 520 print "# \$x = ", $LIB->_str($x), "\n" 521 unless is($LIB->_str($x), '1' . '0' x (length($_))); 522 $LIB->_dec($x); 523 is($LIB->_str($x), $_); 524} 525 526$x = $LIB->_new("1000"); 527$LIB->_inc($x); 528is($LIB->_str($x), '1001'); 529$LIB->_dec($x); 530is($LIB->_str($x), '1000'); 531 532############################################################################### 533 534note "_log_int()"; 535 536# test handling of plain scalar as base, bug up to v1.17) 537 538$x = $LIB->_new("81"); 539 540my ($r, $exact) = $LIB->_log_int($x, $LIB->_new("3")); 541is($LIB->_str($r), '4'); 542ok($LIB->_str($x) eq '81' || $LIB->_str($x) eq '4'); 543is($exact, 1); 544 545$x = $LIB->_new("81"); 546 547($r, $exact) = $LIB->_log_int($x, 3); 548is($LIB->_str($r), '4'); 549ok($LIB->_str($x) eq '81' || $LIB->_str($x) eq '4'); 550is($exact, 1); 551 552############################################################################### 553 554note "_mod()"; 555 556$x = $LIB->_new("1000"); 557$y = $LIB->_new("3"); 558is($LIB->_str(scalar $LIB->_mod($x, $y)), 1); 559$x = $LIB->_new("1000"); 560$y = $LIB->_new("2"); 561is($LIB->_str(scalar $LIB->_mod($x, $y)), 0); 562 563############################################################################### 564 565note "_and(), _or(), _xor()"; 566 567$x = $LIB->_new("5"); 568$y = $LIB->_new("2"); 569is($LIB->_str(scalar $LIB->_xor($x, $y)), 7); 570$x = $LIB->_new("5"); 571$y = $LIB->_new("2"); 572is($LIB->_str(scalar $LIB->_or($x, $y)), 7); 573$x = $LIB->_new("5"); 574$y = $LIB->_new("3"); 575is($LIB->_str(scalar $LIB->_and($x, $y)), 1); 576 577############################################################################### 578 579note "_from_hex() and _from_bin()"; 580 581is($LIB->_str($LIB->_from_hex("0xFf")), 255); 582is($LIB->_str($LIB->_from_bin("0b10101011")), 160+11); 583 584############################################################################### 585 586note "_as_hex() and _as_bin()"; 587 588is($LIB->_str($LIB->_from_hex($LIB->_as_hex($LIB->_new("128")))), 128); 589is($LIB->_str($LIB->_from_bin($LIB->_as_bin($LIB->_new("128")))), 128); 590is($LIB->_str($LIB->_from_hex($LIB->_as_hex($LIB->_new("0")))), 0); 591is($LIB->_str($LIB->_from_bin($LIB->_as_bin($LIB->_new("0")))), 0); 592is($LIB->_as_hex($LIB->_new("0")), '0x0'); 593is($LIB->_as_bin($LIB->_new("0")), '0b0'); 594is($LIB->_as_hex($LIB->_new("12")), '0xc'); 595is($LIB->_as_bin($LIB->_new("12")), '0b1100'); 596 597############################################################################### 598 599note "_from_oct()"; 600 601$x = $LIB->_from_oct("001"); is($LIB->_str($x), '1'); 602$x = $LIB->_from_oct("07"); is($LIB->_str($x), '7'); 603$x = $LIB->_from_oct("077"); is($LIB->_str($x), '63'); 604$x = $LIB->_from_oct("07654321"); is($LIB->_str($x), '2054353'); 605 606############################################################################### 607 608note "_as_oct()"; 609 610$x = $LIB->_new("2054353"); is($LIB->_as_oct($x), '07654321'); 611$x = $LIB->_new("63"); is($LIB->_as_oct($x), '077'); 612$x = $LIB->_new("0"); is($LIB->_as_oct($x), '00'); 613 614############################################################################### 615 616note "_1ex()"; 617 618is($LIB->_str($LIB->_1ex(0)), "1"); 619is($LIB->_str($LIB->_1ex(1)), "10"); 620is($LIB->_str($LIB->_1ex(2)), "100"); 621is($LIB->_str($LIB->_1ex(12)), "1000000000000"); 622is($LIB->_str($LIB->_1ex(16)), "10000000000000000"); 623 624############################################################################### 625 626note "_check()"; 627 628$x = $LIB->_new("123456789"); 629is($LIB->_check($x), 0); 630is($LIB->_check(123), '123 is not a reference to Math::BigInt::GMP'); 631 632# done 633 6341; 635