8 '+' => sub {new Math::BigInt &badd},
9 '-' => sub {new Math::BigInt
10 $_[2]? bsub($_[1],${$_[0]}) : bsub(${$_[0]},$_[1])},
11 '<=>' => sub {$_[2]? bcmp($_[1],${$_[0]}) : bcmp(${$_[0]},$_[1])},
12 'cmp' => sub {$_[2]? ($_[1] cmp ${$_[0]}) : (${$_[0]} cmp $_[1])},
13 '*' => sub {new Math::BigInt &bmul},
14 '/' => sub {new Math::BigInt
15 $_[2]? scalar bdiv($_[1],${$_[0]}) :
16 scalar bdiv(${$_[0]},$_[1])},
17 '%' => sub {new Math::BigInt
18 $_[2]? bmod($_[1],${$_[0]}) : bmod(${$_[0]},$_[1])},
19 '**' => sub {new Math::BigInt
20 $_[2]? bpow($_[1],${$_[0]}) : bpow(${$_[0]},$_[1])},
21 'neg' => sub {new Math::BigInt &bneg},
22 'abs' => sub {new Math::BigInt &babs},
23 '<<' => sub {new Math::BigInt
24 $_[2]? blsft($_[1],${$_[0]}) : blsft(${$_[0]},$_[1])},
25 '>>' => sub {new Math::BigInt
26 $_[2]? brsft($_[1],${$_[0]}) : brsft(${$_[0]},$_[1])},
27 '&' => sub {new Math::BigInt &band},
28 '|' => sub {new Math::BigInt &bior},
29 '^' => sub {new Math::BigInt &bxor},
30 '~' => sub {new Math::BigInt &bnot},
31 'int' => sub { shift },
35 0+ numify) # Order of arguments unsignificant
42 my($foo) = bnorm(shift);
43 die "Not a number initialized to Math::BigInt" if !$NaNOK && $foo eq "NaN";
46 sub stringify { "${$_[0]}" }
47 sub numify { 0 + "${$_[0]}" } # Not needed, additional overhead
48 # comparing to direct compilation based on
53 for ( my $i; $i < @_ ; $i++ ) {
54 if ( $_[$i] eq ':constant' ) {
55 overload::constant integer => sub {Math::BigInt->new(shift)};
60 $self->SUPER::import(@_);
65 # overcome a floating point problem on certain osnames (posix-bc, os390)
68 my $use_mult = int($x*1e-5)*1e5 == $x ? 1 : 0;
71 # normalize string form of number. Strip leading zeros. Strip any
72 # white space and add a sign, if missing.
73 # Strings that are not numbers result the value 'NaN'.
75 sub bnorm { #(num_str) return num_str
77 s/\s+//g; # strip white space
78 if (s/^([+-]?)0*(\d+)$/$1$2/) { # test if number
79 substr($_,$[,0) = '+' unless $1; # Add missing sign
87 # Convert a number from string format to internal base 100000 format.
88 # Assumes normalized value as input.
89 sub internal { #(num_str) return int_num_array
91 ($is,$il) = (substr($d,$[,1),length($d)-2);
93 ($is, reverse(unpack("a" . ($il%5+1) . ("a5" x ($il/5)), $d)));
96 # Convert a number from internal base 100000 format to string format.
97 # This routine scribbles all over input array.
98 sub external { #(int_num_array) return num_str
100 grep($_ > 9999 || ($_ = substr('0000'.$_,-5)), @_); # zero pad
101 &bnorm(join('', $es, reverse(@_))); # reverse concat and normalize
104 # Negate input value.
105 sub bneg { #(num_str) return num_str
106 local($_) = &bnorm(@_);
107 return $_ if $_ eq '+0' or $_ eq 'NaN';
108 vec($_,0,8) ^= ord('+') ^ ord('-');
112 # Returns the absolute value of the input.
113 sub babs { #(num_str) return num_str
117 sub abs { # post-normalized abs for internal use
123 # Compares 2 values. Returns one of undef, <0, =0, >0. (suitable for sort)
124 sub bcmp { #(num_str, num_str) return cond_code
125 local($x,$y) = (&bnorm($_[$[]),&bnorm($_[$[+1]));
128 } elsif ($y eq 'NaN') {
135 sub cmp { # post-normalized compare for internal use
136 local($cx, $cy) = @_;
138 return 0 if ($cx eq $cy);
140 local($sx, $sy) = (substr($cx, 0, 1), substr($cy, 0, 1));
144 return 1 if ($sy eq '-' || $cy eq '+0');
145 $ld = length($cx) - length($cy);
148 } else { # $sx eq '-'
149 return -1 if ($sy eq '+');
150 $ld = length($cy) - length($cx);
156 sub badd { #(num_str, num_str) return num_str
157 local(*x, *y); ($x, $y) = (&bnorm($_[$[]),&bnorm($_[$[+1]));
160 } elsif ($y eq 'NaN') {
163 @x = &internal($x); # convert to internal form
165 local($sx, $sy) = (shift @x, shift @y); # get signs
167 &external($sx, &add(*x, *y)); # if same sign add
169 ($x, $y) = (&abs($x),&abs($y)); # make abs
170 if (&cmp($y,$x) > 0) {
171 &external($sy, &sub(*y, *x));
173 &external($sx, &sub(*x, *y));
179 sub bsub { #(num_str, num_str) return num_str
180 &badd($_[$[],&bneg($_[$[+1]));
183 # GCD -- Euclids algorithm Knuth Vol 2 pg 296
184 sub bgcd { #(num_str, num_str) return num_str
185 local($x,$y) = (&bnorm($_[$[]),&bnorm($_[$[+1]));
186 if ($x eq 'NaN' || $y eq 'NaN') {
189 ($x, $y) = ($y,&bmod($x,$y)) while $y ne '+0';
194 # routine to add two base 1e5 numbers
195 # stolen from Knuth Vol 2 Algorithm A pg 231
196 # there are separate routines to add and sub as per Kunth pg 233
197 sub add { #(int_num_array, int_num_array) return int_num_array
201 last unless @y || $car;
202 $x -= 1e5 if $car = (($x += (@y ? shift(@y) : 0) + $car) >= 1e5) ? 1 : 0;
206 $y -= 1e5 if $car = (($y += $car) >= 1e5) ? 1 : 0;
211 # subtract base 1e5 numbers -- stolen from Knuth Vol 2 pg 232, $x > $y
212 sub sub { #(int_num_array, int_num_array) return int_num_array
213 local(*sx, *sy) = @_;
216 last unless @sy || $bar;
217 $sx += 1e5 if $bar = (($sx -= (@sy ? shift(@sy) : 0) + $bar) < 0);
222 # multiply two numbers -- stolen from Knuth Vol 2 pg 233
223 sub bmul { #(num_str, num_str) return num_str
224 local(*x, *y); ($x, $y) = (&bnorm($_[$[]), &bnorm($_[$[+1]));
227 } elsif ($y eq 'NaN') {
232 &external(&mul(*x,*y));
236 # multiply two numbers in internal representation
237 # destroys the arguments, supposes that two arguments are different
238 sub mul { #(*int_num_array, *int_num_array) return int_num_array
239 local(*x, *y) = (shift, shift);
240 local($signr) = (shift @x ne shift @y) ? '-' : '+';
243 ($car, $cty) = (0, $[);
245 $prod = $x * $y + ($prod[$cty] || 0) + $car;
248 $prod - ($car = int($prod * 1e-5)) * 1e5;
252 $prod - ($car = int($prod / 1e5)) * 1e5;
255 $prod[$cty] += $car if $car;
262 sub bmod { #(num_str, num_str) return num_str
266 sub bdiv { #(dividend: num_str, divisor: num_str) return num_str
267 local (*x, *y); ($x, $y) = (&bnorm($_[$[]), &bnorm($_[$[+1]));
268 return wantarray ? ('NaN','NaN') : 'NaN'
269 if ($x eq 'NaN' || $y eq 'NaN' || $y eq '+0');
270 return wantarray ? ('+0',$x) : '+0' if (&cmp(&abs($x),&abs($y)) < 0);
271 @x = &internal($x); @y = &internal($y);
273 $sr = (shift @x ne shift @y) ? '-' : '+';
274 $car = $bar = $prd = 0;
275 if (($dd = int(1e5/($y[$#y]+1))) != 1) {
277 $x = $x * $dd + $car;
279 $x -= ($car = int($x * 1e-5)) * 1e5;
282 $x -= ($car = int($x / 1e5)) * 1e5;
285 push(@x, $car); $car = 0;
287 $y = $y * $dd + $car;
289 $y -= ($car = int($y * 1e-5)) * 1e5;
292 $y -= ($car = int($y / 1e5)) * 1e5;
299 @q = (); ($v2,$v1) = @y[-2,-1];
302 ($u2,$u1,$u0) = @x[-3..-1];
304 $q = (($u0 == $v1) ? 99999 : int(($u0*1e5+$u1)/$v1));
305 --$q while ($v2*$q > ($u0*1e5+$u1-$q*$v1)*1e5+$u2);
307 ($car, $bar) = (0,0);
308 for ($y = $[, $x = $#x-$#y+$[-1; $y <= $#y; ++$y,++$x) {
309 $prd = $q * $y[$y] + $car;
311 $prd -= ($car = int($prd * 1e-5)) * 1e5;
314 $prd -= ($car = int($prd / 1e5)) * 1e5;
316 $x[$x] += 1e5 if ($bar = (($x[$x] -= $prd + $bar) < 0));
318 if ($x[$#x] < $car + $bar) {
320 for ($y = $[, $x = $#x-$#y+$[-1; $y <= $#y; ++$y,++$x) {
322 if ($car = (($x[$x] += $y[$y] + $car) > 1e5));
326 pop(@x); unshift(@q, $q);
332 for $x (reverse @x) {
333 $prd = $car * 1e5 + $x;
334 $car = $prd - ($tmp = int($prd / $dd)) * $dd;
341 (&external($sr, @q), &external($srem, @d, $zero));
347 # compute power of two numbers -- stolen from Knuth Vol 2 pg 233
348 sub bpow { #(num_str, num_str) return num_str
349 local(*x, *y); ($x, $y) = (&bnorm($_[$[]), &bnorm($_[$[+1]));
352 } elsif ($y eq 'NaN') {
354 } elsif ($x eq '+1') {
356 } elsif ($x eq '-1') {
357 &bmod($x,2) ? '-1': '+1';
358 } elsif ($y =~ /^-/) {
360 } elsif ($x eq '+0' && $y eq '+0') {
365 local(@pow)=&internal("+1");
366 local($y1,$res,@tmp1,@tmp2)=(1); # need tmp to send to mul
368 ($y,$res)=&bdiv($y,2);
369 if ($res ne '+0') {@tmp=@pow2; @pow=&mul(*pow,*tmp);}
370 if ($y ne '+0') {@tmp=@pow2;@pow2=&mul(*pow2,*tmp);}
376 # compute x << y, y >= 0
377 sub blsft { #(num_str, num_str) return num_str
378 &bmul($_[$[], &bpow(2, $_[$[+1]));
381 # compute x >> y, y >= 0
382 sub brsft { #(num_str, num_str) return num_str
383 &bdiv($_[$[], &bpow(2, $_[$[+1]));
387 sub band { #(num_str, num_str) return num_str
388 local($x,$y,$r,$m,$xr,$yr) = (&bnorm($_[$[]),&bnorm($_[$[+1]),0,1);
389 if ($x eq 'NaN' || $y eq 'NaN') {
392 while ($x ne '+0' && $y ne '+0') {
393 ($x, $xr) = &bdiv($x, 0x10000);
394 ($y, $yr) = &bdiv($y, 0x10000);
395 $r = &badd(&bmul(int $xr & $yr, $m), $r);
396 $m = &bmul($m, 0x10000);
403 sub bior { #(num_str, num_str) return num_str
404 local($x,$y,$r,$m,$xr,$yr) = (&bnorm($_[$[]),&bnorm($_[$[+1]),0,1);
405 if ($x eq 'NaN' || $y eq 'NaN') {
408 while ($x ne '+0' || $y ne '+0') {
409 ($x, $xr) = &bdiv($x, 0x10000);
410 ($y, $yr) = &bdiv($y, 0x10000);
411 $r = &badd(&bmul(int $xr | $yr, $m), $r);
412 $m = &bmul($m, 0x10000);
419 sub bxor { #(num_str, num_str) return num_str
420 local($x,$y,$r,$m,$xr,$yr) = (&bnorm($_[$[]),&bnorm($_[$[+1]),0,1);
421 if ($x eq 'NaN' || $y eq 'NaN') {
424 while ($x ne '+0' || $y ne '+0') {
425 ($x, $xr) = &bdiv($x, 0x10000);
426 ($y, $yr) = &bdiv($y, 0x10000);
427 $r = &badd(&bmul(int $xr ^ $yr, $m), $r);
428 $m = &bmul($m, 0x10000);
434 # represent ~x as twos-complement number
435 sub bnot { #(num_str) return num_str
444 Math::BigInt - Arbitrary size integer math package
449 $i = Math::BigInt->new($string);
451 $i->bneg return BINT negation
452 $i->babs return BINT absolute value
453 $i->bcmp(BINT) return CODE compare numbers (undef,<0,=0,>0)
454 $i->badd(BINT) return BINT addition
455 $i->bsub(BINT) return BINT subtraction
456 $i->bmul(BINT) return BINT multiplication
457 $i->bdiv(BINT) return (BINT,BINT) division (quo,rem) just quo if scalar
458 $i->bmod(BINT) return BINT modulus
459 $i->bgcd(BINT) return BINT greatest common divisor
460 $i->bnorm return BINT normalization
461 $i->blsft(BINT) return BINT left shift
462 $i->brsft(BINT) return (BINT,BINT) right shift (quo,rem) just quo if scalar
463 $i->band(BINT) return BINT bit-wise and
464 $i->bior(BINT) return BINT bit-wise inclusive or
465 $i->bxor(BINT) return BINT bit-wise exclusive or
466 $i->bnot return BINT bit-wise not
470 All basic math operations are overloaded if you declare your big
473 $i = new Math::BigInt '123 456 789 123 456 789';
478 =item Canonical notation
480 Big integer value are strings of the form C</^[+-]\d+$/> with leading
485 Input values to these routines may be strings of the form
486 C</^\s*[+-]?[\d\s]+$/>.
490 Output values always always in canonical form
494 Actual math is done in an internal format consisting of an array
495 whose first element is the sign (/^[+-]$/) and whose remaining
496 elements are base 100000 digits with the least significant digit first.
497 The string 'NaN' is used to represent the result when input arguments
498 are not numbers, as well as the result of dividing by zero.
502 '+0' canonical zero value
503 ' -123 123 123' canonical value '-123123123'
504 '1 23 456 7890' canonical value '+1234567890'
507 =head1 Autocreating constants
509 After C<use Math::BigInt ':constant'> all the integer decimal constants
510 in the given scope are converted to C<Math::BigInt>. This conversion
511 happens at compile time.
515 perl -MMath::BigInt=:constant -e 'print 2**100'
517 print the integer value of C<2**100>. Note that without conversion of
518 constants the expression 2**100 will be calculated as floating point number.
522 The current version of this module is a preliminary version of the
523 real thing that is currently (as of perl5.002) under development.
527 Mark Biggar, overloaded interface by Ilya Zakharevich.