1 package Math::BigInt::Calc;
5 # use warnings; # dont use warnings for older Perls
8 use vars qw/@ISA $VERSION/;
13 # Package to store unsigned big integers in decimal and do math with them
15 # Internally the numbers are stored in an array with at least 1 element, no
16 # leading zero parts (except the first) and in base 100000
19 # - fully remove funky $# stuff (maybe)
21 # USE_MUL: due to problems on certain os (os390, posix-bc) "* 1e-5" is used
22 # instead of "/ 1e5" at some places, (marked with USE_MUL). Other platforms
23 # BS2000, some Crays need USE_DIV instead.
24 # The BEGIN block is used to determine which of the two variants gives the
27 ##############################################################################
28 # global constants, flags and accessory
30 # constants for easier life
33 my ($BASE,$RBASE,$BASE_LEN,$MAX_VAL);
41 $BASE = int("1e".$BASE_LEN);
42 $RBASE = abs('1e-'.$BASE_LEN); # see USE_MUL
44 # print "BASE_LEN: $BASE_LEN MAX_VAL: $MAX_VAL\n";
45 # print "int: ",int($BASE * $RBASE),"\n";
46 if (int($BASE * $RBASE) == 0) # should be 1
50 *{_mul} = \&_mul_use_mul;
51 *{_div} = \&_div_use_mul;
57 *{_mul} = \&_mul_use_div;
58 *{_div} = \&_div_use_div;
66 # from Daniel Pfeiffer: determine largest group of digits that is precisely
67 # multipliable with itself plus carry
71 $num = ('9' x ++$e) + 0;
73 } until ($num == $num - 1 or $num - 1 == $num - 2);
77 # for quering and setting, to debug/benchmark things
79 ##############################################################################
80 # create objects from various representations
84 # (string) return ref to num_array
85 # Convert a number from string format to internal base 100000 format.
86 # Assumes normalized value as input.
88 # print "_new $d $$d\n";
89 my $il = CORE::length($$d)-1;
90 # these leaves '00000' instead of int 0 and will be corrected after any op
91 return [ reverse(unpack("a" . ($il % $BASE_LEN+1)
92 . ("a$BASE_LEN" x ($il / $BASE_LEN)), $$d)) ];
112 # catch and throw away
115 ##############################################################################
116 # convert back to string and number
120 # (ref to BINT) return num_str
121 # Convert number from internal base 100000 format to string format.
122 # internal format is always normalized (no leading zeros, "-0" => "+0")
125 my $l = scalar @$ar; # number of parts
126 return $nan if $l < 1; # should not happen
127 # handle first one different to strip leading zeros from it (there are no
128 # leading zero parts in internal representation)
129 $l --; $ret .= $ar->[$l]; $l--;
130 # Interestingly, the pre-padd method uses more time
131 # the old grep variant takes longer (14 to 10 sec)
132 my $z = '0' x ($BASE_LEN-1);
135 $ret .= substr($z.$ar->[$l],-$BASE_LEN); # fastest way I could think of
143 # Make a number (scalar int/float) from a BigInt object
145 return $x->[0] if scalar @$x == 1; # below $BASE
150 $num += $fac*$_; $fac *= $BASE;
155 ##############################################################################
160 # (ref to int_num_array, ref to int_num_array)
161 # routine to add two base 1eX numbers
162 # stolen from Knuth Vol 2 Algorithm A pg 231
163 # there are separate routines to add and sub as per Knuth pg 233
164 # This routine clobbers up array x, but not y.
168 # for each in Y, add Y to X and carry. If after that, something is left in
169 # X, foreach in X add carry to X and then return X, carry
170 # Trades one "$j++" for having to shift arrays, $j could be made integer
171 # but this would impose a limit to number-length of 2**32.
172 my $i; my $car = 0; my $j = 0;
176 if $car = (($x->[$j] += $i + $car) >= $BASE) ? 1 : 0;
181 $x->[$j] -= $BASE if $car = (($x->[$j] += $car) >= $BASE) ? 1 : 0; $j++;
188 # (ref to int_num_array, ref to int_num_array)
189 # subtract base 1eX numbers -- stolen from Knuth Vol 2 pg 232, $x > $y
190 # subtract Y from X (X is always greater/equal!) by modifying x in place
191 my ($c,$sx,$sy,$s) = @_;
193 my $car = 0; my $i; my $j = 0;
199 last unless defined $sy->[$j] || $car;
200 #print "x: $i y: $sy->[$j] c: $car\n";
201 $i += $BASE if $car = (($i -= ($sy->[$j] || 0) + $car) < 0); $j++;
202 #print "x: $i y: $sy->[$j-1] c: $car\n";
204 # might leave leading zeros, so fix that
210 #print "case 1 (swap)\n";
213 last unless defined $sy->[$j] || $car;
214 #print "$sy->[$j] $i $car => $sx->[$j]\n";
216 if $car = (($sy->[$j] = $i-($sy->[$j]||0) - $car) < 0);
217 #print "$sy->[$j] $i $car => $sy->[$j]\n";
220 # might leave leading zeros, so fix that
228 # (BINT, BINT) return nothing
229 # multiply two numbers in internal representation
230 # modifies first arg, second need not be different from first
231 my ($c,$xv,$yv) = @_;
233 my @prod = (); my ($prod,$car,$cty,$xi,$yi);
234 # since multiplying $x with $x fails, make copy in this case
235 $yv = [@$xv] if "$xv" eq "$yv"; # same references?
243 # $prod = $xi * $yi + ($prod[$cty] || 0) + $car;
245 # $prod - ($car = int($prod * RBASE)) * $BASE; # see USE_MUL
247 # $prod[$cty] += $car if $car; # need really to check for 0?
251 # looping through this if $xi == 0 is silly - so optimize it away!
252 $xi = (shift @prod || 0), next if $xi == 0;
255 $prod = $xi * $yi + ($prod[$cty] || 0) + $car;
256 ## this is actually a tad slower
257 ## $prod = $prod[$cty]; $prod += ($car + $xi * $yi); # no ||0 here
259 $prod - ($car = int($prod * $RBASE)) * $BASE; # see USE_MUL
261 $prod[$cty] += $car if $car; # need really to check for 0?
266 # normalize (handled last to save check for $y->is_zero()
272 # (BINT, BINT) return nothing
273 # multiply two numbers in internal representation
274 # modifies first arg, second need not be different from first
275 my ($c,$xv,$yv) = @_;
277 my @prod = (); my ($prod,$car,$cty,$xi,$yi);
278 # since multiplying $x with $x fails, make copy in this case
279 $yv = [@$xv] if "$xv" eq "$yv"; # same references?
283 # looping through this if $xi == 0 is silly - so optimize it away!
284 $xi = (shift @prod || 0), next if $xi == 0;
287 $prod = $xi * $yi + ($prod[$cty] || 0) + $car;
289 $prod - ($car = int($prod / $BASE)) * $BASE;
291 $prod[$cty] += $car if $car; # need really to check for 0?
296 # normalize (handled last to save check for $y->is_zero()
302 # ref to array, ref to array, modify first array and return remainder if
304 # no longer handles sign
305 my ($c,$x,$yorg) = @_;
306 my ($car,$bar,$prd,$dd,$xi,$yi,@q,$v2,$v1);
308 my (@d,$tmp,$q,$u2,$u1,$u0);
310 $car = $bar = $prd = 0;
313 if (($dd = int($BASE/($y->[-1]+1))) != 1)
317 $xi = $xi * $dd + $car;
318 $xi -= ($car = int($xi * $RBASE)) * $BASE; # see USE_MUL
320 push(@$x, $car); $car = 0;
323 $yi = $yi * $dd + $car;
324 $yi -= ($car = int($yi * $RBASE)) * $BASE; # see USE_MUL
331 @q = (); ($v2,$v1) = @$y[-2,-1];
335 ($u2,$u1,$u0) = @$x[-3..-1];
337 #warn "oups v1 is 0, u0: $u0 $y->[-2] $y->[-1] l ",scalar @$y,"\n"
339 # $q = (($u0 == $v1) ? 99999 : int(($u0*$BASE+$u1)/$v1));
340 $q = (($u0 == $v1) ? $MAX_VAL : int(($u0*$BASE+$u1)/$v1));
341 --$q while ($v2*$q > ($u0*$BASE+$u1-$q*$v1)*$BASE+$u2);
344 ($car, $bar) = (0,0);
345 for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)
347 $prd = $q * $y->[$yi] + $car;
348 $prd -= ($car = int($prd * $RBASE)) * $BASE; # see USE_MUL
349 $x->[$xi] += $BASE if ($bar = (($x->[$xi] -= $prd + $bar) < 0));
351 if ($x->[-1] < $car + $bar)
354 for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)
357 if ($car = (($x->[$xi] += $y->[$yi] + $car) > $BASE));
361 pop(@$x); unshift(@q, $q);
369 for $xi (reverse @$x)
371 $prd = $car * $BASE + $xi;
372 $car = $prd - ($tmp = int($prd / $dd)) * $dd; # see USE_MUL
392 # ref to array, ref to array, modify first array and return remainder if
394 # no longer handles sign
395 my ($c,$x,$yorg) = @_;
396 my ($car,$bar,$prd,$dd,$xi,$yi,@q,$v2,$v1);
398 my (@d,$tmp,$q,$u2,$u1,$u0);
400 $car = $bar = $prd = 0;
403 if (($dd = int($BASE/($y->[-1]+1))) != 1)
407 $xi = $xi * $dd + $car;
408 $xi -= ($car = int($xi / $BASE)) * $BASE;
410 push(@$x, $car); $car = 0;
413 $yi = $yi * $dd + $car;
414 $yi -= ($car = int($yi / $BASE)) * $BASE;
421 @q = (); ($v2,$v1) = @$y[-2,-1];
425 ($u2,$u1,$u0) = @$x[-3..-1];
427 #warn "oups v1 is 0, u0: $u0 $y->[-2] $y->[-1] l ",scalar @$y,"\n"
429 # $q = (($u0 == $v1) ? 99999 : int(($u0*$BASE+$u1)/$v1));
430 $q = (($u0 == $v1) ? $MAX_VAL : int(($u0*$BASE+$u1)/$v1));
431 --$q while ($v2*$q > ($u0*$BASE+$u1-$q*$v1)*$BASE+$u2);
434 ($car, $bar) = (0,0);
435 for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)
437 $prd = $q * $y->[$yi] + $car;
438 $prd -= ($car = int($prd / $BASE)) * $BASE;
439 $x->[$xi] += $BASE if ($bar = (($x->[$xi] -= $prd + $bar) < 0));
441 if ($x->[-1] < $car + $bar)
444 for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)
447 if ($car = (($x->[$xi] += $y->[$yi] + $car) > $BASE));
451 pop(@$x); unshift(@q, $q);
459 for $xi (reverse @$x)
461 $prd = $car * $BASE + $xi;
462 $car = $prd - ($tmp = int($prd / $dd)) * $dd;
480 ##############################################################################
485 my ($c,$x,$y,$n) = @_;
489 return; # we cant do this here, due to now _pow, so signal failure
493 # shortcut (faster) for shifting by 10)
494 # multiples of $BASE_LEN
495 my $dst = 0; # destination
496 my $src = _num($c,$y); # as normal int
497 my $rem = $src % $BASE_LEN; # reminder to shift
498 $src = int($src / $BASE_LEN); # source
501 splice (@$x,0,$src); # even faster, 38.4 => 39.3
505 my $len = scalar @$x - $src; # elems to go
506 my $vd; my $z = '0'x $BASE_LEN;
507 $x->[scalar @$x] = 0; # avoid || 0 test inside loop
511 #print "$dst $src '$vd' ";
512 $vd = substr($vd,-$BASE_LEN,$BASE_LEN-$rem);
515 $vd = substr($z.$x->[$src],-$rem,$rem) . $vd;
518 $vd = substr($vd,-$BASE_LEN,$BASE_LEN) if length($vd) > $BASE_LEN;
519 $x->[$dst] = int($vd);
522 splice (@$x,$dst) if $dst > 0; # kill left-over array elems
523 pop @$x if $x->[-1] == 0; # kill last element if 0
531 my ($c,$x,$y,$n) = @_;
535 return; # we cant do this here, due to now _pow, so signal failure
539 # shortcut (faster) for shifting by 10) since we are in base 10eX
540 # multiples of $BASE_LEN:
541 my $src = scalar @$x; # source
542 my $len = _num($c,$y); # shift-len as normal int
543 my $rem = $len % $BASE_LEN; # reminder to shift
544 my $dst = $src + int($len/$BASE_LEN); # destination
545 my $vd; # further speedup
546 #print "src $src:",$x->[$src]||0," dst $dst:",$v->[$dst]||0," rem $rem\n";
547 $x->[$src] = 0; # avoid first ||0 for speed
548 my $z = '0' x $BASE_LEN;
551 $vd = $x->[$src]; $vd = $z.$vd;
552 #print "s $src d $dst '$vd' ";
553 $vd = substr($vd,-$BASE_LEN+$rem,$BASE_LEN-$rem);
555 $vd .= $src > 0 ? substr($z.$x->[$src-1],-$BASE_LEN,$rem) : '0' x $rem;
557 $vd = substr($vd,-$BASE_LEN,$BASE_LEN) if length($vd) > $BASE_LEN;
559 $x->[$dst] = int($vd);
562 # set lowest parts to 0
563 while ($dst >= 0) { $x->[$dst--] = 0; }
564 # fix spurios last zero element
565 splice @$x,-1 if $x->[-1] == 0;
566 #print "elems: "; my $i = 0;
567 #foreach (reverse @$v) { print "$i $_ "; $i++; } print "\n";
572 ##############################################################################
577 # internal absolute post-normalized compare (ignore signs)
578 # ref to array, ref to array, return <0, 0, >0
579 # arrays must have at least one entry; this is not checked for
581 my ($c,$cx, $cy) = @_;
585 # calculate length based on digits, not parts
586 $x = _len('',$cx); $y = _len('',$cy);
587 # print "length: ",($x-$y),"\n";
588 my $lxy = $x - $y; # if different in length
589 return -1 if $lxy < 0;
590 return 1 if $lxy > 0;
591 #print "full compare\n";
593 # first way takes 5.49 sec instead of 4.87, but has the early out advantage
594 # so grep is slightly faster, but more inflexible. hm. $_ instead of $k
595 # yields 5.6 instead of 5.5 sec huh?
596 # manual way (abort if unequal, good for early ne)
597 my $j = scalar @$cx - 1;
600 # print "$cx->[$j] $cy->[$j] $a",$cx->[$j]-$cy->[$j],"\n";
601 last if ($a = $cx->[$j] - $cy->[$j]); $j--;
606 # while it early aborts, it is even slower than the manual variant
607 #grep { return $a if ($a = $_ - $cy->[$i++]); } @$cx;
608 # grep way, go trough all (bad for early ne)
609 #grep { $a = $_ - $cy->[$i++]; } @$cx;
615 # computer number of digits in bigint, minus the sign
616 # int() because add/sub sometimes leaves strings (like '00005') instead of
617 # int ('5') in this place, causing length to fail
620 return (@$cx-1)*$BASE_LEN+length(int($cx->[-1]));
625 # return the nth digit, negative values count backward
626 # zero is rightmost, so _digit(123,0) will give 3
629 my $len = _len('',$x);
631 $n = $len+$n if $n < 0; # -1 last, -2 second-to-last
632 $n = abs($n); # if negative was too big
633 $len--; $n = $len if $n > $len; # n to big?
635 my $elem = int($n / $BASE_LEN); # which array element
636 my $digit = $n % $BASE_LEN; # which digit in this element
637 $elem = '0000'.@$x[$elem]; # get element padded with 0's
638 return substr($elem,-$digit-1,1);
643 # return amount of trailing zeros in decimal
644 # check each array elem in _m for having 0 at end as long as elem == 0
645 # Upon finding a elem != 0, stop
647 my $zeros = 0; my $elem;
652 $elem = "$e"; # preserve x
653 $elem =~ s/.*?(0*$)/$1/; # strip anything not zero
654 $zeros *= $BASE_LEN; # elems * 5
655 $zeros += CORE::length($elem); # count trailing zeros
658 $zeros ++; # real else branch: 50% slower!
663 ##############################################################################
668 # return true if arg (BINT or num_str) is zero (array '+', '0')
670 return (((scalar @$x == 1) && ($x->[0] == 0))) <=> 0;
675 # return true if arg (BINT or num_str) is even
677 return (!($x->[0] & 1)) <=> 0;
682 # return true if arg (BINT or num_str) is even
684 return (($x->[0] & 1)) <=> 0;
689 # return true if arg (BINT or num_str) is one (array '+', '1')
691 return (scalar @$x == 1) && ($x->[0] == 1) <=> 0;
696 # internal normalization function that strips leading zeros from the array
700 my $cnt = scalar @$s; # get count of parts
702 #print "strip: cnt $cnt i $i\n";
703 # '0', '3', '4', '0', '0',
708 # => fcnt = cnt - i (5-2 => 3, cnt => 5-1 = 4, throw away from 4th pos)
709 # >= 1: skip first part (this can be zero)
710 while ($i > 0) { last if $s->[$i] != 0; $i--; }
711 $i++; splice @$s,$i if ($i < $cnt); # $i cant be 0
715 ###############################################################################
716 # check routine to test internal state of corruptions
720 # used by the test suite
723 return "$x is not a reference" if !ref($x);
725 # are all parts are valid?
726 my $i = 0; my $j = scalar @$x; my ($e,$try);
729 $e = $x->[$i]; $e = 'undef' unless defined $e;
730 $try = '=~ /^[\+]?[0-9]+\$/; '."($x, $e)";
731 last if $e !~ /^[+]?[0-9]+$/;
732 $try = ' < 0 || >= $BASE; '."($x, $e)";
733 last if $e <0 || $e >= $BASE;
734 # this test is disabled, since new/bnorm and certain ops (like early out
735 # in add/sub) are allowed/expected to leave '00000' in some elements
736 #$try = '=~ /^00+/; '."($x, $e)";
737 #last if $e =~ /^00+/;
740 return "Illegal part '$e' at pos $i (tested: $try)" if $i < $j;
749 Math::BigInt::Calc - Pure Perl module to support Math::BigInt
753 Provides support for big integer calculations. Not intended to be used by other
754 modules (except Math::BigInt::Cached). Other modules which sport the same
755 functions can also be used to support Math::Bigint, like Math::BigInt::Pari.
759 In order to allow for multiple big integer libraries, Math::BigInt
760 was rewritten to use library modules for core math routines. Any
761 module which follows the same API as this can be used instead by
762 using the following call:
764 use Math::BigInt lib => 'libname';
768 The following functions MUST be defined in order to support
769 the use by Math::BigInt:
771 _new(string) return ref to new object from ref to decimal string
772 _zero() return a new object with value 0
773 _one() return a new object with value 1
775 _str(obj) return ref to a string representing the object
776 _num(obj) returns a Perl integer/floating point number
777 NOTE: because of Perl numeric notation defaults,
778 the _num'ified obj may lose accuracy due to
779 machine-dependend floating point size limitations
781 _add(obj,obj) Simple addition of two objects
782 _mul(obj,obj) Multiplication of two objects
783 _div(obj,obj) Division of the 1st object by the 2nd
784 In list context, returns (result,remainder).
785 NOTE: this is integer math, so no
786 fractional part will be returned.
787 _sub(obj,obj) Simple subtraction of 1 object from another
788 a third, optional parameter indicates that the params
789 are swapped. In this case, the first param needs to
790 be preserved, while you can destroy the second.
791 sub (x,y,1) => return x - y and keep x intact!
793 _acmp(obj,obj) <=> operator for objects (return -1, 0 or 1)
795 _len(obj) returns count of the decimal digits of the object
796 _digit(obj,n) returns the n'th decimal digit of object
798 _is_one(obj) return true if argument is +1
799 _is_zero(obj) return true if argument is 0
800 _is_even(obj) return true if argument is even (0,2,4,6..)
801 _is_odd(obj) return true if argument is odd (1,3,5,7..)
803 _copy return a ref to a true copy of the object
805 _check(obj) check whether internal representation is still intact
806 return 0 for ok, otherwise error message as string
808 The following functions are optional, and can be defined if the underlying lib
809 has a fast way to do them. If undefined, Math::BigInt will use a pure, but
810 slow, Perl way as fallback to emulate these:
812 _from_hex(str) return ref to new object from ref to hexadecimal string
813 _from_bin(str) return ref to new object from ref to binary string
815 _as_hex(str) return ref to scalar string containing the value as
816 unsigned hex string, with the '0x' prepended.
817 Leading zeros must be stripped.
818 _as_bin(str) Like as_hex, only as binary string containing only
819 zeros and ones. Leading zeros must be stripped and a
820 '0b' must be prepended.
822 _rsft(obj,N,B) shift object in base B by N 'digits' right
823 _lsft(obj,N,B) shift object in base B by N 'digits' left
825 _xor(obj1,obj2) XOR (bit-wise) object 1 with object 2
826 Mote: XOR, AND and OR pad with zeros if size mismatches
827 _and(obj1,obj2) AND (bit-wise) object 1 with object 2
828 _or(obj1,obj2) OR (bit-wise) object 1 with object 2
830 _sqrt(obj) return the square root of object
831 _pow(obj,obj) return object 1 to the power of object 2
832 _gcd(obj,obj) return Greatest Common Divisor of two objects
834 _zeros(obj) return number of trailing decimal zeros
836 _dec(obj) decrement object by one (input is >= 1)
837 _inc(obj) increment object by one
839 Input strings come in as unsigned but with prefix (i.e. as '123', '0xabc'
842 Testing of input parameter validity is done by the caller, so you need not
843 worry about underflow (f.i. in C<_sub()>, C<_dec()>) nor about division by
844 zero or similar cases.
846 The first parameter can be modified, that includes the possibility that you
847 return a reference to a completely different object instead. Although keeping
848 the reference is prefered over creating and returning a different one.
850 Return values are always references to objects or strings. Exceptions are
851 C<_lsft()> and C<_rsft()>, which return undef if they can not shift the
852 argument. This is used to delegate shifting of bases different than 10 back
853 to BigInt, which will use some generic code to calculate the result.
857 If you want to port your own favourite c-lib for big numbers to the
858 Math::BigInt interface, you can take any of the already existing modules as
859 a rough guideline. You should really wrap up the latest BigInt and BigFloat
860 testsuites with your module, and replace in them any of the following:
866 use Math::BigInt lib => 'yourlib';
868 This way you ensure that your library really works 100% within Math::BigInt.
872 This program is free software; you may redistribute it and/or modify it under
873 the same terms as Perl itself.
877 Original math code by Mark Biggar, rewritten by Tels L<http://bloodgate.com/>
879 Seperated from BigInt and shaped API with the help of John Peacock.
883 L<Math::BigInt>, L<Math::BigFloat>, L<Math::BigInt::BitVect>,
884 L<Math::BigInt::GMP>, L<Math::BigInt::Cached> and L<Math::BigInt::Pari>.