package bigint;
-
+#
+# This library is no longer being maintained, and is included for backward
+# compatibility with Perl 4 programs which may require it.
+#
+# In particular, this should not be used as an example of modern Perl
+# programming techniques.
+#
+# Suggested alternative: Math::BigInt
+#
# arbitrary size integer math package
#
# by Mark Biggar
# bgcd(BINT,BINT) return BINT greatest common divisor
# bnorm(BINT) return BINT normalization
#
+
+# overcome a floating point problem on certain osnames (posix-bc, os390)
+BEGIN {
+ my $x = 100000.0;
+ my $use_mult = int($x*1e-5)*1e5 == $x ? 1 : 0;
+}
+
+$zero = 0;
+
\f
# normalize string form of number. Strip leading zeros. Strip any
# white space and add a sign, if missing.
# Strings that are not numbers result the value 'NaN'.
+
sub main'bnorm { #(num_str) return num_str
local($_) = @_;
s/\s+//g; # strip white space
sub main'bneg { #(num_str) return num_str
local($_) = &'bnorm(@_);
vec($_,0,8) ^= ord('+') ^ ord('-') unless $_ eq '+0';
- s/^H/N/;
+ s/^./N/ unless /^[-+]/; # works both in ASCII and EBCDIC
$_;
}
sub cmp { # post-normalized compare for internal use
local($cx, $cy) = @_;
- $cx cmp $cy
- &&
- (
- ord($cy) <=> ord($cx)
- ||
- ($cx cmp ',') * (length($cy) <=> length($cx) || $cy cmp $cx)
- );
+ return 0 if ($cx eq $cy);
+
+ local($sx, $sy) = (substr($cx, 0, 1), substr($cy, 0, 1));
+ local($ld);
+
+ if ($sx eq '+') {
+ return 1 if ($sy eq '-' || $cy eq '+0');
+ $ld = length($cx) - length($cy);
+ return $ld if ($ld);
+ return $cx cmp $cy;
+ } else { # $sx eq '-'
+ return -1 if ($sy eq '+');
+ $ld = length($cy) - length($cx);
+ return $ld if ($ld);
+ return $cy cmp $cx;
+ }
+
}
sub main'badd { #(num_str, num_str) return num_str
$car = 0;
for $x (@x) {
last unless @y || $car;
- $x -= 1e5 if $car = (($x += shift(@y) + $car) >= 1e5);
+ $x -= 1e5 if $car = (($x += shift(@y) + $car) >= 1e5) ? 1 : 0;
}
for $y (@y) {
last unless $car;
- $y -= 1e5 if $car = (($y += $car) >= 1e5);
+ $y -= 1e5 if $car = (($y += $car) >= 1e5) ? 1 : 0;
}
(@x, @y, $car);
}
($car, $cty) = (0, $[);
for $y (@y) {
$prod = $x * $y + $prod[$cty] + $car;
- $prod[$cty++] =
- $prod - ($car = int($prod * 1e-5)) * 1e5;
+ if ($use_mult) {
+ $prod[$cty++] =
+ $prod - ($car = int($prod * 1e-5)) * 1e5;
+ }
+ else {
+ $prod[$cty++] =
+ $prod - ($car = int($prod / 1e5)) * 1e5;
+ }
}
$prod[$cty] += $car if $car;
$x = shift @prod;
if (($dd = int(1e5/($y[$#y]+1))) != 1) {
for $x (@x) {
$x = $x * $dd + $car;
+ if ($use_mult) {
$x -= ($car = int($x * 1e-5)) * 1e5;
+ }
+ else {
+ $x -= ($car = int($x / 1e5)) * 1e5;
+ }
}
push(@x, $car); $car = 0;
for $y (@y) {
$y = $y * $dd + $car;
+ if ($use_mult) {
$y -= ($car = int($y * 1e-5)) * 1e5;
+ }
+ else {
+ $y -= ($car = int($y / 1e5)) * 1e5;
+ }
}
}
else {
($car, $bar) = (0,0);
for ($y = $[, $x = $#x-$#y+$[-1; $y <= $#y; ++$y,++$x) {
$prd = $q * $y[$y] + $car;
+ if ($use_mult) {
$prd -= ($car = int($prd * 1e-5)) * 1e5;
+ }
+ else {
+ $prd -= ($car = int($prd / 1e5)) * 1e5;
+ }
$x[$x] += 1e5 if ($bar = (($x[$x] -= $prd + $bar) < 0));
}
if ($x[$#x] < $car + $bar) {
else {
@d = @x;
}
- (&external($sr, @q), &external($srem, @d, 0));
+ (&external($sr, @q), &external($srem, @d, $zero));
} else {
&external($sr, @q);
}