summaryrefslogtreecommitdiffstats
path: root/contrib/perl5/lib/Math/BigFloat.pm
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/perl5/lib/Math/BigFloat.pm')
-rw-r--r--contrib/perl5/lib/Math/BigFloat.pm57
1 files changed, 43 insertions, 14 deletions
diff --git a/contrib/perl5/lib/Math/BigFloat.pm b/contrib/perl5/lib/Math/BigFloat.pm
index 03bc2f4..d8d643c 100644
--- a/contrib/perl5/lib/Math/BigFloat.pm
+++ b/contrib/perl5/lib/Math/BigFloat.pm
@@ -9,10 +9,8 @@ use overload
'+' => sub {new Math::BigFloat &fadd},
'-' => sub {new Math::BigFloat
$_[2]? fsub($_[1],${$_[0]}) : fsub(${$_[0]},$_[1])},
-'<=>' => sub {new Math::BigFloat
- $_[2]? fcmp($_[1],${$_[0]}) : fcmp(${$_[0]},$_[1])},
-'cmp' => sub {new Math::BigFloat
- $_[2]? ($_[1] cmp ${$_[0]}) : (${$_[0]} cmp $_[1])},
+'<=>' => 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
$_[2]? scalar fdiv($_[1],${$_[0]}) :
@@ -28,9 +26,9 @@ qw(
sub new {
my ($class) = shift;
my ($foo) = fnorm(shift);
- panic("Not a number initialized to Math::BigFloat") if $foo eq "NaN";
bless \$foo, $class;
}
+
sub numify { 0 + "${$_[0]}" } # Not needed, additional overhead
# comparing to direct compilation based on
# stringify
@@ -76,6 +74,7 @@ sub fnorm; sub fsqrt;
sub fnorm { #(string) return fnum_str
local($_) = @_;
s/\s+//g; # strip white space
+ no warnings; # $4 and $5 below might legitimately be undefined
if (/^([+-]?)(\d*)(\.(\d*))?([Ee]([+-]?\d+))?$/ && "$2$4" ne '') {
&norm(($1 ? "$1$2$4" : "+$2$4"),(($4 ne '') ? $6-length($4) : $6));
} else {
@@ -159,7 +158,8 @@ sub fdiv #(fnum_str, fnum_str[,scale]) return fnum_str
$scale = length($xm)-1 if (length($xm)-1 > $scale);
$scale = length($ym)-1 if (length($ym)-1 > $scale);
$scale = $scale + length($ym) - length($xm);
- &norm(&round(Math::BigInt::bdiv($xm.('0' x $scale),$ym),$ym),
+ &norm(&round(Math::BigInt::bdiv($xm.('0' x $scale),$ym),
+ Math::BigInt::babs($ym)),
$xe-$ye-$scale);
}
}
@@ -219,7 +219,11 @@ sub ffround { #(fnum_str, scale) return fnum_str
if ($xe < 1) {
'+0E+0';
} elsif ($xe == 1) {
- &norm(&round('+0',"+0".substr($xm,$[+1,1),"+10"), $scale);
+ # The first substr preserves the sign, passing a non-
+ # 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);
} else {
&norm(&round(substr($xm,$[,$xe),
"+0".substr($xm,$[+$xe,1),"+10"), $scale);
@@ -236,12 +240,13 @@ sub fcmp #(fnum_str, fnum_str) return cond_code
if ($x eq "NaN" || $y eq "NaN") {
undef;
} else {
+ local($xm,$xe,$ym,$ye) = split('E', $x."E$y");
+ if ($xm eq '+0' || $ym eq '+0') {
+ return $xm <=> $ym;
+ }
ord($y) <=> ord($x)
- ||
- ( local($xm,$xe,$ym,$ye) = split('E', $x."E$y"),
- (($xe <=> $ye) * (substr($x,$[,1).'1')
- || Math::BigInt::cmp($xm,$ym))
- );
+ || ($xe <=> $ye) * (substr($x,$[,1).'1')
+ || Math::BigInt::cmp($xm,$ym);
}
}
@@ -301,7 +306,7 @@ floats as
=item number format
canonical strings have the form /[+-]\d+E[+-]\d+/ . Input values can
-have imbedded whitespace.
+have embedded whitespace.
=item Error returns 'NaN'
@@ -310,9 +315,24 @@ negative number.
=item Division is computed to
-C<max($div_scale,length(dividend)+length(divisor))> digits by default.
+C<max($Math::BigFloat::div_scale,length(dividend)+length(divisor))>
+digits by default.
Also used for default sqrt scale.
+=item Rounding is performed
+
+according to the value of
+C<$Math::BigFloat::rnd_mode>:
+
+ trunc truncate the value
+ zero round towards 0
+ +inf round towards +infinity (round up)
+ -inf round towards -infinity (round down)
+ even round to the nearest, .5 to the even digit
+ odd round to the nearest, .5 to the odd digit
+
+The default is C<even> rounding.
+
=back
=head1 BUGS
@@ -320,6 +340,15 @@ Also used for default sqrt scale.
The current version of this module is a preliminary version of the
real thing that is currently (as of perl5.002) under development.
+The printf subroutine does not use the value of
+C<$Math::BigFloat::rnd_mode> when rounding values for printing.
+Consequently, the way to print rounded values is
+to specify the number of digits both as an
+argument to C<ffround> and in the C<%f> printf string,
+as follows:
+
+ printf "%.3f\n", $bigfloat->ffround(-3);
+
=head1 AUTHOR
Mark Biggar
OpenPOWER on IntegriCloud