1package Math::BigInt::Calc; 2 3use 5.006001; 4use strict; 5use warnings; 6 7our $VERSION = '1.999715'; 8$VERSION = eval $VERSION; 9 10# Package to store unsigned big integers in decimal and do math with them 11 12# Internally the numbers are stored in an array with at least 1 element, no 13# leading zero parts (except the first) and in base 1eX where X is determined 14# automatically at loading time to be the maximum possible value 15 16# todo: 17# - fully remove funky $# stuff in div() (maybe - that code scares me...) 18 19# USE_MUL: due to problems on certain os (os390, posix-bc) "* 1e-5" is used 20# instead of "/ 1e5" at some places, (marked with USE_MUL). Other platforms 21# BS2000, some Crays need USE_DIV instead. 22# The BEGIN block is used to determine which of the two variants gives the 23# correct result. 24 25# Beware of things like: 26# $i = $i * $y + $car; $car = int($i / $BASE); $i = $i % $BASE; 27# This works on x86, but fails on ARM (SA1100, iPAQ) due to who knows what 28# reasons. So, use this instead (slower, but correct): 29# $i = $i * $y + $car; $car = int($i / $BASE); $i -= $BASE * $car; 30 31############################################################################## 32# global constants, flags and accessory 33 34# announce that we are compatible with MBI v1.83 and up 35sub api_version () { 2; } 36 37# constants for easier life 38my ($BASE,$BASE_LEN,$RBASE,$MAX_VAL); 39my ($AND_BITS,$XOR_BITS,$OR_BITS); 40my ($AND_MASK,$XOR_MASK,$OR_MASK); 41 42sub _base_len 43 { 44 # Set/get the BASE_LEN and assorted other, connected values. 45 # Used only by the testsuite, the set variant is used only by the BEGIN 46 # block below: 47 shift; 48 49 my ($b, $int) = @_; 50 if (defined $b) 51 { 52 # avoid redefinitions 53 undef &_mul; 54 undef &_div; 55 56 if ($] >= 5.008 && $int && $b > 7) 57 { 58 $BASE_LEN = $b; 59 *_mul = \&_mul_use_div_64; 60 *_div = \&_div_use_div_64; 61 $BASE = int("1e".$BASE_LEN); 62 $MAX_VAL = $BASE-1; 63 return $BASE_LEN unless wantarray; 64 return ($BASE_LEN, $BASE, $AND_BITS, $XOR_BITS, $OR_BITS, $BASE_LEN, $MAX_VAL,); 65 } 66 67 # find whether we can use mul or div in mul()/div() 68 $BASE_LEN = $b+1; 69 my $caught = 0; 70 while (--$BASE_LEN > 5) 71 { 72 $BASE = int("1e".$BASE_LEN); 73 $RBASE = abs('1e-'.$BASE_LEN); # see USE_MUL 74 $caught = 0; 75 $caught += 1 if (int($BASE * $RBASE) != 1); # should be 1 76 $caught += 2 if (int($BASE / $BASE) != 1); # should be 1 77 last if $caught != 3; 78 } 79 $BASE = int("1e".$BASE_LEN); 80 $RBASE = abs('1e-'.$BASE_LEN); # see USE_MUL 81 $MAX_VAL = $BASE-1; 82 83 # ($caught & 1) != 0 => cannot use MUL 84 # ($caught & 2) != 0 => cannot use DIV 85 if ($caught == 2) # 2 86 { 87 # must USE_MUL since we cannot use DIV 88 *_mul = \&_mul_use_mul; 89 *_div = \&_div_use_mul; 90 } 91 else # 0 or 1 92 { 93 # can USE_DIV instead 94 *_mul = \&_mul_use_div; 95 *_div = \&_div_use_div; 96 } 97 } 98 return $BASE_LEN unless wantarray; 99 return ($BASE_LEN, $BASE, $AND_BITS, $XOR_BITS, $OR_BITS, $BASE_LEN, $MAX_VAL); 100 } 101 102sub _new { 103 # Given a string representing an integer, returns a reference to an array 104 # of integers, where each integer represents a chunk of the original input 105 # integer. Assumes normalized value as input. 106 107 my ($proto, $str) = @_; 108 109 my $input_len = length($str) - 1; 110 111 # Shortcut for small numbers. 112 return [ int($str) ] if $input_len < $BASE_LEN; 113 114 my $format = "a" . (($input_len % $BASE_LEN) + 1); 115 $format .= $] < 5.008 ? "a$BASE_LEN" x int($input_len / $BASE_LEN) 116 : "(a$BASE_LEN)*"; 117 118 [ reverse(map { 0 + $_ } unpack($format, $str)) ]; 119} 120 121BEGIN 122 { 123 # from Daniel Pfeiffer: determine largest group of digits that is precisely 124 # multipliable with itself plus carry 125 # Test now changed to expect the proper pattern, not a result off by 1 or 2 126 my ($e, $num) = 3; # lowest value we will use is 3+1-1 = 3 127 do { 128 $num = '9' x ++$e; 129 $num *= $num + 1; 130 } while $num =~ /9{$e}0{$e}/; # must be a certain pattern 131 $e--; # last test failed, so retract one step 132 # the limits below brush the problems with the test above under the rug: 133 # the test should be able to find the proper $e automatically 134 $e = 5 if $^O =~ /^uts/; # UTS get's some special treatment 135 $e = 5 if $^O =~ /^unicos/; # unicos is also problematic (6 seems to work 136 # there, but we play safe) 137 138 my $int = 0; 139 if ($e > 7) 140 { 141 use integer; 142 my $e1 = 7; 143 $num = 7; 144 do 145 { 146 $num = ('9' x ++$e1) + 0; 147 $num *= $num + 1; 148 } while ("$num" =~ /9{$e1}0{$e1}/); # must be a certain pattern 149 $e1--; # last test failed, so retract one step 150 if ($e1 > 7) 151 { 152 $int = 1; $e = $e1; 153 } 154 } 155 156 __PACKAGE__->_base_len($e,$int); # set and store 157 158 use integer; 159 # find out how many bits _and, _or and _xor can take (old default = 16) 160 # I don't think anybody has yet 128 bit scalars, so let's play safe. 161 local $^W = 0; # don't warn about 'nonportable number' 162 $AND_BITS = 15; $XOR_BITS = 15; $OR_BITS = 15; 163 164 # find max bits, we will not go higher than numberofbits that fit into $BASE 165 # to make _and etc simpler (and faster for smaller, slower for large numbers) 166 my $max = 16; 167 while (2 ** $max < $BASE) { $max++; } 168 { 169 no integer; 170 $max = 16 if $] < 5.006; # older Perls might not take >16 too well 171 } 172 my ($x,$y,$z); 173 do { 174 $AND_BITS++; 175 $x = CORE::oct('0b' . '1' x $AND_BITS); $y = $x & $x; 176 $z = (2 ** $AND_BITS) - 1; 177 } while ($AND_BITS < $max && $x == $z && $y == $x); 178 $AND_BITS --; # retreat one step 179 do { 180 $XOR_BITS++; 181 $x = CORE::oct('0b' . '1' x $XOR_BITS); $y = $x ^ 0; 182 $z = (2 ** $XOR_BITS) - 1; 183 } while ($XOR_BITS < $max && $x == $z && $y == $x); 184 $XOR_BITS --; # retreat one step 185 do { 186 $OR_BITS++; 187 $x = CORE::oct('0b' . '1' x $OR_BITS); $y = $x | $x; 188 $z = (2 ** $OR_BITS) - 1; 189 } while ($OR_BITS < $max && $x == $z && $y == $x); 190 $OR_BITS --; # retreat one step 191 192 $AND_MASK = __PACKAGE__->_new( ( 2 ** $AND_BITS )); 193 $XOR_MASK = __PACKAGE__->_new( ( 2 ** $XOR_BITS )); 194 $OR_MASK = __PACKAGE__->_new( ( 2 ** $OR_BITS )); 195 196 # We can compute the approximate length no faster than the real length: 197 *_alen = \&_len; 198 } 199 200############################################################################### 201 202sub _zero 203 { 204 # create a zero 205 [ 0 ]; 206 } 207 208sub _one 209 { 210 # create a one 211 [ 1 ]; 212 } 213 214sub _two 215 { 216 # create a two (used internally for shifting) 217 [ 2 ]; 218 } 219 220sub _ten 221 { 222 # create a 10 (used internally for shifting) 223 [ 10 ]; 224 } 225 226sub _1ex 227 { 228 # create a 1Ex 229 my $rem = $_[1] % $BASE_LEN; # remainder 230 my $parts = $_[1] / $BASE_LEN; # parts 231 232 # 000000, 000000, 100 233 [ (0) x $parts, '1' . ('0' x $rem) ]; 234 } 235 236sub _copy 237 { 238 # make a true copy 239 [ @{$_[1]} ]; 240 } 241 242# catch and throw away 243sub import { } 244 245############################################################################## 246# convert back to string and number 247 248sub _str { 249 # Convert number from internal base 1eN format to string format. Internal 250 # format is always normalized, i.e., no leading zeros. 251 252 my $ary = $_[1]; 253 my $idx = $#$ary; # index of last element 254 255 if ($idx < 0) { # should not happen 256 require Carp; 257 Carp::croak("$_[1] has no elements"); 258 } 259 260 # Handle first one differently, since it should not have any leading zeros. 261 my $ret = int($ary->[$idx]); 262 if ($idx > 0) { 263 $idx--; 264 # Interestingly, the pre-padd method uses more time 265 # the old grep variant takes longer (14 vs. 10 sec) 266 my $z = '0' x ($BASE_LEN - 1); 267 while ($idx >= 0) { 268 $ret .= substr($z . $ary->[$idx], -$BASE_LEN); 269 $idx--; 270 } 271 } 272 $ret; 273} 274 275sub _num 276 { 277 # Make a Perl scalar number (int/float) from a BigInt object. 278 my $x = $_[1]; 279 280 return 0 + $x->[0] if scalar @$x == 1; # below $BASE 281 282 # Start with the most significant element and work towards the least 283 # significant element. Avoid multiplying "inf" (which happens if the number 284 # overflows) with "0" (if there are zero elements in $x) since this gives 285 # "nan" which propagates to the output. 286 287 my $num = 0; 288 for (my $i = $#$x ; $i >= 0 ; --$i) { 289 $num *= $BASE; 290 $num += $x -> [$i]; 291 } 292 return $num; 293 } 294 295############################################################################## 296# actual math code 297 298sub _add { 299 # (ref to int_num_array, ref to int_num_array) 300 # 301 # Routine to add two base 1eX numbers stolen from Knuth Vol 2 Algorithm A 302 # pg 231. There are separate routines to add and sub as per Knuth pg 233. 303 # This routine modifies array x, but not y. 304 305 my ($c, $x, $y) = @_; 306 307 return $x if @$y == 1 && $y->[0] == 0; # $x + 0 => $x 308 if (@$x == 1 && $x->[0] == 0) { # 0 + $y => $y->copy 309 # Twice as slow as $x = [ @$y ], but necessary to modify $x in-place. 310 @$x = @$y; 311 return $x; 312 } 313 314 # For each in Y, add Y to X and carry. If after that, something is left in 315 # X, foreach in X add carry to X and then return X, carry. Trades one 316 # "$j++" for having to shift arrays. 317 my $i; 318 my $car = 0; 319 my $j = 0; 320 for $i (@$y) { 321 $x->[$j] -= $BASE if $car = (($x->[$j] += $i + $car) >= $BASE) ? 1 : 0; 322 $j++; 323 } 324 while ($car != 0) { 325 $x->[$j] -= $BASE if $car = (($x->[$j] += $car) >= $BASE) ? 1 : 0; 326 $j++; 327 } 328 $x; 329} 330 331sub _inc { 332 # (ref to int_num_array, ref to int_num_array) 333 # Add 1 to $x, modify $x in place 334 my ($c, $x) = @_; 335 336 for my $i (@$x) { 337 return $x if ($i += 1) < $BASE; # early out 338 $i = 0; # overflow, next 339 } 340 push @$x, 1 if $x->[-1] == 0; # last overflowed, so extend 341 $x; 342} 343 344sub _dec { 345 # (ref to int_num_array, ref to int_num_array) 346 # Sub 1 from $x, modify $x in place 347 my ($c, $x) = @_; 348 349 my $MAX = $BASE - 1; # since MAX_VAL based on BASE 350 for my $i (@$x) { 351 last if ($i -= 1) >= 0; # early out 352 $i = $MAX; # underflow, next 353 } 354 pop @$x if $x->[-1] == 0 && @$x > 1; # last underflowed (but leave 0) 355 $x; 356} 357 358sub _sub { 359 # (ref to int_num_array, ref to int_num_array, swap) 360 # 361 # Subtract base 1eX numbers -- stolen from Knuth Vol 2 pg 232, $x > $y 362 # subtract Y from X by modifying x in place 363 my ($c, $sx, $sy, $s) = @_; 364 365 my $car = 0; 366 my $i; 367 my $j = 0; 368 if (!$s) { 369 for $i (@$sx) { 370 last unless defined $sy->[$j] || $car; 371 $i += $BASE if $car = (($i -= ($sy->[$j] || 0) + $car) < 0); 372 $j++; 373 } 374 # might leave leading zeros, so fix that 375 return __strip_zeros($sx); 376 } 377 for $i (@$sx) { 378 # We can't do an early out if $x < $y, since we need to copy the high 379 # chunks from $y. Found by Bob Mathews. 380 #last unless defined $sy->[$j] || $car; 381 $sy->[$j] += $BASE 382 if $car = ($sy->[$j] = $i - ($sy->[$j] || 0) - $car) < 0; 383 $j++; 384 } 385 # might leave leading zeros, so fix that 386 __strip_zeros($sy); 387} 388 389sub _mul_use_mul 390 { 391 # (ref to int_num_array, ref to int_num_array) 392 # multiply two numbers in internal representation 393 # modifies first arg, second need not be different from first 394 my ($c,$xv,$yv) = @_; 395 396 if (@$yv == 1) 397 { 398 # shortcut for two very short numbers (improved by Nathan Zook) 399 # works also if xv and yv are the same reference, and handles also $x == 0 400 if (@$xv == 1) 401 { 402 if (($xv->[0] *= $yv->[0]) >= $BASE) 403 { 404 $xv->[0] = $xv->[0] - ($xv->[1] = int($xv->[0] * $RBASE)) * $BASE; 405 }; 406 return $xv; 407 } 408 # $x * 0 => 0 409 if ($yv->[0] == 0) 410 { 411 @$xv = (0); 412 return $xv; 413 } 414 # multiply a large number a by a single element one, so speed up 415 my $y = $yv->[0]; my $car = 0; 416 foreach my $i (@$xv) 417 { 418 $i = $i * $y + $car; $car = int($i * $RBASE); $i -= $car * $BASE; 419 } 420 push @$xv, $car if $car != 0; 421 return $xv; 422 } 423 # shortcut for result $x == 0 => result = 0 424 return $xv if ( ((@$xv == 1) && ($xv->[0] == 0)) ); 425 426 # since multiplying $x with $x fails, make copy in this case 427 $yv = [@$xv] if $xv == $yv; # same references? 428 429 my @prod = (); my ($prod,$car,$cty,$xi,$yi); 430 431 for $xi (@$xv) 432 { 433 $car = 0; $cty = 0; 434 435 # slow variant 436# for $yi (@$yv) 437# { 438# $prod = $xi * $yi + ($prod[$cty] || 0) + $car; 439# $prod[$cty++] = 440# $prod - ($car = int($prod * RBASE)) * $BASE; # see USE_MUL 441# } 442# $prod[$cty] += $car if $car; # need really to check for 0? 443# $xi = shift @prod; 444 445 # faster variant 446 # looping through this if $xi == 0 is silly - so optimize it away! 447 $xi = (shift @prod || 0), next if $xi == 0; 448 for $yi (@$yv) 449 { 450 $prod = $xi * $yi + ($prod[$cty] || 0) + $car; 451## this is actually a tad slower 452## $prod = $prod[$cty]; $prod += ($car + $xi * $yi); # no ||0 here 453 $prod[$cty++] = 454 $prod - ($car = int($prod * $RBASE)) * $BASE; # see USE_MUL 455 } 456 $prod[$cty] += $car if $car; # need really to check for 0? 457 $xi = shift @prod || 0; # || 0 makes v5.005_3 happy 458 } 459 push @$xv, @prod; 460 # can't have leading zeros 461# __strip_zeros($xv); 462 $xv; 463 } 464 465sub _mul_use_div_64 466 { 467 # (ref to int_num_array, ref to int_num_array) 468 # multiply two numbers in internal representation 469 # modifies first arg, second need not be different from first 470 # works for 64 bit integer with "use integer" 471 my ($c,$xv,$yv) = @_; 472 473 use integer; 474 if (@$yv == 1) 475 { 476 # shortcut for two small numbers, also handles $x == 0 477 if (@$xv == 1) 478 { 479 # shortcut for two very short numbers (improved by Nathan Zook) 480 # works also if xv and yv are the same reference, and handles also $x == 0 481 if (($xv->[0] *= $yv->[0]) >= $BASE) 482 { 483 $xv->[0] = 484 $xv->[0] - ($xv->[1] = $xv->[0] / $BASE) * $BASE; 485 }; 486 return $xv; 487 } 488 # $x * 0 => 0 489 if ($yv->[0] == 0) 490 { 491 @$xv = (0); 492 return $xv; 493 } 494 # multiply a large number a by a single element one, so speed up 495 my $y = $yv->[0]; my $car = 0; 496 foreach my $i (@$xv) 497 { 498 #$i = $i * $y + $car; $car = $i / $BASE; $i -= $car * $BASE; 499 $i = $i * $y + $car; $i -= ($car = $i / $BASE) * $BASE; 500 } 501 push @$xv, $car if $car != 0; 502 return $xv; 503 } 504 # shortcut for result $x == 0 => result = 0 505 return $xv if ( ((@$xv == 1) && ($xv->[0] == 0)) ); 506 507 # since multiplying $x with $x fails, make copy in this case 508 $yv = [@$xv] if $xv == $yv; # same references? 509 510 my @prod = (); my ($prod,$car,$cty,$xi,$yi); 511 for $xi (@$xv) 512 { 513 $car = 0; $cty = 0; 514 # looping through this if $xi == 0 is silly - so optimize it away! 515 $xi = (shift @prod || 0), next if $xi == 0; 516 for $yi (@$yv) 517 { 518 $prod = $xi * $yi + ($prod[$cty] || 0) + $car; 519 $prod[$cty++] = $prod - ($car = $prod / $BASE) * $BASE; 520 } 521 $prod[$cty] += $car if $car; # need really to check for 0? 522 $xi = shift @prod || 0; # || 0 makes v5.005_3 happy 523 } 524 push @$xv, @prod; 525 $xv; 526 } 527 528sub _mul_use_div 529 { 530 # (ref to int_num_array, ref to int_num_array) 531 # multiply two numbers in internal representation 532 # modifies first arg, second need not be different from first 533 my ($c,$xv,$yv) = @_; 534 535 if (@$yv == 1) 536 { 537 # shortcut for two small numbers, also handles $x == 0 538 if (@$xv == 1) 539 { 540 # shortcut for two very short numbers (improved by Nathan Zook) 541 # works also if xv and yv are the same reference, and handles also $x == 0 542 if (($xv->[0] *= $yv->[0]) >= $BASE) 543 { 544 $xv->[0] = 545 $xv->[0] - ($xv->[1] = int($xv->[0] / $BASE)) * $BASE; 546 }; 547 return $xv; 548 } 549 # $x * 0 => 0 550 if ($yv->[0] == 0) 551 { 552 @$xv = (0); 553 return $xv; 554 } 555 # multiply a large number a by a single element one, so speed up 556 my $y = $yv->[0]; my $car = 0; 557 foreach my $i (@$xv) 558 { 559 $i = $i * $y + $car; $car = int($i / $BASE); $i -= $car * $BASE; 560 # This (together with use integer;) does not work on 32-bit Perls 561 #$i = $i * $y + $car; $i -= ($car = $i / $BASE) * $BASE; 562 } 563 push @$xv, $car if $car != 0; 564 return $xv; 565 } 566 # shortcut for result $x == 0 => result = 0 567 return $xv if ( ((@$xv == 1) && ($xv->[0] == 0)) ); 568 569 # since multiplying $x with $x fails, make copy in this case 570 $yv = [@$xv] if $xv == $yv; # same references? 571 572 my @prod = (); my ($prod,$car,$cty,$xi,$yi); 573 for $xi (@$xv) 574 { 575 $car = 0; $cty = 0; 576 # looping through this if $xi == 0 is silly - so optimize it away! 577 $xi = (shift @prod || 0), next if $xi == 0; 578 for $yi (@$yv) 579 { 580 $prod = $xi * $yi + ($prod[$cty] || 0) + $car; 581 $prod[$cty++] = $prod - ($car = int($prod / $BASE)) * $BASE; 582 } 583 $prod[$cty] += $car if $car; # need really to check for 0? 584 $xi = shift @prod || 0; # || 0 makes v5.005_3 happy 585 } 586 push @$xv, @prod; 587 # can't have leading zeros 588# __strip_zeros($xv); 589 $xv; 590 } 591 592sub _div_use_mul 593 { 594 # ref to array, ref to array, modify first array and return remainder if 595 # in list context 596 597 # see comments in _div_use_div() for more explanations 598 599 my ($c,$x,$yorg) = @_; 600 601 # the general div algorithm here is about O(N*N) and thus quite slow, so 602 # we first check for some special cases and use shortcuts to handle them. 603 604 # This works, because we store the numbers in a chunked format where each 605 # element contains 5..7 digits (depending on system). 606 607 # if both numbers have only one element: 608 if (@$x == 1 && @$yorg == 1) 609 { 610 # shortcut, $yorg and $x are two small numbers 611 if (wantarray) 612 { 613 my $r = [ $x->[0] % $yorg->[0] ]; 614 $x->[0] = int($x->[0] / $yorg->[0]); 615 return ($x,$r); 616 } 617 else 618 { 619 $x->[0] = int($x->[0] / $yorg->[0]); 620 return $x; 621 } 622 } 623 624 # if x has more than one, but y has only one element: 625 if (@$yorg == 1) 626 { 627 my $rem; 628 $rem = _mod($c,[ @$x ],$yorg) if wantarray; 629 630 # shortcut, $y is < $BASE 631 my $j = scalar @$x; my $r = 0; 632 my $y = $yorg->[0]; my $b; 633 while ($j-- > 0) 634 { 635 $b = $r * $BASE + $x->[$j]; 636 $x->[$j] = int($b/$y); 637 $r = $b % $y; 638 } 639 pop @$x if @$x > 1 && $x->[-1] == 0; # splice up a leading zero 640 return ($x,$rem) if wantarray; 641 return $x; 642 } 643 644 # now x and y have more than one element 645 646 # check whether y has more elements than x, if yet, the result will be 0 647 if (@$yorg > @$x) 648 { 649 my $rem; 650 $rem = [@$x] if wantarray; # make copy 651 splice (@$x,1); # keep ref to original array 652 $x->[0] = 0; # set to 0 653 return ($x,$rem) if wantarray; # including remainder? 654 return $x; # only x, which is [0] now 655 } 656 # check whether the numbers have the same number of elements, in that case 657 # the result will fit into one element and can be computed efficiently 658 if (@$yorg == @$x) 659 { 660 my $rem; 661 # if $yorg has more digits than $x (it's leading element is longer than 662 # the one from $x), the result will also be 0: 663 if (length(int($yorg->[-1])) > length(int($x->[-1]))) 664 { 665 $rem = [@$x] if wantarray; # make copy 666 splice (@$x,1); # keep ref to org array 667 $x->[0] = 0; # set to 0 668 return ($x,$rem) if wantarray; # including remainder? 669 return $x; 670 } 671 # now calculate $x / $yorg 672 if (length(int($yorg->[-1])) == length(int($x->[-1]))) 673 { 674 # same length, so make full compare 675 676 my $a = 0; my $j = scalar @$x - 1; 677 # manual way (abort if unequal, good for early ne) 678 while ($j >= 0) 679 { 680 last if ($a = $x->[$j] - $yorg->[$j]); $j--; 681 } 682 # $a contains the result of the compare between X and Y 683 # a < 0: x < y, a == 0: x == y, a > 0: x > y 684 if ($a <= 0) 685 { 686 $rem = [ 0 ]; # a = 0 => x == y => rem 0 687 $rem = [@$x] if $a != 0; # a < 0 => x < y => rem = x 688 splice(@$x,1); # keep single element 689 $x->[0] = 0; # if $a < 0 690 $x->[0] = 1 if $a == 0; # $x == $y 691 return ($x,$rem) if wantarray; 692 return $x; 693 } 694 # $x >= $y, so proceed normally 695 } 696 } 697 698 # all other cases: 699 700 my $y = [ @$yorg ]; # always make copy to preserve 701 702 my ($car,$bar,$prd,$dd,$xi,$yi,@q,$v2,$v1,@d,$tmp,$q,$u2,$u1,$u0); 703 704 $car = $bar = $prd = 0; 705 if (($dd = int($BASE/($y->[-1]+1))) != 1) 706 { 707 for $xi (@$x) 708 { 709 $xi = $xi * $dd + $car; 710 $xi -= ($car = int($xi * $RBASE)) * $BASE; # see USE_MUL 711 } 712 push(@$x, $car); $car = 0; 713 for $yi (@$y) 714 { 715 $yi = $yi * $dd + $car; 716 $yi -= ($car = int($yi * $RBASE)) * $BASE; # see USE_MUL 717 } 718 } 719 else 720 { 721 push(@$x, 0); 722 } 723 @q = (); ($v2,$v1) = @$y[-2,-1]; 724 $v2 = 0 unless $v2; 725 while ($#$x > $#$y) 726 { 727 ($u2,$u1,$u0) = @$x[-3..-1]; 728 $u2 = 0 unless $u2; 729 #warn "oups v1 is 0, u0: $u0 $y->[-2] $y->[-1] l ",scalar @$y,"\n" 730 # if $v1 == 0; 731 $q = (($u0 == $v1) ? $MAX_VAL : int(($u0*$BASE+$u1)/$v1)); 732 --$q while ($v2*$q > ($u0*$BASE+$u1-$q*$v1)*$BASE+$u2); 733 if ($q) 734 { 735 ($car, $bar) = (0,0); 736 for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi) 737 { 738 $prd = $q * $y->[$yi] + $car; 739 $prd -= ($car = int($prd * $RBASE)) * $BASE; # see USE_MUL 740 $x->[$xi] += $BASE if ($bar = (($x->[$xi] -= $prd + $bar) < 0)); 741 } 742 if ($x->[-1] < $car + $bar) 743 { 744 $car = 0; --$q; 745 for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi) 746 { 747 $x->[$xi] -= $BASE 748 if ($car = (($x->[$xi] += $y->[$yi] + $car) >= $BASE)); 749 } 750 } 751 } 752 pop(@$x); 753 unshift(@q, $q); 754 } 755 if (wantarray) 756 { 757 @d = (); 758 if ($dd != 1) 759 { 760 $car = 0; 761 for $xi (reverse @$x) 762 { 763 $prd = $car * $BASE + $xi; 764 $car = $prd - ($tmp = int($prd / $dd)) * $dd; # see USE_MUL 765 unshift(@d, $tmp); 766 } 767 } 768 else 769 { 770 @d = @$x; 771 } 772 @$x = @q; 773 my $d = \@d; 774 __strip_zeros($x); 775 __strip_zeros($d); 776 return ($x,$d); 777 } 778 @$x = @q; 779 __strip_zeros($x); 780 $x; 781 } 782 783sub _div_use_div_64 784 { 785 # ref to array, ref to array, modify first array and return remainder if 786 # in list context 787 # This version works on 64 bit integers 788 my ($c,$x,$yorg) = @_; 789 790 use integer; 791 # the general div algorithm here is about O(N*N) and thus quite slow, so 792 # we first check for some special cases and use shortcuts to handle them. 793 794 # This works, because we store the numbers in a chunked format where each 795 # element contains 5..7 digits (depending on system). 796 797 # if both numbers have only one element: 798 if (@$x == 1 && @$yorg == 1) 799 { 800 # shortcut, $yorg and $x are two small numbers 801 if (wantarray) 802 { 803 my $r = [ $x->[0] % $yorg->[0] ]; 804 $x->[0] = int($x->[0] / $yorg->[0]); 805 return ($x,$r); 806 } 807 else 808 { 809 $x->[0] = int($x->[0] / $yorg->[0]); 810 return $x; 811 } 812 } 813 # if x has more than one, but y has only one element: 814 if (@$yorg == 1) 815 { 816 my $rem; 817 $rem = _mod($c,[ @$x ],$yorg) if wantarray; 818 819 # shortcut, $y is < $BASE 820 my $j = scalar @$x; my $r = 0; 821 my $y = $yorg->[0]; my $b; 822 while ($j-- > 0) 823 { 824 $b = $r * $BASE + $x->[$j]; 825 $x->[$j] = int($b/$y); 826 $r = $b % $y; 827 } 828 pop @$x if @$x > 1 && $x->[-1] == 0; # splice up a leading zero 829 return ($x,$rem) if wantarray; 830 return $x; 831 } 832 # now x and y have more than one element 833 834 # check whether y has more elements than x, if yet, the result will be 0 835 if (@$yorg > @$x) 836 { 837 my $rem; 838 $rem = [@$x] if wantarray; # make copy 839 splice (@$x,1); # keep ref to original array 840 $x->[0] = 0; # set to 0 841 return ($x,$rem) if wantarray; # including remainder? 842 return $x; # only x, which is [0] now 843 } 844 # check whether the numbers have the same number of elements, in that case 845 # the result will fit into one element and can be computed efficiently 846 if (@$yorg == @$x) 847 { 848 my $rem; 849 # if $yorg has more digits than $x (it's leading element is longer than 850 # the one from $x), the result will also be 0: 851 if (length(int($yorg->[-1])) > length(int($x->[-1]))) 852 { 853 $rem = [@$x] if wantarray; # make copy 854 splice (@$x,1); # keep ref to org array 855 $x->[0] = 0; # set to 0 856 return ($x,$rem) if wantarray; # including remainder? 857 return $x; 858 } 859 # now calculate $x / $yorg 860 861 if (length(int($yorg->[-1])) == length(int($x->[-1]))) 862 { 863 # same length, so make full compare 864 865 my $a = 0; my $j = scalar @$x - 1; 866 # manual way (abort if unequal, good for early ne) 867 while ($j >= 0) 868 { 869 last if ($a = $x->[$j] - $yorg->[$j]); $j--; 870 } 871 # $a contains the result of the compare between X and Y 872 # a < 0: x < y, a == 0: x == y, a > 0: x > y 873 if ($a <= 0) 874 { 875 $rem = [ 0 ]; # a = 0 => x == y => rem 0 876 $rem = [@$x] if $a != 0; # a < 0 => x < y => rem = x 877 splice(@$x,1); # keep single element 878 $x->[0] = 0; # if $a < 0 879 $x->[0] = 1 if $a == 0; # $x == $y 880 return ($x,$rem) if wantarray; # including remainder? 881 return $x; 882 } 883 # $x >= $y, so proceed normally 884 885 } 886 } 887 888 # all other cases: 889 890 my $y = [ @$yorg ]; # always make copy to preserve 891 892 my ($car,$bar,$prd,$dd,$xi,$yi,@q,$v2,$v1,@d,$tmp,$q,$u2,$u1,$u0); 893 894 $car = $bar = $prd = 0; 895 if (($dd = int($BASE/($y->[-1]+1))) != 1) 896 { 897 for $xi (@$x) 898 { 899 $xi = $xi * $dd + $car; 900 $xi -= ($car = int($xi / $BASE)) * $BASE; 901 } 902 push(@$x, $car); $car = 0; 903 for $yi (@$y) 904 { 905 $yi = $yi * $dd + $car; 906 $yi -= ($car = int($yi / $BASE)) * $BASE; 907 } 908 } 909 else 910 { 911 push(@$x, 0); 912 } 913 914 # @q will accumulate the final result, $q contains the current computed 915 # part of the final result 916 917 @q = (); ($v2,$v1) = @$y[-2,-1]; 918 $v2 = 0 unless $v2; 919 while ($#$x > $#$y) 920 { 921 ($u2,$u1,$u0) = @$x[-3..-1]; 922 $u2 = 0 unless $u2; 923 #warn "oups v1 is 0, u0: $u0 $y->[-2] $y->[-1] l ",scalar @$y,"\n" 924 # if $v1 == 0; 925 $q = (($u0 == $v1) ? $MAX_VAL : int(($u0*$BASE+$u1)/$v1)); 926 --$q while ($v2*$q > ($u0*$BASE+$u1-$q*$v1)*$BASE+$u2); 927 if ($q) 928 { 929 ($car, $bar) = (0,0); 930 for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi) 931 { 932 $prd = $q * $y->[$yi] + $car; 933 $prd -= ($car = int($prd / $BASE)) * $BASE; 934 $x->[$xi] += $BASE if ($bar = (($x->[$xi] -= $prd + $bar) < 0)); 935 } 936 if ($x->[-1] < $car + $bar) 937 { 938 $car = 0; --$q; 939 for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi) 940 { 941 $x->[$xi] -= $BASE 942 if ($car = (($x->[$xi] += $y->[$yi] + $car) >= $BASE)); 943 } 944 } 945 } 946 pop(@$x); unshift(@q, $q); 947 } 948 if (wantarray) 949 { 950 @d = (); 951 if ($dd != 1) 952 { 953 $car = 0; 954 for $xi (reverse @$x) 955 { 956 $prd = $car * $BASE + $xi; 957 $car = $prd - ($tmp = int($prd / $dd)) * $dd; 958 unshift(@d, $tmp); 959 } 960 } 961 else 962 { 963 @d = @$x; 964 } 965 @$x = @q; 966 my $d = \@d; 967 __strip_zeros($x); 968 __strip_zeros($d); 969 return ($x,$d); 970 } 971 @$x = @q; 972 __strip_zeros($x); 973 $x; 974 } 975 976sub _div_use_div 977 { 978 # ref to array, ref to array, modify first array and return remainder if 979 # in list context 980 my ($c,$x,$yorg) = @_; 981 982 # the general div algorithm here is about O(N*N) and thus quite slow, so 983 # we first check for some special cases and use shortcuts to handle them. 984 985 # This works, because we store the numbers in a chunked format where each 986 # element contains 5..7 digits (depending on system). 987 988 # if both numbers have only one element: 989 if (@$x == 1 && @$yorg == 1) 990 { 991 # shortcut, $yorg and $x are two small numbers 992 if (wantarray) 993 { 994 my $r = [ $x->[0] % $yorg->[0] ]; 995 $x->[0] = int($x->[0] / $yorg->[0]); 996 return ($x,$r); 997 } 998 else 999 { 1000 $x->[0] = int($x->[0] / $yorg->[0]); 1001 return $x; 1002 } 1003 } 1004 # if x has more than one, but y has only one element: 1005 if (@$yorg == 1) 1006 { 1007 my $rem; 1008 $rem = _mod($c,[ @$x ],$yorg) if wantarray; 1009 1010 # shortcut, $y is < $BASE 1011 my $j = scalar @$x; my $r = 0; 1012 my $y = $yorg->[0]; my $b; 1013 while ($j-- > 0) 1014 { 1015 $b = $r * $BASE + $x->[$j]; 1016 $x->[$j] = int($b/$y); 1017 $r = $b % $y; 1018 } 1019 pop @$x if @$x > 1 && $x->[-1] == 0; # splice up a leading zero 1020 return ($x,$rem) if wantarray; 1021 return $x; 1022 } 1023 # now x and y have more than one element 1024 1025 # check whether y has more elements than x, if yet, the result will be 0 1026 if (@$yorg > @$x) 1027 { 1028 my $rem; 1029 $rem = [@$x] if wantarray; # make copy 1030 splice (@$x,1); # keep ref to original array 1031 $x->[0] = 0; # set to 0 1032 return ($x,$rem) if wantarray; # including remainder? 1033 return $x; # only x, which is [0] now 1034 } 1035 # check whether the numbers have the same number of elements, in that case 1036 # the result will fit into one element and can be computed efficiently 1037 if (@$yorg == @$x) 1038 { 1039 my $rem; 1040 # if $yorg has more digits than $x (it's leading element is longer than 1041 # the one from $x), the result will also be 0: 1042 if (length(int($yorg->[-1])) > length(int($x->[-1]))) 1043 { 1044 $rem = [@$x] if wantarray; # make copy 1045 splice (@$x,1); # keep ref to org array 1046 $x->[0] = 0; # set to 0 1047 return ($x,$rem) if wantarray; # including remainder? 1048 return $x; 1049 } 1050 # now calculate $x / $yorg 1051 1052 if (length(int($yorg->[-1])) == length(int($x->[-1]))) 1053 { 1054 # same length, so make full compare 1055 1056 my $a = 0; my $j = scalar @$x - 1; 1057 # manual way (abort if unequal, good for early ne) 1058 while ($j >= 0) 1059 { 1060 last if ($a = $x->[$j] - $yorg->[$j]); $j--; 1061 } 1062 # $a contains the result of the compare between X and Y 1063 # a < 0: x < y, a == 0: x == y, a > 0: x > y 1064 if ($a <= 0) 1065 { 1066 $rem = [ 0 ]; # a = 0 => x == y => rem 0 1067 $rem = [@$x] if $a != 0; # a < 0 => x < y => rem = x 1068 splice(@$x,1); # keep single element 1069 $x->[0] = 0; # if $a < 0 1070 $x->[0] = 1 if $a == 0; # $x == $y 1071 return ($x,$rem) if wantarray; # including remainder? 1072 return $x; 1073 } 1074 # $x >= $y, so proceed normally 1075 1076 } 1077 } 1078 1079 # all other cases: 1080 1081 my $y = [ @$yorg ]; # always make copy to preserve 1082 1083 my ($car,$bar,$prd,$dd,$xi,$yi,@q,$v2,$v1,@d,$tmp,$q,$u2,$u1,$u0); 1084 1085 $car = $bar = $prd = 0; 1086 if (($dd = int($BASE/($y->[-1]+1))) != 1) 1087 { 1088 for $xi (@$x) 1089 { 1090 $xi = $xi * $dd + $car; 1091 $xi -= ($car = int($xi / $BASE)) * $BASE; 1092 } 1093 push(@$x, $car); $car = 0; 1094 for $yi (@$y) 1095 { 1096 $yi = $yi * $dd + $car; 1097 $yi -= ($car = int($yi / $BASE)) * $BASE; 1098 } 1099 } 1100 else 1101 { 1102 push(@$x, 0); 1103 } 1104 1105 # @q will accumulate the final result, $q contains the current computed 1106 # part of the final result 1107 1108 @q = (); ($v2,$v1) = @$y[-2,-1]; 1109 $v2 = 0 unless $v2; 1110 while ($#$x > $#$y) 1111 { 1112 ($u2,$u1,$u0) = @$x[-3..-1]; 1113 $u2 = 0 unless $u2; 1114 #warn "oups v1 is 0, u0: $u0 $y->[-2] $y->[-1] l ",scalar @$y,"\n" 1115 # if $v1 == 0; 1116 $q = (($u0 == $v1) ? $MAX_VAL : int(($u0*$BASE+$u1)/$v1)); 1117 --$q while ($v2*$q > ($u0*$BASE+$u1-$q*$v1)*$BASE+$u2); 1118 if ($q) 1119 { 1120 ($car, $bar) = (0,0); 1121 for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi) 1122 { 1123 $prd = $q * $y->[$yi] + $car; 1124 $prd -= ($car = int($prd / $BASE)) * $BASE; 1125 $x->[$xi] += $BASE if ($bar = (($x->[$xi] -= $prd + $bar) < 0)); 1126 } 1127 if ($x->[-1] < $car + $bar) 1128 { 1129 $car = 0; --$q; 1130 for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi) 1131 { 1132 $x->[$xi] -= $BASE 1133 if ($car = (($x->[$xi] += $y->[$yi] + $car) >= $BASE)); 1134 } 1135 } 1136 } 1137 pop(@$x); unshift(@q, $q); 1138 } 1139 if (wantarray) 1140 { 1141 @d = (); 1142 if ($dd != 1) 1143 { 1144 $car = 0; 1145 for $xi (reverse @$x) 1146 { 1147 $prd = $car * $BASE + $xi; 1148 $car = $prd - ($tmp = int($prd / $dd)) * $dd; 1149 unshift(@d, $tmp); 1150 } 1151 } 1152 else 1153 { 1154 @d = @$x; 1155 } 1156 @$x = @q; 1157 my $d = \@d; 1158 __strip_zeros($x); 1159 __strip_zeros($d); 1160 return ($x,$d); 1161 } 1162 @$x = @q; 1163 __strip_zeros($x); 1164 $x; 1165 } 1166 1167############################################################################## 1168# testing 1169 1170sub _acmp { 1171 # Internal absolute post-normalized compare (ignore signs) 1172 # ref to array, ref to array, return <0, 0, >0 1173 # Arrays must have at least one entry; this is not checked for. 1174 my ($c, $cx, $cy) = @_; 1175 1176 # shortcut for short numbers 1177 return (($cx->[0] <=> $cy->[0]) <=> 0) 1178 if @$cx == @$cy && @$cx == 1; 1179 1180 # fast comp based on number of array elements (aka pseudo-length) 1181 my $lxy = (@$cx - @$cy) 1182 # or length of first element if same number of elements (aka difference 0) 1183 || 1184 # need int() here because sometimes the last element is '00018' vs '18' 1185 (length(int($cx->[-1])) - length(int($cy->[-1]))); 1186 1187 return -1 if $lxy < 0; # already differs, ret 1188 return 1 if $lxy > 0; # ditto 1189 1190 # manual way (abort if unequal, good for early ne) 1191 my $a; 1192 my $j = @$cx; 1193 while (--$j >= 0) { 1194 last if $a = $cx->[$j] - $cy->[$j]; 1195 } 1196 $a <=> 0; 1197} 1198 1199sub _len { 1200 # compute number of digits in base 10 1201 1202 # int() because add/sub sometimes leaves strings (like '00005') instead of 1203 # '5' in this place, thus causing length() to report wrong length 1204 my $cx = $_[1]; 1205 1206 (@$cx - 1) * $BASE_LEN + length(int($cx->[-1])); 1207} 1208 1209sub _digit { 1210 # Return the nth digit. Zero is rightmost, so _digit(123,0) gives 3. 1211 # Negative values count from the left, so _digit(123, -1) gives 1. 1212 my ($c, $x, $n) = @_; 1213 1214 my $len = _len('', $x); 1215 1216 $n += $len if $n < 0; # -1 last, -2 second-to-last 1217 return "0" if $n < 0 || $n >= $len; # return 0 for digits out of range 1218 1219 my $elem = int($n / $BASE_LEN); # which array element 1220 my $digit = $n % $BASE_LEN; # which digit in this element 1221 substr("$x->[$elem]", -$digit - 1, 1); 1222} 1223 1224sub _zeros { 1225 # Return number of trailing zeros in decimal. 1226 # Check each array element for having 0 at end as long as elem == 0 1227 # Upon finding a elem != 0, stop. 1228 1229 my $x = $_[1]; 1230 1231 return 0 if @$x == 1 && $x->[0] == 0; 1232 1233 my $zeros = 0; 1234 my $elem; 1235 foreach my $e (@$x) { 1236 if ($e != 0) { 1237 $elem = "$e"; # preserve x 1238 $elem =~ s/.*?(0*$)/$1/; # strip anything not zero 1239 $zeros *= $BASE_LEN; # elems * 5 1240 $zeros += length($elem); # count trailing zeros 1241 last; # early out 1242 } 1243 $zeros ++; # real else branch: 50% slower! 1244 } 1245 $zeros; 1246} 1247 1248############################################################################## 1249# _is_* routines 1250 1251sub _is_zero { 1252 # return true if arg is zero 1253 @{$_[1]} == 1 && $_[1]->[0] == 0 ? 1 : 0; 1254} 1255 1256sub _is_even { 1257 # return true if arg is even 1258 $_[1]->[0] & 1 ? 0 : 1; 1259} 1260 1261sub _is_odd { 1262 # return true if arg is odd 1263 $_[1]->[0] & 1 ? 1 : 0; 1264} 1265 1266sub _is_one { 1267 # return true if arg is one 1268 @{$_[1]} == 1 && $_[1]->[0] == 1 ? 1 : 0; 1269} 1270 1271sub _is_two { 1272 # return true if arg is two 1273 @{$_[1]} == 1 && $_[1]->[0] == 2 ? 1 : 0; 1274} 1275 1276sub _is_ten { 1277 # return true if arg is ten 1278 @{$_[1]} == 1 && $_[1]->[0] == 10 ? 1 : 0; 1279} 1280 1281sub __strip_zeros { 1282 # Internal normalization function that strips leading zeros from the array. 1283 # Args: ref to array 1284 my $s = shift; 1285 1286 my $cnt = @$s; # get count of parts 1287 my $i = $cnt - 1; 1288 push @$s, 0 if $i < 0; # div might return empty results, so fix it 1289 1290 return $s if @$s == 1; # early out 1291 1292 #print "strip: cnt $cnt i $i\n"; 1293 # '0', '3', '4', '0', '0', 1294 # 0 1 2 3 4 1295 # cnt = 5, i = 4 1296 # i = 4 1297 # i = 3 1298 # => fcnt = cnt - i (5-2 => 3, cnt => 5-1 = 4, throw away from 4th pos) 1299 # >= 1: skip first part (this can be zero) 1300 while ($i > 0) { 1301 last if $s->[$i] != 0; 1302 $i--; 1303 } 1304 $i++; 1305 splice @$s, $i if $i < $cnt; # $i cant be 0 1306 $s; 1307} 1308 1309############################################################################### 1310# check routine to test internal state for corruptions 1311 1312sub _check { 1313 # used by the test suite 1314 my $x = $_[1]; 1315 1316 return "$x is not a reference" if !ref($x); 1317 1318 # are all parts are valid? 1319 my $i = 0; 1320 my $j = @$x; 1321 my ($e, $try); 1322 while ($i < $j) { 1323 $e = $x->[$i]; $e = 'undef' unless defined $e; 1324 $try = '=~ /^[\+]?[0-9]+\$/; '."($x, $e)"; 1325 last if $e !~ /^[+]?[0-9]+$/; 1326 $try = '=~ /^[\+]?[0-9]+\$/; '."($x, $e) (stringify)"; 1327 last if "$e" !~ /^[+]?[0-9]+$/; 1328 $try = '=~ /^[\+]?[0-9]+\$/; '."($x, $e) (cat-stringify)"; 1329 last if '' . "$e" !~ /^[+]?[0-9]+$/; 1330 $try = ' < 0 || >= $BASE; '."($x, $e)"; 1331 last if $e <0 || $e >= $BASE; 1332 # This test is disabled, since new/bnorm and certain ops (like early out 1333 # in add/sub) are allowed/expected to leave '00000' in some elements. 1334 #$try = '=~ /^00+/; '."($x, $e)"; 1335 #last if $e =~ /^00+/; 1336 $i++; 1337 } 1338 return "Illegal part '$e' at pos $i (tested: $try)" if $i < $j; 1339 0; 1340} 1341 1342############################################################################### 1343 1344sub _mod { 1345 # if possible, use mod shortcut 1346 my ($c, $x, $yo) = @_; 1347 1348 # slow way since $y too big 1349 if (@$yo > 1) { 1350 my ($xo, $rem) = _div($c, $x, $yo); 1351 @$x = @$rem; 1352 return $x; 1353 } 1354 1355 my $y = $yo->[0]; 1356 1357 # if both are single element arrays 1358 if (scalar @$x == 1) { 1359 $x->[0] %= $y; 1360 return $x; 1361 } 1362 1363 # if @$x has more than one element, but @$y is a single element 1364 my $b = $BASE % $y; 1365 if ($b == 0) { 1366 # when BASE % Y == 0 then (B * BASE) % Y == 0 1367 # (B * BASE) % $y + A % Y => A % Y 1368 # so need to consider only last element: O(1) 1369 $x->[0] %= $y; 1370 } elsif ($b == 1) { 1371 # else need to go through all elements in @$x: O(N), but loop is a bit 1372 # simplified 1373 my $r = 0; 1374 foreach (@$x) { 1375 $r = ($r + $_) % $y; # not much faster, but heh... 1376 #$r += $_ % $y; $r %= $y; 1377 } 1378 $r = 0 if $r == $y; 1379 $x->[0] = $r; 1380 } else { 1381 # else need to go through all elements in @$x: O(N) 1382 my $r = 0; 1383 my $bm = 1; 1384 foreach (@$x) { 1385 $r = ($_ * $bm + $r) % $y; 1386 $bm = ($bm * $b) % $y; 1387 1388 #$r += ($_ % $y) * $bm; 1389 #$bm *= $b; 1390 #$bm %= $y; 1391 #$r %= $y; 1392 } 1393 $r = 0 if $r == $y; 1394 $x->[0] = $r; 1395 } 1396 @$x = $x->[0]; # keep one element of @$x 1397 return $x; 1398} 1399 1400############################################################################## 1401# shifts 1402 1403sub _rsft { 1404 my ($c, $x, $y, $n) = @_; 1405 1406 if ($n != 10) { 1407 $n = _new($c, $n); 1408 return _div($c, $x, _pow($c, $n, $y)); 1409 } 1410 1411 # shortcut (faster) for shifting by 10) 1412 # multiples of $BASE_LEN 1413 my $dst = 0; # destination 1414 my $src = _num($c, $y); # as normal int 1415 my $xlen = (@$x - 1) * $BASE_LEN + length(int($x->[-1])); 1416 if ($src >= $xlen or ($src == $xlen and !defined $x->[1])) { 1417 # 12345 67890 shifted right by more than 10 digits => 0 1418 splice(@$x, 1); # leave only one element 1419 $x->[0] = 0; # set to zero 1420 return $x; 1421 } 1422 my $rem = $src % $BASE_LEN; # remainder to shift 1423 $src = int($src / $BASE_LEN); # source 1424 if ($rem == 0) { 1425 splice(@$x, 0, $src); # even faster, 38.4 => 39.3 1426 } else { 1427 my $len = @$x - $src; # elems to go 1428 my $vd; 1429 my $z = '0' x $BASE_LEN; 1430 $x->[@$x] = 0; # avoid || 0 test inside loop 1431 while ($dst < $len) { 1432 $vd = $z . $x->[$src]; 1433 $vd = substr($vd, -$BASE_LEN, $BASE_LEN - $rem); 1434 $src++; 1435 $vd = substr($z . $x->[$src], -$rem, $rem) . $vd; 1436 $vd = substr($vd, -$BASE_LEN, $BASE_LEN) if length($vd) > $BASE_LEN; 1437 $x->[$dst] = int($vd); 1438 $dst++; 1439 } 1440 splice(@$x, $dst) if $dst > 0; # kill left-over array elems 1441 pop @$x if $x->[-1] == 0 && @$x > 1; # kill last element if 0 1442 } # else rem == 0 1443 $x; 1444} 1445 1446sub _lsft { 1447 my ($c, $x, $y, $n) = @_; 1448 1449 if ($n != 10) { 1450 $n = _new($c, $n); 1451 return _mul($c, $x, _pow($c, $n, $y)); 1452 } 1453 1454 # shortcut (faster) for shifting by 10) since we are in base 10eX 1455 # multiples of $BASE_LEN: 1456 my $src = @$x; # source 1457 my $len = _num($c, $y); # shift-len as normal int 1458 my $rem = $len % $BASE_LEN; # remainder to shift 1459 my $dst = $src + int($len / $BASE_LEN); # destination 1460 my $vd; # further speedup 1461 $x->[$src] = 0; # avoid first ||0 for speed 1462 my $z = '0' x $BASE_LEN; 1463 while ($src >= 0) { 1464 $vd = $x->[$src]; 1465 $vd = $z . $vd; 1466 $vd = substr($vd, -$BASE_LEN + $rem, $BASE_LEN - $rem); 1467 $vd .= $src > 0 ? substr($z . $x->[$src - 1], -$BASE_LEN, $rem) 1468 : '0' x $rem; 1469 $vd = substr($vd, -$BASE_LEN, $BASE_LEN) if length($vd) > $BASE_LEN; 1470 $x->[$dst] = int($vd); 1471 $dst--; 1472 $src--; 1473 } 1474 # set lowest parts to 0 1475 while ($dst >= 0) { 1476 $x->[$dst--] = 0; 1477 } 1478 # fix spurious last zero element 1479 splice @$x, -1 if $x->[-1] == 0; 1480 $x; 1481} 1482 1483sub _pow { 1484 # power of $x to $y 1485 # ref to array, ref to array, return ref to array 1486 my ($c, $cx, $cy) = @_; 1487 1488 if (@$cy == 1 && $cy->[0] == 0) { 1489 splice(@$cx, 1); 1490 $cx->[0] = 1; # y == 0 => x => 1 1491 return $cx; 1492 } 1493 1494 if ((@$cx == 1 && $cx->[0] == 1) || # x == 1 1495 (@$cy == 1 && $cy->[0] == 1)) # or y == 1 1496 { 1497 return $cx; 1498 } 1499 1500 if (@$cx == 1 && $cx->[0] == 0) { 1501 splice (@$cx, 1); 1502 $cx->[0] = 0; # 0 ** y => 0 (if not y <= 0) 1503 return $cx; 1504 } 1505 1506 my $pow2 = _one(); 1507 1508 my $y_bin = _as_bin($c, $cy); 1509 $y_bin =~ s/^0b//; 1510 my $len = length($y_bin); 1511 while (--$len > 0) { 1512 _mul($c, $pow2, $cx) if substr($y_bin, $len, 1) eq '1'; # is odd? 1513 _mul($c, $cx, $cx); 1514 } 1515 1516 _mul($c, $cx, $pow2); 1517 $cx; 1518} 1519 1520sub _nok { 1521 # Return binomial coefficient (n over k). 1522 # Given refs to arrays, return ref to array. 1523 # First input argument is modified. 1524 1525 my ($c, $n, $k) = @_; 1526 1527 # If k > n/2, or, equivalently, 2*k > n, compute nok(n, k) as 1528 # nok(n, n-k), to minimize the number if iterations in the loop. 1529 1530 { 1531 my $twok = _mul($c, _two($c), _copy($c, $k)); # 2 * k 1532 if (_acmp($c, $twok, $n) > 0) { # if 2*k > n 1533 $k = _sub($c, _copy($c, $n), $k); # k = n - k 1534 } 1535 } 1536 1537 # Example: 1538 # 1539 # / 7 \ 7! 1*2*3*4 * 5*6*7 5 * 6 * 7 6 7 1540 # | | = --------- = --------------- = --------- = 5 * - * - 1541 # \ 3 / (7-3)! 3! 1*2*3*4 * 1*2*3 1 * 2 * 3 2 3 1542 1543 if (_is_zero($c, $k)) { 1544 @$n = 1; 1545 } 1546 1547 else { 1548 1549 # Make a copy of the original n, since we'll be modifying n in-place. 1550 1551 my $n_orig = _copy($c, $n); 1552 1553 # n = 5, f = 6, d = 2 (cf. example above) 1554 1555 _sub($c, $n, $k); 1556 _inc($c, $n); 1557 1558 my $f = _copy($c, $n); 1559 _inc($c, $f); 1560 1561 my $d = _two($c); 1562 1563 # while f <= n (the original n, that is) ... 1564 1565 while (_acmp($c, $f, $n_orig) <= 0) { 1566 1567 # n = (n * f / d) == 5 * 6 / 2 (cf. example above) 1568 1569 _mul($c, $n, $f); 1570 _div($c, $n, $d); 1571 1572 # f = 7, d = 3 (cf. example above) 1573 1574 _inc($c, $f); 1575 _inc($c, $d); 1576 } 1577 1578 } 1579 1580 return $n; 1581} 1582 1583my @factorials = ( 1584 1, 1585 1, 1586 2, 1587 2*3, 1588 2*3*4, 1589 2*3*4*5, 1590 2*3*4*5*6, 1591 2*3*4*5*6*7, 1592); 1593 1594sub _fac 1595 { 1596 # factorial of $x 1597 # ref to array, return ref to array 1598 my ($c,$cx) = @_; 1599 1600 if ((@$cx == 1) && ($cx->[0] <= 7)) 1601 { 1602 $cx->[0] = $factorials[$cx->[0]]; # 0 => 1, 1 => 1, 2 => 2 etc. 1603 return $cx; 1604 } 1605 1606 if ((@$cx == 1) && # we do this only if $x >= 12 and $x <= 7000 1607 ($cx->[0] >= 12 && $cx->[0] < 7000)) 1608 { 1609 1610 # Calculate (k-j) * (k-j+1) ... k .. (k+j-1) * (k + j) 1611 # See http://blogten.blogspot.com/2007/01/calculating-n.html 1612 # The above series can be expressed as factors: 1613 # k * k - (j - i) * 2 1614 # We cache k*k, and calculate (j * j) as the sum of the first j odd integers 1615 1616 # This will not work when N exceeds the storage of a Perl scalar, however, 1617 # in this case the algorithm would be way to slow to terminate, anyway. 1618 1619 # As soon as the last element of $cx is 0, we split it up and remember 1620 # how many zeors we got so far. The reason is that n! will accumulate 1621 # zeros at the end rather fast. 1622 my $zero_elements = 0; 1623 1624 # If n is even, set n = n -1 1625 my $k = _num($c,$cx); my $even = 1; 1626 if (($k & 1) == 0) 1627 { 1628 $even = $k; $k --; 1629 } 1630 # set k to the center point 1631 $k = ($k + 1) / 2; 1632# print "k $k even: $even\n"; 1633 # now calculate k * k 1634 my $k2 = $k * $k; 1635 my $odd = 1; my $sum = 1; 1636 my $i = $k - 1; 1637 # keep reference to x 1638 my $new_x = _new($c, $k * $even); 1639 @$cx = @$new_x; 1640 if ($cx->[0] == 0) 1641 { 1642 $zero_elements ++; shift @$cx; 1643 } 1644# print STDERR "x = ", _str($c,$cx),"\n"; 1645 my $BASE2 = int(sqrt($BASE))-1; 1646 my $j = 1; 1647 while ($j <= $i) 1648 { 1649 my $m = ($k2 - $sum); $odd += 2; $sum += $odd; $j++; 1650 while ($j <= $i && ($m < $BASE2) && (($k2 - $sum) < $BASE2)) 1651 { 1652 $m *= ($k2 - $sum); 1653 $odd += 2; $sum += $odd; $j++; 1654# print STDERR "\n k2 $k2 m $m sum $sum odd $odd\n"; sleep(1); 1655 } 1656 if ($m < $BASE) 1657 { 1658 _mul($c,$cx,[$m]); 1659 } 1660 else 1661 { 1662 _mul($c,$cx,$c->_new($m)); 1663 } 1664 if ($cx->[0] == 0) 1665 { 1666 $zero_elements ++; shift @$cx; 1667 } 1668# print STDERR "Calculate $k2 - $sum = $m (x = ", _str($c,$cx),")\n"; 1669 } 1670 # multiply in the zeros again 1671 unshift @$cx, (0) x $zero_elements; 1672 return $cx; 1673 } 1674 1675 # go forward until $base is exceeded 1676 # limit is either $x steps (steps == 100 means a result always too high) or 1677 # $base. 1678 my $steps = 100; $steps = $cx->[0] if @$cx == 1; 1679 my $r = 2; my $cf = 3; my $step = 2; my $last = $r; 1680 while ($r*$cf < $BASE && $step < $steps) 1681 { 1682 $last = $r; $r *= $cf++; $step++; 1683 } 1684 if ((@$cx == 1) && $step == $cx->[0]) 1685 { 1686 # completely done, so keep reference to $x and return 1687 $cx->[0] = $r; 1688 return $cx; 1689 } 1690 1691 # now we must do the left over steps 1692 my $n; # steps still to do 1693 if (scalar @$cx == 1) 1694 { 1695 $n = $cx->[0]; 1696 } 1697 else 1698 { 1699 $n = _copy($c,$cx); 1700 } 1701 1702 # Set $cx to the last result below $BASE (but keep ref to $x) 1703 $cx->[0] = $last; splice (@$cx,1); 1704 # As soon as the last element of $cx is 0, we split it up and remember 1705 # how many zeors we got so far. The reason is that n! will accumulate 1706 # zeros at the end rather fast. 1707 my $zero_elements = 0; 1708 1709 # do left-over steps fit into a scalar? 1710 if (ref $n eq 'ARRAY') 1711 { 1712 # No, so use slower inc() & cmp() 1713 # ($n is at least $BASE here) 1714 my $base_2 = int(sqrt($BASE)) - 1; 1715 #print STDERR "base_2: $base_2\n"; 1716 while ($step < $base_2) 1717 { 1718 if ($cx->[0] == 0) 1719 { 1720 $zero_elements ++; shift @$cx; 1721 } 1722 my $b = $step * ($step + 1); $step += 2; 1723 _mul($c,$cx,[$b]); 1724 } 1725 $step = [$step]; 1726 while (_acmp($c,$step,$n) <= 0) 1727 { 1728 if ($cx->[0] == 0) 1729 { 1730 $zero_elements ++; shift @$cx; 1731 } 1732 _mul($c,$cx,$step); _inc($c,$step); 1733 } 1734 } 1735 else 1736 { 1737 # Yes, so we can speed it up slightly 1738 1739# print "# left over steps $n\n"; 1740 1741 my $base_4 = int(sqrt(sqrt($BASE))) - 2; 1742 #print STDERR "base_4: $base_4\n"; 1743 my $n4 = $n - 4; 1744 while ($step < $n4 && $step < $base_4) 1745 { 1746 if ($cx->[0] == 0) 1747 { 1748 $zero_elements ++; shift @$cx; 1749 } 1750 my $b = $step * ($step + 1); $step += 2; $b *= $step * ($step + 1); $step += 2; 1751 _mul($c,$cx,[$b]); 1752 } 1753 my $base_2 = int(sqrt($BASE)) - 1; 1754 my $n2 = $n - 2; 1755 #print STDERR "base_2: $base_2\n"; 1756 while ($step < $n2 && $step < $base_2) 1757 { 1758 if ($cx->[0] == 0) 1759 { 1760 $zero_elements ++; shift @$cx; 1761 } 1762 my $b = $step * ($step + 1); $step += 2; 1763 _mul($c,$cx,[$b]); 1764 } 1765 # do what's left over 1766 while ($step <= $n) 1767 { 1768 _mul($c,$cx,[$step]); $step++; 1769 if ($cx->[0] == 0) 1770 { 1771 $zero_elements ++; shift @$cx; 1772 } 1773 } 1774 } 1775 # multiply in the zeros again 1776 unshift @$cx, (0) x $zero_elements; 1777 $cx; # return result 1778 } 1779 1780############################################################################# 1781 1782sub _log_int 1783 { 1784 # calculate integer log of $x to base $base 1785 # ref to array, ref to array - return ref to array 1786 my ($c,$x,$base) = @_; 1787 1788 # X == 0 => NaN 1789 return if (scalar @$x == 1 && $x->[0] == 0); 1790 # BASE 0 or 1 => NaN 1791 return if (scalar @$base == 1 && $base->[0] < 2); 1792 my $cmp = _acmp($c,$x,$base); # X == BASE => 1 1793 if ($cmp == 0) 1794 { 1795 splice (@$x,1); $x->[0] = 1; 1796 return ($x,1) 1797 } 1798 # X < BASE 1799 if ($cmp < 0) 1800 { 1801 splice (@$x,1); $x->[0] = 0; 1802 return ($x,undef); 1803 } 1804 1805 my $x_org = _copy($c,$x); # preserve x 1806 splice(@$x,1); $x->[0] = 1; # keep ref to $x 1807 1808 # Compute a guess for the result based on: 1809 # $guess = int ( length_in_base_10(X) / ( log(base) / log(10) ) ) 1810 my $len = _len($c,$x_org); 1811 my $log = log($base->[-1]) / log(10); 1812 1813 # for each additional element in $base, we add $BASE_LEN to the result, 1814 # based on the observation that log($BASE,10) is BASE_LEN and 1815 # log(x*y) == log(x) + log(y): 1816 $log += ((scalar @$base)-1) * $BASE_LEN; 1817 1818 # calculate now a guess based on the values obtained above: 1819 my $res = int($len / $log); 1820 1821 $x->[0] = $res; 1822 my $trial = _pow ($c, _copy($c, $base), $x); 1823 my $a = _acmp($c,$trial,$x_org); 1824 1825# print STDERR "# trial ", _str($c,$x)," was: $a (0 = exact, -1 too small, +1 too big)\n"; 1826 1827 # found an exact result? 1828 return ($x,1) if $a == 0; 1829 1830 if ($a > 0) 1831 { 1832 # or too big 1833 _div($c,$trial,$base); _dec($c, $x); 1834 while (($a = _acmp($c,$trial,$x_org)) > 0) 1835 { 1836# print STDERR "# big _log_int at ", _str($c,$x), "\n"; 1837 _div($c,$trial,$base); _dec($c, $x); 1838 } 1839 # result is now exact (a == 0), or too small (a < 0) 1840 return ($x, $a == 0 ? 1 : 0); 1841 } 1842 1843 # else: result was to small 1844 _mul($c,$trial,$base); 1845 1846 # did we now get the right result? 1847 $a = _acmp($c,$trial,$x_org); 1848 1849 if ($a == 0) # yes, exactly 1850 { 1851 _inc($c, $x); 1852 return ($x,1); 1853 } 1854 return ($x,0) if $a > 0; 1855 1856 # Result still too small (we should come here only if the estimate above 1857 # was very off base): 1858 1859 # Now let the normal trial run obtain the real result 1860 # Simple loop that increments $x by 2 in each step, possible overstepping 1861 # the real result 1862 1863 my $base_mul = _mul($c, _copy($c,$base), $base); # $base * $base 1864 1865 while (($a = _acmp($c,$trial,$x_org)) < 0) 1866 { 1867# print STDERR "# small _log_int at ", _str($c,$x), "\n"; 1868 _mul($c,$trial,$base_mul); _add($c, $x, [2]); 1869 } 1870 1871 my $exact = 1; 1872 if ($a > 0) 1873 { 1874 # overstepped the result 1875 _dec($c, $x); 1876 _div($c,$trial,$base); 1877 $a = _acmp($c,$trial,$x_org); 1878 if ($a > 0) 1879 { 1880 _dec($c, $x); 1881 } 1882 $exact = 0 if $a != 0; # a = -1 => not exact result, a = 0 => exact 1883 } 1884 1885 ($x,$exact); # return result 1886 } 1887 1888# for debugging: 1889 use constant DEBUG => 0; 1890 my $steps = 0; 1891 sub steps { $steps }; 1892 1893sub _sqrt 1894 { 1895 # square-root of $x in place 1896 # Compute a guess of the result (by rule of thumb), then improve it via 1897 # Newton's method. 1898 my ($c,$x) = @_; 1899 1900 if (scalar @$x == 1) 1901 { 1902 # fits into one Perl scalar, so result can be computed directly 1903 $x->[0] = int(sqrt($x->[0])); 1904 return $x; 1905 } 1906 my $y = _copy($c,$x); 1907 # hopefully _len/2 is < $BASE, the -1 is to always undershot the guess 1908 # since our guess will "grow" 1909 my $l = int((_len($c,$x)-1) / 2); 1910 1911 my $lastelem = $x->[-1]; # for guess 1912 my $elems = scalar @$x - 1; 1913 # not enough digits, but could have more? 1914 if ((length($lastelem) <= 3) && ($elems > 1)) 1915 { 1916 # right-align with zero pad 1917 my $len = length($lastelem) & 1; 1918 print "$lastelem => " if DEBUG; 1919 $lastelem .= substr($x->[-2] . '0' x $BASE_LEN,0,$BASE_LEN); 1920 # former odd => make odd again, or former even to even again 1921 $lastelem = $lastelem / 10 if (length($lastelem) & 1) != $len; 1922 print "$lastelem\n" if DEBUG; 1923 } 1924 1925 # construct $x (instead of _lsft($c,$x,$l,10) 1926 my $r = $l % $BASE_LEN; # 10000 00000 00000 00000 ($BASE_LEN=5) 1927 $l = int($l / $BASE_LEN); 1928 print "l = $l " if DEBUG; 1929 1930 splice @$x,$l; # keep ref($x), but modify it 1931 1932 # we make the first part of the guess not '1000...0' but int(sqrt($lastelem)) 1933 # that gives us: 1934 # 14400 00000 => sqrt(14400) => guess first digits to be 120 1935 # 144000 000000 => sqrt(144000) => guess 379 1936 1937 print "$lastelem (elems $elems) => " if DEBUG; 1938 $lastelem = $lastelem / 10 if ($elems & 1 == 1); # odd or even? 1939 my $g = sqrt($lastelem); $g =~ s/\.//; # 2.345 => 2345 1940 $r -= 1 if $elems & 1 == 0; # 70 => 7 1941 1942 # padd with zeros if result is too short 1943 $x->[$l--] = int(substr($g . '0' x $r,0,$r+1)); 1944 print "now ",$x->[-1] if DEBUG; 1945 print " would have been ", int('1' . '0' x $r),"\n" if DEBUG; 1946 1947 # If @$x > 1, we could compute the second elem of the guess, too, to create 1948 # an even better guess. Not implemented yet. Does it improve performance? 1949 $x->[$l--] = 0 while ($l >= 0); # all other digits of guess are zero 1950 1951 print "start x= ",_str($c,$x),"\n" if DEBUG; 1952 my $two = _two(); 1953 my $last = _zero(); 1954 my $lastlast = _zero(); 1955 $steps = 0 if DEBUG; 1956 while (_acmp($c,$last,$x) != 0 && _acmp($c,$lastlast,$x) != 0) 1957 { 1958 $steps++ if DEBUG; 1959 $lastlast = _copy($c,$last); 1960 $last = _copy($c,$x); 1961 _add($c,$x, _div($c,_copy($c,$y),$x)); 1962 _div($c,$x, $two ); 1963 print " x= ",_str($c,$x),"\n" if DEBUG; 1964 } 1965 print "\nsteps in sqrt: $steps, " if DEBUG; 1966 _dec($c,$x) if _acmp($c,$y,_mul($c,_copy($c,$x),$x)) < 0; # overshot? 1967 print " final ",$x->[-1],"\n" if DEBUG; 1968 $x; 1969 } 1970 1971sub _root 1972 { 1973 # take n'th root of $x in place (n >= 3) 1974 my ($c,$x,$n) = @_; 1975 1976 if (scalar @$x == 1) 1977 { 1978 if (scalar @$n > 1) 1979 { 1980 # result will always be smaller than 2 so trunc to 1 at once 1981 $x->[0] = 1; 1982 } 1983 else 1984 { 1985 # fits into one Perl scalar, so result can be computed directly 1986 # cannot use int() here, because it rounds wrongly (try 1987 # (81 ** 3) ** (1/3) to see what I mean) 1988 #$x->[0] = int( $x->[0] ** (1 / $n->[0]) ); 1989 # round to 8 digits, then truncate result to integer 1990 $x->[0] = int ( sprintf ("%.8f", $x->[0] ** (1 / $n->[0]) ) ); 1991 } 1992 return $x; 1993 } 1994 1995 # we know now that X is more than one element long 1996 1997 # if $n is a power of two, we can repeatedly take sqrt($X) and find the 1998 # proper result, because sqrt(sqrt($x)) == root($x,4) 1999 my $b = _as_bin($c,$n); 2000 if ($b =~ /0b1(0+)$/) 2001 { 2002 my $count = CORE::length($1); # 0b100 => len('00') => 2 2003 my $cnt = $count; # counter for loop 2004 unshift (@$x, 0); # add one element, together with one 2005 # more below in the loop this makes 2 2006 while ($cnt-- > 0) 2007 { 2008 # 'inflate' $X by adding one element, basically computing 2009 # $x * $BASE * $BASE. This gives us more $BASE_LEN digits for result 2010 # since len(sqrt($X)) approx == len($x) / 2. 2011 unshift (@$x, 0); 2012 # calculate sqrt($x), $x is now one element to big, again. In the next 2013 # round we make that two, again. 2014 _sqrt($c,$x); 2015 } 2016 # $x is now one element to big, so truncate result by removing it 2017 splice (@$x,0,1); 2018 } 2019 else 2020 { 2021 # trial computation by starting with 2,4,8,16 etc until we overstep 2022 my $step; 2023 my $trial = _two(); 2024 2025 # while still to do more than X steps 2026 do 2027 { 2028 $step = _two(); 2029 while (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) < 0) 2030 { 2031 _mul ($c, $step, [2]); 2032 _add ($c, $trial, $step); 2033 } 2034 2035 # hit exactly? 2036 if (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) == 0) 2037 { 2038 @$x = @$trial; # make copy while preserving ref to $x 2039 return $x; 2040 } 2041 # overstepped, so go back on step 2042 _sub($c, $trial, $step); 2043 } while (scalar @$step > 1 || $step->[0] > 128); 2044 2045 # reset step to 2 2046 $step = _two(); 2047 # add two, because $trial cannot be exactly the result (otherwise we would 2048 # already have found it) 2049 _add($c, $trial, $step); 2050 2051 # and now add more and more (2,4,6,8,10 etc) 2052 while (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) < 0) 2053 { 2054 _add ($c, $trial, $step); 2055 } 2056 2057 # hit not exactly? (overstepped) 2058 if (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) > 0) 2059 { 2060 _dec($c,$trial); 2061 } 2062 2063 # hit not exactly? (overstepped) 2064 # 80 too small, 81 slightly too big, 82 too big 2065 if (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) > 0) 2066 { 2067 _dec ($c, $trial); 2068 } 2069 2070 @$x = @$trial; # make copy while preserving ref to $x 2071 return $x; 2072 } 2073 $x; 2074 } 2075 2076############################################################################## 2077# binary stuff 2078 2079sub _and 2080 { 2081 my ($c,$x,$y) = @_; 2082 2083 # the shortcut makes equal, large numbers _really_ fast, and makes only a 2084 # very small performance drop for small numbers (e.g. something with less 2085 # than 32 bit) Since we optimize for large numbers, this is enabled. 2086 return $x if _acmp($c,$x,$y) == 0; # shortcut 2087 2088 my $m = _one(); my ($xr,$yr); 2089 my $mask = $AND_MASK; 2090 2091 my $x1 = $x; 2092 my $y1 = _copy($c,$y); # make copy 2093 $x = _zero(); 2094 my ($b,$xrr,$yrr); 2095 use integer; 2096 while (!_is_zero($c,$x1) && !_is_zero($c,$y1)) 2097 { 2098 ($x1, $xr) = _div($c,$x1,$mask); 2099 ($y1, $yr) = _div($c,$y1,$mask); 2100 2101 # make ints() from $xr, $yr 2102 # this is when the AND_BITS are greater than $BASE and is slower for 2103 # small (<256 bits) numbers, but faster for large numbers. Disabled 2104 # due to KISS principle 2105 2106# $b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; } 2107# $b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; } 2108# _add($c,$x, _mul($c, _new( $c, ($xrr & $yrr) ), $m) ); 2109 2110 # 0+ due to '&' doesn't work in strings 2111 _add($c,$x, _mul($c, [ 0+$xr->[0] & 0+$yr->[0] ], $m) ); 2112 _mul($c,$m,$mask); 2113 } 2114 $x; 2115 } 2116 2117sub _xor 2118 { 2119 my ($c,$x,$y) = @_; 2120 2121 return _zero() if _acmp($c,$x,$y) == 0; # shortcut (see -and) 2122 2123 my $m = _one(); my ($xr,$yr); 2124 my $mask = $XOR_MASK; 2125 2126 my $x1 = $x; 2127 my $y1 = _copy($c,$y); # make copy 2128 $x = _zero(); 2129 my ($b,$xrr,$yrr); 2130 use integer; 2131 while (!_is_zero($c,$x1) && !_is_zero($c,$y1)) 2132 { 2133 ($x1, $xr) = _div($c,$x1,$mask); 2134 ($y1, $yr) = _div($c,$y1,$mask); 2135 # make ints() from $xr, $yr (see _and()) 2136 #$b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; } 2137 #$b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; } 2138 #_add($c,$x, _mul($c, _new( $c, ($xrr ^ $yrr) ), $m) ); 2139 2140 # 0+ due to '^' doesn't work in strings 2141 _add($c,$x, _mul($c, [ 0+$xr->[0] ^ 0+$yr->[0] ], $m) ); 2142 _mul($c,$m,$mask); 2143 } 2144 # the loop stops when the shorter of the two numbers is exhausted 2145 # the remainder of the longer one will survive bit-by-bit, so we simple 2146 # multiply-add it in 2147 _add($c,$x, _mul($c, $x1, $m) ) if !_is_zero($c,$x1); 2148 _add($c,$x, _mul($c, $y1, $m) ) if !_is_zero($c,$y1); 2149 2150 $x; 2151 } 2152 2153sub _or 2154 { 2155 my ($c,$x,$y) = @_; 2156 2157 return $x if _acmp($c,$x,$y) == 0; # shortcut (see _and) 2158 2159 my $m = _one(); my ($xr,$yr); 2160 my $mask = $OR_MASK; 2161 2162 my $x1 = $x; 2163 my $y1 = _copy($c,$y); # make copy 2164 $x = _zero(); 2165 my ($b,$xrr,$yrr); 2166 use integer; 2167 while (!_is_zero($c,$x1) && !_is_zero($c,$y1)) 2168 { 2169 ($x1, $xr) = _div($c,$x1,$mask); 2170 ($y1, $yr) = _div($c,$y1,$mask); 2171 # make ints() from $xr, $yr (see _and()) 2172# $b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; } 2173# $b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; } 2174# _add($c,$x, _mul($c, _new( $c, ($xrr | $yrr) ), $m) ); 2175 2176 # 0+ due to '|' doesn't work in strings 2177 _add($c,$x, _mul($c, [ 0+$xr->[0] | 0+$yr->[0] ], $m) ); 2178 _mul($c,$m,$mask); 2179 } 2180 # the loop stops when the shorter of the two numbers is exhausted 2181 # the remainder of the longer one will survive bit-by-bit, so we simple 2182 # multiply-add it in 2183 _add($c,$x, _mul($c, $x1, $m) ) if !_is_zero($c,$x1); 2184 _add($c,$x, _mul($c, $y1, $m) ) if !_is_zero($c,$y1); 2185 2186 $x; 2187 } 2188 2189sub _as_hex 2190 { 2191 # convert a decimal number to hex (ref to array, return ref to string) 2192 my ($c,$x) = @_; 2193 2194 # fits into one element (handle also 0x0 case) 2195 return sprintf("0x%x",$x->[0]) if @$x == 1; 2196 2197 my $x1 = _copy($c,$x); 2198 2199 my $es = ''; 2200 my ($xr, $h, $x10000); 2201 if ($] >= 5.006) 2202 { 2203 $x10000 = [ 0x10000 ]; $h = 'h4'; 2204 } 2205 else 2206 { 2207 $x10000 = [ 0x1000 ]; $h = 'h3'; 2208 } 2209 while (@$x1 != 1 || $x1->[0] != 0) # _is_zero() 2210 { 2211 ($x1, $xr) = _div($c,$x1,$x10000); 2212 $es .= unpack($h,pack('V',$xr->[0])); 2213 } 2214 $es = reverse $es; 2215 $es =~ s/^[0]+//; # strip leading zeros 2216 '0x' . $es; # return result prepended with 0x 2217 } 2218 2219sub _as_bin 2220 { 2221 # convert a decimal number to bin (ref to array, return ref to string) 2222 my ($c,$x) = @_; 2223 2224 # fits into one element (and Perl recent enough), handle also 0b0 case 2225 # handle zero case for older Perls 2226 if ($] <= 5.005 && @$x == 1 && $x->[0] == 0) 2227 { 2228 my $t = '0b0'; return $t; 2229 } 2230 if (@$x == 1 && $] >= 5.006) 2231 { 2232 my $t = sprintf("0b%b",$x->[0]); 2233 return $t; 2234 } 2235 my $x1 = _copy($c,$x); 2236 2237 my $es = ''; 2238 my ($xr, $b, $x10000); 2239 if ($] >= 5.006) 2240 { 2241 $x10000 = [ 0x10000 ]; $b = 'b16'; 2242 } 2243 else 2244 { 2245 $x10000 = [ 0x1000 ]; $b = 'b12'; 2246 } 2247 while (!(@$x1 == 1 && $x1->[0] == 0)) # _is_zero() 2248 { 2249 ($x1, $xr) = _div($c,$x1,$x10000); 2250 $es .= unpack($b,pack('v',$xr->[0])); 2251 } 2252 $es = reverse $es; 2253 $es =~ s/^[0]+//; # strip leading zeros 2254 '0b' . $es; # return result prepended with 0b 2255 } 2256 2257sub _as_oct 2258 { 2259 # convert a decimal number to octal (ref to array, return ref to string) 2260 my ($c,$x) = @_; 2261 2262 # fits into one element (handle also 0 case) 2263 return sprintf("0%o",$x->[0]) if @$x == 1; 2264 2265 my $x1 = _copy($c,$x); 2266 2267 my $es = ''; 2268 my $xr; 2269 my $x1000 = [ 0100000 ]; 2270 while (@$x1 != 1 || $x1->[0] != 0) # _is_zero() 2271 { 2272 ($x1, $xr) = _div($c,$x1,$x1000); 2273 $es .= reverse sprintf("%05o", $xr->[0]); 2274 } 2275 $es = reverse $es; 2276 $es =~ s/^0+//; # strip leading zeros 2277 '0' . $es; # return result prepended with 0 2278 } 2279 2280sub _from_oct 2281 { 2282 # convert a octal number to decimal (string, return ref to array) 2283 my ($c,$os) = @_; 2284 2285 # for older Perls, play safe 2286 my $m = [ 0100000 ]; 2287 my $d = 5; # 5 digits at a time 2288 2289 my $mul = _one(); 2290 my $x = _zero(); 2291 2292 my $len = int( (length($os)-1)/$d ); # $d digit parts, w/o the '0' 2293 my $val; my $i = -$d; 2294 while ($len >= 0) 2295 { 2296 $val = substr($os,$i,$d); # get oct digits 2297 $val = CORE::oct($val); 2298 $i -= $d; $len --; 2299 my $adder = [ $val ]; 2300 _add ($c, $x, _mul ($c, $adder, $mul ) ) if $val != 0; 2301 _mul ($c, $mul, $m ) if $len >= 0; # skip last mul 2302 } 2303 $x; 2304 } 2305 2306sub _from_hex 2307 { 2308 # convert a hex number to decimal (string, return ref to array) 2309 my ($c,$hs) = @_; 2310 2311 my $m = _new($c, 0x10000000); # 28 bit at a time (<32 bit!) 2312 my $d = 7; # 7 digits at a time 2313 if ($] <= 5.006) 2314 { 2315 # for older Perls, play safe 2316 $m = [ 0x10000 ]; # 16 bit at a time (<32 bit!) 2317 $d = 4; # 4 digits at a time 2318 } 2319 2320 my $mul = _one(); 2321 my $x = _zero(); 2322 2323 my $len = int( (length($hs)-2)/$d ); # $d digit parts, w/o the '0x' 2324 my $val; my $i = -$d; 2325 while ($len >= 0) 2326 { 2327 $val = substr($hs,$i,$d); # get hex digits 2328 $val =~ s/^0x// if $len == 0; # for last part only because 2329 $val = CORE::hex($val); # hex does not like wrong chars 2330 $i -= $d; $len --; 2331 my $adder = [ $val ]; 2332 # if the resulting number was to big to fit into one element, create a 2333 # two-element version (bug found by Mark Lakata - Thanx!) 2334 if (CORE::length($val) > $BASE_LEN) 2335 { 2336 $adder = _new($c,$val); 2337 } 2338 _add ($c, $x, _mul ($c, $adder, $mul ) ) if $val != 0; 2339 _mul ($c, $mul, $m ) if $len >= 0; # skip last mul 2340 } 2341 $x; 2342 } 2343 2344sub _from_bin 2345 { 2346 # convert a hex number to decimal (string, return ref to array) 2347 my ($c,$bs) = @_; 2348 2349 # instead of converting X (8) bit at a time, it is faster to "convert" the 2350 # number to hex, and then call _from_hex. 2351 2352 my $hs = $bs; 2353 $hs =~ s/^[+-]?0b//; # remove sign and 0b 2354 my $l = length($hs); # bits 2355 $hs = '0' x (8-($l % 8)) . $hs if ($l % 8) != 0; # padd left side w/ 0 2356 my $h = '0x' . unpack('H*', pack ('B*', $hs)); # repack as hex 2357 2358 $c->_from_hex($h); 2359 } 2360 2361############################################################################## 2362# special modulus functions 2363 2364sub _modinv 2365 { 2366 # modular multiplicative inverse 2367 my ($c,$x,$y) = @_; 2368 2369 # modulo zero 2370 if (_is_zero($c, $y)) { 2371 return (undef, undef); 2372 } 2373 2374 # modulo one 2375 if (_is_one($c, $y)) { 2376 return (_zero($c), '+'); 2377 } 2378 2379 my $u = _zero($c); 2380 my $v = _one($c); 2381 my $a = _copy($c,$y); 2382 my $b = _copy($c,$x); 2383 2384 # Euclid's Algorithm for bgcd(), only that we calc bgcd() ($a) and the result 2385 # ($u) at the same time. See comments in BigInt for why this works. 2386 my $q; 2387 my $sign = 1; 2388 { 2389 ($a, $q, $b) = ($b, _div($c, $a, $b)); # step 1 2390 last if _is_zero($c, $b); 2391 2392 my $t = _add($c, # step 2: 2393 _mul($c, _copy($c, $v), $q) , # t = v * q 2394 $u ); # + u 2395 $u = $v; # u = v 2396 $v = $t; # v = t 2397 $sign = -$sign; 2398 redo; 2399 } 2400 2401 # if the gcd is not 1, then return NaN 2402 return (undef, undef) unless _is_one($c, $a); 2403 2404 ($v, $sign == 1 ? '+' : '-'); 2405 } 2406 2407sub _modpow 2408 { 2409 # modulus of power ($x ** $y) % $z 2410 my ($c,$num,$exp,$mod) = @_; 2411 2412 # a^b (mod 1) = 0 for all a and b 2413 if (_is_one($c,$mod)) 2414 { 2415 @$num = 0; 2416 return $num; 2417 } 2418 2419 # 0^a (mod m) = 0 if m != 0, a != 0 2420 # 0^0 (mod m) = 1 if m != 0 2421 if (_is_zero($c, $num)) { 2422 if (_is_zero($c, $exp)) { 2423 @$num = 1; 2424 } else { 2425 @$num = 0; 2426 } 2427 return $num; 2428 } 2429 2430# $num = _mod($c,$num,$mod); # this does not make it faster 2431 2432 my $acc = _copy($c,$num); my $t = _one(); 2433 2434 my $expbin = _as_bin($c,$exp); $expbin =~ s/^0b//; 2435 my $len = length($expbin); 2436 while (--$len >= 0) 2437 { 2438 if ( substr($expbin,$len,1) eq '1') # is_odd 2439 { 2440 _mul($c,$t,$acc); 2441 $t = _mod($c,$t,$mod); 2442 } 2443 _mul($c,$acc,$acc); 2444 $acc = _mod($c,$acc,$mod); 2445 } 2446 @$num = @$t; 2447 $num; 2448 } 2449 2450sub _gcd { 2451 # Greatest common divisor. 2452 2453 my ($c, $x, $y) = @_; 2454 2455 # gcd(0,0) = 0 2456 # gcd(0,a) = a, if a != 0 2457 2458 if (@$x == 1 && $x->[0] == 0) { 2459 if (@$y == 1 && $y->[0] == 0) { 2460 @$x = 0; 2461 } else { 2462 @$x = @$y; 2463 } 2464 return $x; 2465 } 2466 2467 # Until $y is zero ... 2468 2469 until (@$y == 1 && $y->[0] == 0) { 2470 2471 # Compute remainder. 2472 2473 _mod($c, $x, $y); 2474 2475 # Swap $x and $y. 2476 2477 my $tmp = [ @$x ]; 2478 @$x = @$y; 2479 $y = $tmp; # no deref here; that would modify input $y 2480 } 2481 2482 return $x; 2483} 2484 2485############################################################################## 2486############################################################################## 2487 24881; 2489__END__ 2490 2491=pod 2492 2493=head1 NAME 2494 2495Math::BigInt::Calc - Pure Perl module to support Math::BigInt 2496 2497=head1 SYNOPSIS 2498 2499This library provides support for big integer calculations. It is not 2500intended to be used by other modules. Other modules which support the same 2501API (see below) can also be used to support Math::BigInt, like 2502Math::BigInt::GMP and Math::BigInt::Pari. 2503 2504=head1 DESCRIPTION 2505 2506In this library, the numbers are represented in base B = 10**N, where N is 2507the largest possible value that does not cause overflow in the intermediate 2508computations. The base B elements are stored in an array, with the least 2509significant element stored in array element zero. There are no leading zero 2510elements, except a single zero element when the number is zero. 2511 2512For instance, if B = 10000, the number 1234567890 is represented internally 2513as [3456, 7890, 12]. 2514 2515=head1 THE Math::BigInt API 2516 2517In order to allow for multiple big integer libraries, Math::BigInt was 2518rewritten to use a plug-in library for core math routines. Any module which 2519conforms to the API can be used by Math::BigInt by using this in your program: 2520 2521 use Math::BigInt lib => 'libname'; 2522 2523'libname' is either the long name, like 'Math::BigInt::Pari', or only the short 2524version, like 'Pari'. 2525 2526=head2 General Notes 2527 2528A library only needs to deal with unsigned big integers. Testing of input 2529parameter validity is done by the caller, so there is no need to worry about 2530underflow (e.g., in C<_sub()> and C<_dec()>) nor about division by zero (e.g., 2531in C<_div()>) or similar cases. 2532 2533For some methods, the first parameter can be modified. That includes the 2534possibility that you return a reference to a completely different object 2535instead. Although keeping the reference and just changing its contents is 2536preferred over creating and returning a different reference. 2537 2538Return values are always objects, strings, Perl scalars, or true/false for 2539comparison routines. 2540 2541=head2 API version 1 2542 2543The following methods must be defined in order to support the use by 2544Math::BigInt v1.70 or later. 2545 2546=head3 API version 2547 2548=over 4 2549 2550=item I<api_version()> 2551 2552Return API version as a Perl scalar, 1 for Math::BigInt v1.70, 2 for 2553Math::BigInt v1.83. 2554 2555=back 2556 2557=head3 Constructors 2558 2559=over 4 2560 2561=item I<_new(STR)> 2562 2563Convert a string representing an unsigned decimal number to an object 2564representing the same number. The input is normalize, i.e., it matches 2565C<^(0|[1-9]\d*)$>. 2566 2567=item I<_zero()> 2568 2569Return an object representing the number zero. 2570 2571=item I<_one()> 2572 2573Return an object representing the number one. 2574 2575=item I<_two()> 2576 2577Return an object representing the number two. 2578 2579=item I<_ten()> 2580 2581Return an object representing the number ten. 2582 2583=item I<_from_bin(STR)> 2584 2585Return an object given a string representing a binary number. The input has a 2586'0b' prefix and matches the regular expression C<^0[bB](0|1[01]*)$>. 2587 2588=item I<_from_oct(STR)> 2589 2590Return an object given a string representing an octal number. The input has a 2591'0' prefix and matches the regular expression C<^0[1-7]*$>. 2592 2593=item I<_from_hex(STR)> 2594 2595Return an object given a string representing a hexadecimal number. The input 2596has a '0x' prefix and matches the regular expression 2597C<^0x(0|[1-9a-fA-F][\da-fA-F]*)$>. 2598 2599=back 2600 2601=head3 Mathematical functions 2602 2603Each of these methods may modify the first input argument, except I<_bgcd()>, 2604which shall not modify any input argument, and I<_sub()> which may modify the 2605second input argument. 2606 2607=over 4 2608 2609=item I<_add(OBJ1, OBJ2)> 2610 2611Returns the result of adding OBJ2 to OBJ1. 2612 2613=item I<_mul(OBJ1, OBJ2)> 2614 2615Returns the result of multiplying OBJ2 and OBJ1. 2616 2617=item I<_div(OBJ1, OBJ2)> 2618 2619Returns the result of dividing OBJ1 by OBJ2 and truncating the result to an 2620integer. 2621 2622=item I<_sub(OBJ1, OBJ2, FLAG)> 2623 2624=item I<_sub(OBJ1, OBJ2)> 2625 2626Returns the result of subtracting OBJ2 by OBJ1. If C<flag> is false or omitted, 2627OBJ1 might be modified. If C<flag> is true, OBJ2 might be modified. 2628 2629=item I<_dec(OBJ)> 2630 2631Decrement OBJ by one. 2632 2633=item I<_inc(OBJ)> 2634 2635Increment OBJ by one. 2636 2637=item I<_mod(OBJ1, OBJ2)> 2638 2639Return OBJ1 modulo OBJ2, i.e., the remainder after dividing OBJ1 by OBJ2. 2640 2641=item I<_sqrt(OBJ)> 2642 2643Return the square root of the object, truncated to integer. 2644 2645=item I<_root(OBJ, N)> 2646 2647Return Nth root of the object, truncated to int. N is E<gt>= 3. 2648 2649=item I<_fac(OBJ)> 2650 2651Return factorial of object (1*2*3*4*...). 2652 2653=item I<_pow(OBJ1, OBJ2)> 2654 2655Return OBJ1 to the power of OBJ2. By convention, 0**0 = 1. 2656 2657=item I<_modinv(OBJ1, OBJ2)> 2658 2659Return modular multiplicative inverse, i.e., return OBJ3 so that 2660 2661 (OBJ3 * OBJ1) % OBJ2 = 1 % OBJ2 2662 2663The result is returned as two arguments. If the modular multiplicative 2664inverse does not exist, both arguments are undefined. Otherwise, the 2665arguments are a number (object) and its sign ("+" or "-"). 2666 2667The output value, with its sign, must either be a positive value in the 2668range 1,2,...,OBJ2-1 or the same value subtracted OBJ2. For instance, if the 2669input arguments are objects representing the numbers 7 and 5, the method 2670must either return an object representing the number 3 and a "+" sign, since 2671(3*7) % 5 = 1 % 5, or an object representing the number 2 and "-" sign, 2672since (-2*7) % 5 = 1 % 5. 2673 2674=item I<_modpow(OBJ1, OBJ2, OBJ3)> 2675 2676Return modular exponentiation, (OBJ1 ** OBJ2) % OBJ3. 2677 2678=item I<_rsft(OBJ, N, B)> 2679 2680Shift object N digits right in base B and return the resulting object. This is 2681equivalent to performing integer division by B**N and discarding the remainder, 2682except that it might be much faster, depending on how the number is represented 2683internally. 2684 2685For instance, if the object $obj represents the hexadecimal number 0xabcde, 2686then C<_rsft($obj, 2, 16)> returns an object representing the number 0xabc. The 2687"remainer", 0xde, is discarded and not returned. 2688 2689=item I<_lsft(OBJ, N, B)> 2690 2691Shift the object N digits left in base B. This is equivalent to multiplying by 2692B**N, except that it might be much faster, depending on how the number is 2693represented internally. 2694 2695=item I<_log_int(OBJ, B)> 2696 2697Return integer log of OBJ to base BASE. This method has two output arguments, 2698the OBJECT and a STATUS. The STATUS is Perl scalar; it is 1 if OBJ is the exact 2699result, 0 if the result was truncted to give OBJ, and undef if it is unknown 2700whether OBJ is the exact result. 2701 2702=item I<_gcd(OBJ1, OBJ2)> 2703 2704Return the greatest common divisor of OBJ1 and OBJ2. 2705 2706=back 2707 2708=head3 Bitwise operators 2709 2710Each of these methods may modify the first input argument. 2711 2712=over 4 2713 2714=item I<_and(OBJ1, OBJ2)> 2715 2716Return bitwise and. If necessary, the smallest number is padded with leading 2717zeros. 2718 2719=item I<_or(OBJ1, OBJ2)> 2720 2721Return bitwise or. If necessary, the smallest number is padded with leading 2722zeros. 2723 2724=item I<_xor(OBJ1, OBJ2)> 2725 2726Return bitwise exclusive or. If necessary, the smallest number is padded 2727with leading zeros. 2728 2729=back 2730 2731=head3 Boolean operators 2732 2733=over 4 2734 2735=item I<_is_zero(OBJ)> 2736 2737Returns a true value if OBJ is zero, and false value otherwise. 2738 2739=item I<_is_one(OBJ)> 2740 2741Returns a true value if OBJ is one, and false value otherwise. 2742 2743=item I<_is_two(OBJ)> 2744 2745Returns a true value if OBJ is two, and false value otherwise. 2746 2747=item I<_is_ten(OBJ)> 2748 2749Returns a true value if OBJ is ten, and false value otherwise. 2750 2751=item I<_is_even(OBJ)> 2752 2753Return a true value if OBJ is an even integer, and a false value otherwise. 2754 2755=item I<_is_odd(OBJ)> 2756 2757Return a true value if OBJ is an even integer, and a false value otherwise. 2758 2759=item I<_acmp(OBJ1, OBJ2)> 2760 2761Compare OBJ1 and OBJ2 and return -1, 0, or 1, if OBJ1 is less than, equal 2762to, or larger than OBJ2, respectively. 2763 2764=back 2765 2766=head3 String conversion 2767 2768=over 4 2769 2770=item I<_str(OBJ)> 2771 2772Return a string representing the object. The returned string should have no 2773leading zeros, i.e., it should match C<^(0|[1-9]\d*)$>. 2774 2775=item I<_as_bin(OBJ)> 2776 2777Return the binary string representation of the number. The string must have a 2778'0b' prefix. 2779 2780=item I<_as_oct(OBJ)> 2781 2782Return the octal string representation of the number. The string must have 2783a '0x' prefix. 2784 2785Note: This method was required from Math::BigInt version 1.78, but the required 2786API version number was not incremented, so there are older libraries that 2787support API version 1, but do not support C<_as_oct()>. 2788 2789=item I<_as_hex(OBJ)> 2790 2791Return the hexadecimal string representation of the number. The string must 2792have a '0x' prefix. 2793 2794=back 2795 2796=head3 Numeric conversion 2797 2798=over 4 2799 2800=item I<_num(OBJ)> 2801 2802Given an object, return a Perl scalar number (int/float) representing this 2803number. 2804 2805=back 2806 2807=head3 Miscellaneous 2808 2809=over 4 2810 2811=item I<_copy(OBJ)> 2812 2813Return a true copy of the object. 2814 2815=item I<_len(OBJ)> 2816 2817Returns the number of the decimal digits in the number. The output is a 2818Perl scalar. 2819 2820=item I<_zeros(OBJ)> 2821 2822Return the number of trailing decimal zeros. The output is a Perl scalar. 2823 2824=item I<_digit(OBJ, N)> 2825 2826Return the Nth digit as a Perl scalar. N is a Perl scalar, where zero refers to 2827the rightmost (least significant) digit, and negative values count from the 2828left (most significant digit). If $obj represents the number 123, then 2829I<_digit($obj, 0)> is 3 and I<_digit(123, -1)> is 1. 2830 2831=item I<_check(OBJ)> 2832 2833Return a true value if the object is OK, and a false value otherwise. This is a 2834check routine to test the internal state of the object for corruption. 2835 2836=back 2837 2838=head2 API version 2 2839 2840The following methods are required for an API version of 2 or greater. 2841 2842=head3 Constructors 2843 2844=over 4 2845 2846=item I<_1ex(N)> 2847 2848Return an object representing the number 10**N where N E<gt>= 0 is a Perl 2849scalar. 2850 2851=back 2852 2853=head3 Mathematical functions 2854 2855=over 4 2856 2857=item I<_nok(OBJ1, OBJ2)> 2858 2859Return the binomial coefficient OBJ1 over OBJ1. 2860 2861=back 2862 2863=head3 Miscellaneous 2864 2865=over 4 2866 2867=item I<_alen(OBJ)> 2868 2869Return the approximate number of decimal digits of the object. The 2870output is one Perl scalar. This estimate must be greater than or equal 2871to what C<_len()> returns. 2872 2873=back 2874 2875=head2 API optional methods 2876 2877The following methods are optional, and can be defined if the underlying lib 2878has a fast way to do them. If undefined, Math::BigInt will use pure Perl (hence 2879slow) fallback routines to emulate these: 2880 2881=head3 Signed bitwise operators. 2882 2883Each of these methods may modify the first input argument. 2884 2885=over 4 2886 2887=item I<_signed_or(OBJ1, OBJ2, SIGN1, SIGN2)> 2888 2889Return the signed bitwise or. 2890 2891=item I<_signed_and(OBJ1, OBJ2, SIGN1, SIGN2)> 2892 2893Return the signed bitwise and. 2894 2895=item I<_signed_xor(OBJ1, OBJ2, SIGN1, SIGN2)> 2896 2897Return the signed bitwise exclusive or. 2898 2899=back 2900 2901=head1 WRAP YOUR OWN 2902 2903If you want to port your own favourite c-lib for big numbers to the 2904Math::BigInt interface, you can take any of the already existing modules as 2905a rough guideline. You should really wrap up the latest BigInt and BigFloat 2906testsuites with your module, and replace in them any of the following: 2907 2908 use Math::BigInt; 2909 2910by this: 2911 2912 use Math::BigInt lib => 'yourlib'; 2913 2914This way you ensure that your library really works 100% within Math::BigInt. 2915 2916=head1 BUGS 2917 2918Please report any bugs or feature requests to 2919C<bug-math-bigint at rt.cpan.org>, or through the web interface at 2920L<https://rt.cpan.org/Ticket/Create.html?Queue=Math-BigInt> 2921(requires login). 2922We will be notified, and then you'll automatically be notified of progress on 2923your bug as I make changes. 2924 2925=head1 SUPPORT 2926 2927You can find documentation for this module with the perldoc command. 2928 2929 perldoc Math::BigInt::Calc 2930 2931You can also look for information at: 2932 2933=over 4 2934 2935=item * RT: CPAN's request tracker 2936 2937L<https://rt.cpan.org/Public/Dist/Display.html?Name=Math-BigInt> 2938 2939=item * AnnoCPAN: Annotated CPAN documentation 2940 2941L<http://annocpan.org/dist/Math-BigInt> 2942 2943=item * CPAN Ratings 2944 2945L<http://cpanratings.perl.org/dist/Math-BigInt> 2946 2947=item * Search CPAN 2948 2949L<http://search.cpan.org/dist/Math-BigInt/> 2950 2951=item * CPAN Testers Matrix 2952 2953L<http://matrix.cpantesters.org/?dist=Math-BigInt> 2954 2955=item * The Bignum mailing list 2956 2957=over 4 2958 2959=item * Post to mailing list 2960 2961C<bignum at lists.scsys.co.uk> 2962 2963=item * View mailing list 2964 2965L<http://lists.scsys.co.uk/pipermail/bignum/> 2966 2967=item * Subscribe/Unsubscribe 2968 2969L<http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/bignum> 2970 2971=back 2972 2973=back 2974 2975=head1 LICENSE 2976 2977This program is free software; you may redistribute it and/or modify it under 2978the same terms as Perl itself. 2979 2980=head1 AUTHORS 2981 2982=over 4 2983 2984=item * 2985 2986Original math code by Mark Biggar, rewritten by Tels L<http://bloodgate.com/> 2987in late 2000. 2988 2989=item * 2990 2991Separated from BigInt and shaped API with the help of John Peacock. 2992 2993=item * 2994 2995Fixed, speed-up, streamlined and enhanced by Tels 2001 - 2007. 2996 2997=item * 2998 2999API documentation corrected and extended by Peter John Acklam, 3000E<lt>pjacklam@online.noE<gt> 3001 3002=back 3003 3004=head1 SEE ALSO 3005 3006L<Math::BigInt>, L<Math::BigFloat>, 3007L<Math::BigInt::GMP>, L<Math::BigInt::FastCalc> and L<Math::BigInt::Pari>. 3008 3009=cut 3010