5 '+' => sub {new Math
::BigInt
&badd
},
6 '-' => sub {new Math
::BigInt
7 $_[2]? bsub
($_[1],${$_[0]}) : bsub
(${$_[0]},$_[1])},
8 '<=>' => sub {$_[2]? bcmp
($_[1],${$_[0]}) : bcmp
(${$_[0]},$_[1])},
9 'cmp' => sub {$_[2]?
($_[1] cmp ${$_[0]}) : (${$_[0]} cmp $_[1])},
10 '*' => sub {new Math
::BigInt
&bmul
},
11 '/' => sub {new Math
::BigInt
12 $_[2]?
scalar bdiv
($_[1],${$_[0]}) :
13 scalar bdiv
(${$_[0]},$_[1])},
14 '%' => sub {new Math
::BigInt
15 $_[2]? bmod
($_[1],${$_[0]}) : bmod
(${$_[0]},$_[1])},
16 '**' => sub {new Math
::BigInt
17 $_[2]? bpow
($_[1],${$_[0]}) : bpow
(${$_[0]},$_[1])},
18 'neg' => sub {new Math
::BigInt
&bneg
},
19 'abs' => sub {new Math
::BigInt
&babs
},
20 '<<' => sub {new Math
::BigInt
21 $_[2]? blsft
($_[1],${$_[0]}) : blsft
(${$_[0]},$_[1])},
22 '>>' => sub {new Math
::BigInt
23 $_[2]? brsft
($_[1],${$_[0]}) : brsft
(${$_[0]},$_[1])},
24 '&' => sub {new Math
::BigInt
&band
},
25 '|' => sub {new Math
::BigInt
&bior
},
26 '^' => sub {new Math
::BigInt
&bxor
},
27 '~' => sub {new Math
::BigInt
&bnot
},
31 0+ numify) # Order of arguments unsignificant
38 my($foo) = bnorm
(shift);
39 die "Not a number initialized to Math::BigInt" if !$NaNOK && $foo eq "NaN";
42 sub stringify
{ "${$_[0]}" }
43 sub numify
{ 0 + "${$_[0]}" } # Not needed, additional overhead
44 # comparing to direct compilation based on
49 die "unknown import: @_" unless @_ == 1 and $_[0] eq ':constant';
50 overload
::constant integer
=> sub {Math
::BigInt
->new(shift)};
55 # overcome a floating point problem on certain osnames (posix-bc, os390)
58 my $use_mult = int($x*1e-5)*1e5
== $x ?
1 : 0;
61 # normalize string form of number. Strip leading zeros. Strip any
62 # white space and add a sign, if missing.
63 # Strings that are not numbers result the value 'NaN'.
65 sub bnorm
{ #(num_str) return num_str
67 s/\s+//g; # strip white space
68 if (s/^([+-]?)0*(\d+)$/$1$2/) { # test if number
69 substr($_,$[,0) = '+' unless $1; # Add missing sign
77 # Convert a number from string format to internal base 100000 format.
78 # Assumes normalized value as input.
79 sub internal
{ #(num_str) return int_num_array
81 ($is,$il) = (substr($d,$[,1),length($d)-2);
83 ($is, reverse(unpack("a" . ($il%5+1) . ("a5" x
($il/5)), $d)));
86 # Convert a number from internal base 100000 format to string format.
87 # This routine scribbles all over input array.
88 sub external
{ #(int_num_array) return num_str
90 grep($_ > 9999 || ($_ = substr('0000'.$_,-5)), @_); # zero pad
91 &bnorm
(join('', $es, reverse(@_))); # reverse concat and normalize
95 sub bneg
{ #(num_str) return num_str
96 local($_) = &bnorm
(@_);
97 return $_ if $_ eq '+0' or $_ eq 'NaN';
98 vec($_,0,8) ^= ord('+') ^ ord('-');
102 # Returns the absolute value of the input.
103 sub babs
{ #(num_str) return num_str
107 sub abs { # post-normalized abs for internal use
113 # Compares 2 values. Returns one of undef, <0, =0, >0. (suitable for sort)
114 sub bcmp
{ #(num_str, num_str) return cond_code
115 local($x,$y) = (&bnorm
($_[$[]),&bnorm
($_[$[+1]));
118 } elsif ($y eq 'NaN') {
125 sub cmp { # post-normalized compare for internal use
126 local($cx, $cy) = @_;
128 return 0 if ($cx eq $cy);
130 local($sx, $sy) = (substr($cx, 0, 1), substr($cy, 0, 1));
134 return 1 if ($sy eq '-' || $cy eq '+0');
135 $ld = length($cx) - length($cy);
138 } else { # $sx eq '-'
139 return -1 if ($sy eq '+');
140 $ld = length($cy) - length($cx);
146 sub badd
{ #(num_str, num_str) return num_str
147 local(*x
, *y
); ($x, $y) = (&bnorm
($_[$[]),&bnorm
($_[$[+1]));
150 } elsif ($y eq 'NaN') {
153 @x = &internal
($x); # convert to internal form
155 local($sx, $sy) = (shift @x, shift @y); # get signs
157 &external
($sx, &add
(*x
, *y
)); # if same sign add
159 ($x, $y) = (&abs($x),&abs($y)); # make abs
160 if (&cmp($y,$x) > 0) {
161 &external
($sy, &sub(*y
, *x
));
163 &external
($sx, &sub(*x
, *y
));
169 sub bsub
{ #(num_str, num_str) return num_str
170 &badd
($_[$[],&bneg
($_[$[+1]));
173 # GCD -- Euclids algorithm Knuth Vol 2 pg 296
174 sub bgcd
{ #(num_str, num_str) return num_str
175 local($x,$y) = (&bnorm
($_[$[]),&bnorm
($_[$[+1]));
176 if ($x eq 'NaN' || $y eq 'NaN') {
179 ($x, $y) = ($y,&bmod
($x,$y)) while $y ne '+0';
184 # routine to add two base 1e5 numbers
185 # stolen from Knuth Vol 2 Algorithm A pg 231
186 # there are separate routines to add and sub as per Kunth pg 233
187 sub add
{ #(int_num_array, int_num_array) return int_num_array
191 last unless @y || $car;
192 $x -= 1e5
if $car = (($x += (@y ?
shift(@y) : 0) + $car) >= 1e5
) ?
1 : 0;
196 $y -= 1e5
if $car = (($y += $car) >= 1e5
) ?
1 : 0;
201 # subtract base 1e5 numbers -- stolen from Knuth Vol 2 pg 232, $x > $y
202 sub sub { #(int_num_array, int_num_array) return int_num_array
203 local(*sx
, *sy
) = @_;
206 last unless @sy || $bar;
207 $sx += 1e5
if $bar = (($sx -= (@sy ?
shift(@sy) : 0) + $bar) < 0);
212 # multiply two numbers -- stolen from Knuth Vol 2 pg 233
213 sub bmul
{ #(num_str, num_str) return num_str
214 local(*x
, *y
); ($x, $y) = (&bnorm
($_[$[]), &bnorm
($_[$[+1]));
217 } elsif ($y eq 'NaN') {
222 &external
(&mul
(*x
,*y
));
226 # multiply two numbers in internal representation
227 # destroys the arguments, supposes that two arguments are different
228 sub mul
{ #(*int_num_array, *int_num_array) return int_num_array
229 local(*x
, *y
) = (shift, shift);
230 local($signr) = (shift @x ne shift @y) ?
'-' : '+';
233 ($car, $cty) = (0, $[);
235 $prod = $x * $y + ($prod[$cty] || 0) + $car;
238 $prod - ($car = int($prod * 1e-5)) * 1e5
;
242 $prod - ($car = int($prod / 1e5
)) * 1e5
;
245 $prod[$cty] += $car if $car;
252 sub bmod
{ #(num_str, num_str) return num_str
256 sub bdiv
{ #(dividend: num_str, divisor: num_str) return num_str
257 local (*x
, *y
); ($x, $y) = (&bnorm
($_[$[]), &bnorm
($_[$[+1]));
258 return wantarray ?
('NaN','NaN') : 'NaN'
259 if ($x eq 'NaN' || $y eq 'NaN' || $y eq '+0');
260 return wantarray ?
('+0',$x) : '+0' if (&cmp(&abs($x),&abs($y)) < 0);
261 @x = &internal
($x); @y = &internal
($y);
263 $sr = (shift @x ne shift @y) ?
'-' : '+';
264 $car = $bar = $prd = 0;
265 if (($dd = int(1e5
/($y[$#y]+1))) != 1) {
267 $x = $x * $dd + $car;
269 $x -= ($car = int($x * 1e-5)) * 1e5
;
272 $x -= ($car = int($x / 1e5
)) * 1e5
;
275 push(@x, $car); $car = 0;
277 $y = $y * $dd + $car;
279 $y -= ($car = int($y * 1e-5)) * 1e5
;
282 $y -= ($car = int($y / 1e5
)) * 1e5
;
289 @q = (); ($v2,$v1) = @y[-2,-1];
292 ($u2,$u1,$u0) = @x[-3..-1];
294 $q = (($u0 == $v1) ?
99999 : int(($u0*1e5
+$u1)/$v1));
295 --$q while ($v2*$q > ($u0*1e5
+$u1-$q*$v1)*1e5
+$u2);
297 ($car, $bar) = (0,0);
298 for ($y = $[, $x = $#x-$#y+$[-1; $y <= $#y; ++$y,++$x) {
299 $prd = $q * $y[$y] + $car;
301 $prd -= ($car = int($prd * 1e-5)) * 1e5
;
304 $prd -= ($car = int($prd / 1e5
)) * 1e5
;
306 $x[$x] += 1e5
if ($bar = (($x[$x] -= $prd + $bar) < 0));
308 if ($x[$#x] < $car + $bar) {
310 for ($y = $[, $x = $#x-$#y+$[-1; $y <= $#y; ++$y,++$x) {
312 if ($car = (($x[$x] += $y[$y] + $car) > 1e5
));
316 pop(@x); unshift(@q, $q);
322 for $x (reverse @x) {
323 $prd = $car * 1e5
+ $x;
324 $car = $prd - ($tmp = int($prd / $dd)) * $dd;
331 (&external
($sr, @q), &external
($srem, @d, $zero));
337 # compute power of two numbers -- stolen from Knuth Vol 2 pg 233
338 sub bpow
{ #(num_str, num_str) return num_str
339 local(*x
, *y
); ($x, $y) = (&bnorm
($_[$[]), &bnorm
($_[$[+1]));
342 } elsif ($y eq 'NaN') {
344 } elsif ($x eq '+1') {
346 } elsif ($x eq '-1') {
347 &bmod
($x,2) ?
'-1': '+1';
348 } elsif ($y =~ /^-/) {
350 } elsif ($x eq '+0' && $y eq '+0') {
355 local(@pow)=&internal
("+1");
356 local($y1,$res,@tmp1,@tmp2)=(1); # need tmp to send to mul
358 ($y,$res)=&bdiv
($y,2);
359 if ($res ne '+0') {@tmp=@pow2; @pow=&mul
(*pow
,*tmp
);}
360 if ($y ne '+0') {@tmp=@pow2;@pow2=&mul
(*pow2
,*tmp
);}
366 # compute x << y, y >= 0
367 sub blsft
{ #(num_str, num_str) return num_str
368 &bmul
($_[$[], &bpow
(2, $_[$[+1]));
371 # compute x >> y, y >= 0
372 sub brsft
{ #(num_str, num_str) return num_str
373 &bdiv
($_[$[], &bpow
(2, $_[$[+1]));
377 sub band
{ #(num_str, num_str) return num_str
378 local($x,$y,$r,$m,$xr,$yr) = (&bnorm
($_[$[]),&bnorm
($_[$[+1]),0,1);
379 if ($x eq 'NaN' || $y eq 'NaN') {
382 while ($x ne '+0' && $y ne '+0') {
383 ($x, $xr) = &bdiv
($x, 0x10000);
384 ($y, $yr) = &bdiv
($y, 0x10000);
385 $r = &badd
(&bmul
(int $xr & $yr, $m), $r);
386 $m = &bmul
($m, 0x10000);
393 sub bior
{ #(num_str, num_str) return num_str
394 local($x,$y,$r,$m,$xr,$yr) = (&bnorm
($_[$[]),&bnorm
($_[$[+1]),0,1);
395 if ($x eq 'NaN' || $y eq 'NaN') {
398 while ($x ne '+0' || $y ne '+0') {
399 ($x, $xr) = &bdiv
($x, 0x10000);
400 ($y, $yr) = &bdiv
($y, 0x10000);
401 $r = &badd
(&bmul
(int $xr | $yr, $m), $r);
402 $m = &bmul
($m, 0x10000);
409 sub bxor
{ #(num_str, num_str) return num_str
410 local($x,$y,$r,$m,$xr,$yr) = (&bnorm
($_[$[]),&bnorm
($_[$[+1]),0,1);
411 if ($x eq 'NaN' || $y eq 'NaN') {
414 while ($x ne '+0' || $y ne '+0') {
415 ($x, $xr) = &bdiv
($x, 0x10000);
416 ($y, $yr) = &bdiv
($y, 0x10000);
417 $r = &badd
(&bmul
(int $xr ^ $yr, $m), $r);
418 $m = &bmul
($m, 0x10000);
424 # represent ~x as twos-complement number
425 sub bnot
{ #(num_str) return num_str
434 Math::BigInt - Arbitrary size integer math package
439 $i = Math::BigInt->new($string);
441 $i->bneg return BINT negation
442 $i->babs return BINT absolute value
443 $i->bcmp(BINT) return CODE compare numbers (undef,<0,=0,>0)
444 $i->badd(BINT) return BINT addition
445 $i->bsub(BINT) return BINT subtraction
446 $i->bmul(BINT) return BINT multiplication
447 $i->bdiv(BINT) return (BINT,BINT) division (quo,rem) just quo if scalar
448 $i->bmod(BINT) return BINT modulus
449 $i->bgcd(BINT) return BINT greatest common divisor
450 $i->bnorm return BINT normalization
451 $i->blsft(BINT) return BINT left shift
452 $i->brsft(BINT) return (BINT,BINT) right shift (quo,rem) just quo if scalar
453 $i->band(BINT) return BINT bit-wise and
454 $i->bior(BINT) return BINT bit-wise inclusive or
455 $i->bxor(BINT) return BINT bit-wise exclusive or
456 $i->bnot return BINT bit-wise not
460 All basic math operations are overloaded if you declare your big
463 $i = new Math::BigInt '123 456 789 123 456 789';
468 =item Canonical notation
470 Big integer value are strings of the form C</^[+-]\d+$/> with leading
475 Input values to these routines may be strings of the form
476 C</^\s*[+-]?[\d\s]+$/>.
480 Output values always always in canonical form
484 Actual math is done in an internal format consisting of an array
485 whose first element is the sign (/^[+-]$/) and whose remaining
486 elements are base 100000 digits with the least significant digit first.
487 The string 'NaN' is used to represent the result when input arguments
488 are not numbers, as well as the result of dividing by zero.
492 '+0' canonical zero value
493 ' -123 123 123' canonical value '-123123123'
494 '1 23 456 7890' canonical value '+1234567890'
497 =head1 Autocreating constants
499 After C<use Math::BigInt ':constant'> all the integer decimal constants
500 in the given scope are converted to C<Math::BigInt>. This conversion
501 happens at compile time.
505 perl -MMath::BigInt=:constant -e 'print 2**100'
507 print the integer value of C<2**100>. Note that without conversion of
508 constants the expression 2**100 will be calculated as floating point number.
512 The current version of this module is a preliminary version of the
513 real thing that is currently (as of perl5.002) under development.
517 Mark Biggar, overloaded interface by Ilya Zakharevich.