1 package Math::BigInt::Calc;
5 # use warnings; # dont use warnings for older Perls
9 # Package to store unsigned big integers in decimal and do math with them
11 # Internally the numbers are stored in an array with at least 1 element, no
12 # leading zero parts (except the first) and in base 1eX where X is determined
13 # automatically at loading time to be the maximum possible value
16 # - fully remove funky $# stuff in div() (maybe - that code scares me...)
18 # USE_MUL: due to problems on certain os (os390, posix-bc) "* 1e-5" is used
19 # instead of "/ 1e5" at some places, (marked with USE_MUL). Other platforms
20 # BS2000, some Crays need USE_DIV instead.
21 # The BEGIN block is used to determine which of the two variants gives the
24 # Beware of things like:
25 # $i = $i * $y + $car; $car = int($i / $BASE); $i = $i % $BASE;
26 # This works on x86, but fails on ARM (SA1100, iPAQ) due to whoknows what
27 # reasons. So, use this instead (slower, but correct):
28 # $i = $i * $y + $car; $car = int($i / $BASE); $i -= $BASE * $car;
30 ##############################################################################
31 # global constants, flags and accessory
33 # announce that we are compatible with MBI v1.83 and up
34 sub api_version () { 2; }
36 # constants for easier life
37 my ($BASE,$BASE_LEN,$RBASE,$MAX_VAL);
38 my ($AND_BITS,$XOR_BITS,$OR_BITS);
39 my ($AND_MASK,$XOR_MASK,$OR_MASK);
43 # Set/get the BASE_LEN and assorted other, connected values.
44 # Used only by the testsuite, the set variant is used only by the BEGIN
55 if ($] > 5.008 && $int && $b > 7)
58 *_mul = \&_mul_use_div_64;
59 *_div = \&_div_use_div_64;
60 $BASE = int("1e".$BASE_LEN);
62 return $BASE_LEN unless wantarray;
63 return ($BASE_LEN, $AND_BITS, $XOR_BITS, $OR_BITS, $BASE_LEN, $MAX_VAL, $BASE);
66 # find whether we can use mul or div in mul()/div()
69 while (--$BASE_LEN > 5)
71 $BASE = int("1e".$BASE_LEN);
72 $RBASE = abs('1e-'.$BASE_LEN); # see USE_MUL
74 $caught += 1 if (int($BASE * $RBASE) != 1); # should be 1
75 $caught += 2 if (int($BASE / $BASE) != 1); # should be 1
78 $BASE = int("1e".$BASE_LEN);
79 $RBASE = abs('1e-'.$BASE_LEN); # see USE_MUL
82 # ($caught & 1) != 0 => cannot use MUL
83 # ($caught & 2) != 0 => cannot use DIV
86 # must USE_MUL since we cannot use DIV
87 *_mul = \&_mul_use_mul;
88 *_div = \&_div_use_mul;
93 *_mul = \&_mul_use_div;
94 *_div = \&_div_use_div;
97 return $BASE_LEN unless wantarray;
98 return ($BASE_LEN, $AND_BITS, $XOR_BITS, $OR_BITS, $BASE_LEN, $MAX_VAL, $BASE);
103 # (ref to string) return ref to num_array
104 # Convert a number from string format (without sign) to internal base
105 # 1ex format. Assumes normalized value as input.
106 my $il = length($_[1])-1;
108 # < BASE_LEN due len-1 above
109 return [ int($_[1]) ] if $il < $BASE_LEN; # shortcut for short numbers
111 # this leaves '00000' instead of int 0 and will be corrected after any op
112 [ reverse(unpack("a" . ($il % $BASE_LEN+1)
113 . ("a$BASE_LEN" x ($il / $BASE_LEN)), $_[1])) ];
118 # from Daniel Pfeiffer: determine largest group of digits that is precisely
119 # multipliable with itself plus carry
120 # Test now changed to expect the proper pattern, not a result off by 1 or 2
121 my ($e, $num) = 3; # lowest value we will use is 3+1-1 = 3
124 $num = ('9' x ++$e) + 0;
126 } while ("$num" =~ /9{$e}0{$e}/); # must be a certain pattern
127 $e--; # last test failed, so retract one step
128 # the limits below brush the problems with the test above under the rug:
129 # the test should be able to find the proper $e automatically
130 $e = 5 if $^O =~ /^uts/; # UTS get's some special treatment
131 $e = 5 if $^O =~ /^unicos/; # unicos is also problematic (6 seems to work
132 # there, but we play safe)
134 # $e = 5 if $] < 5.006; # cap, for older Perls
135 # $e = 7 if $e > 7; # cap, for VMS, OS/390 and other 64 bit systems
136 # # 8 fails inside random testsuite, so take 7
145 $num = ('9' x ++$e1) + 0;
147 } while ("$num" =~ /9{$e1}0{$e1}/); # must be a certain pattern
148 $e1--; # last test failed, so retract one step
155 __PACKAGE__->_base_len($e,$int); # set and store
158 # find out how many bits _and, _or and _xor can take (old default = 16)
159 # I don't think anybody has yet 128 bit scalars, so let's play safe.
160 local $^W = 0; # don't warn about 'nonportable number'
161 $AND_BITS = 15; $XOR_BITS = 15; $OR_BITS = 15;
163 # find max bits, we will not go higher than numberofbits that fit into $BASE
164 # to make _and etc simpler (and faster for smaller, slower for large numbers)
166 while (2 ** $max < $BASE) { $max++; }
169 $max = 16 if $] < 5.006; # older Perls might not take >16 too well
174 $x = oct('0b' . '1' x $AND_BITS); $y = $x & $x;
175 $z = (2 ** $AND_BITS) - 1;
176 } while ($AND_BITS < $max && $x == $z && $y == $x);
177 $AND_BITS --; # retreat one step
180 $x = oct('0b' . '1' x $XOR_BITS); $y = $x ^ 0;
181 $z = (2 ** $XOR_BITS) - 1;
182 } while ($XOR_BITS < $max && $x == $z && $y == $x);
183 $XOR_BITS --; # retreat one step
186 $x = oct('0b' . '1' x $OR_BITS); $y = $x | $x;
187 $z = (2 ** $OR_BITS) - 1;
188 } while ($OR_BITS < $max && $x == $z && $y == $x);
189 $OR_BITS --; # retreat one step
191 $AND_MASK = __PACKAGE__->_new( ( 2 ** $AND_BITS ));
192 $XOR_MASK = __PACKAGE__->_new( ( 2 ** $XOR_BITS ));
193 $OR_MASK = __PACKAGE__->_new( ( 2 ** $OR_BITS ));
195 # We can compute the approximate lenght no faster than the real length:
199 ###############################################################################
215 # create a two (used internally for shifting)
221 # create a 10 (used internally for shifting)
228 my $rem = $_[1] % $BASE_LEN; # remainder
229 my $parts = $_[1] / $BASE_LEN; # parts
231 # 000000, 000000, 100
232 [ (0) x $parts, '1' . ('0' x $rem) ];
241 # catch and throw away
244 ##############################################################################
245 # convert back to string and number
249 # (ref to BINT) return num_str
250 # Convert number from internal base 100000 format to string format.
251 # internal format is always normalized (no leading zeros, "-0" => "+0")
254 my $l = scalar @$ar; # number of parts
255 if ($l < 1) # should not happen
258 Carp::croak("$_[1] has no elements");
262 # handle first one different to strip leading zeros from it (there are no
263 # leading zero parts in internal representation)
264 $l --; $ret .= int($ar->[$l]); $l--;
265 # Interestingly, the pre-padd method uses more time
266 # the old grep variant takes longer (14 vs. 10 sec)
267 my $z = '0' x ($BASE_LEN-1);
270 $ret .= substr($z.$ar->[$l],-$BASE_LEN); # fastest way I could think of
278 # Make a number (scalar int/float) from a BigInt object
281 return 0+$x->[0] if scalar @$x == 1; # below $BASE
286 $num += $fac*$_; $fac *= $BASE;
291 ##############################################################################
296 # (ref to int_num_array, ref to int_num_array)
297 # routine to add two base 1eX numbers
298 # stolen from Knuth Vol 2 Algorithm A pg 231
299 # there are separate routines to add and sub as per Knuth pg 233
300 # This routine clobbers up array x, but not y.
304 return $x if (@$y == 1) && $y->[0] == 0; # $x + 0 => $x
305 if ((@$x == 1) && $x->[0] == 0) # 0 + $y => $y->copy
307 # twice as slow as $x = [ @$y ], but nec. to retain $x as ref :(
308 @$x = @$y; return $x;
311 # for each in Y, add Y to X and carry. If after that, something is left in
312 # X, foreach in X add carry to X and then return X, carry
313 # Trades one "$j++" for having to shift arrays
314 my $i; my $car = 0; my $j = 0;
317 $x->[$j] -= $BASE if $car = (($x->[$j] += $i + $car) >= $BASE) ? 1 : 0;
322 $x->[$j] -= $BASE if $car = (($x->[$j] += $car) >= $BASE) ? 1 : 0; $j++;
329 # (ref to int_num_array, ref to int_num_array)
330 # Add 1 to $x, modify $x in place
335 return $x if (($i += 1) < $BASE); # early out
336 $i = 0; # overflow, next
338 push @$x,1 if (($x->[-1] || 0) == 0); # last overflowed, so extend
344 # (ref to int_num_array, ref to int_num_array)
345 # Sub 1 from $x, modify $x in place
348 my $MAX = $BASE-1; # since MAX_VAL based on BASE
351 last if (($i -= 1) >= 0); # early out
352 $i = $MAX; # underflow, next
354 pop @$x if $x->[-1] == 0 && @$x > 1; # last underflowed (but leave 0)
360 # (ref to int_num_array, ref to int_num_array, swap)
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) = @_;
365 my $car = 0; my $i; my $j = 0;
370 last unless defined $sy->[$j] || $car;
371 $i += $BASE if $car = (($i -= ($sy->[$j] || 0) + $car) < 0); $j++;
373 # might leave leading zeros, so fix that
374 return __strip_zeros($sx);
378 # we can't do an early out if $x is < than $y, since we
379 # need to copy the high chunks from $y. Found by Bob Mathews.
380 #last unless defined $sy->[$j] || $car;
382 if $car = (($sy->[$j] = $i-($sy->[$j]||0) - $car) < 0);
385 # might leave leading zeros, so fix that
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) = @_;
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
402 if (($xv->[0] *= $yv->[0]) >= $BASE)
404 $xv->[0] = $xv->[0] - ($xv->[1] = int($xv->[0] * $RBASE)) * $BASE;
414 # multiply a large number a by a single element one, so speed up
415 my $y = $yv->[0]; my $car = 0;
418 $i = $i * $y + $car; $car = int($i * $RBASE); $i -= $car * $BASE;
420 push @$xv, $car if $car != 0;
423 # shortcut for result $x == 0 => result = 0
424 return $xv if ( ((@$xv == 1) && ($xv->[0] == 0)) );
426 # since multiplying $x with $x fails, make copy in this case
427 $yv = [@$xv] if $xv == $yv; # same references?
429 my @prod = (); my ($prod,$car,$cty,$xi,$yi);
438 # $prod = $xi * $yi + ($prod[$cty] || 0) + $car;
440 # $prod - ($car = int($prod * RBASE)) * $BASE; # see USE_MUL
442 # $prod[$cty] += $car if $car; # need really to check for 0?
446 # looping through this if $xi == 0 is silly - so optimize it away!
447 $xi = (shift @prod || 0), next if $xi == 0;
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
454 $prod - ($car = int($prod * $RBASE)) * $BASE; # see USE_MUL
456 $prod[$cty] += $car if $car; # need really to check for 0?
457 $xi = shift @prod || 0; # || 0 makes v5.005_3 happy
460 # can't have leading zeros
461 # __strip_zeros($xv);
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) = @_;
476 # shortcut for two small numbers, also handles $x == 0
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)
484 $xv->[0] - ($xv->[1] = $xv->[0] / $BASE) * $BASE;
494 # multiply a large number a by a single element one, so speed up
495 my $y = $yv->[0]; my $car = 0;
498 #$i = $i * $y + $car; $car = $i / $BASE; $i -= $car * $BASE;
499 $i = $i * $y + $car; $i -= ($car = $i / $BASE) * $BASE;
501 push @$xv, $car if $car != 0;
504 # shortcut for result $x == 0 => result = 0
505 return $xv if ( ((@$xv == 1) && ($xv->[0] == 0)) );
507 # since multiplying $x with $x fails, make copy in this case
508 $yv = [@$xv] if $xv == $yv; # same references?
510 my @prod = (); my ($prod,$car,$cty,$xi,$yi);
514 # looping through this if $xi == 0 is silly - so optimize it away!
515 $xi = (shift @prod || 0), next if $xi == 0;
518 $prod = $xi * $yi + ($prod[$cty] || 0) + $car;
519 $prod[$cty++] = $prod - ($car = $prod / $BASE) * $BASE;
521 $prod[$cty] += $car if $car; # need really to check for 0?
522 $xi = shift @prod || 0; # || 0 makes v5.005_3 happy
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) = @_;
537 # shortcut for two small numbers, also handles $x == 0
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)
545 $xv->[0] - ($xv->[1] = int($xv->[0] / $BASE)) * $BASE;
555 # multiply a large number a by a single element one, so speed up
556 my $y = $yv->[0]; my $car = 0;
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;
563 push @$xv, $car if $car != 0;
566 # shortcut for result $x == 0 => result = 0
567 return $xv if ( ((@$xv == 1) && ($xv->[0] == 0)) );
569 # since multiplying $x with $x fails, make copy in this case
570 $yv = [@$xv] if $xv == $yv; # same references?
572 my @prod = (); my ($prod,$car,$cty,$xi,$yi);
576 # looping through this if $xi == 0 is silly - so optimize it away!
577 $xi = (shift @prod || 0), next if $xi == 0;
580 $prod = $xi * $yi + ($prod[$cty] || 0) + $car;
581 $prod[$cty++] = $prod - ($car = int($prod / $BASE)) * $BASE;
583 $prod[$cty] += $car if $car; # need really to check for 0?
584 $xi = shift @prod || 0; # || 0 makes v5.005_3 happy
587 # can't have leading zeros
588 # __strip_zeros($xv);
594 # ref to array, ref to array, modify first array and return remainder if
597 # see comments in _div_use_div() for more explanations
599 my ($c,$x,$yorg) = @_;
601 # the general div algorithmn 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.
604 # This works, because we store the numbers in a chunked format where each
605 # element contains 5..7 digits (depending on system).
607 # if both numbers have only one element:
608 if (@$x == 1 && @$yorg == 1)
610 # shortcut, $yorg and $x are two small numbers
613 my $r = [ $x->[0] % $yorg->[0] ];
614 $x->[0] = int($x->[0] / $yorg->[0]);
619 $x->[0] = int($x->[0] / $yorg->[0]);
624 # if x has more than one, but y has only one element:
628 $rem = _mod($c,[ @$x ],$yorg) if wantarray;
630 # shortcut, $y is < $BASE
631 my $j = scalar @$x; my $r = 0;
632 my $y = $yorg->[0]; my $b;
635 $b = $r * $BASE + $x->[$j];
636 $x->[$j] = int($b/$y);
639 pop @$x if @$x > 1 && $x->[-1] == 0; # splice up a leading zero
640 return ($x,$rem) if wantarray;
644 # now x and y have more than one element
646 # check whether y has more elements than x, if yet, the result will be 0
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
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
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])))
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?
671 # now calculate $x / $yorg
672 if (length(int($yorg->[-1])) == length(int($x->[-1])))
674 # same length, so make full compare
676 my $a = 0; my $j = scalar @$x - 1;
677 # manual way (abort if unequal, good for early ne)
680 last if ($a = $x->[$j] - $yorg->[$j]); $j--;
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
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;
694 # $x >= $y, so proceed normally
700 my $y = [ @$yorg ]; # always make copy to preserve
702 my ($car,$bar,$prd,$dd,$xi,$yi,@q,$v2,$v1,@d,$tmp,$q,$u2,$u1,$u0);
704 $car = $bar = $prd = 0;
705 if (($dd = int($BASE/($y->[-1]+1))) != 1)
709 $xi = $xi * $dd + $car;
710 $xi -= ($car = int($xi * $RBASE)) * $BASE; # see USE_MUL
712 push(@$x, $car); $car = 0;
715 $yi = $yi * $dd + $car;
716 $yi -= ($car = int($yi * $RBASE)) * $BASE; # see USE_MUL
723 @q = (); ($v2,$v1) = @$y[-2,-1];
727 ($u2,$u1,$u0) = @$x[-3..-1];
729 #warn "oups v1 is 0, u0: $u0 $y->[-2] $y->[-1] l ",scalar @$y,"\n"
731 $q = (($u0 == $v1) ? $MAX_VAL : int(($u0*$BASE+$u1)/$v1));
732 --$q while ($v2*$q > ($u0*$BASE+$u1-$q*$v1)*$BASE+$u2);
735 ($car, $bar) = (0,0);
736 for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)
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));
742 if ($x->[-1] < $car + $bar)
745 for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)
748 if ($car = (($x->[$xi] += $y->[$yi] + $car) >= $BASE));
761 for $xi (reverse @$x)
763 $prd = $car * $BASE + $xi;
764 $car = $prd - ($tmp = int($prd / $dd)) * $dd; # see USE_MUL
785 # ref to array, ref to array, modify first array and return remainder if
787 # This version works on 64 bit integers
788 my ($c,$x,$yorg) = @_;
791 # the general div algorithmn 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.
794 # This works, because we store the numbers in a chunked format where each
795 # element contains 5..7 digits (depending on system).
797 # if both numbers have only one element:
798 if (@$x == 1 && @$yorg == 1)
800 # shortcut, $yorg and $x are two small numbers
803 my $r = [ $x->[0] % $yorg->[0] ];
804 $x->[0] = int($x->[0] / $yorg->[0]);
809 $x->[0] = int($x->[0] / $yorg->[0]);
813 # if x has more than one, but y has only one element:
817 $rem = _mod($c,[ @$x ],$yorg) if wantarray;
819 # shortcut, $y is < $BASE
820 my $j = scalar @$x; my $r = 0;
821 my $y = $yorg->[0]; my $b;
824 $b = $r * $BASE + $x->[$j];
825 $x->[$j] = int($b/$y);
828 pop @$x if @$x > 1 && $x->[-1] == 0; # splice up a leading zero
829 return ($x,$rem) if wantarray;
832 # now x and y have more than one element
834 # check whether y has more elements than x, if yet, the result will be 0
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
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
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])))
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?
859 # now calculate $x / $yorg
861 if (length(int($yorg->[-1])) == length(int($x->[-1])))
863 # same length, so make full compare
865 my $a = 0; my $j = scalar @$x - 1;
866 # manual way (abort if unequal, good for early ne)
869 last if ($a = $x->[$j] - $yorg->[$j]); $j--;
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
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?
883 # $x >= $y, so proceed normally
890 my $y = [ @$yorg ]; # always make copy to preserve
892 my ($car,$bar,$prd,$dd,$xi,$yi,@q,$v2,$v1,@d,$tmp,$q,$u2,$u1,$u0);
894 $car = $bar = $prd = 0;
895 if (($dd = int($BASE/($y->[-1]+1))) != 1)
899 $xi = $xi * $dd + $car;
900 $xi -= ($car = int($xi / $BASE)) * $BASE;
902 push(@$x, $car); $car = 0;
905 $yi = $yi * $dd + $car;
906 $yi -= ($car = int($yi / $BASE)) * $BASE;
914 # @q will accumulate the final result, $q contains the current computed
915 # part of the final result
917 @q = (); ($v2,$v1) = @$y[-2,-1];
921 ($u2,$u1,$u0) = @$x[-3..-1];
923 #warn "oups v1 is 0, u0: $u0 $y->[-2] $y->[-1] l ",scalar @$y,"\n"
925 $q = (($u0 == $v1) ? $MAX_VAL : int(($u0*$BASE+$u1)/$v1));
926 --$q while ($v2*$q > ($u0*$BASE+$u1-$q*$v1)*$BASE+$u2);
929 ($car, $bar) = (0,0);
930 for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)
932 $prd = $q * $y->[$yi] + $car;
933 $prd -= ($car = int($prd / $BASE)) * $BASE;
934 $x->[$xi] += $BASE if ($bar = (($x->[$xi] -= $prd + $bar) < 0));
936 if ($x->[-1] < $car + $bar)
939 for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)
942 if ($car = (($x->[$xi] += $y->[$yi] + $car) >= $BASE));
946 pop(@$x); unshift(@q, $q);
954 for $xi (reverse @$x)
956 $prd = $car * $BASE + $xi;
957 $car = $prd - ($tmp = int($prd / $dd)) * $dd;
978 # ref to array, ref to array, modify first array and return remainder if
980 my ($c,$x,$yorg) = @_;
982 # the general div algorithmn 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.
985 # This works, because we store the numbers in a chunked format where each
986 # element contains 5..7 digits (depending on system).
988 # if both numbers have only one element:
989 if (@$x == 1 && @$yorg == 1)
991 # shortcut, $yorg and $x are two small numbers
994 my $r = [ $x->[0] % $yorg->[0] ];
995 $x->[0] = int($x->[0] / $yorg->[0]);
1000 $x->[0] = int($x->[0] / $yorg->[0]);
1004 # if x has more than one, but y has only one element:
1008 $rem = _mod($c,[ @$x ],$yorg) if wantarray;
1010 # shortcut, $y is < $BASE
1011 my $j = scalar @$x; my $r = 0;
1012 my $y = $yorg->[0]; my $b;
1015 $b = $r * $BASE + $x->[$j];
1016 $x->[$j] = int($b/$y);
1019 pop @$x if @$x > 1 && $x->[-1] == 0; # splice up a leading zero
1020 return ($x,$rem) if wantarray;
1023 # now x and y have more than one element
1025 # check whether y has more elements than x, if yet, the result will be 0
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
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
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])))
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?
1050 # now calculate $x / $yorg
1052 if (length(int($yorg->[-1])) == length(int($x->[-1])))
1054 # same length, so make full compare
1056 my $a = 0; my $j = scalar @$x - 1;
1057 # manual way (abort if unequal, good for early ne)
1060 last if ($a = $x->[$j] - $yorg->[$j]); $j--;
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
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?
1074 # $x >= $y, so proceed normally
1081 my $y = [ @$yorg ]; # always make copy to preserve
1083 my ($car,$bar,$prd,$dd,$xi,$yi,@q,$v2,$v1,@d,$tmp,$q,$u2,$u1,$u0);
1085 $car = $bar = $prd = 0;
1086 if (($dd = int($BASE/($y->[-1]+1))) != 1)
1090 $xi = $xi * $dd + $car;
1091 $xi -= ($car = int($xi / $BASE)) * $BASE;
1093 push(@$x, $car); $car = 0;
1096 $yi = $yi * $dd + $car;
1097 $yi -= ($car = int($yi / $BASE)) * $BASE;
1105 # @q will accumulate the final result, $q contains the current computed
1106 # part of the final result
1108 @q = (); ($v2,$v1) = @$y[-2,-1];
1112 ($u2,$u1,$u0) = @$x[-3..-1];
1114 #warn "oups v1 is 0, u0: $u0 $y->[-2] $y->[-1] l ",scalar @$y,"\n"
1116 $q = (($u0 == $v1) ? $MAX_VAL : int(($u0*$BASE+$u1)/$v1));
1117 --$q while ($v2*$q > ($u0*$BASE+$u1-$q*$v1)*$BASE+$u2);
1120 ($car, $bar) = (0,0);
1121 for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)
1123 $prd = $q * $y->[$yi] + $car;
1124 $prd -= ($car = int($prd / $BASE)) * $BASE;
1125 $x->[$xi] += $BASE if ($bar = (($x->[$xi] -= $prd + $bar) < 0));
1127 if ($x->[-1] < $car + $bar)
1130 for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)
1133 if ($car = (($x->[$xi] += $y->[$yi] + $car) >= $BASE));
1137 pop(@$x); unshift(@q, $q);
1145 for $xi (reverse @$x)
1147 $prd = $car * $BASE + $xi;
1148 $car = $prd - ($tmp = int($prd / $dd)) * $dd;
1167 ##############################################################################
1172 # internal absolute post-normalized compare (ignore signs)
1173 # ref to array, ref to array, return <0, 0, >0
1174 # arrays must have at least one entry; this is not checked for
1175 my ($c,$cx,$cy) = @_;
1177 # shortcut for short numbers
1178 return (($cx->[0] <=> $cy->[0]) <=> 0)
1179 if scalar @$cx == scalar @$cy && scalar @$cx == 1;
1181 # fast comp based on number of array elements (aka pseudo-length)
1182 my $lxy = (scalar @$cx - scalar @$cy)
1183 # or length of first element if same number of elements (aka difference 0)
1185 # need int() here because sometimes the last element is '00018' vs '18'
1186 (length(int($cx->[-1])) - length(int($cy->[-1])));
1187 return -1 if $lxy < 0; # already differs, ret
1188 return 1 if $lxy > 0; # ditto
1190 # manual way (abort if unequal, good for early ne)
1191 my $a; my $j = scalar @$cx;
1194 last if ($a = $cx->[$j] - $cy->[$j]);
1201 # compute number of digits in base 10
1203 # int() because add/sub sometimes leaves strings (like '00005') instead of
1204 # '5' in this place, thus causing length() to report wrong length
1207 (@$cx-1)*$BASE_LEN+length(int($cx->[-1]));
1212 # return the nth digit, negative values count backward
1213 # zero is rightmost, so _digit(123,0) will give 3
1216 my $len = _len('',$x);
1218 $n = $len+$n if $n < 0; # -1 last, -2 second-to-last
1219 $n = abs($n); # if negative was too big
1220 $len--; $n = $len if $n > $len; # n to big?
1222 my $elem = int($n / $BASE_LEN); # which array element
1223 my $digit = $n % $BASE_LEN; # which digit in this element
1224 $elem = '0' x $BASE_LEN . @$x[$elem]; # get element padded with 0's
1225 substr($elem,-$digit-1,1);
1230 # return amount of trailing zeros in decimal
1231 # check each array elem in _m for having 0 at end as long as elem == 0
1232 # Upon finding a elem != 0, stop
1235 return 0 if scalar @$x == 1 && $x->[0] == 0;
1237 my $zeros = 0; my $elem;
1242 $elem = "$e"; # preserve x
1243 $elem =~ s/.*?(0*$)/$1/; # strip anything not zero
1244 $zeros *= $BASE_LEN; # elems * 5
1245 $zeros += length($elem); # count trailing zeros
1248 $zeros ++; # real else branch: 50% slower!
1253 ##############################################################################
1258 # return true if arg is zero
1259 (((scalar @{$_[1]} == 1) && ($_[1]->[0] == 0))) <=> 0;
1264 # return true if arg is even
1265 (!($_[1]->[0] & 1)) <=> 0;
1270 # return true if arg is even
1271 (($_[1]->[0] & 1)) <=> 0;
1276 # return true if arg is one
1277 (scalar @{$_[1]} == 1) && ($_[1]->[0] == 1) <=> 0;
1282 # return true if arg is two
1283 (scalar @{$_[1]} == 1) && ($_[1]->[0] == 2) <=> 0;
1288 # return true if arg is ten
1289 (scalar @{$_[1]} == 1) && ($_[1]->[0] == 10) <=> 0;
1294 # internal normalization function that strips leading zeros from the array
1295 # args: ref to array
1298 my $cnt = scalar @$s; # get count of parts
1300 push @$s,0 if $i < 0; # div might return empty results, so fix it
1302 return $s if @$s == 1; # early out
1304 #print "strip: cnt $cnt i $i\n";
1305 # '0', '3', '4', '0', '0',
1310 # => fcnt = cnt - i (5-2 => 3, cnt => 5-1 = 4, throw away from 4th pos)
1311 # >= 1: skip first part (this can be zero)
1312 while ($i > 0) { last if $s->[$i] != 0; $i--; }
1313 $i++; splice @$s,$i if ($i < $cnt); # $i cant be 0
1317 ###############################################################################
1318 # check routine to test internal state for corruptions
1322 # used by the test suite
1325 return "$x is not a reference" if !ref($x);
1327 # are all parts are valid?
1328 my $i = 0; my $j = scalar @$x; my ($e,$try);
1331 $e = $x->[$i]; $e = 'undef' unless defined $e;
1332 $try = '=~ /^[\+]?[0-9]+\$/; '."($x, $e)";
1333 last if $e !~ /^[+]?[0-9]+$/;
1334 $try = '=~ /^[\+]?[0-9]+\$/; '."($x, $e) (stringify)";
1335 last if "$e" !~ /^[+]?[0-9]+$/;
1336 $try = '=~ /^[\+]?[0-9]+\$/; '."($x, $e) (cat-stringify)";
1337 last if '' . "$e" !~ /^[+]?[0-9]+$/;
1338 $try = ' < 0 || >= $BASE; '."($x, $e)";
1339 last if $e <0 || $e >= $BASE;
1340 # this test is disabled, since new/bnorm and certain ops (like early out
1341 # in add/sub) are allowed/expected to leave '00000' in some elements
1342 #$try = '=~ /^00+/; '."($x, $e)";
1343 #last if $e =~ /^00+/;
1346 return "Illegal part '$e' at pos $i (tested: $try)" if $i < $j;
1351 ###############################################################################
1355 # if possible, use mod shortcut
1356 my ($c,$x,$yo) = @_;
1358 # slow way since $y to big
1359 if (scalar @$yo > 1)
1361 my ($xo,$rem) = _div($c,$x,$yo);
1366 # both are single element arrays
1367 if (scalar @$x == 1)
1373 # @y is a single element, but @x has more than one element
1377 # when BASE % Y == 0 then (B * BASE) % Y == 0
1378 # (B * BASE) % $y + A % Y => A % Y
1379 # so need to consider only last element: O(1)
1384 # else need to go through all elements: O(N), but loop is a bit simplified
1388 $r = ($r + $_) % $y; # not much faster, but heh...
1389 #$r += $_ % $y; $r %= $y;
1396 # else need to go through all elements: O(N)
1397 my $r = 0; my $bm = 1;
1400 $r = ($_ * $bm + $r) % $y;
1401 $bm = ($bm * $b) % $y;
1403 #$r += ($_ % $y) * $bm;
1411 splice (@$x,1); # keep one element of $x
1415 ##############################################################################
1420 my ($c,$x,$y,$n) = @_;
1424 $n = _new($c,$n); return _div($c,$x, _pow($c,$n,$y));
1427 # shortcut (faster) for shifting by 10)
1428 # multiples of $BASE_LEN
1429 my $dst = 0; # destination
1430 my $src = _num($c,$y); # as normal int
1431 my $xlen = (@$x-1)*$BASE_LEN+length(int($x->[-1])); # len of x in digits
1432 if ($src >= $xlen or ($src == $xlen and ! defined $x->[1]))
1434 # 12345 67890 shifted right by more than 10 digits => 0
1435 splice (@$x,1); # leave only one element
1436 $x->[0] = 0; # set to zero
1439 my $rem = $src % $BASE_LEN; # remainder to shift
1440 $src = int($src / $BASE_LEN); # source
1443 splice (@$x,0,$src); # even faster, 38.4 => 39.3
1447 my $len = scalar @$x - $src; # elems to go
1448 my $vd; my $z = '0'x $BASE_LEN;
1449 $x->[scalar @$x] = 0; # avoid || 0 test inside loop
1452 $vd = $z.$x->[$src];
1453 $vd = substr($vd,-$BASE_LEN,$BASE_LEN-$rem);
1455 $vd = substr($z.$x->[$src],-$rem,$rem) . $vd;
1456 $vd = substr($vd,-$BASE_LEN,$BASE_LEN) if length($vd) > $BASE_LEN;
1457 $x->[$dst] = int($vd);
1460 splice (@$x,$dst) if $dst > 0; # kill left-over array elems
1461 pop @$x if $x->[-1] == 0 && @$x > 1; # kill last element if 0
1468 my ($c,$x,$y,$n) = @_;
1472 $n = _new($c,$n); return _mul($c,$x, _pow($c,$n,$y));
1475 # shortcut (faster) for shifting by 10) since we are in base 10eX
1476 # multiples of $BASE_LEN:
1477 my $src = scalar @$x; # source
1478 my $len = _num($c,$y); # shift-len as normal int
1479 my $rem = $len % $BASE_LEN; # remainder to shift
1480 my $dst = $src + int($len/$BASE_LEN); # destination
1481 my $vd; # further speedup
1482 $x->[$src] = 0; # avoid first ||0 for speed
1483 my $z = '0' x $BASE_LEN;
1486 $vd = $x->[$src]; $vd = $z.$vd;
1487 $vd = substr($vd,-$BASE_LEN+$rem,$BASE_LEN-$rem);
1488 $vd .= $src > 0 ? substr($z.$x->[$src-1],-$BASE_LEN,$rem) : '0' x $rem;
1489 $vd = substr($vd,-$BASE_LEN,$BASE_LEN) if length($vd) > $BASE_LEN;
1490 $x->[$dst] = int($vd);
1493 # set lowest parts to 0
1494 while ($dst >= 0) { $x->[$dst--] = 0; }
1495 # fix spurios last zero element
1496 splice @$x,-1 if $x->[-1] == 0;
1503 # ref to array, ref to array, return ref to array
1504 my ($c,$cx,$cy) = @_;
1506 if (scalar @$cy == 1 && $cy->[0] == 0)
1508 splice (@$cx,1); $cx->[0] = 1; # y == 0 => x => 1
1511 if ((scalar @$cx == 1 && $cx->[0] == 1) || # x == 1
1512 (scalar @$cy == 1 && $cy->[0] == 1)) # or y == 1
1516 if (scalar @$cx == 1 && $cx->[0] == 0)
1518 splice (@$cx,1); $cx->[0] = 0; # 0 ** y => 0 (if not y <= 0)
1524 my $y_bin = _as_bin($c,$cy); $y_bin =~ s/^0b//;
1525 my $len = length($y_bin);
1528 _mul($c,$pow2,$cx) if substr($y_bin,$len,1) eq '1'; # is odd?
1539 # ref to array, return ref to array
1542 # ( 7 ) 7! 7*6*5 * 4*3*2*1 7 * 6 * 5
1543 # ( - ) = --------- = --------------- = ---------
1544 # ( 3 ) 3! (7-3)! 3*2*1 * 4*3*2*1 3 * 2 * 1
1546 # compute n - k + 2 (so we start with 5 in the example above)
1547 my $x = _copy($c,$n);
1550 if (!_is_one($c,$n))
1553 my $f = _copy($c,$n); _inc($c,$f); # n = 5, f = 6, d = 2
1555 while (_acmp($c,$f,$x) <= 0) # f < n ?
1557 # n = (n * f / d) == 5 * 6 / 2 => n == 3
1558 $n = _mul($c,$n,$f); $n = _div($c,$n,$d);
1560 _inc($c,$f); _inc($c,$d);
1565 # keep ref to $n and set it to 1
1566 splice (@$n,1); $n->[0] = 1;
1585 # ref to array, return ref to array
1588 if ((@$cx == 1) && ($cx->[0] <= 7))
1590 $cx->[0] = $factorials[$cx->[0]]; # 0 => 1, 1 => 1, 2 => 2 etc.
1594 if ((@$cx == 1) && # we do this only if $x >= 12 and $x <= 7000
1595 ($cx->[0] >= 12 && $cx->[0] < 7000))
1598 # Calculate (k-j) * (k-j+1) ... k .. (k+j-1) * (k + j)
1599 # See http://blogten.blogspot.com/2007/01/calculating-n.html
1600 # The above series can be expressed as factors:
1601 # k * k - (j - i) * 2
1602 # We cache k*k, and calculate (j * j) as the sum of the first j odd integers
1604 # This will not work when N exceeds the storage of a Perl scalar, however,
1605 # in this case the algorithm would be way to slow to terminate, anyway.
1607 # As soon as the last element of $cx is 0, we split it up and remember
1608 # how many zeors we got so far. The reason is that n! will accumulate
1609 # zeros at the end rather fast.
1610 my $zero_elements = 0;
1612 # If n is even, set n = n -1
1613 my $k = _num($c,$cx); my $even = 1;
1618 # set k to the center point
1620 # print "k $k even: $even\n";
1621 # now calculate k * k
1623 my $odd = 1; my $sum = 1;
1625 # keep reference to x
1626 my $new_x = _new($c, $k * $even);
1630 $zero_elements ++; shift @$cx;
1632 # print STDERR "x = ", _str($c,$cx),"\n";
1633 my $BASE2 = int(sqrt($BASE))-1;
1637 my $m = ($k2 - $sum); $odd += 2; $sum += $odd; $j++;
1638 while ($j <= $i && ($m < $BASE2) && (($k2 - $sum) < $BASE2))
1641 $odd += 2; $sum += $odd; $j++;
1642 # print STDERR "\n k2 $k2 m $m sum $sum odd $odd\n"; sleep(1);
1650 _mul($c,$cx,$c->_new($m));
1654 $zero_elements ++; shift @$cx;
1656 # print STDERR "Calculate $k2 - $sum = $m (x = ", _str($c,$cx),")\n";
1658 # multiply in the zeros again
1659 unshift @$cx, (0) x $zero_elements;
1663 # go forward until $base is exceeded
1664 # limit is either $x steps (steps == 100 means a result always too high) or
1666 my $steps = 100; $steps = $cx->[0] if @$cx == 1;
1667 my $r = 2; my $cf = 3; my $step = 2; my $last = $r;
1668 while ($r*$cf < $BASE && $step < $steps)
1670 $last = $r; $r *= $cf++; $step++;
1672 if ((@$cx == 1) && $step == $cx->[0])
1674 # completely done, so keep reference to $x and return
1679 # now we must do the left over steps
1680 my $n; # steps still to do
1681 if (scalar @$cx == 1)
1690 # Set $cx to the last result below $BASE (but keep ref to $x)
1691 $cx->[0] = $last; splice (@$cx,1);
1692 # As soon as the last element of $cx is 0, we split it up and remember
1693 # how many zeors we got so far. The reason is that n! will accumulate
1694 # zeros at the end rather fast.
1695 my $zero_elements = 0;
1697 # do left-over steps fit into a scalar?
1698 if (ref $n eq 'ARRAY')
1700 # No, so use slower inc() & cmp()
1701 # ($n is at least $BASE here)
1702 my $base_2 = int(sqrt($BASE)) - 1;
1703 #print STDERR "base_2: $base_2\n";
1704 while ($step < $base_2)
1708 $zero_elements ++; shift @$cx;
1710 my $b = $step * ($step + 1); $step += 2;
1714 while (_acmp($c,$step,$n) <= 0)
1718 $zero_elements ++; shift @$cx;
1720 _mul($c,$cx,$step); _inc($c,$step);
1725 # Yes, so we can speed it up slightly
1727 # print "# left over steps $n\n";
1729 my $base_4 = int(sqrt(sqrt($BASE))) - 2;
1730 #print STDERR "base_4: $base_4\n";
1732 while ($step < $n4 && $step < $base_4)
1736 $zero_elements ++; shift @$cx;
1738 my $b = $step * ($step + 1); $step += 2; $b *= $step * ($step + 1); $step += 2;
1741 my $base_2 = int(sqrt($BASE)) - 1;
1743 #print STDERR "base_2: $base_2\n";
1744 while ($step < $n2 && $step < $base_2)
1748 $zero_elements ++; shift @$cx;
1750 my $b = $step * ($step + 1); $step += 2;
1753 # do what's left over
1756 _mul($c,$cx,[$step]); $step++;
1759 $zero_elements ++; shift @$cx;
1763 # multiply in the zeros again
1764 unshift @$cx, (0) x $zero_elements;
1765 $cx; # return result
1768 #############################################################################
1772 # calculate integer log of $x to base $base
1773 # ref to array, ref to array - return ref to array
1774 my ($c,$x,$base) = @_;
1777 return if (scalar @$x == 1 && $x->[0] == 0);
1778 # BASE 0 or 1 => NaN
1779 return if (scalar @$base == 1 && $base->[0] < 2);
1780 my $cmp = _acmp($c,$x,$base); # X == BASE => 1
1783 splice (@$x,1); $x->[0] = 1;
1789 splice (@$x,1); $x->[0] = 0;
1793 my $x_org = _copy($c,$x); # preserve x
1794 splice(@$x,1); $x->[0] = 1; # keep ref to $x
1796 # Compute a guess for the result based on:
1797 # $guess = int ( length_in_base_10(X) / ( log(base) / log(10) ) )
1798 my $len = _len($c,$x_org);
1799 my $log = log($base->[-1]) / log(10);
1801 # for each additional element in $base, we add $BASE_LEN to the result,
1802 # based on the observation that log($BASE,10) is BASE_LEN and
1803 # log(x*y) == log(x) + log(y):
1804 $log += ((scalar @$base)-1) * $BASE_LEN;
1806 # calculate now a guess based on the values obtained above:
1807 my $res = int($len / $log);
1810 my $trial = _pow ($c, _copy($c, $base), $x);
1811 my $a = _acmp($c,$trial,$x_org);
1813 # print STDERR "# trial ", _str($c,$x)," was: $a (0 = exact, -1 too small, +1 too big)\n";
1815 # found an exact result?
1816 return ($x,1) if $a == 0;
1821 _div($c,$trial,$base); _dec($c, $x);
1822 while (($a = _acmp($c,$trial,$x_org)) > 0)
1824 # print STDERR "# big _log_int at ", _str($c,$x), "\n";
1825 _div($c,$trial,$base); _dec($c, $x);
1827 # result is now exact (a == 0), or too small (a < 0)
1828 return ($x, $a == 0 ? 1 : 0);
1831 # else: result was to small
1832 _mul($c,$trial,$base);
1834 # did we now get the right result?
1835 $a = _acmp($c,$trial,$x_org);
1837 if ($a == 0) # yes, exactly
1842 return ($x,0) if $a > 0;
1844 # Result still too small (we should come here only if the estimate above
1845 # was very off base):
1847 # Now let the normal trial run obtain the real result
1848 # Simple loop that increments $x by 2 in each step, possible overstepping
1851 my $base_mul = _mul($c, _copy($c,$base), $base); # $base * $base
1853 while (($a = _acmp($c,$trial,$x_org)) < 0)
1855 # print STDERR "# small _log_int at ", _str($c,$x), "\n";
1856 _mul($c,$trial,$base_mul); _add($c, $x, [2]);
1862 # overstepped the result
1864 _div($c,$trial,$base);
1865 $a = _acmp($c,$trial,$x_org);
1870 $exact = 0 if $a != 0; # a = -1 => not exact result, a = 0 => exact
1873 ($x,$exact); # return result
1877 use constant DEBUG => 0;
1879 sub steps { $steps };
1883 # square-root of $x in place
1884 # Compute a guess of the result (by rule of thumb), then improve it via
1888 if (scalar @$x == 1)
1890 # fits into one Perl scalar, so result can be computed directly
1891 $x->[0] = int(sqrt($x->[0]));
1894 my $y = _copy($c,$x);
1895 # hopefully _len/2 is < $BASE, the -1 is to always undershot the guess
1896 # since our guess will "grow"
1897 my $l = int((_len($c,$x)-1) / 2);
1899 my $lastelem = $x->[-1]; # for guess
1900 my $elems = scalar @$x - 1;
1901 # not enough digits, but could have more?
1902 if ((length($lastelem) <= 3) && ($elems > 1))
1904 # right-align with zero pad
1905 my $len = length($lastelem) & 1;
1906 print "$lastelem => " if DEBUG;
1907 $lastelem .= substr($x->[-2] . '0' x $BASE_LEN,0,$BASE_LEN);
1908 # former odd => make odd again, or former even to even again
1909 $lastelem = $lastelem / 10 if (length($lastelem) & 1) != $len;
1910 print "$lastelem\n" if DEBUG;
1913 # construct $x (instead of _lsft($c,$x,$l,10)
1914 my $r = $l % $BASE_LEN; # 10000 00000 00000 00000 ($BASE_LEN=5)
1915 $l = int($l / $BASE_LEN);
1916 print "l = $l " if DEBUG;
1918 splice @$x,$l; # keep ref($x), but modify it
1920 # we make the first part of the guess not '1000...0' but int(sqrt($lastelem))
1922 # 14400 00000 => sqrt(14400) => guess first digits to be 120
1923 # 144000 000000 => sqrt(144000) => guess 379
1925 print "$lastelem (elems $elems) => " if DEBUG;
1926 $lastelem = $lastelem / 10 if ($elems & 1 == 1); # odd or even?
1927 my $g = sqrt($lastelem); $g =~ s/\.//; # 2.345 => 2345
1928 $r -= 1 if $elems & 1 == 0; # 70 => 7
1930 # padd with zeros if result is too short
1931 $x->[$l--] = int(substr($g . '0' x $r,0,$r+1));
1932 print "now ",$x->[-1] if DEBUG;
1933 print " would have been ", int('1' . '0' x $r),"\n" if DEBUG;
1935 # If @$x > 1, we could compute the second elem of the guess, too, to create
1936 # an even better guess. Not implemented yet. Does it improve performance?
1937 $x->[$l--] = 0 while ($l >= 0); # all other digits of guess are zero
1939 print "start x= ",_str($c,$x),"\n" if DEBUG;
1942 my $lastlast = _zero();
1943 $steps = 0 if DEBUG;
1944 while (_acmp($c,$last,$x) != 0 && _acmp($c,$lastlast,$x) != 0)
1947 $lastlast = _copy($c,$last);
1948 $last = _copy($c,$x);
1949 _add($c,$x, _div($c,_copy($c,$y),$x));
1951 print " x= ",_str($c,$x),"\n" if DEBUG;
1953 print "\nsteps in sqrt: $steps, " if DEBUG;
1954 _dec($c,$x) if _acmp($c,$y,_mul($c,_copy($c,$x),$x)) < 0; # overshot?
1955 print " final ",$x->[-1],"\n" if DEBUG;
1961 # take n'th root of $x in place (n >= 3)
1964 if (scalar @$x == 1)
1968 # result will always be smaller than 2 so trunc to 1 at once
1973 # fits into one Perl scalar, so result can be computed directly
1974 # cannot use int() here, because it rounds wrongly (try
1975 # (81 ** 3) ** (1/3) to see what I mean)
1976 #$x->[0] = int( $x->[0] ** (1 / $n->[0]) );
1977 # round to 8 digits, then truncate result to integer
1978 $x->[0] = int ( sprintf ("%.8f", $x->[0] ** (1 / $n->[0]) ) );
1983 # we know now that X is more than one element long
1985 # if $n is a power of two, we can repeatedly take sqrt($X) and find the
1986 # proper result, because sqrt(sqrt($x)) == root($x,4)
1987 my $b = _as_bin($c,$n);
1988 if ($b =~ /0b1(0+)$/)
1990 my $count = CORE::length($1); # 0b100 => len('00') => 2
1991 my $cnt = $count; # counter for loop
1992 unshift (@$x, 0); # add one element, together with one
1993 # more below in the loop this makes 2
1996 # 'inflate' $X by adding one element, basically computing
1997 # $x * $BASE * $BASE. This gives us more $BASE_LEN digits for result
1998 # since len(sqrt($X)) approx == len($x) / 2.
2000 # calculate sqrt($x), $x is now one element to big, again. In the next
2001 # round we make that two, again.
2004 # $x is now one element to big, so truncate result by removing it
2009 # trial computation by starting with 2,4,8,16 etc until we overstep
2013 # while still to do more than X steps
2017 while (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) < 0)
2019 _mul ($c, $step, [2]);
2020 _add ($c, $trial, $step);
2024 if (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) == 0)
2026 @$x = @$trial; # make copy while preserving ref to $x
2029 # overstepped, so go back on step
2030 _sub($c, $trial, $step);
2031 } while (scalar @$step > 1 || $step->[0] > 128);
2035 # add two, because $trial cannot be exactly the result (otherwise we would
2036 # alrady have found it)
2037 _add($c, $trial, $step);
2039 # and now add more and more (2,4,6,8,10 etc)
2040 while (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) < 0)
2042 _add ($c, $trial, $step);
2045 # hit not exactly? (overstepped)
2046 if (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) > 0)
2051 # hit not exactly? (overstepped)
2052 # 80 too small, 81 slightly too big, 82 too big
2053 if (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) > 0)
2058 @$x = @$trial; # make copy while preserving ref to $x
2064 ##############################################################################
2071 # the shortcut makes equal, large numbers _really_ fast, and makes only a
2072 # very small performance drop for small numbers (e.g. something with less
2073 # than 32 bit) Since we optimize for large numbers, this is enabled.
2074 return $x if _acmp($c,$x,$y) == 0; # shortcut
2076 my $m = _one(); my ($xr,$yr);
2077 my $mask = $AND_MASK;
2080 my $y1 = _copy($c,$y); # make copy
2084 while (!_is_zero($c,$x1) && !_is_zero($c,$y1))
2086 ($x1, $xr) = _div($c,$x1,$mask);
2087 ($y1, $yr) = _div($c,$y1,$mask);
2089 # make ints() from $xr, $yr
2090 # this is when the AND_BITS are greater than $BASE and is slower for
2091 # small (<256 bits) numbers, but faster for large numbers. Disabled
2092 # due to KISS principle
2094 # $b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; }
2095 # $b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; }
2096 # _add($c,$x, _mul($c, _new( $c, ($xrr & $yrr) ), $m) );
2098 # 0+ due to '&' doesn't work in strings
2099 _add($c,$x, _mul($c, [ 0+$xr->[0] & 0+$yr->[0] ], $m) );
2109 return _zero() if _acmp($c,$x,$y) == 0; # shortcut (see -and)
2111 my $m = _one(); my ($xr,$yr);
2112 my $mask = $XOR_MASK;
2115 my $y1 = _copy($c,$y); # make copy
2119 while (!_is_zero($c,$x1) && !_is_zero($c,$y1))
2121 ($x1, $xr) = _div($c,$x1,$mask);
2122 ($y1, $yr) = _div($c,$y1,$mask);
2123 # make ints() from $xr, $yr (see _and())
2124 #$b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; }
2125 #$b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; }
2126 #_add($c,$x, _mul($c, _new( $c, ($xrr ^ $yrr) ), $m) );
2128 # 0+ due to '^' doesn't work in strings
2129 _add($c,$x, _mul($c, [ 0+$xr->[0] ^ 0+$yr->[0] ], $m) );
2132 # the loop stops when the shorter of the two numbers is exhausted
2133 # the remainder of the longer one will survive bit-by-bit, so we simple
2134 # multiply-add it in
2135 _add($c,$x, _mul($c, $x1, $m) ) if !_is_zero($c,$x1);
2136 _add($c,$x, _mul($c, $y1, $m) ) if !_is_zero($c,$y1);
2145 return $x if _acmp($c,$x,$y) == 0; # shortcut (see _and)
2147 my $m = _one(); my ($xr,$yr);
2148 my $mask = $OR_MASK;
2151 my $y1 = _copy($c,$y); # make copy
2155 while (!_is_zero($c,$x1) && !_is_zero($c,$y1))
2157 ($x1, $xr) = _div($c,$x1,$mask);
2158 ($y1, $yr) = _div($c,$y1,$mask);
2159 # make ints() from $xr, $yr (see _and())
2160 # $b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; }
2161 # $b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; }
2162 # _add($c,$x, _mul($c, _new( $c, ($xrr | $yrr) ), $m) );
2164 # 0+ due to '|' doesn't work in strings
2165 _add($c,$x, _mul($c, [ 0+$xr->[0] | 0+$yr->[0] ], $m) );
2168 # the loop stops when the shorter of the two numbers is exhausted
2169 # the remainder of the longer one will survive bit-by-bit, so we simple
2170 # multiply-add it in
2171 _add($c,$x, _mul($c, $x1, $m) ) if !_is_zero($c,$x1);
2172 _add($c,$x, _mul($c, $y1, $m) ) if !_is_zero($c,$y1);
2179 # convert a decimal number to hex (ref to array, return ref to string)
2182 # fits into one element (handle also 0x0 case)
2183 return sprintf("0x%x",$x->[0]) if @$x == 1;
2185 my $x1 = _copy($c,$x);
2188 my ($xr, $h, $x10000);
2191 $x10000 = [ 0x10000 ]; $h = 'h4';
2195 $x10000 = [ 0x1000 ]; $h = 'h3';
2197 while (@$x1 != 1 || $x1->[0] != 0) # _is_zero()
2199 ($x1, $xr) = _div($c,$x1,$x10000);
2200 $es .= unpack($h,pack('V',$xr->[0]));
2203 $es =~ s/^[0]+//; # strip leading zeros
2204 '0x' . $es; # return result prepended with 0x
2209 # convert a decimal number to bin (ref to array, return ref to string)
2212 # fits into one element (and Perl recent enough), handle also 0b0 case
2213 # handle zero case for older Perls
2214 if ($] <= 5.005 && @$x == 1 && $x->[0] == 0)
2216 my $t = '0b0'; return $t;
2218 if (@$x == 1 && $] >= 5.006)
2220 my $t = sprintf("0b%b",$x->[0]);
2223 my $x1 = _copy($c,$x);
2226 my ($xr, $b, $x10000);
2229 $x10000 = [ 0x10000 ]; $b = 'b16';
2233 $x10000 = [ 0x1000 ]; $b = 'b12';
2235 while (!(@$x1 == 1 && $x1->[0] == 0)) # _is_zero()
2237 ($x1, $xr) = _div($c,$x1,$x10000);
2238 $es .= unpack($b,pack('v',$xr->[0]));
2241 $es =~ s/^[0]+//; # strip leading zeros
2242 '0b' . $es; # return result prepended with 0b
2247 # convert a decimal number to octal (ref to array, return ref to string)
2250 # fits into one element (handle also 0 case)
2251 return sprintf("0%o",$x->[0]) if @$x == 1;
2253 my $x1 = _copy($c,$x);
2257 my $x1000 = [ 0100000 ];
2258 while (@$x1 != 1 || $x1->[0] != 0) # _is_zero()
2260 ($x1, $xr) = _div($c,$x1,$x1000);
2261 $es .= reverse sprintf("%05o", $xr->[0]);
2264 $es =~ s/^[0]+//; # strip leading zeros
2265 '0' . $es; # return result prepended with 0
2270 # convert a octal number to decimal (string, return ref to array)
2273 # for older Perls, play safe
2274 my $m = [ 0100000 ];
2275 my $d = 5; # 5 digits at a time
2280 my $len = int( (length($os)-1)/$d ); # $d digit parts, w/o the '0'
2281 my $val; my $i = -$d;
2284 $val = substr($os,$i,$d); # get oct digits
2287 my $adder = [ $val ];
2288 _add ($c, $x, _mul ($c, $adder, $mul ) ) if $val != 0;
2289 _mul ($c, $mul, $m ) if $len >= 0; # skip last mul
2296 # convert a hex number to decimal (string, return ref to array)
2299 my $m = _new($c, 0x10000000); # 28 bit at a time (<32 bit!)
2300 my $d = 7; # 7 digits at a time
2303 # for older Perls, play safe
2304 $m = [ 0x10000 ]; # 16 bit at a time (<32 bit!)
2305 $d = 4; # 4 digits at a time
2311 my $len = int( (length($hs)-2)/$d ); # $d digit parts, w/o the '0x'
2312 my $val; my $i = -$d;
2315 $val = substr($hs,$i,$d); # get hex digits
2316 $val =~ s/^0x// if $len == 0; # for last part only because
2317 $val = hex($val); # hex does not like wrong chars
2319 my $adder = [ $val ];
2320 # if the resulting number was to big to fit into one element, create a
2321 # two-element version (bug found by Mark Lakata - Thanx!)
2322 if (CORE::length($val) > $BASE_LEN)
2324 $adder = _new($c,$val);
2326 _add ($c, $x, _mul ($c, $adder, $mul ) ) if $val != 0;
2327 _mul ($c, $mul, $m ) if $len >= 0; # skip last mul
2334 # convert a hex number to decimal (string, return ref to array)
2337 # instead of converting X (8) bit at a time, it is faster to "convert" the
2338 # number to hex, and then call _from_hex.
2341 $hs =~ s/^[+-]?0b//; # remove sign and 0b
2342 my $l = length($hs); # bits
2343 $hs = '0' x (8-($l % 8)) . $hs if ($l % 8) != 0; # padd left side w/ 0
2344 my $h = '0x' . unpack('H*', pack ('B*', $hs)); # repack as hex
2349 ##############################################################################
2350 # special modulus functions
2357 my $u = _zero($c); my $u1 = _one($c);
2358 my $a = _copy($c,$y); my $b = _copy($c,$x);
2360 # Euclid's Algorithm for bgcd(), only that we calc bgcd() ($a) and the
2361 # result ($u) at the same time. See comments in BigInt for why this works.
2363 ($a, $q, $b) = ($b, _div($c,$a,$b)); # step 1
2365 while (!_is_zero($c,$b))
2367 my $t = _add($c, # step 2:
2368 _mul($c,_copy($c,$u1), $q) , # t = u1 * q
2370 $u = $u1; # u = u1, u1 = t
2373 ($a, $q, $b) = ($b, _div($c,$a,$b)); # step 1
2376 # if the gcd is not 1, then return NaN
2377 return (undef,undef) unless _is_one($c,$a);
2379 ($u1, $sign == 1 ? '+' : '-');
2384 # modulus of power ($x ** $y) % $z
2385 my ($c,$num,$exp,$mod) = @_;
2387 # in the trivial case,
2388 if (_is_one($c,$mod))
2390 splice @$num,0,1; $num->[0] = 0;
2393 if ((scalar @$num == 1) && (($num->[0] == 0) || ($num->[0] == 1)))
2399 # $num = _mod($c,$num,$mod); # this does not make it faster
2401 my $acc = _copy($c,$num); my $t = _one();
2403 my $expbin = _as_bin($c,$exp); $expbin =~ s/^0b//;
2404 my $len = length($expbin);
2407 if ( substr($expbin,$len,1) eq '1') # is_odd
2410 $t = _mod($c,$t,$mod);
2413 $acc = _mod($c,$acc,$mod);
2421 # greatest common divisor
2424 while ( (scalar @$y != 1) || ($y->[0] != 0) ) # while ($y != 0)
2426 my $t = _copy($c,$y);
2427 $y = _mod($c, $x, $y);
2433 ##############################################################################
2434 ##############################################################################
2441 Math::BigInt::Calc - Pure Perl module to support Math::BigInt
2445 Provides support for big integer calculations. Not intended to be used by other
2446 modules. Other modules which sport the same functions can also be used to support
2447 Math::BigInt, like Math::BigInt::GMP or Math::BigInt::Pari.
2451 In order to allow for multiple big integer libraries, Math::BigInt was
2452 rewritten to use library modules for core math routines. Any module which
2453 follows the same API as this can be used instead by using the following:
2455 use Math::BigInt lib => 'libname';
2457 'libname' is either the long name ('Math::BigInt::Pari'), or only the short
2458 version like 'Pari'.
2464 The following functions MUST be defined in order to support the use by
2465 Math::BigInt v1.70 or later:
2467 api_version() return API version, 1 for v1.70, 2 for v1.83
2468 _new(string) return ref to new object from ref to decimal string
2469 _zero() return a new object with value 0
2470 _one() return a new object with value 1
2471 _two() return a new object with value 2
2472 _ten() return a new object with value 10
2474 _str(obj) return ref to a string representing the object
2475 _num(obj) returns a Perl integer/floating point number
2476 NOTE: because of Perl numeric notation defaults,
2477 the _num'ified obj may lose accuracy due to
2478 machine-dependent floating point size limitations
2480 _add(obj,obj) Simple addition of two objects
2481 _mul(obj,obj) Multiplication of two objects
2482 _div(obj,obj) Division of the 1st object by the 2nd
2483 In list context, returns (result,remainder).
2484 NOTE: this is integer math, so no
2485 fractional part will be returned.
2486 The second operand will be not be 0, so no need to
2488 _sub(obj,obj) Simple subtraction of 1 object from another
2489 a third, optional parameter indicates that the params
2490 are swapped. In this case, the first param needs to
2491 be preserved, while you can destroy the second.
2492 sub (x,y,1) => return x - y and keep x intact!
2493 _dec(obj) decrement object by one (input is guaranteed to be > 0)
2494 _inc(obj) increment object by one
2497 _acmp(obj,obj) <=> operator for objects (return -1, 0 or 1)
2499 _len(obj) returns count of the decimal digits of the object
2500 _digit(obj,n) returns the n'th decimal digit of object
2502 _is_one(obj) return true if argument is 1
2503 _is_two(obj) return true if argument is 2
2504 _is_ten(obj) return true if argument is 10
2505 _is_zero(obj) return true if argument is 0
2506 _is_even(obj) return true if argument is even (0,2,4,6..)
2507 _is_odd(obj) return true if argument is odd (1,3,5,7..)
2509 _copy return a ref to a true copy of the object
2511 _check(obj) check whether internal representation is still intact
2512 return 0 for ok, otherwise error message as string
2514 _from_hex(str) return new object from a hexadecimal string
2515 _from_bin(str) return new object from a binary string
2516 _from_oct(str) return new object from an octal string
2518 _as_hex(str) return string containing the value as
2519 unsigned hex string, with the '0x' prepended.
2520 Leading zeros must be stripped.
2521 _as_bin(str) Like as_hex, only as binary string containing only
2522 zeros and ones. Leading zeros must be stripped and a
2523 '0b' must be prepended.
2525 _rsft(obj,N,B) shift object in base B by N 'digits' right
2526 _lsft(obj,N,B) shift object in base B by N 'digits' left
2528 _xor(obj1,obj2) XOR (bit-wise) object 1 with object 2
2529 Note: XOR, AND and OR pad with zeros if size mismatches
2530 _and(obj1,obj2) AND (bit-wise) object 1 with object 2
2531 _or(obj1,obj2) OR (bit-wise) object 1 with object 2
2533 _mod(obj1,obj2) Return remainder of div of the 1st by the 2nd object
2534 _sqrt(obj) return the square root of object (truncated to int)
2535 _root(obj) return the n'th (n >= 3) root of obj (truncated to int)
2536 _fac(obj) return factorial of object 1 (1*2*3*4..)
2537 _pow(obj1,obj2) return object 1 to the power of object 2
2538 return undef for NaN
2539 _zeros(obj) return number of trailing decimal zeros
2540 _modinv return inverse modulus
2541 _modpow return modulus of power ($x ** $y) % $z
2542 _log_int(X,N) calculate integer log() of X in base N
2543 X >= 0, N >= 0 (return undef for NaN)
2544 returns (RESULT, EXACT) where EXACT is:
2545 1 : result is exactly RESULT
2546 0 : result was truncated to RESULT
2547 undef : unknown whether result is exactly RESULT
2548 _gcd(obj,obj) return Greatest Common Divisor of two objects
2550 The following functions are REQUIRED for an api_version of 2 or greater:
2552 _1ex($x) create the number 1Ex where x >= 0
2553 _alen(obj) returns approximate count of the decimal digits of the
2554 object. This estimate MUST always be greater or equal
2555 to what _len() returns.
2556 _nok(n,k) calculate n over k (binomial coefficient)
2558 The following functions are optional, and can be defined if the underlying lib
2559 has a fast way to do them. If undefined, Math::BigInt will use pure Perl (hence
2560 slow) fallback routines to emulate these:
2566 Input strings come in as unsigned but with prefix (i.e. as '123', '0xabc'
2569 So the library needs only to deal with unsigned big integers. Testing of input
2570 parameter validity is done by the caller, so you need not worry about
2571 underflow (f.i. in C<_sub()>, C<_dec()>) nor about division by zero or similar
2574 The first parameter can be modified, that includes the possibility that you
2575 return a reference to a completely different object instead. Although keeping
2576 the reference and just changing its contents is preferred over creating and
2577 returning a different reference.
2579 Return values are always references to objects, strings, or true/false for
2580 comparison routines.
2582 =head1 WRAP YOUR OWN
2584 If you want to port your own favourite c-lib for big numbers to the
2585 Math::BigInt interface, you can take any of the already existing modules as
2586 a rough guideline. You should really wrap up the latest BigInt and BigFloat
2587 testsuites with your module, and replace in them any of the following:
2593 use Math::BigInt lib => 'yourlib';
2595 This way you ensure that your library really works 100% within Math::BigInt.
2599 This program is free software; you may redistribute it and/or modify it under
2600 the same terms as Perl itself.
2604 Original math code by Mark Biggar, rewritten by Tels L<http://bloodgate.com/>
2606 Seperated from BigInt and shaped API with the help of John Peacock.
2608 Fixed, speed-up, streamlined and enhanced by Tels 2001 - 2007.
2612 L<Math::BigInt>, L<Math::BigFloat>,
2613 L<Math::BigInt::GMP>, L<Math::BigInt::FastCalc> and L<Math::BigInt::Pari>.