summaryrefslogtreecommitdiff
path: root/lib/Math/BigFloat.pm
diff options
context:
space:
mode:
authorJarkko Hietaniemi <jhi@iki.fi>2001-04-06 13:54:52 +0000
committerJarkko Hietaniemi <jhi@iki.fi>2001-04-06 13:54:52 +0000
commit288d023a84099384e11cf3c2fe39903b18188b9d (patch)
tree507bbb0d8739231ed827ffdec4856369813e8d40 /lib/Math/BigFloat.pm
parent92dc35679cb164be847199993634f6d2cabffe53 (diff)
downloadperl-288d023a84099384e11cf3c2fe39903b18188b9d.tar.gz
Math::BigFloat patches from John Peacock. The equivalent
of #9586 from maintperl but reworked by John to work with the bleadperl. p4raw-id: //depot/perl@9590
Diffstat (limited to 'lib/Math/BigFloat.pm')
-rw-r--r--lib/Math/BigFloat.pm68
1 files changed, 49 insertions, 19 deletions
diff --git a/lib/Math/BigFloat.pm b/lib/Math/BigFloat.pm
index 4c520fdd49..ff8aea5adb 100644
--- a/lib/Math/BigFloat.pm
+++ b/lib/Math/BigFloat.pm
@@ -4,7 +4,7 @@ use Math::BigInt;
use Exporter; # just for use to be happy
@ISA = (Exporter);
-$VERSION = '0.01'; # never had version before
+$VERSION = '0.03';
use overload
'+' => sub {new Math::BigFloat &fadd},
@@ -13,9 +13,12 @@ use overload
'<=>' => sub {$_[2]? fcmp($_[1],${$_[0]}) : fcmp(${$_[0]},$_[1])},
'cmp' => sub {$_[2]? ($_[1] cmp ${$_[0]}) : (${$_[0]} cmp $_[1])},
'*' => sub {new Math::BigFloat &fmul},
-'/' => sub {new Math::BigFloat
+'/' => sub {new Math::BigFloat
$_[2]? scalar fdiv($_[1],${$_[0]}) :
scalar fdiv(${$_[0]},$_[1])},
+'%' => sub {new Math::BigFloat
+ $_[2]? scalar fmod($_[1],${$_[0]}) :
+ scalar fmod(${$_[0]},$_[1])},
'neg' => sub {new Math::BigFloat &fneg},
'abs' => sub {new Math::BigFloat &fabs},
'int' => sub {new Math::BigInt &f2int},
@@ -45,12 +48,15 @@ sub stringify {
my $e = $1;
my $ln = length($n);
- if ($e > 0) {
- $n .= "0" x $e . '.';
- } elsif (abs($e) < $ln) {
- substr($n, $ln + $e, 0) = '.';
- } else {
- $n = '.' . ("0" x (abs($e) - $ln)) . $n;
+ if ( defined $e )
+ {
+ if ($e > 0) {
+ $n .= "0" x $e . '.';
+ } elsif (abs($e) < $ln) {
+ substr($n, $ln + $e, 0) = '.';
+ } else {
+ $n = '.' . ("0" x (abs($e) - $ln)) . $n;
+ }
}
$n = "-$n" if $minus;
@@ -150,7 +156,7 @@ sub fadd { #(fnum_str, fnum_str) return fnum_str
# subtraction
sub fsub { #(fnum_str, fnum_str) return fnum_str
- fadd($_[$[],fneg($_[$[+1]));
+ fadd($_[$[],fneg($_[$[+1]));
}
# division
@@ -174,6 +180,27 @@ sub fdiv #(fnum_str, fnum_str[,scale]) return fnum_str
}
}
+# modular division
+# args are dividend, divisor
+sub fmod #(fnum_str, fnum_str) return fnum_str
+{
+ local($x,$y) = (fnorm($_[$[]),fnorm($_[$[+1]));
+ if ($x eq 'NaN' || $y eq 'NaN' || $y eq '+0E+0') {
+ 'NaN';
+ } else {
+ local($xm,$xe) = split('E',$x);
+ local($ym,$ye) = split('E',$y);
+ if ( $xe < $ye )
+ {
+ $ym .= ('0' x ($ye-$xe));
+ }
+ else
+ {
+ $xm .= ('0' x ($xe-$ye));
+ }
+ &norm(Math::BigInt::bmod($xm,$ym));
+ }
+}
# round int $q based on fraction $r/$base using $rnd_mode
sub round { #(int_str, int_str, int_str) return int_str
local($q,$r,$base) = @_;
@@ -188,9 +215,9 @@ sub round { #(int_str, int_str, int_str) return int_str
($rnd_mode eq 'zero' ) ||
($rnd_mode eq '-inf' && (substr($q,$[,1) eq '+')) ||
($rnd_mode eq '+inf' && (substr($q,$[,1) eq '-')) ||
- ($rnd_mode eq 'even' && $q =~ /[13579]$/ ) ||
- ($rnd_mode eq 'odd' && $q =~ /[24680]$/ ) )
- )
+ ($rnd_mode eq 'even' && $q =~ /[24680]$/ ) ||
+ ($rnd_mode eq 'odd' && $q =~ /[13579]$/ ) )
+ )
) {
$q; # round down
} else {
@@ -210,8 +237,8 @@ sub fround { #(fnum_str, scale) return fnum_str
if (length($xm)-1 <= $scale) {
$x;
} else {
- &norm(&round(substr($xm,$[,$scale+1),
- "+0".substr($xm,$[+$scale+1,1),"+10"),
+ &norm(&round(substr($xm,$[,$scale+1),
+ "+0".substr($xm,$[+$scale+1),"+1"."0" x length(substr($xm,$[+$scale+1))),
$xe+length($xm)-$scale-1);
}
}
@@ -235,10 +262,12 @@ sub ffround { #(fnum_str, scale) return fnum_str
# normalized "-0" to &round when rounding -0.006 (for
# example), purely so &round won't lose the sign.
&norm(&round(substr($xm,$[,1).'0',
- "+0".substr($xm,$[+1,1),"+10"), $scale);
+ "+0".substr($xm,$[+1),
+ "+1"."0" x length(substr($xm,$[+1))), $scale);
} else {
&norm(&round(substr($xm,$[,$xe),
- "+0".substr($xm,$[+$xe,1),"+10"), $scale);
+ "+0".substr($xm,$[+$xe),
+ "+1"."0" x length(substr($xm,$[+$xe))), $scale);
}
}
}
@@ -263,7 +292,7 @@ sub f2int { #(fnum_str) return inum_str
}
}
}
-
+
# compare 2 values returns one of undef, <0, =0, >0
# returns undef if either or both input value are not numbers
sub fcmp #(fnum_str, fnum_str) return cond_code
@@ -326,6 +355,7 @@ Math::BigFloat - Arbitrary length float math package
$f->fsub(NSTR) return NSTR subtraction
$f->fmul(NSTR) return NSTR multiplication
$f->fdiv(NSTR[,SCALE]) returns NSTR division to SCALE places
+ $f->fmod(NSTR) returns NSTR modular remainder
$f->fneg() return NSTR negation
$f->fabs() return NSTR absolute value
$f->fcmp(NSTR) return CODE compare undef,<0,=0,>0
@@ -353,7 +383,7 @@ have embedded whitespace.
An input parameter was "Not a Number" or divide by zero or sqrt of
negative number.
-=item Division is computed to
+=item Division is computed to
C<max($Math::BigFloat::div_scale,length(dividend)+length(divisor))>
digits by default.
@@ -392,5 +422,5 @@ as follows:
=head1 AUTHOR
Mark Biggar
-
+Patches by John Peacock Apr 2001
=cut