summaryrefslogtreecommitdiff
path: root/systems/texlive/tlnet/tlpkg/tlperl/lib/Math/BigFloat.pm
diff options
context:
space:
mode:
Diffstat (limited to 'systems/texlive/tlnet/tlpkg/tlperl/lib/Math/BigFloat.pm')
-rw-r--r--systems/texlive/tlnet/tlpkg/tlperl/lib/Math/BigFloat.pm823
1 files changed, 449 insertions, 374 deletions
diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Math/BigFloat.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Math/BigFloat.pm
index b716b88a34..8a92b5818d 100644
--- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Math/BigFloat.pm
+++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Math/BigFloat.pm
@@ -6,9 +6,9 @@ package Math::BigFloat;
# The following hash values are used internally:
# sign : "+", "-", "+inf", "-inf", or "NaN" if not a number
-# _m : mantissa ($CALC object)
+# _m : mantissa ($LIB thingy)
# _es : sign of _e
-# _e : exponent ($CALC object)
+# _e : exponent ($LIB thingy)
# _a : accuracy
# _p : precision
@@ -16,12 +16,11 @@ use 5.006001;
use strict;
use warnings;
-use Carp ();
+use Carp qw< carp croak >;
use Math::BigInt ();
-our $VERSION = '1.999811';
+our $VERSION = '1.999816';
-require Exporter;
our @ISA = qw/Math::BigInt/;
our @EXPORT_OK = qw/bpi/;
@@ -72,7 +71,6 @@ use overload
'**=' => sub { $_[0]->bpow($_[1]); },
-
'<<=' => sub { $_[0]->blsft($_[1]); },
'>>=' => sub { $_[0]->brsft($_[1]); },
@@ -218,7 +216,7 @@ $upgrade = undef;
$downgrade = undef;
# the package we are using for our private parts, defaults to:
# Math::BigInt->config('lib')
-my $MBI = 'Math::BigInt::Calc';
+my $LIB = 'Math::BigInt::Calc';
# are NaNs ok? (otherwise it dies when encountering an NaN) set w/ config()
$_trap_nan = 0;
@@ -281,11 +279,11 @@ sub AUTOLOAD {
if (!_method_alias($name)) {
if (!defined $name) {
# delayed load of Carp and avoid recursion
- Carp::croak("$c: Can't call a method without name");
+ croak("$c: Can't call a method without name");
}
if (!_method_hand_up($name)) {
# delayed load of Carp and avoid recursion
- Carp::croak("Can't call $c\-\>$name, not a valid method");
+ croak("Can't call $c\-\>$name, not a valid method");
}
# try one level up, but subst. bxxx() for fxxx() since MBI only got bxxx()
$name =~ s/^f/b/;
@@ -320,8 +318,6 @@ sub AUTOLOAD {
sub _method_hand_up { exists $hand_ups{$_[0]||''}; }
}
-sub DEBUG () { 0; }
-
sub isa {
my ($self, $class) = @_;
return if $class =~ /^Math::BigInt/; # we aren't one of these
@@ -332,16 +328,22 @@ sub config {
# return (later set?) configuration data as hash ref
my $class = shift || 'Math::BigFloat';
+ # Getter/accessor.
+
if (@_ == 1 && ref($_[0]) ne 'HASH') {
- my $cfg = $class->SUPER::config();
- return $cfg->{$_[0]};
+ my $param = shift;
+ return $class if $param eq 'class';
+ return $LIB if $param eq 'with';
+ return $class->SUPER::config($param);
}
+ # Setter.
+
my $cfg = $class->SUPER::config(@_);
# now we need only to override the ones that are different from our parent
$cfg->{class} = $class;
- $cfg->{with} = $MBI;
+ $cfg->{with} = $LIB;
$cfg;
}
@@ -364,7 +366,7 @@ sub new {
# avoid numify-calls by not using || on $wanted!
unless (defined $wanted) {
- #Carp::carp("Use of uninitialized value in new");
+ #carp("Use of uninitialized value in new");
return $self->bzero(@r);
}
@@ -390,7 +392,7 @@ sub new {
# shortcut for bigints and its subclasses
if ((ref($wanted)) && $wanted -> can("as_number")) {
$self->{_m} = $wanted->as_number()->{value}; # get us a bigint copy
- $self->{_e} = $MBI->_zero();
+ $self->{_e} = $LIB->_zero();
$self->{_es} = '+';
$self->{sign} = $wanted->sign();
return $self->bnorm();
@@ -434,10 +436,10 @@ sub new {
# Shortcut for simple forms like '12' that have no trailing zeros.
if ($wanted =~ /^([+-]?)0*([1-9][0-9]*[1-9])$/) {
- $self->{_e} = $MBI -> _zero();
+ $self->{_e} = $LIB -> _zero();
$self->{_es} = '+';
$self->{sign} = $1 || '+';
- $self->{_m} = $MBI -> _new($2);
+ $self->{_m} = $LIB -> _new($2);
if (!$downgrade) {
$self->round(@r) unless @r >= 2 && !defined $r[0] && !defined $r[1];
return $self;
@@ -447,26 +449,26 @@ sub new {
my ($mis, $miv, $mfv, $es, $ev) = Math::BigInt::_split($wanted);
if (!ref $mis) {
if ($_trap_nan) {
- Carp::croak("$wanted is not a number initialized to $class");
+ croak("$wanted is not a number initialized to $class");
}
return $downgrade->bnan() if $downgrade;
- $self->{_e} = $MBI->_zero();
+ $self->{_e} = $LIB->_zero();
$self->{_es} = '+';
- $self->{_m} = $MBI->_zero();
+ $self->{_m} = $LIB->_zero();
$self->{sign} = $nan;
} else {
# make integer from mantissa by adjusting exp, then convert to int
- $self->{_e} = $MBI->_new($$ev); # exponent
+ $self->{_e} = $LIB->_new($$ev); # exponent
$self->{_es} = $$es || '+';
my $mantissa = "$$miv$$mfv"; # create mant.
$mantissa =~ s/^0+(\d)/$1/; # strip leading zeros
- $self->{_m} = $MBI->_new($mantissa); # create mant.
+ $self->{_m} = $LIB->_new($mantissa); # create mant.
# 3.123E0 = 3123E-3, and 3.123E-2 => 3123E-5
if (CORE::length($$mfv) != 0) {
- my $len = $MBI->_new(CORE::length($$mfv));
+ my $len = $LIB->_new(CORE::length($$mfv));
($self->{_e}, $self->{_es}) =
_e_sub($self->{_e}, $len, $self->{_es}, '+');
}
@@ -478,9 +480,9 @@ sub new {
my $zeros = 0;
$zeros = CORE::length($1) if $$miv =~ /[1-9](0*)$/;
if ($zeros != 0) {
- my $z = $MBI->_new($zeros);
+ my $z = $LIB->_new($zeros);
# turn '120e2' into '12e3'
- $self->{_m} = $MBI->_rsft($self->{_m}, $z, 10);
+ $self->{_m} = $LIB->_rsft($self->{_m}, $z, 10);
($self->{_e}, $self->{_es}) =
_e_add($self->{_e}, $z, $self->{_es}, '+');
}
@@ -489,8 +491,8 @@ sub new {
# for something like 0Ey, set y to 0, and -0 => +0
# Check $$miv for being '0' and $$mfv eq '', because otherwise _m could not
- # have become 0. That's faster than to call $MBI->_is_zero().
- $self->{sign} = '+', $self->{_e} = $MBI->_zero()
+ # have become 0. That's faster than to call $LIB->_is_zero().
+ $self->{sign} = '+', $self->{_e} = $LIB->_zero()
if $$miv eq '0' and $$mfv eq '';
if (!$downgrade) {
@@ -502,8 +504,8 @@ sub new {
# if downgrade, inf, NaN or integers go down
if ($downgrade && $self->{_es} eq '+') {
- if ($MBI->_is_zero($self->{_e})) {
- return $downgrade->new($$mis . $MBI->_str($self->{_m}));
+ if ($LIB->_is_zero($self->{_e})) {
+ return $downgrade->new($$mis . $LIB->_str($self->{_m}));
}
return $downgrade->new($self->bsstr());
}
@@ -587,7 +589,7 @@ sub from_hex {
}
$self -> {sign} = $s_sign;
- $self -> {_m} = $MBI -> _from_hex('0x' . $s_value);
+ $self -> {_m} = $LIB -> _from_hex('0x' . $s_value);
if ($two_expon > 0) {
my $factor = $class -> new("2") -> bpow($two_expon);
@@ -675,7 +677,7 @@ sub from_oct {
}
$self -> {sign} = $s_sign;
- $self -> {_m} = $MBI -> _from_oct($s_value);
+ $self -> {_m} = $LIB -> _from_oct($s_value);
if ($two_expon > 0) {
my $factor = $class -> new("2") -> bpow($two_expon);
@@ -763,7 +765,7 @@ sub from_bin {
}
$self -> {sign} = $s_sign;
- $self -> {_m} = $MBI -> _from_bin('0b' . $s_value);
+ $self -> {_m} = $LIB -> _from_bin('0b' . $s_value);
if ($two_expon > 0) {
my $factor = $class -> new("2") -> bpow($two_expon);
@@ -783,7 +785,7 @@ sub bzero {
# create/assign '+0'
if (@_ == 0) {
- #Carp::carp("Using bone() as a function is deprecated;",
+ #carp("Using bone() as a function is deprecated;",
# " use bone() as a method instead");
unshift @_, __PACKAGE__;
}
@@ -798,20 +800,23 @@ sub bzero {
$self = bless {}, $class unless $selfref;
$self -> {sign} = '+';
- $self -> {_m} = $MBI -> _zero();
+ $self -> {_m} = $LIB -> _zero();
$self -> {_es} = '+';
- $self -> {_e} = $MBI -> _zero();
+ $self -> {_e} = $LIB -> _zero();
- if (@_ > 0) {
- if (@_ > 3) {
- # call like: $x->bzero($a, $p, $r, $y);
- ($self, $self->{_a}, $self->{_p}) = $self->_find_round_parameters(@_);
- } else {
- # call like: $x->bzero($a, $p, $r);
- $self->{_a} = $_[0]
- if !defined $self->{_a} || (defined $_[0] && $_[0] > $self->{_a});
- $self->{_p} = $_[1]
- if !defined $self->{_p} || (defined $_[1] && $_[1] > $self->{_p});
+ # If rounding parameters are given as arguments, use them. If no rounding
+ # parameters are given, and if called as a class method initialize the new
+ # instance with the class variables.
+
+ if (@_) {
+ croak "can't specify both accuracy and precision"
+ if @_ >= 2 && defined $_[0] && defined $_[1];
+ $self->{_a} = $_[0];
+ $self->{_p} = $_[1];
+ } else {
+ unless($selfref) {
+ $self->{_a} = $class -> accuracy();
+ $self->{_p} = $class -> precision();
}
}
@@ -822,7 +827,7 @@ sub bone {
# Create or assign '+1' (or -1 if given sign '-').
if (@_ == 0 || (defined($_[0]) && ($_[0] eq '+' || $_[0] eq '-'))) {
- #Carp::carp("Using bone() as a function is deprecated;",
+ #carp("Using bone() as a function is deprecated;",
# " use bone() as a method instead");
unshift @_, __PACKAGE__;
}
@@ -840,20 +845,23 @@ sub bone {
$self = bless {}, $class unless $selfref;
$self -> {sign} = $sign;
- $self -> {_m} = $MBI -> _one();
+ $self -> {_m} = $LIB -> _one();
$self -> {_es} = '+';
- $self -> {_e} = $MBI -> _zero();
+ $self -> {_e} = $LIB -> _zero();
- if (@_ > 0) {
- if (@_ > 3) {
- # call like: $x->bone($sign, $a, $p, $r, $y, ...);
- ($self, $self->{_a}, $self->{_p}) = $self->_find_round_parameters(@_);
- } else {
- # call like: $x->bone($sign, $a, $p, $r);
- $self->{_a} = $_[0]
- if ((!defined $self->{_a}) || (defined $_[0] && $_[0] > $self->{_a}));
- $self->{_p} = $_[1]
- if ((!defined $self->{_p}) || (defined $_[1] && $_[1] > $self->{_p}));
+ # If rounding parameters are given as arguments, use them. If no rounding
+ # parameters are given, and if called as a class method initialize the new
+ # instance with the class variables.
+
+ if (@_) {
+ croak "can't specify both accuracy and precision"
+ if @_ >= 2 && defined $_[0] && defined $_[1];
+ $self->{_a} = $_[0];
+ $self->{_p} = $_[1];
+ } else {
+ unless($selfref) {
+ $self->{_a} = $class -> accuracy();
+ $self->{_p} = $class -> precision();
}
}
@@ -866,7 +874,7 @@ sub binf {
if (@_ == 0 || (defined($_[0]) && !ref($_[0]) &&
$_[0] =~ /^\s*[+-](inf(inity)?)?\s*$/))
{
- #Carp::carp("Using binf() as a function is deprecated;",
+ #carp("Using binf() as a function is deprecated;",
# " use binf() as a method instead");
unshift @_, __PACKAGE__;
}
@@ -878,7 +886,7 @@ sub binf {
{
no strict 'refs';
if (${"${class}::_trap_inf"}) {
- Carp::croak("Tried to create +-inf in $class->binf()");
+ croak("Tried to create +-inf in $class->binf()");
}
}
@@ -891,9 +899,25 @@ sub binf {
$self = bless {}, $class unless $selfref;
$self -> {sign} = $sign . 'inf';
- $self -> {_m} = $MBI -> _zero();
+ $self -> {_m} = $LIB -> _zero();
$self -> {_es} = '+';
- $self -> {_e} = $MBI -> _zero();
+ $self -> {_e} = $LIB -> _zero();
+
+ # If rounding parameters are given as arguments, use them. If no rounding
+ # parameters are given, and if called as a class method initialize the new
+ # instance with the class variables.
+
+ if (@_) {
+ croak "can't specify both accuracy and precision"
+ if @_ >= 2 && defined $_[0] && defined $_[1];
+ $self->{_a} = $_[0];
+ $self->{_p} = $_[1];
+ } else {
+ unless($selfref) {
+ $self->{_a} = $class -> accuracy();
+ $self->{_p} = $class -> precision();
+ }
+ }
return $self;
}
@@ -902,7 +926,7 @@ sub bnan {
# create/assign a 'NaN'
if (@_ == 0) {
- #Carp::carp("Using bnan() as a function is deprecated;",
+ #carp("Using bnan() as a function is deprecated;",
# " use bnan() as a method instead");
unshift @_, __PACKAGE__;
}
@@ -914,7 +938,7 @@ sub bnan {
{
no strict 'refs';
if (${"${class}::_trap_nan"}) {
- Carp::croak("Tried to create NaN in $class->bnan()");
+ croak("Tried to create NaN in $class->bnan()");
}
}
@@ -924,9 +948,25 @@ sub bnan {
$self = bless {}, $class unless $selfref;
$self -> {sign} = $nan;
- $self -> {_m} = $MBI -> _zero();
+ $self -> {_m} = $LIB -> _zero();
$self -> {_es} = '+';
- $self -> {_e} = $MBI -> _zero();
+ $self -> {_e} = $LIB -> _zero();
+
+ # If rounding parameters are given as arguments, use them. If no rounding
+ # parameters are given, and if called as a class method initialize the new
+ # instance with the class variables.
+
+ if (@_) {
+ croak "can't specify both accuracy and precision"
+ if @_ >= 2 && defined $_[0] && defined $_[1];
+ $self->{_a} = $_[0];
+ $self->{_p} = $_[1];
+ } else {
+ unless($selfref) {
+ $self->{_a} = $class -> accuracy();
+ $self->{_p} = $class -> precision();
+ }
+ }
return $self;
}
@@ -1032,13 +1072,12 @@ EOF
my $digits = substr($all_digits, 0, $nchrs);
- # Find out whether we should round up or down. Since pi is a
- # transcendental number, we only have to look at one digit after the
- # last digit we want.
+ # Find out whether we should round up or down. Rounding is easy, since
+ # pi is trancendental. With directed rounding, it doesn't matter what
+ # the following digits are. With rounding to nearest, we only have to
+ # look at one extra digit.
- if ($rmode eq '+inf') {
- $round_up = 1;
- } elsif ($rmode eq 'trunc' || $rmode eq 'zero' || $rmode eq '-inf') {
+ if ($rmode eq 'trunc') {
$round_up = 0;
} else {
my $next_digit = substr($all_digits, $nchrs, 1);
@@ -1072,7 +1111,7 @@ EOF
# Math::BigFloat, so use Brent-Salamin (aka AGM or Gauss-Legendre).
# Use a few more digits in the intermediate computations.
- my $nextra = 8;
+ $n += 8;
$HALF = $class -> new($HALF) unless ref($HALF);
my ($an, $bn, $tn, $pn) = ($class -> bone, $HALF -> copy() -> bsqrt($n),
@@ -1118,8 +1157,8 @@ sub copy {
$copy->{sign} = $self->{sign};
$copy->{_es} = $self->{_es};
- $copy->{_m} = $MBI->_copy($self->{_m});
- $copy->{_e} = $MBI->_copy($self->{_e});
+ $copy->{_m} = $LIB->_copy($self->{_m});
+ $copy->{_e} = $LIB->_copy($self->{_e});
$copy->{_a} = $self->{_a} if exists $self->{_a};
$copy->{_p} = $self->{_p} if exists $self->{_p};
@@ -1142,13 +1181,13 @@ sub as_number {
return Math::BigInt->binf($x->sign()) if $x->is_inf();
return Math::BigInt->bnan() if $x->is_nan();
- my $z = $MBI->_copy($x->{_m});
+ my $z = $LIB->_copy($x->{_m});
if ($x->{_es} eq '-') { # < 0
- $z = $MBI->_rsft($z, $x->{_e}, 10);
- } elsif (! $MBI->_is_zero($x->{_e})) { # > 0
- $z = $MBI->_lsft($z, $x->{_e}, 10);
+ $z = $LIB->_rsft($z, $x->{_e}, 10);
+ } elsif (! $LIB->_is_zero($x->{_e})) { # > 0
+ $z = $LIB->_lsft($z, $x->{_e}, 10);
}
- $z = Math::BigInt->new($x->{sign} . $MBI->_str($z));
+ $z = Math::BigInt->new($x->{sign} . $LIB->_str($z));
$z;
}
@@ -1160,7 +1199,7 @@ sub is_zero {
# return true if arg (BFLOAT or num_str) is zero
my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
- ($x->{sign} eq '+' && $MBI->_is_zero($x->{_m})) ? 1 : 0;
+ ($x->{sign} eq '+' && $LIB->_is_zero($x->{_m})) ? 1 : 0;
}
sub is_one {
@@ -1170,8 +1209,8 @@ sub is_one {
$sign = '+' if !defined $sign || $sign ne '-';
($x->{sign} eq $sign &&
- $MBI->_is_zero($x->{_e}) &&
- $MBI->_is_one($x->{_m})) ? 1 : 0;
+ $LIB->_is_zero($x->{_e}) &&
+ $LIB->_is_one($x->{_m})) ? 1 : 0;
}
sub is_odd {
@@ -1179,8 +1218,8 @@ sub is_odd {
my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
(($x->{sign} =~ /^[+-]$/) && # NaN & +-inf aren't
- ($MBI->_is_zero($x->{_e})) &&
- ($MBI->_is_odd($x->{_m}))) ? 1 : 0;
+ ($LIB->_is_zero($x->{_e})) &&
+ ($LIB->_is_odd($x->{_m}))) ? 1 : 0;
}
sub is_even {
@@ -1189,7 +1228,7 @@ sub is_even {
(($x->{sign} =~ /^[+-]$/) && # NaN & +-inf aren't
($x->{_es} eq '+') && # 123.45 isn't
- ($MBI->_is_even($x->{_m}))) ? 1 : 0; # but 1200 is
+ ($LIB->_is_even($x->{_m}))) ? 1 : 0; # but 1200 is
}
sub is_int {
@@ -1252,8 +1291,8 @@ sub bcmp {
# integer of arbitrary value, the exponents must be normalized by the length
# of the mantissas before we can compare them.
- my $mxl = $MBI->_len($x->{_m});
- my $myl = $MBI->_len($y->{_m});
+ my $mxl = $LIB->_len($x->{_m});
+ my $myl = $LIB->_len($y->{_m});
# If the mantissas have the same length, there is no point in normalizing the
# exponents by the length of the mantissas, so treat that as a special case.
@@ -1271,7 +1310,7 @@ sub bcmp {
# Then handle the case where the exponents have the same sign.
else {
- $cmp = $MBI->_acmp($x->{_e}, $y->{_e});
+ $cmp = $LIB->_acmp($x->{_e}, $y->{_e});
$cmp = -$cmp if $x->{_es} eq '-';
}
@@ -1298,17 +1337,17 @@ sub bcmp {
# need to do anything special.
if ($y->{_es} eq '+') {
- $ex = $MBI->_copy($x->{_e});
- $ey = $MBI->_copy($y->{_e});
+ $ex = $LIB->_copy($x->{_e});
+ $ey = $LIB->_copy($y->{_e});
}
# If the exponent of x is >= 0 and the exponent of y is < 0, add the
# absolute value of the exponent of y to both.
else {
- $ex = $MBI->_copy($x->{_e});
- $ex = $MBI->_add($ex, $y->{_e}); # ex + |ey|
- $ey = $MBI->_zero(); # -ex + |ey| = 0
+ $ex = $LIB->_copy($x->{_e});
+ $ex = $LIB->_add($ex, $y->{_e}); # ex + |ey|
+ $ey = $LIB->_zero(); # -ex + |ey| = 0
}
} else {
@@ -1317,29 +1356,29 @@ sub bcmp {
# absolute value of the exponent of x to both.
if ($y->{_es} eq '+') {
- $ex = $MBI->_zero(); # -ex + |ex| = 0
- $ey = $MBI->_copy($y->{_e});
- $ey = $MBI->_add($ey, $x->{_e}); # ey + |ex|
+ $ex = $LIB->_zero(); # -ex + |ex| = 0
+ $ey = $LIB->_copy($y->{_e});
+ $ey = $LIB->_add($ey, $x->{_e}); # ey + |ex|
}
# If the exponent of x is < 0 and the exponent of y is < 0, add the
# absolute values of both exponents to both exponents.
else {
- $ex = $MBI->_copy($y->{_e}); # -ex + |ey| + |ex| = |ey|
- $ey = $MBI->_copy($x->{_e}); # -ey + |ex| + |ey| = |ex|
+ $ex = $LIB->_copy($y->{_e}); # -ex + |ey| + |ex| = |ey|
+ $ey = $LIB->_copy($x->{_e}); # -ey + |ex| + |ey| = |ex|
}
}
# Now we can normalize the exponents by adding lengths of the mantissas.
- $ex = $MBI->_add($ex, $MBI->_new($mxl));
- $ey = $MBI->_add($ey, $MBI->_new($myl));
+ $ex = $LIB->_add($ex, $LIB->_new($mxl));
+ $ey = $LIB->_add($ey, $LIB->_new($myl));
# We're done if the exponents are different.
- $cmp = $MBI->_acmp($ex, $ey);
+ $cmp = $LIB->_acmp($ex, $ey);
$cmp = -$cmp if $x->{sign} eq '-'; # 124 > 123, but -124 < -123
return $cmp if $cmp;
@@ -1351,12 +1390,12 @@ sub bcmp {
my $my = $y->{_m};
if ($mxl > $myl) {
- $my = $MBI->_lsft($MBI->_copy($my), $MBI->_new($mxl - $myl), 10);
+ $my = $LIB->_lsft($LIB->_copy($my), $LIB->_new($mxl - $myl), 10);
} elsif ($mxl < $myl) {
- $mx = $MBI->_lsft($MBI->_copy($mx), $MBI->_new($myl - $mxl), 10);
+ $mx = $LIB->_lsft($LIB->_copy($mx), $LIB->_new($myl - $mxl), 10);
}
- $cmp = $MBI->_acmp($mx, $my);
+ $cmp = $LIB->_acmp($mx, $my);
$cmp = -$cmp if $x->{sign} eq '-'; # 124 > 123, but -124 < -123
return $cmp;
@@ -1392,14 +1431,14 @@ sub bacmp {
return 1 if $yz && !$xz; # +x <=> 0
# adjust so that exponents are equal
- my $lxm = $MBI->_len($x->{_m});
- my $lym = $MBI->_len($y->{_m});
+ my $lxm = $LIB->_len($x->{_m});
+ my $lym = $LIB->_len($y->{_m});
my ($xes, $yes) = (1, 1);
$xes = -1 if $x->{_es} ne '+';
$yes = -1 if $y->{_es} ne '+';
# the numify somewhat limits our length, but makes it much faster
- my $lx = $lxm + $xes * $MBI->_num($x->{_e});
- my $ly = $lym + $yes * $MBI->_num($y->{_e});
+ my $lx = $lxm + $xes * $LIB->_num($x->{_e});
+ my $ly = $lym + $yes * $LIB->_num($y->{_e});
my $l = $lx - $ly;
return $l <=> 0 if $l != 0;
@@ -1409,13 +1448,13 @@ sub bacmp {
my $xm = $x->{_m}; # not yet copy it
my $ym = $y->{_m};
if ($diff > 0) {
- $ym = $MBI->_copy($y->{_m});
- $ym = $MBI->_lsft($ym, $MBI->_new($diff), 10);
+ $ym = $LIB->_copy($y->{_m});
+ $ym = $LIB->_lsft($ym, $LIB->_new($diff), 10);
} elsif ($diff < 0) {
- $xm = $MBI->_copy($x->{_m});
- $xm = $MBI->_lsft($xm, $MBI->_new(-$diff), 10);
+ $xm = $LIB->_copy($x->{_m});
+ $xm = $LIB->_lsft($xm, $LIB->_new(-$diff), 10);
}
- $MBI->_acmp($xm, $ym);
+ $LIB->_acmp($xm, $ym);
}
###############################################################################
@@ -1430,7 +1469,7 @@ sub bneg {
return $x if $x->modify('bneg');
# for +0 do not negate (to have always normalized +0). Does nothing for 'NaN'
- $x->{sign} =~ tr/+-/-+/ unless ($x->{sign} eq '+' && $MBI->_is_zero($x->{_m}));
+ $x->{sign} =~ tr/+-/-+/ unless ($x->{sign} eq '+' && $LIB->_is_zero($x->{_m}));
$x;
}
@@ -1440,26 +1479,26 @@ sub bnorm {
return $x if $x->{sign} !~ /^[+-]$/; # inf, nan etc
- my $zeros = $MBI->_zeros($x->{_m}); # correct for trailing zeros
+ my $zeros = $LIB->_zeros($x->{_m}); # correct for trailing zeros
if ($zeros != 0) {
- my $z = $MBI->_new($zeros);
- $x->{_m} = $MBI->_rsft($x->{_m}, $z, 10);
+ my $z = $LIB->_new($zeros);
+ $x->{_m} = $LIB->_rsft($x->{_m}, $z, 10);
if ($x->{_es} eq '-') {
- if ($MBI->_acmp($x->{_e}, $z) >= 0) {
- $x->{_e} = $MBI->_sub($x->{_e}, $z);
- $x->{_es} = '+' if $MBI->_is_zero($x->{_e});
+ if ($LIB->_acmp($x->{_e}, $z) >= 0) {
+ $x->{_e} = $LIB->_sub($x->{_e}, $z);
+ $x->{_es} = '+' if $LIB->_is_zero($x->{_e});
} else {
- $x->{_e} = $MBI->_sub($MBI->_copy($z), $x->{_e});
+ $x->{_e} = $LIB->_sub($LIB->_copy($z), $x->{_e});
$x->{_es} = '+';
}
} else {
- $x->{_e} = $MBI->_add($x->{_e}, $z);
+ $x->{_e} = $LIB->_add($x->{_e}, $z);
}
} else {
# $x can only be 0Ey if there are no trailing zeros ('0' has 0 trailing
# zeros). So, for something like 0Ey, set y to 1, and -0 => +0
- $x->{sign} = '+', $x->{_es} = '+', $x->{_e} = $MBI->_one()
- if $MBI->_is_zero($x->{_m});
+ $x->{sign} = '+', $x->{_es} = '+', $x->{_e} = $LIB->_one()
+ if $LIB->_is_zero($x->{_m});
}
$x;
@@ -1475,22 +1514,22 @@ sub binc {
return $x->badd($class->bone(), @r); # digits after dot
}
- if (!$MBI->_is_zero($x->{_e})) # _e == 0 for NaN, inf, -inf
+ if (!$LIB->_is_zero($x->{_e})) # _e == 0 for NaN, inf, -inf
{
# 1e2 => 100, so after the shift below _m has a '0' as last digit
- $x->{_m} = $MBI->_lsft($x->{_m}, $x->{_e}, 10); # 1e2 => 100
- $x->{_e} = $MBI->_zero(); # normalize
+ $x->{_m} = $LIB->_lsft($x->{_m}, $x->{_e}, 10); # 1e2 => 100
+ $x->{_e} = $LIB->_zero(); # normalize
$x->{_es} = '+';
# we know that the last digit of $x will be '1' or '9', depending on the
# sign
}
# now $x->{_e} == 0
if ($x->{sign} eq '+') {
- $x->{_m} = $MBI->_inc($x->{_m});
+ $x->{_m} = $LIB->_inc($x->{_m});
return $x->bnorm()->bround(@r);
} elsif ($x->{sign} eq '-') {
- $x->{_m} = $MBI->_dec($x->{_m});
- $x->{sign} = '+' if $MBI->_is_zero($x->{_m}); # -1 +1 => -0 => +0
+ $x->{_m} = $LIB->_dec($x->{_m});
+ $x->{sign} = '+' if $LIB->_is_zero($x->{_m}); # -1 +1 => -0 => +0
return $x->bnorm()->bround(@r);
}
# inf, nan handling etc
@@ -1507,23 +1546,23 @@ sub bdec {
return $x->badd($class->bone('-'), @r); # digits after dot
}
- if (!$MBI->_is_zero($x->{_e})) {
- $x->{_m} = $MBI->_lsft($x->{_m}, $x->{_e}, 10); # 1e2 => 100
- $x->{_e} = $MBI->_zero(); # normalize
+ if (!$LIB->_is_zero($x->{_e})) {
+ $x->{_m} = $LIB->_lsft($x->{_m}, $x->{_e}, 10); # 1e2 => 100
+ $x->{_e} = $LIB->_zero(); # normalize
$x->{_es} = '+';
}
# now $x->{_e} == 0
my $zero = $x->is_zero();
# <= 0
if (($x->{sign} eq '-') || $zero) {
- $x->{_m} = $MBI->_inc($x->{_m});
+ $x->{_m} = $LIB->_inc($x->{_m});
$x->{sign} = '-' if $zero; # 0 => 1 => -1
- $x->{sign} = '+' if $MBI->_is_zero($x->{_m}); # -1 +1 => -0 => +0
+ $x->{sign} = '+' if $LIB->_is_zero($x->{_m}); # -1 +1 => -0 => +0
return $x->bnorm()->round(@r);
}
# > 0
elsif ($x->{sign} eq '+') {
- $x->{_m} = $MBI->_dec($x->{_m});
+ $x->{_m} = $LIB->_dec($x->{_m});
return $x->bnorm()->round(@r);
}
# inf, nan handling etc
@@ -1568,37 +1607,37 @@ sub badd {
if ($x->is_zero()) # 0+y
{
# make copy, clobbering up x (modify in place!)
- $x->{_e} = $MBI->_copy($y->{_e});
+ $x->{_e} = $LIB->_copy($y->{_e});
$x->{_es} = $y->{_es};
- $x->{_m} = $MBI->_copy($y->{_m});
+ $x->{_m} = $LIB->_copy($y->{_m});
$x->{sign} = $y->{sign} || $nan;
return $x->round(@r);
}
# take lower of the two e's and adapt m1 to it to match m2
my $e = $y->{_e};
- $e = $MBI->_zero() if !defined $e; # if no BFLOAT?
- $e = $MBI->_copy($e); # make copy (didn't do it yet)
+ $e = $LIB->_zero() if !defined $e; # if no BFLOAT?
+ $e = $LIB->_copy($e); # make copy (didn't do it yet)
my $es;
($e, $es) = _e_sub($e, $x->{_e}, $y->{_es} || '+', $x->{_es});
- my $add = $MBI->_copy($y->{_m});
+ my $add = $LIB->_copy($y->{_m});
if ($es eq '-') # < 0
{
- $x->{_m} = $MBI->_lsft($x->{_m}, $e, 10);
+ $x->{_m} = $LIB->_lsft($x->{_m}, $e, 10);
($x->{_e}, $x->{_es}) = _e_add($x->{_e}, $e, $x->{_es}, $es);
- } elsif (!$MBI->_is_zero($e)) # > 0
+ } elsif (!$LIB->_is_zero($e)) # > 0
{
- $add = $MBI->_lsft($add, $e, 10);
+ $add = $LIB->_lsft($add, $e, 10);
}
# else: both e are the same, so just leave them
if ($x->{sign} eq $y->{sign}) {
# add
- $x->{_m} = $MBI->_add($x->{_m}, $add);
+ $x->{_m} = $LIB->_add($x->{_m}, $add);
} else {
($x->{_m}, $x->{sign}) =
_e_add($x->{_m}, $add, $x->{sign}, $y->{sign});
@@ -1672,7 +1711,7 @@ sub bmul {
((!$x->isa($class)) || (!$y->isa($class)));
# aEb * cEd = (a*c)E(b+d)
- $x->{_m} = $MBI->_mul($x->{_m}, $y->{_m});
+ $x->{_m} = $LIB->_mul($x->{_m}, $y->{_m});
($x->{_e}, $x->{_es}) = _e_add($x->{_e}, $y->{_e}, $x->{_es}, $y->{_es});
$r[3] = $y; # no push!
@@ -1709,7 +1748,7 @@ sub bmuladd {
((!$x->isa($class)) || (!$y->isa($class)));
# aEb * cEd = (a*c)E(b+d)
- $x->{_m} = $MBI->_mul($x->{_m}, $y->{_m});
+ $x->{_m} = $LIB->_mul($x->{_m}, $y->{_m});
($x->{_e}, $x->{_es}) = _e_add($x->{_e}, $y->{_e}, $x->{_es}, $y->{_es});
$r[3] = $y; # no push!
@@ -1722,28 +1761,28 @@ sub bmuladd {
# take lower of the two e's and adapt m1 to it to match m2
my $e = $z->{_e};
- $e = $MBI->_zero() if !defined $e; # if no BFLOAT?
- $e = $MBI->_copy($e); # make copy (didn't do it yet)
+ $e = $LIB->_zero() if !defined $e; # if no BFLOAT?
+ $e = $LIB->_copy($e); # make copy (didn't do it yet)
my $es;
($e, $es) = _e_sub($e, $x->{_e}, $z->{_es} || '+', $x->{_es});
- my $add = $MBI->_copy($z->{_m});
+ my $add = $LIB->_copy($z->{_m});
if ($es eq '-') # < 0
{
- $x->{_m} = $MBI->_lsft($x->{_m}, $e, 10);
+ $x->{_m} = $LIB->_lsft($x->{_m}, $e, 10);
($x->{_e}, $x->{_es}) = _e_add($x->{_e}, $e, $x->{_es}, $es);
- } elsif (!$MBI->_is_zero($e)) # > 0
+ } elsif (!$LIB->_is_zero($e)) # > 0
{
- $add = $MBI->_lsft($add, $e, 10);
+ $add = $LIB->_lsft($add, $e, 10);
}
# else: both e are the same, so just leave them
if ($x->{sign} eq $z->{sign}) {
# add
- $x->{_m} = $MBI->_add($x->{_m}, $add);
+ $x->{_m} = $LIB->_add($x->{_m}, $add);
} else {
($x->{_m}, $x->{sign}) =
_e_add($x->{_m}, $add, $x->{sign}, $z->{sign});
@@ -1870,14 +1909,14 @@ sub bdiv {
$y = $class->new($y) unless $y->isa('Math::BigFloat');
- my $lx = $MBI -> _len($x->{_m}); my $ly = $MBI -> _len($y->{_m});
+ my $lx = $LIB -> _len($x->{_m}); my $ly = $LIB -> _len($y->{_m});
$scale = $lx if $lx > $scale;
$scale = $ly if $ly > $scale;
my $diff = $ly - $lx;
$scale += $diff if $diff > 0; # if lx << ly, but not if ly << lx!
# check that $y is not 1 nor -1 and cache the result:
- my $y_not_one = !($MBI->_is_zero($y->{_e}) && $MBI->_is_one($y->{_m}));
+ my $y_not_one = !($LIB->_is_zero($y->{_e}) && $LIB->_is_one($y->{_m}));
# flipping the sign of $y will also flip the sign of $x for the special
# case of $x->bsub($x); so we can catch it below:
@@ -1906,13 +1945,13 @@ sub bdiv {
# calculate the result to $scale digits and then round it
# a * 10 ** b / c * 10 ** d => a/c * 10 ** (b-d)
- $x->{_m} = $MBI->_lsft($x->{_m}, $MBI->_new($scale), 10);
- $x->{_m} = $MBI->_div($x->{_m}, $y->{_m}); # a/c
+ $x->{_m} = $LIB->_lsft($x->{_m}, $LIB->_new($scale), 10);
+ $x->{_m} = $LIB->_div($x->{_m}, $y->{_m}); # a/c
# correct exponent of $x
($x->{_e}, $x->{_es}) = _e_sub($x->{_e}, $y->{_e}, $x->{_es}, $y->{_es});
# correct for 10**scale
- ($x->{_e}, $x->{_es}) = _e_sub($x->{_e}, $MBI->_new($scale), $x->{_es}, '+');
+ ($x->{_e}, $x->{_es}) = _e_sub($x->{_e}, $LIB->_new($scale), $x->{_es}, '+');
$x->bnorm(); # remove trailing 0's
}
} # end else $x != $y
@@ -1990,7 +2029,7 @@ sub bmod {
return $x->bzero() if $x->is_zero()
|| ($x->is_int() &&
# check that $y == +1 or $y == -1:
- ($MBI->_is_zero($y->{_e}) && $MBI->_is_one($y->{_m})));
+ ($LIB->_is_zero($y->{_e}) && $LIB->_is_one($y->{_m})));
my $cmp = $x->bacmp($y); # equal or $x < $y?
if ($cmp == 0) { # $x == $y => result 0
@@ -2005,19 +2044,19 @@ sub bmod {
return $x -> round($a, $p, $r);
}
- my $ym = $MBI->_copy($y->{_m});
+ my $ym = $LIB->_copy($y->{_m});
# 2e1 => 20
- $ym = $MBI->_lsft($ym, $y->{_e}, 10)
- if $y->{_es} eq '+' && !$MBI->_is_zero($y->{_e});
+ $ym = $LIB->_lsft($ym, $y->{_e}, 10)
+ if $y->{_es} eq '+' && !$LIB->_is_zero($y->{_e});
# if $y has digits after dot
my $shifty = 0; # correct _e of $x by this
if ($y->{_es} eq '-') # has digits after dot
{
# 123 % 2.5 => 1230 % 25 => 5 => 0.5
- $shifty = $MBI->_num($y->{_e}); # no more digits after dot
- $x->{_m} = $MBI->_lsft($x->{_m}, $y->{_e}, 10); # 123 => 1230, $y->{_m} is already 25
+ $shifty = $LIB->_num($y->{_e}); # no more digits after dot
+ $x->{_m} = $LIB->_lsft($x->{_m}, $y->{_e}, 10); # 123 => 1230, $y->{_m} is already 25
}
# $ym is now mantissa of $y based on exponent 0
@@ -2025,24 +2064,24 @@ sub bmod {
if ($x->{_es} eq '-') # has digits after dot
{
# 123.4 % 20 => 1234 % 200
- $shiftx = $MBI->_num($x->{_e}); # no more digits after dot
- $ym = $MBI->_lsft($ym, $x->{_e}, 10); # 123 => 1230
+ $shiftx = $LIB->_num($x->{_e}); # no more digits after dot
+ $ym = $LIB->_lsft($ym, $x->{_e}, 10); # 123 => 1230
}
# 123e1 % 20 => 1230 % 20
- if ($x->{_es} eq '+' && !$MBI->_is_zero($x->{_e})) {
- $x->{_m} = $MBI->_lsft($x->{_m}, $x->{_e}, 10); # es => '+' here
+ if ($x->{_es} eq '+' && !$LIB->_is_zero($x->{_e})) {
+ $x->{_m} = $LIB->_lsft($x->{_m}, $x->{_e}, 10); # es => '+' here
}
- $x->{_e} = $MBI->_new($shiftx);
+ $x->{_e} = $LIB->_new($shiftx);
$x->{_es} = '+';
$x->{_es} = '-' if $shiftx != 0 || $shifty != 0;
- $x->{_e} = $MBI->_add($x->{_e}, $MBI->_new($shifty)) if $shifty != 0;
+ $x->{_e} = $LIB->_add($x->{_e}, $LIB->_new($shifty)) if $shifty != 0;
# now mantissas are equalized, exponent of $x is adjusted, so calc result
- $x->{_m} = $MBI->_mod($x->{_m}, $ym);
+ $x->{_m} = $LIB->_mod($x->{_m}, $ym);
- $x->{sign} = '+' if $MBI->_is_zero($x->{_m}); # fix sign for -0
+ $x->{sign} = '+' if $LIB->_is_zero($x->{_m}); # fix sign for -0
$x->bnorm();
if ($neg != 0 && ! $x -> is_zero()) # one of them negative => correct in place
@@ -2051,7 +2090,7 @@ sub bmod {
$x->{_m} = $r->{_m};
$x->{_e} = $r->{_e};
$x->{_es} = $r->{_es};
- $x->{sign} = '+' if $MBI->_is_zero($x->{_m}); # fix sign for -0
+ $x->{sign} = '+' if $LIB->_is_zero($x->{_m}); # fix sign for -0
$x->bnorm();
}
@@ -2062,7 +2101,7 @@ sub bmodpow {
# takes a very large number to a very large exponent in a given very
# large modulus, quickly, thanks to binary exponentiation. Supports
# negative exponents.
- my ($class, $num, $exp, $mod, @r) = objectify(3, @_);
+ my ($class, $num, $exp, $mod) = objectify(3, @_);
return $num if $num->modify('bmodpow');
@@ -2101,8 +2140,33 @@ sub bpow {
return $x if $x->modify('bpow');
- return $x->bnan() if $x->{sign} eq $nan || $y->{sign} eq $nan;
- return $x if $x->{sign} =~ /^[+-]inf$/;
+ # $x and/or $y is a NaN
+ return $x->bnan() if $x->is_nan() || $y->is_nan();
+
+ # $x and/or $y is a +/-Inf
+ if ($x->is_inf("-")) {
+ return $x->bzero() if $y->is_negative();
+ return $x->bnan() if $y->is_zero();
+ return $x if $y->is_odd();
+ return $x->bneg();
+ } elsif ($x->is_inf("+")) {
+ return $x->bzero() if $y->is_negative();
+ return $x->bnan() if $y->is_zero();
+ return $x;
+ } elsif ($y->is_inf("-")) {
+ return $x->bnan() if $x -> is_one("-");
+ return $x->binf("+") if $x > -1 && $x < 1;
+ return $x->bone() if $x -> is_one("+");
+ return $x->bzero();
+ } elsif ($y->is_inf("+")) {
+ return $x->bnan() if $x -> is_one("-");
+ return $x->bzero() if $x > -1 && $x < 1;
+ return $x->bone() if $x -> is_one("+");
+ return $x->binf("+");
+ }
+
+ # we don't support complex numbers, so return NaN
+ return $x->bnan() if $x->is_negative() && !$y->is_int();
# cache the result of is_zero
my $y_is_zero = $y->is_zero();
@@ -2110,14 +2174,13 @@ sub bpow {
return $x if $x->is_one() || $y->is_one();
my $x_is_zero = $x->is_zero();
- return $x->_pow($y, $a, $p, $r) if !$x_is_zero && !$y->is_int(); # non-integer power
+ return $x->_pow($y, $a, $p, $r) if !$x_is_zero && !$y->is_int();
my $y1 = $y->as_number()->{value}; # make MBI part
- # if ($x == -1)
- if ($x->{sign} eq '-' && $MBI->_is_one($x->{_m}) && $MBI->_is_zero($x->{_e})) {
+ if ($x->is_one("-")) {
# if $x == -1 and odd/even y => +1/-1 because +-1 ^ (+-1) => +-1
- return $MBI->_is_odd($y1) ? $x : $x->babs(1);
+ return $LIB->_is_odd($y1) ? $x : $x->babs(1);
}
if ($x_is_zero) {
return $x if $y->{sign} eq '+'; # 0**y => 0 (if not y <= 0)
@@ -2126,11 +2189,11 @@ sub bpow {
}
my $new_sign = '+';
- $new_sign = $MBI->_is_odd($y1) ? '-' : '+' if $x->{sign} ne '+';
+ $new_sign = $LIB->_is_odd($y1) ? '-' : '+' if $x->{sign} ne '+';
# calculate $x->{_m} ** $y and $x->{_e} * $y separately (faster)
- $x->{_m} = $MBI->_pow($x->{_m}, $y1);
- $x->{_e} = $MBI->_mul ($x->{_e}, $y1);
+ $x->{_m} = $LIB->_pow($x->{_m}, $y1);
+ $x->{_e} = $LIB->_mul ($x->{_e}, $y1);
$x->{sign} = $new_sign;
$x->bnorm();
@@ -2267,32 +2330,33 @@ sub blog {
# first. This is very fast, and in case the real result was found, we can
# stop right here.
if (defined $base && $base->is_int() && $x->is_int()) {
- my $i = $MBI->_copy($x->{_m});
- $i = $MBI->_lsft($i, $x->{_e}, 10) unless $MBI->_is_zero($x->{_e});
- my $int = Math::BigInt->bzero();
- $int->{value} = $i;
- $int->blog($base->as_number());
- # if ($exact)
- if ($base->as_number()->bpow($int) == $x) {
- # found result, return it
- $x->{_m} = $int->{value};
- $x->{_e} = $MBI->_zero();
- $x->{_es} = '+';
- $x->bnorm();
+ my $xint = Math::BigInt -> new($x -> bdstr());
+ my $bint = Math::BigInt -> new($base -> bdstr());
+ $xint->blog($bint);
+
+ # if we found the exact result, we're done
+ if ($bint -> bpow($xint) == $x) {
+ my $xflt = Math::BigFloat -> new($xint -> bdstr());
+ $x->{sign} = $xflt->{sign};
+ $x->{_m} = $xflt->{_m};
+ $x->{_es} = $xflt->{_es};
+ $x->{_e} = $xflt->{_e};
$done = 1;
}
}
if ($done == 0) {
- # base is undef, so base should be e (Euler's number), so first calculate the
- # log to base e (using reduction by 10 (and probably 2)):
- $class->_log_10($x, $scale);
+ # First calculate the log to base e (using reduction by 10 and possibly
+ # also by 2):
+ $x->_log_10($scale);
# and if a different base was requested, convert it
if (defined $base) {
- $base = Math::BigFloat->new($base) unless $base->isa('Math::BigFloat');
- # not ln, but some other base (don't modify $base)
- $x->bdiv($base->copy()->blog(undef, $scale), $scale);
+ $base = Math::BigFloat->new($base)
+ unless $base->isa('Math::BigFloat');
+ # log_b(x) = ln(x) / ln(b), so compute ln(b)
+ my $base_log_e = $base->copy()->_log_10($scale);
+ $x->bdiv($base_log_e, $scale);
}
}
@@ -2340,7 +2404,8 @@ sub bexp {
$params[2] = $r; # round mode by caller or undef
$fallback = 1; # to clear a/p afterwards
} else {
- # the 4 below is empirical, and there might be cases where it's not enough...
+ # the 4 below is empirical, and there might be cases where it's not
+ # enough ...
$scale = abs($params[0] || $params[1]) + 4; # take whatever is defined
}
@@ -2410,21 +2475,23 @@ sub bexp {
# -- + -- + -- + -- + -- + --- + --- + ---- = -----
# 1 1 2 6 24 120 720 5040 5040
- # Note that we cannot simple reduce 13700/5040 to 685/252, but must keep A and B!
+ # Note that we cannot simply reduce 13700/5040 to 685/252, but must keep
+ # the numerator and the denominator!
if ($scale <= 75) {
# set $x directly from a cached string form
- $x->{_m} = $MBI->_new(
- "27182818284590452353602874713526624977572470936999595749669676277240766303535476");
+ $x->{_m} = $LIB->_new("2718281828459045235360287471352662497757" .
+ "2470936999595749669676277240766303535476");
$x->{sign} = '+';
$x->{_es} = '-';
- $x->{_e} = $MBI->_new(79);
+ $x->{_e} = $LIB->_new(79);
} else {
# compute A and B so that e = A / B.
# After some terms we end up with this, so we use it as a starting point:
- my $A = $MBI->_new("90933395208605785401971970164779391644753259799242");
- my $F = $MBI->_new(42);
+ my $A = $LIB->_new("9093339520860578540197197" .
+ "0164779391644753259799242");
+ my $F = $LIB->_new(42);
my $step = 42;
# Compute how many steps we need to take to get $A and $B sufficiently big
@@ -2432,24 +2499,24 @@ sub bexp {
# print STDERR "# Doing $steps steps for ", $scale-4, " digits\n";
while ($step++ <= $steps) {
# calculate $a * $f + 1
- $A = $MBI->_mul($A, $F);
- $A = $MBI->_inc($A);
+ $A = $LIB->_mul($A, $F);
+ $A = $LIB->_inc($A);
# increment f
- $F = $MBI->_inc($F);
+ $F = $LIB->_inc($F);
}
# compute $B as factorial of $steps (this is faster than doing it manually)
- my $B = $MBI->_fac($MBI->_new($steps));
+ my $B = $LIB->_fac($LIB->_new($steps));
- # print "A ", $MBI->_str($A), "\nB ", $MBI->_str($B), "\n";
+ # print "A ", $LIB->_str($A), "\nB ", $LIB->_str($B), "\n";
# compute A/B with $scale digits in the result (truncate, not round)
- $A = $MBI->_lsft($A, $MBI->_new($scale), 10);
- $A = $MBI->_div($A, $B);
+ $A = $LIB->_lsft($A, $LIB->_new($scale), 10);
+ $A = $LIB->_div($A, $B);
$x->{_m} = $A;
$x->{sign} = '+';
$x->{_es} = '-';
- $x->{_e} = $MBI->_new($scale);
+ $x->{_e} = $LIB->_new($scale);
}
# $x contains now an estimate of e, with some surplus digits, so we can round
@@ -2502,16 +2569,20 @@ sub bnok {
return $x if $x->modify('bnok');
return $x->bnan() if $x->is_nan() || $y->is_nan();
- return $x->binf() if $x->is_inf();
+ return $x->bnan() if (($x->is_finite() && !$x->is_int()) ||
+ ($y->is_finite() && !$y->is_int()));
- my $u = $x->as_int();
- $u->bnok($y->as_int());
+ my $xint = Math::BigInt -> new($x -> bsstr());
+ my $yint = Math::BigInt -> new($y -> bsstr());
+ $xint -> bnok($yint);
+ my $xflt = Math::BigFloat -> new($xint);
- $x->{_m} = $u->{value};
- $x->{_e} = $MBI->_zero();
- $x->{_es} = '+';
- $x->{sign} = '+';
- $x->bnorm(@r);
+ $x->{_m} = $xflt->{_m};
+ $x->{_e} = $xflt->{_e};
+ $x->{_es} = $xflt->{_es};
+ $x->{sign} = $xflt->{sign};
+
+ return $x;
}
sub bsin {
@@ -2558,7 +2629,6 @@ sub bsin {
# need to disable $upgrade in BigInt, to avoid deep recursion
local $Math::BigInt::upgrade = undef;
- my $last = 0;
my $over = $x * $x; # X ^ 2
my $x2 = $over->copy(); # X ^ 2; difference between terms
$over->bmul($x); # X ^ 3 as starting value
@@ -2648,7 +2718,6 @@ sub bcos {
# need to disable $upgrade in BigInt, to avoid deep recursion
local $Math::BigInt::upgrade = undef;
- my $last = 0;
my $over = $x * $x; # X ^ 2
my $x2 = $over->copy(); # X ^ 2; difference between terms
my $sign = 1; # start with -=
@@ -2730,7 +2799,7 @@ sub batan {
$self->{_es} = $pi->{_es};
# -y => -PI/2, +y => PI/2
$self->{sign} = substr($self->{sign}, 0, 1); # "+inf" => "+"
- $self -> {_m} = $MBI->_div($self->{_m}, $MBI->_new(2));
+ $self -> {_m} = $LIB->_div($self->{_m}, $LIB->_new(2));
return $self;
}
@@ -2752,25 +2821,24 @@ sub batan {
# 1 or -1 => PI/4
# inlined is_one() && is_one('-')
- if ($MBI->_is_one($self->{_m}) && $MBI->_is_zero($self->{_e})) {
+ if ($LIB->_is_one($self->{_m}) && $LIB->_is_zero($self->{_e})) {
my $pi = $class->bpi($scale - 3);
# modify $self in place
$self->{_m} = $pi->{_m};
$self->{_e} = $pi->{_e};
$self->{_es} = $pi->{_es};
# leave the sign of $self alone (+1 => +PI/4, -1 => -PI/4)
- $self->{_m} = $MBI->_div($self->{_m}, $MBI->_new(4));
+ $self->{_m} = $LIB->_div($self->{_m}, $LIB->_new(4));
return $self;
}
# This series is only valid if -1 < x < 1, so for other x we need to
# calculate PI/2 - atan(1/x):
- my $one = $MBI->_new(1);
my $pi = undef;
if ($self->bacmp($self->copy()->bone) >= 0) {
# calculate PI/2
$pi = $class->bpi($scale - 3);
- $pi->{_m} = $MBI->_div($pi->{_m}, $MBI->_new(2));
+ $pi->{_m} = $LIB->_div($pi->{_m}, $LIB->_new(2));
# calculate 1/$self:
my $self_copy = $self->copy();
# modify $self in place
@@ -2779,7 +2847,7 @@ sub batan {
}
my $fmul = 1;
- foreach my $k (0 .. int($scale / 20)) {
+ foreach (0 .. int($scale / 20)) {
$fmul *= 2;
$self->bdiv($self->copy()->bmul($self)->binc->bsqrt($scale + 4)->binc, $scale + 4);
}
@@ -2796,7 +2864,6 @@ sub batan {
# Need to disable $upgrade in BigInt, to avoid deep recursion.
local $Math::BigInt::upgrade = undef;
- my $last = 0;
my $over = $self * $self; # X ^ 2
my $self2 = $over->copy(); # X ^ 2; difference between terms
$over->bmul($self); # X ^ 3 as starting value
@@ -2992,8 +3059,8 @@ sub bsqrt {
# need to disable $upgrade in BigInt, to avoid deep recursion
local $Math::BigInt::upgrade = undef; # should be really parent class vs MBI
- my $i = $MBI->_copy($x->{_m});
- $i = $MBI->_lsft($i, $x->{_e}, 10) unless $MBI->_is_zero($x->{_e});
+ my $i = $LIB->_copy($x->{_m});
+ $i = $LIB->_lsft($i, $x->{_e}, 10) unless $LIB->_is_zero($x->{_e});
my $xas = Math::BigInt->bzero();
$xas->{value} = $i;
@@ -3005,7 +3072,7 @@ sub bsqrt {
{
# exact result, copy result over to keep $x
$x->{_m} = $gs->{value};
- $x->{_e} = $MBI->_zero();
+ $x->{_e} = $LIB->_zero();
$x->{_es} = '+';
$x->bnorm();
# shortcut to not run through _find_round_parameters again
@@ -3030,9 +3097,9 @@ sub bsqrt {
# result of sqrt(input) by 10. Rounding afterwards returns the real result.
# The following steps will transform 123.456 (in $x) into 123456 (in $y1)
- my $y1 = $MBI->_copy($x->{_m});
+ my $y1 = $LIB->_copy($x->{_m});
- my $length = $MBI->_len($y1);
+ my $length = $LIB->_len($y1);
# Now calculate how many digits the result of sqrt(y1) would have
my $digits = int($length / 2);
@@ -3053,19 +3120,19 @@ sub bsqrt {
# steps of 10. The length of $x does not count, since an even or odd number
# of digits before the dot is not changed by adding an even number of digits
# after the dot (the result is still odd or even digits long).
- $s2++ if $MBI->_is_odd($x->{_e});
+ $s2++ if $LIB->_is_odd($x->{_e});
- $y1 = $MBI->_lsft($y1, $MBI->_new($s2), 10);
+ $y1 = $LIB->_lsft($y1, $LIB->_new($s2), 10);
# now take the square root and truncate to integer
- $y1 = $MBI->_sqrt($y1);
+ $y1 = $LIB->_sqrt($y1);
# By "shifting" $y1 right (by creating a negative _e) we calculate the final
# result, which is than later rounded to the desired scale.
# calculate how many zeros $x had after the '.' (or before it, depending
# on sign of $dat, the result should have half as many:
- my $dat = $MBI->_num($x->{_e});
+ my $dat = $LIB->_num($x->{_e});
$dat = -$dat if $x->{_es} eq '-';
$dat += $length;
@@ -3077,13 +3144,13 @@ sub bsqrt {
} else {
$dat = int(($dat)/2);
}
- $dat -= $MBI->_len($y1);
+ $dat -= $LIB->_len($y1);
if ($dat < 0) {
$dat = abs($dat);
- $x->{_e} = $MBI->_new($dat);
+ $x->{_e} = $LIB->_new($dat);
$x->{_es} = '-';
} else {
- $x->{_e} = $MBI->_new($dat);
+ $x->{_e} = $LIB->_new($dat);
$x->{_es} = '+';
}
$x->{_m} = $y1;
@@ -3163,7 +3230,7 @@ sub broot {
my $is_two = 0;
if ($y->isa('Math::BigFloat')) {
- $is_two = ($y->{sign} eq '+' && $MBI->_is_two($y->{_m}) && $MBI->_is_zero($y->{_e}));
+ $is_two = ($y->{sign} eq '+' && $LIB->_is_two($y->{_m}) && $LIB->_is_zero($y->{_e}));
} else {
$is_two = ($y == 2);
}
@@ -3184,8 +3251,8 @@ sub broot {
my $done = 0; # not yet
if ($y->is_int() && $x->is_int()) {
- my $i = $MBI->_copy($x->{_m});
- $i = $MBI->_lsft($i, $x->{_e}, 10) unless $MBI->_is_zero($x->{_e});
+ my $i = $LIB->_copy($x->{_m});
+ $i = $LIB->_lsft($i, $x->{_e}, 10) unless $LIB->_is_zero($x->{_e});
my $int = Math::BigInt->bzero();
$int->{value} = $i;
$int->broot($y->as_number());
@@ -3193,7 +3260,7 @@ sub broot {
if ($int->copy()->bpow($y) == $x) {
# found result, return it
$x->{_m} = $int->{value};
- $x->{_e} = $MBI->_zero();
+ $x->{_e} = $LIB->_zero();
$x->{_es} = '+';
$x->bnorm();
$done = 1;
@@ -3240,12 +3307,12 @@ sub bfac {
if (($x->{sign} ne '+') || # inf, NaN, <0 etc => NaN
($x->{_es} ne '+')); # digits after dot?
- if (! $MBI->_is_zero($x->{_e})) {
- $x->{_m} = $MBI->_lsft($x->{_m}, $x->{_e}, 10); # change 12e1 to 120e0
- $x->{_e} = $MBI->_zero(); # normalize
+ if (! $LIB->_is_zero($x->{_e})) {
+ $x->{_m} = $LIB->_lsft($x->{_m}, $x->{_e}, 10); # change 12e1 to 120e0
+ $x->{_e} = $LIB->_zero(); # normalize
$x->{_es} = '+';
}
- $x->{_m} = $MBI->_fac($x->{_m}); # calculate factorial
+ $x->{_m} = $LIB->_fac($x->{_m}); # calculate factorial
$x->bnorm()->round(@r); # norm again and round result
}
@@ -3264,15 +3331,15 @@ sub bdfac {
if (($x->{sign} ne '+') || # inf, NaN, <0 etc => NaN
($x->{_es} ne '+')); # digits after dot?
- Carp::croak("bdfac() requires a newer version of the $MBI library.")
- unless $MBI->can('_dfac');
+ croak("bdfac() requires a newer version of the $LIB library.")
+ unless $LIB->can('_dfac');
- if (! $MBI->_is_zero($x->{_e})) {
- $x->{_m} = $MBI->_lsft($x->{_m}, $x->{_e}, 10); # change 12e1 to 120e0
- $x->{_e} = $MBI->_zero(); # normalize
+ if (! $LIB->_is_zero($x->{_e})) {
+ $x->{_m} = $LIB->_lsft($x->{_m}, $x->{_e}, 10); # change 12e1 to 120e0
+ $x->{_e} = $LIB->_zero(); # normalize
$x->{_es} = '+';
}
- $x->{_m} = $MBI->_dfac($x->{_m}); # calculate factorial
+ $x->{_m} = $LIB->_dfac($x->{_m}); # calculate factorial
$x->bnorm()->round(@r); # norm again and round result
}
@@ -3337,8 +3404,8 @@ sub band {
my $xref = ref($x);
my $class = $xref || $x;
- Carp::croak 'band() is an instance method, not a class method' unless $xref;
- Carp::croak 'Not enough arguments for band()' if @_ < 1;
+ croak 'band() is an instance method, not a class method' unless $xref;
+ croak 'Not enough arguments for band()' if @_ < 1;
return if $x -> modify('band');
@@ -3364,8 +3431,8 @@ sub bior {
my $xref = ref($x);
my $class = $xref || $x;
- Carp::croak 'bior() is an instance method, not a class method' unless $xref;
- Carp::croak 'Not enough arguments for bior()' if @_ < 1;
+ croak 'bior() is an instance method, not a class method' unless $xref;
+ croak 'Not enough arguments for bior()' if @_ < 1;
return if $x -> modify('bior');
@@ -3391,8 +3458,8 @@ sub bxor {
my $xref = ref($x);
my $class = $xref || $x;
- Carp::croak 'bxor() is an instance method, not a class method' unless $xref;
- Carp::croak 'Not enough arguments for bxor()' if @_ < 1;
+ croak 'bxor() is an instance method, not a class method' unless $xref;
+ croak 'Not enough arguments for bxor()' if @_ < 1;
return if $x -> modify('bxor');
@@ -3418,7 +3485,7 @@ sub bnot {
my $xref = ref($x);
my $class = $xref || $x;
- Carp::croak 'bnot() is an instance method, not a class method' unless $xref;
+ croak 'bnot() is an instance method, not a class method' unless $xref;
return if $x -> modify('bnot');
@@ -3447,7 +3514,7 @@ sub bround {
$x = $class->new(shift) if !ref($x);
if (($_[0] || 0) < 0) {
- Carp::croak('bround() needs positive accuracy');
+ croak('bround() needs positive accuracy');
}
my ($scale, $mode) = $x->_scale_a(@_);
@@ -3466,7 +3533,7 @@ sub bround {
# 1: never round a 0
# 2: if we should keep more digits than the mantissa has, do nothing
- if ($x->is_zero() || $MBI->_len($x->{_m}) <= $scale) {
+ if ($x->is_zero() || $LIB->_len($x->{_m}) <= $scale) {
$x->{_a} = $scale if !defined $x->{_a} || $x->{_a} > $scale;
return $x;
}
@@ -3510,11 +3577,11 @@ sub bfround {
return $x if $x->{_es} eq '+'; # e >= 0 => nothing to round
$scale = -$scale; # positive for simplicity
- my $len = $MBI->_len($x->{_m}); # length of mantissa
+ my $len = $LIB->_len($x->{_m}); # length of mantissa
# the following poses a restriction on _e, but if _e is bigger than a
# scalar, you got other problems (memory etc) anyway
- my $dad = -(0+ ($x->{_es}.$MBI->_num($x->{_e}))); # digits after dot
+ my $dad = -(0+ ($x->{_es}.$LIB->_num($x->{_e}))); # digits after dot
my $zad = 0; # zeros after dot
$zad = $dad - $len if (-$dad < -$len); # for 0.00..00xxx style
@@ -3550,9 +3617,9 @@ sub bfround {
# 123 => 100 means length(123) = 3 - $scale (2) => 1
- my $dbt = $MBI->_len($x->{_m});
+ my $dbt = $LIB->_len($x->{_m});
# digits before dot
- my $dbd = $dbt + ($x->{_es} . $MBI->_num($x->{_e}));
+ my $dbd = $dbt + ($x->{_es} . $LIB->_num($x->{_e}));
# should be the same, so treat it as this
$scale = 1 if $scale == 0;
# shortcut if already integer
@@ -3586,10 +3653,10 @@ sub bfloor {
# if $x has digits after dot
if ($x->{_es} eq '-') {
- $x->{_m} = $MBI->_rsft($x->{_m}, $x->{_e}, 10); # cut off digits after dot
- $x->{_e} = $MBI->_zero(); # trunc/norm
+ $x->{_m} = $LIB->_rsft($x->{_m}, $x->{_e}, 10); # cut off digits after dot
+ $x->{_e} = $LIB->_zero(); # trunc/norm
$x->{_es} = '+'; # abs e
- $x->{_m} = $MBI->_inc($x->{_m}) if $x->{sign} eq '-'; # increment if negative
+ $x->{_m} = $LIB->_inc($x->{_m}) if $x->{sign} eq '-'; # increment if negative
}
$x->round($a, $p, $r);
}
@@ -3603,13 +3670,13 @@ sub bceil {
# if $x has digits after dot
if ($x->{_es} eq '-') {
- $x->{_m} = $MBI->_rsft($x->{_m}, $x->{_e}, 10); # cut off digits after dot
- $x->{_e} = $MBI->_zero(); # trunc/norm
+ $x->{_m} = $LIB->_rsft($x->{_m}, $x->{_e}, 10); # cut off digits after dot
+ $x->{_e} = $LIB->_zero(); # trunc/norm
$x->{_es} = '+'; # abs e
if ($x->{sign} eq '+') {
- $x->{_m} = $MBI->_inc($x->{_m}); # increment if positive
+ $x->{_m} = $LIB->_inc($x->{_m}); # increment if positive
} else {
- $x->{sign} = '+' if $MBI->_is_zero($x->{_m}); # avoid -0
+ $x->{sign} = '+' if $LIB->_is_zero($x->{_m}); # avoid -0
}
}
$x->round($a, $p, $r);
@@ -3624,10 +3691,10 @@ sub bint {
# if $x has digits after the decimal point
if ($x->{_es} eq '-') {
- $x->{_m} = $MBI->_rsft($x->{_m}, $x->{_e}, 10); # cut off digits after dot
- $x->{_e} = $MBI->_zero(); # truncate/normalize
+ $x->{_m} = $LIB->_rsft($x->{_m}, $x->{_e}, 10); # cut off digits after dot
+ $x->{_e} = $LIB->_zero(); # truncate/normalize
$x->{_es} = '+'; # abs e
- $x->{sign} = '+' if $MBI->_is_zero($x->{_m}); # avoid -0
+ $x->{sign} = '+' if $LIB->_is_zero($x->{_m}); # avoid -0
}
$x->round($a, $p, $r);
}
@@ -3698,13 +3765,13 @@ sub length {
my $class = ref($x) || $x;
$x = $class->new(shift) unless ref($x);
- return 1 if $MBI->_is_zero($x->{_m});
+ return 1 if $LIB->_is_zero($x->{_m});
- my $len = $MBI->_len($x->{_m});
- $len += $MBI->_num($x->{_e}) if $x->{_es} eq '+';
+ my $len = $LIB->_len($x->{_m});
+ $len += $LIB->_num($x->{_e}) if $x->{_es} eq '+';
if (wantarray()) {
my $t = 0;
- $t = $MBI->_num($x->{_e}) if $x->{_es} eq '-';
+ $t = $LIB->_num($x->{_e}) if $x->{_es} eq '-';
return ($len, $t);
}
$len;
@@ -3719,7 +3786,7 @@ sub mantissa {
$s =~ s/^[+]//;
return Math::BigInt->new($s, undef, undef); # -inf, +inf => +inf
}
- my $m = Math::BigInt->new($MBI->_str($x->{_m}), undef, undef);
+ my $m = Math::BigInt->new($LIB->_str($x->{_m}), undef, undef);
$m->bneg() if $x->{sign} eq '-';
$m;
@@ -3734,7 +3801,7 @@ sub exponent {
$s =~ s/^[+-]//;
return Math::BigInt->new($s, undef, undef); # -inf, +inf => +inf
}
- Math::BigInt->new($x->{_es} . $MBI->_str($x->{_e}), undef, undef);
+ Math::BigInt->new($x->{_es} . $LIB->_str($x->{_e}), undef, undef);
}
sub parts {
@@ -3749,16 +3816,16 @@ $se =~ s/^[-]//;
return ($class->new($s), $class->new($se)); # +inf => inf and -inf, +inf => inf
}
my $m = Math::BigInt->bzero();
- $m->{value} = $MBI->_copy($x->{_m});
+ $m->{value} = $LIB->_copy($x->{_m});
$m->bneg() if $x->{sign} eq '-';
- ($m, Math::BigInt->new($x->{_es} . $MBI->_num($x->{_e})));
+ ($m, Math::BigInt->new($x->{_es} . $LIB->_num($x->{_e})));
}
sub sparts {
my $self = shift;
my $class = ref $self;
- Carp::croak("sparts() is an instance method, not a class method")
+ croak("sparts() is an instance method, not a class method")
unless $class;
# Not-a-number.
@@ -3783,12 +3850,12 @@ sub sparts {
my $mant = $class -> bzero();
$mant -> {sign} = $self -> {sign};
- $mant -> {_m} = $MBI->_copy($self -> {_m});
+ $mant -> {_m} = $LIB->_copy($self -> {_m});
return $mant unless wantarray;
my $expo = $class -> bzero();
$expo -> {sign} = $self -> {_es};
- $expo -> {_m} = $MBI->_copy($self -> {_e});
+ $expo -> {_m} = $LIB->_copy($self -> {_e});
return ($mant, $expo);
}
@@ -3797,7 +3864,7 @@ sub nparts {
my $self = shift;
my $class = ref $self;
- Carp::croak("nparts() is an instance method, not a class method")
+ croak("nparts() is an instance method, not a class method")
unless $class;
# Not-a-number.
@@ -3843,7 +3910,7 @@ sub eparts {
my $self = shift;
my $class = ref $self;
- Carp::croak("eparts() is an instance method, not a class method")
+ croak("eparts() is an instance method, not a class method")
unless $class;
# Not-a-number and Infinity.
@@ -3866,7 +3933,7 @@ sub dparts {
my $self = shift;
my $class = ref $self;
- Carp::croak("dparts() is an instance method, not a class method")
+ croak("dparts() is an instance method, not a class method")
unless $class;
# Not-a-number and Infinity.
@@ -3884,10 +3951,10 @@ sub dparts {
# If the input has a fraction part.
if ($int->{_es} eq '-') {
- $int->{_m} = $MBI -> _rsft($int->{_m}, $int->{_e}, 10);
- $int->{_e} = $MBI -> _zero();
+ $int->{_m} = $LIB -> _rsft($int->{_m}, $int->{_e}, 10);
+ $int->{_e} = $LIB -> _zero();
$int->{_es} = '+';
- $int->{sign} = '+' if $MBI->_is_zero($int->{_m}); # avoid -0
+ $int->{sign} = '+' if $LIB->_is_zero($int->{_m}); # avoid -0
return $int unless wantarray;
$frc = $self -> copy() -> bsub($int);
@@ -3919,11 +3986,11 @@ my $cad = 0;
my $dot = '.';
# $x is zero?
- my $not_zero = !($x->{sign} eq '+' && $MBI->_is_zero($x->{_m}));
+ my $not_zero = !($x->{sign} eq '+' && $LIB->_is_zero($x->{_m}));
if ($not_zero) {
- $es = $MBI->_str($x->{_m});
+ $es = $LIB->_str($x->{_m});
$len = CORE::length($es);
- my $e = $MBI->_num($x->{_e});
+ my $e = $LIB->_num($x->{_e});
$e = -$e if $x->{_es} eq '-';
if ($e < 0) {
$dot = '';
@@ -3934,7 +4001,7 @@ my $dot = '.';
$cad = -($len+$r);
} else {
substr($es, $e, 0) = '.';
- $cad = $MBI->_num($x->{_e});
+ $cad = $LIB->_num($x->{_e});
$cad = -$cad if $x->{_es} eq '-';
}
} elsif ($e > 0) {
@@ -3970,7 +4037,7 @@ sub bdstr {
return 'inf'; # +inf
}
- my $mant = $MBI->_str($x->{_m});
+ my $mant = $LIB->_str($x->{_m});
my $expo = $x -> exponent();
my $str = $mant;
@@ -3997,7 +4064,7 @@ sub bsstr {
return 'inf'; # +inf
}
- my $str = $MBI->_str($x->{_m}) . 'e' . $x->{_es}. $MBI->_str($x->{_e});
+ my $str = $LIB->_str($x->{_m}) . 'e' . $x->{_es}. $LIB->_str($x->{_e});
return $x->{sign} eq '-' ? "-$str" : $str;
}
@@ -4049,11 +4116,11 @@ sub to_hex {
return $nan if $x->{_es} ne '+'; # how to do 1e-1 in hex?
- my $z = $MBI->_copy($x->{_m});
- if (! $MBI->_is_zero($x->{_e})) { # > 0
- $z = $MBI->_lsft($z, $x->{_e}, 10);
+ my $z = $LIB->_copy($x->{_m});
+ if (! $LIB->_is_zero($x->{_e})) { # > 0
+ $z = $LIB->_lsft($z, $x->{_e}, 10);
}
- my $str = $MBI->_to_hex($z);
+ my $str = $LIB->_to_hex($z);
return $x->{sign} eq '-' ? "-$str" : $str;
}
@@ -4067,11 +4134,11 @@ sub to_oct {
return $nan if $x->{_es} ne '+'; # how to do 1e-1 in octal?
- my $z = $MBI->_copy($x->{_m});
- if (! $MBI->_is_zero($x->{_e})) { # > 0
- $z = $MBI->_lsft($z, $x->{_e}, 10);
+ my $z = $LIB->_copy($x->{_m});
+ if (! $LIB->_is_zero($x->{_e})) { # > 0
+ $z = $LIB->_lsft($z, $x->{_e}, 10);
}
- my $str = $MBI->_to_oct($z);
+ my $str = $LIB->_to_oct($z);
return $x->{sign} eq '-' ? "-$str" : $str;
}
@@ -4085,11 +4152,11 @@ sub to_bin {
return $nan if $x->{_es} ne '+'; # how to do 1e-1 in binary?
- my $z = $MBI->_copy($x->{_m});
- if (! $MBI->_is_zero($x->{_e})) { # > 0
- $z = $MBI->_lsft($z, $x->{_e}, 10);
+ my $z = $LIB->_copy($x->{_m});
+ if (! $LIB->_is_zero($x->{_e})) { # > 0
+ $z = $LIB->_lsft($z, $x->{_e}, 10);
}
- my $str = $MBI->_to_bin($z);
+ my $str = $LIB->_to_bin($z);
return $x->{sign} eq '-' ? "-$str" : $str;
}
@@ -4103,11 +4170,11 @@ sub as_hex {
return $nan if $x->{_es} ne '+'; # how to do 1e-1 in hex?
- my $z = $MBI->_copy($x->{_m});
- if (! $MBI->_is_zero($x->{_e})) { # > 0
- $z = $MBI->_lsft($z, $x->{_e}, 10);
+ my $z = $LIB->_copy($x->{_m});
+ if (! $LIB->_is_zero($x->{_e})) { # > 0
+ $z = $LIB->_lsft($z, $x->{_e}, 10);
}
- my $str = $MBI->_as_hex($z);
+ my $str = $LIB->_as_hex($z);
return $x->{sign} eq '-' ? "-$str" : $str;
}
@@ -4121,11 +4188,11 @@ sub as_oct {
return $nan if $x->{_es} ne '+'; # how to do 1e-1 in octal?
- my $z = $MBI->_copy($x->{_m});
- if (! $MBI->_is_zero($x->{_e})) { # > 0
- $z = $MBI->_lsft($z, $x->{_e}, 10);
+ my $z = $LIB->_copy($x->{_m});
+ if (! $LIB->_is_zero($x->{_e})) { # > 0
+ $z = $LIB->_lsft($z, $x->{_e}, 10);
}
- my $str = $MBI->_as_oct($z);
+ my $str = $LIB->_as_oct($z);
return $x->{sign} eq '-' ? "-$str" : $str;
}
@@ -4139,11 +4206,11 @@ sub as_bin {
return $nan if $x->{_es} ne '+'; # how to do 1e-1 in binary?
- my $z = $MBI->_copy($x->{_m});
- if (! $MBI->_is_zero($x->{_e})) { # > 0
- $z = $MBI->_lsft($z, $x->{_e}, 10);
+ my $z = $LIB->_copy($x->{_m});
+ if (! $LIB->_is_zero($x->{_e})) { # > 0
+ $z = $LIB->_lsft($z, $x->{_e}, 10);
}
- my $str = $MBI->_as_bin($z);
+ my $str = $LIB->_as_bin($z);
return $x->{sign} eq '-' ? "-$str" : $str;
}
@@ -4199,7 +4266,7 @@ my @a;
} elsif ($_[$i] eq 'with') {
# alternative class for our private parts()
# XXX: no longer supported
- # $MBI = $_[$i+1] || 'Math::BigInt';
+ # $LIB = $_[$i+1] || 'Math::BigInt';
$i++;
} else {
push @a, $_[$i];
@@ -4209,11 +4276,11 @@ my @a;
$lib =~ tr/a-zA-Z0-9,://cd; # restrict to sane characters
# let use Math::BigInt lib => 'GMP'; use Math::BigFloat; still work
my $mbilib = eval { Math::BigInt->config('lib') };
- if ((defined $mbilib) && ($MBI eq 'Math::BigInt::Calc')) {
- # MBI already loaded
+ if ((defined $mbilib) && ($LIB eq 'Math::BigInt::Calc')) {
+ # $LIB already loaded
Math::BigInt->import($lib_kind, "$lib, $mbilib", 'objectify');
} else {
- # MBI not loaded, or with ne "Math::BigInt::Calc"
+ # $LIB not loaded, or with ne "Math::BigInt::Calc"
$lib .= ",$mbilib" if defined $mbilib;
$lib =~ s/^,//; # don't leave empty
@@ -4225,13 +4292,13 @@ my @a;
Math::BigInt->import($lib_kind => $lib, 'objectify');
}
if ($@) {
- Carp::croak("Couldn't load $lib: $! $@");
+ croak("Couldn't load $lib: $! $@");
}
# find out which one was actually loaded
- $MBI = Math::BigInt->config('lib');
+ $LIB = Math::BigInt->config('lib');
# register us with MBI to get notified of future lib changes
- Math::BigInt::_register_callback($class, sub { $MBI = $_[0]; });
+ Math::BigInt::_register_callback($class, sub { $LIB = $_[0]; });
$class->export_to_level(1, $class, @a); # export wanted functions
}
@@ -4268,7 +4335,8 @@ my $r = $d;
sub _log {
# internal log function to calculate ln() based on Taylor series.
# Modifies $x in place.
- my ($class, $x, $scale) = @_;
+ my ($x, $scale) = @_;
+ my $class = ref $x;
# in case of $x == 1, result is 0
return $x->bzero() if $x->is_one();
@@ -4290,7 +4358,7 @@ sub _log {
# ln (x) = 2 | --- + - * --- + - * --- + ... | x > 1/2
# |_ x 2 x^2 3 x^3 _|
- my ($limit, $v, $u, $below, $factor, $two, $next, $over, $f);
+ my ($limit, $v, $u, $below, $factor, $next, $over, $f);
$v = $x->copy(); $v->binc(); # v = x+1
$x->bdec(); $u = $x->copy(); # u = x-1; x = x-1
@@ -4304,6 +4372,7 @@ sub _log {
my $steps = 0;
$limit = $class->new("1E-". ($scale-1));
+
while (3 < 5) {
# we calculate the next term, and add it to the last
# when the next term is below our limit, it won't affect the outcome
@@ -4337,19 +4406,15 @@ sub _log {
$over *= $u;
$below *= $v;
$factor->badd($f);
- if (DEBUG) {
- $steps++;
- print "step $steps = $x\n" if $steps % 10 == 0;
- }
}
- print "took $steps steps\n" if DEBUG;
$x->bmul($f); # $x *= 2
}
sub _log_10 {
# Internal log function based on reducing input to the range of 0.1 .. 9.99
# and then "correcting" the result to the proper one. Modifies $x in place.
- my ($class, $x, $scale) = @_;
+ my ($x, $scale) = @_;
+ my $class = ref $x;
# Taking blog() from numbers greater than 10 takes a *very long* time, so we
# break the computation down into parts based on the observation that:
@@ -4365,16 +4430,18 @@ sub _log_10 {
# To get $x even closer to 1, we also divide by 2 and then use log(2) to
# correct for this. For instance if $x is 2.4, we use the formula:
- # blog(2.4 * 2) == blog (1.2) + blog(2)
+ # blog(2.4 * 2) == blog(1.2) + blog(2)
# and thus calculate only blog(1.2) and blog(2), which is faster in total
# than calculating blog(2.4).
# In addition, the values for blog(2) and blog(10) are cached.
- # Calculate nr of digits before dot:
- my $dbd = $MBI->_num($x->{_e});
+ # Calculate nr of digits before dot. x = 123, dbd = 3; x = 1.23, dbd = 1;
+ # x = 0.0123, dbd = -1; x = 0.000123, dbd = -3, etc.
+
+ my $dbd = $LIB->_num($x->{_e});
$dbd = -$dbd if $x->{_es} eq '-';
- $dbd += $MBI->_len($x->{_m});
+ $dbd += $LIB->_len($x->{_m});
# more than one digit (e.g. at least 10), but *not* exactly 10 to avoid
# infinite recursion
@@ -4383,7 +4450,10 @@ sub _log_10 {
# disable the shortcut for 10, since we need log(10) and this would recurse
# infinitely deep
- if ($x->{_es} eq '+' && $MBI->_is_one($x->{_e}) && $MBI->_is_one($x->{_m})) {
+ if ($x->{_es} eq '+' && # $x == 10
+ ($LIB->_is_one($x->{_e}) &&
+ $LIB->_is_one($x->{_m})))
+ {
$dbd = 0; # disable shortcut
# we can use the cached value in these cases
if ($scale <= $LOG_10_A) {
@@ -4394,7 +4464,9 @@ sub _log_10 {
# if we can't use the shortcut, we continue normally
} else {
# disable the shortcut for 2, since we maybe have it cached
- if (($MBI->_is_zero($x->{_e}) && $MBI->_is_two($x->{_m}))) {
+ if (($LIB->_is_zero($x->{_e}) && # $x == 2
+ $LIB->_is_two($x->{_m})))
+ {
$dbd = 0; # disable shortcut
# we can use the cached value in these cases
if ($scale <= $LOG_2_A) {
@@ -4407,8 +4479,11 @@ sub _log_10 {
}
# if $x = 0.1, we know the result must be 0-log(10)
- if ($calc != 0 && $x->{_es} eq '-' && $MBI->_is_one($x->{_e}) &&
- $MBI->_is_one($x->{_m})) {
+ if ($calc != 0 &&
+ ($x->{_es} eq '-' && # $x == 0.1
+ ($LIB->_is_one($x->{_e}) &&
+ $LIB->_is_one($x->{_m}))))
+ {
$dbd = 0; # disable shortcut
# we can use the cached value in these cases
if ($scale <= $LOG_10_A) {
@@ -4418,7 +4493,7 @@ sub _log_10 {
}
}
- return if $calc == 0; # already have the result
+ return $x if $calc == 0; # already have the result
# default: these correction factors are undef and thus not used
my $l_10; # value of ln(10) to A of $scale
@@ -4459,7 +4534,7 @@ sub _log_10 {
} else {
# else: slower, compute and cache result
$l_2 = $two->copy();
- $class->_log($l_2, $scale); # scale+4, actually
+ $l_2->_log($scale); # scale+4, actually
$LOG_2 = $l_2->copy(); # cache the result for later
# the copy() is for mul below
$LOG_2_A = $scale;
@@ -4467,7 +4542,7 @@ sub _log_10 {
# now calculate log(1.25):
$l_10 = $class->new('1.25');
- $class->_log($l_10, $scale); # scale+4, actually
+ $l_10->_log($scale); # scale+4, actually
# log(1.25) + log(2) + log(2) + log(2):
$l_10->badd($l_2);
@@ -4485,7 +4560,7 @@ sub _log_10 {
$dbd_sign = '-';
}
($x->{_e}, $x->{_es}) =
- _e_sub($x->{_e}, $MBI->_new($dbd), $x->{_es}, $dbd_sign); # 123 => 1.23
+ _e_sub($x->{_e}, $LIB->_new($dbd), $x->{_es}, $dbd_sign); # 123 => 1.23
}
@@ -4518,7 +4593,7 @@ sub _log_10 {
# also disable downgrade for this code path
local $Math::BigFloat::downgrade = undef;
$l_2 = $two->copy();
- $class->_log($l_2, $scale); # scale+4, actually
+ $l_2->_log($scale); # scale+4, actually
$LOG_2 = $l_2->copy(); # cache the result for later
# the copy() is for mul below
$LOG_2_A = $scale;
@@ -4528,7 +4603,7 @@ sub _log_10 {
undef $l_2;
}
- $class->_log($x, $scale); # need to do the "normal" way
+ $x->_log($scale); # need to do the "normal" way
$x->badd($l_10) if defined $l_10; # correct it by ln(10)
$x->badd($l_2) if defined $l_2; # and maybe by ln(2)
@@ -4538,39 +4613,39 @@ sub _log_10 {
sub _e_add {
# Internal helper sub to take two positive integers and their signs and
- # then add them. Input ($CALC, $CALC, ('+'|'-'), ('+'|'-')), output
- # ($CALC, ('+'|'-')).
+ # then add them. Input ($LIB, $LIB, ('+'|'-'), ('+'|'-')), output
+ # ($LIB, ('+'|'-')).
my ($x, $y, $xs, $ys) = @_;
# if the signs are equal we can add them (-5 + -3 => -(5 + 3) => -8)
if ($xs eq $ys) {
- $x = $MBI->_add($x, $y); # +a + +b or -a + -b
+ $x = $LIB->_add($x, $y); # +a + +b or -a + -b
} else {
- my $a = $MBI->_acmp($x, $y);
+ my $a = $LIB->_acmp($x, $y);
if ($a == 0) {
# This does NOT modify $x in-place. TODO: Fix this?
- $x = $MBI->_zero(); # result is 0
+ $x = $LIB->_zero(); # result is 0
$xs = '+';
return ($x, $xs);
}
if ($a > 0) {
- $x = $MBI->_sub($x, $y); # abs sub
+ $x = $LIB->_sub($x, $y); # abs sub
} else { # a < 0
- $x = $MBI->_sub ($y, $x, 1); # abs sub
+ $x = $LIB->_sub ($y, $x, 1); # abs sub
$xs = $ys;
}
}
- $xs = '+' if $xs eq '-' && $MBI->_is_zero($x); # no "-0"
+ $xs = '+' if $xs eq '-' && $LIB->_is_zero($x); # no "-0"
return ($x, $xs);
}
sub _e_sub {
# Internal helper sub to take two positive integers and their signs and
- # then subtract them. Input ($CALC, $CALC, ('+'|'-'), ('+'|'-')),
- # output ($CALC, ('+'|'-'))
+ # then subtract them. Input ($LIB, $LIB, ('+'|'-'), ('+'|'-')),
+ # output ($LIB, ('+'|'-'))
my ($x, $y, $xs, $ys) = @_;
# flip sign
@@ -4706,7 +4781,7 @@ Math::BigFloat - Arbitrary size floating point math package
Math::BigFloat->round_mode($m); # set global round mode, must be one of
# 'even', 'odd', '+inf', '-inf', 'zero',
# 'trunc', or 'common'
- Math::BigFloat->config(); # return hash with configuration
+ Math::BigFloat->config("lib"); # name of backend math library
# Constructor methods (when the class methods below are used as instance
# methods, the value is assigned the invocand)
@@ -4791,7 +4866,7 @@ Math::BigFloat - Arbitrary size floating point math package
$x->bcos(); # cosine
$x->batan(); # inverse tangent
$x->batan2($y); # two-argument inverse tangent
- $x->bsqrt(); # calculate square-root
+ $x->bsqrt(); # calculate square root
$x->broot($y); # $y'th root of $x (e.g. $y == 3 => cubic root)
$x->bfac(); # factorial of $x (1*2*3*4*..$x)
@@ -5062,7 +5137,7 @@ This method was added in v1.87 of Math::BigInt (June 2007).
In scalar context, divides $x by $y and returns the result to the given or
default accuracy/precision. In list context, does floored division
(F-division), returning an integer $q and a remainder $r so that $x = $q * $y +
-$r. The remainer (modulo) is equal to what is returned by C<$x->bmod($y)>.
+$r. The remainer (modulo) is equal to what is returned by C<< $x->bmod($y) >>.
=item bmod()