diff options
author | William Mann <wmann@avici.com> | 1999-04-12 08:25:22 -0400 |
---|---|---|
committer | Gurusamy Sarathy <gsar@cpan.org> | 1999-05-08 16:46:44 +0000 |
commit | e16b8f4913aae827d19b2f53293805a3a74f33c6 (patch) | |
tree | 2d5bab52feb1356f6128dcff673173e3a170ca89 /lib/Math | |
parent | e8827f643862721daef784554b14d7800b59dd07 (diff) | |
download | perl-e16b8f4913aae827d19b2f53293805a3a74f33c6.tar.gz |
applied suggested patch, added tests
Message-Id: <199904121625.MAA00983@hwsrv1.avici.com>
Subject: BigInt.pm extensions for logical operations
p4raw-id: //depot/perl@3332
Diffstat (limited to 'lib/Math')
-rw-r--r-- | lib/Math/BigInt.pm | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/lib/Math/BigInt.pm b/lib/Math/BigInt.pm index 16ebb1d5dd..a43969c2b2 100644 --- a/lib/Math/BigInt.pm +++ b/lib/Math/BigInt.pm @@ -16,6 +16,14 @@ use overload $_[2]? bpow($_[1],${$_[0]}) : bpow(${$_[0]},$_[1])}, 'neg' => sub {new Math::BigInt &bneg}, 'abs' => sub {new Math::BigInt &babs}, +'<<' => sub {new Math::BigInt + $_[2]? blsft($_[1],${$_[0]}) : blsft(${$_[0]},$_[1])}, +'>>' => sub {new Math::BigInt + $_[2]? brsft($_[1],${$_[0]}) : brsft(${$_[0]},$_[1])}, +'&' => sub {new Math::BigInt &band}, +'|' => sub {new Math::BigInt &bior}, +'^' => sub {new Math::BigInt &bxor}, +'~' => sub {new Math::BigInt &bnot}, qw( "" stringify @@ -328,6 +336,69 @@ sub bpow { #(num_str, num_str) return num_str } } +# compute x << y, y >= 0 +sub blsft { #(num_str, num_str) return num_str + &bmul($_[$[], &bpow(2, $_[$[+1])); +} + +# compute x >> y, y >= 0 +sub brsft { #(num_str, num_str) return num_str + &bdiv($_[$[], &bpow(2, $_[$[+1])); +} + +# compute x & y +sub band { #(num_str, num_str) return num_str + local($x,$y,$r,$m,$xr,$yr) = (&bnorm($_[$[]),&bnorm($_[$[+1]),0,1); + if ($x eq 'NaN' || $y eq 'NaN') { + 'NaN'; + } else { + while ($x ne '+0' && $y ne '+0') { + ($x, $xr) = &bdiv($x, 0x10000); + ($y, $yr) = &bdiv($y, 0x10000); + $r = &badd(&bmul(int $xr & $yr, $m), $r); + $m = &bmul($m, 0x10000); + } + $r; + } +} + +# compute x | y +sub bior { #(num_str, num_str) return num_str + local($x,$y,$r,$m,$xr,$yr) = (&bnorm($_[$[]),&bnorm($_[$[+1]),0,1); + if ($x eq 'NaN' || $y eq 'NaN') { + 'NaN'; + } else { + while ($x ne '+0' || $y ne '+0') { + ($x, $xr) = &bdiv($x, 0x10000); + ($y, $yr) = &bdiv($y, 0x10000); + $r = &badd(&bmul(int $xr | $yr, $m), $r); + $m = &bmul($m, 0x10000); + } + $r; + } +} + +# compute x ^ y +sub bxor { #(num_str, num_str) return num_str + local($x,$y,$r,$m,$xr,$yr) = (&bnorm($_[$[]),&bnorm($_[$[+1]),0,1); + if ($x eq 'NaN' || $y eq 'NaN') { + 'NaN'; + } else { + while ($x ne '+0' || $y ne '+0') { + ($x, $xr) = &bdiv($x, 0x10000); + ($y, $yr) = &bdiv($y, 0x10000); + $r = &badd(&bmul(int $xr ^ $yr, $m), $r); + $m = &bmul($m, 0x10000); + } + $r; + } +} + +# represent ~x as twos-complement number +sub bnot { #(num_str) return num_str + &bsub(-1,$_[$[]); +} + 1; __END__ @@ -350,6 +421,12 @@ Math::BigInt - Arbitrary size integer math package $i->bmod(BINT) return BINT modulus $i->bgcd(BINT) return BINT greatest common divisor $i->bnorm return BINT normalization + $i->blsft(BINT) return BINT left shift + $i->brsft(BINT) return (BINT,BINT) right shift (quo,rem) just quo if scalar + $i->band(BINT) return BINT bit-wise and + $i->bior(BINT) return BINT bit-wise inclusive or + $i->bxor(BINT) return BINT bit-wise exclusive or + $i->bnot return BINT bit-wise not =head1 DESCRIPTION |