# _a : accuracy
# _p : precision
-$VERSION = '1.50';
+$VERSION = '1.51';
require 5.005;
require Exporter;
my $z = $MBI->_new($zeros);
# turn '120e2' into '12e3'
$MBI->_rsft ( $self->{_m}, $z, 10);
- _e_add ( $self->{_e}, $z, $self->{_es}, '+');
+ ($self->{_e}, $self->{_es}) =
+ _e_add ( $self->{_e}, $z, $self->{_es}, '+');
}
}
$self->{sign} = $$mis;
# already handled inf/NaN/-inf above:
- my $xsign = $x->{sign};
- $y->{sign} =~ tr/+-/-+/;
-
# 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}));
+ # 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:
+ my $xsign = $x->{sign};
+ $y->{sign} =~ tr/+-/-+/;
+
if ($xsign ne $x->{sign})
{
# special case of $x /= $x results in 1
return $x;
}
- return $x->bzero() if $x->is_zero() ||
- # check that $y == -1 or +1:
- ($MBI->_is_zero($y->{_e}) && $MBI->_is_one($y->{_m}));
+ 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})));
my $cmp = $x->bacmp($y); # equal or $x < $y?
return $x->bzero($a,$p) if $cmp == 0; # $x == $y => result 0
use vars qw/$VERSION/;
-$VERSION = '0.46';
+$VERSION = '0.47';
# Package to store unsigned big integers in decimal and do math with them
# now calculate $x / $yorg
if (length(int($yorg->[-1])) == length(int($x->[-1])))
{
-
- # We take a shortcut here, because the result must be
- # between 1 and MAX_VAL (e.g. one element) and rem is not wanted.
- if (!wantarray)
- {
- # fit's into one Perl scalar, so result can be computed directly
- # cannot use int() here, because it rounds wrongly on some systems
- #$x->[0] = int($x->[-1] / $yorg->[-1]);
-
- # Due to chopping up the number into parts, the two first parts
- # may have only one or two digits. So we use more from the second
- # parts (it always has at least two parts) for more accuracy:
- # Round to 8 digits, then truncate result to integer:
- my $x0 = $x->[-1];
- my $y0 = $yorg->[-1];
- if (length ($x0) < $BASE_LEN) # len($x0) == len($y0)!
- {
- $x0 .= substr('0' x $BASE_LEN . $x->[-2], -$BASE_LEN, $BASE_LEN);
- $x0 = substr($x0,0,$BASE_LEN);
- $y0 .= substr('0' x $BASE_LEN . $yorg->[-2], -$BASE_LEN, $BASE_LEN);
- $y0 = substr($y0,0,$BASE_LEN);
- }
- $x->[0] = int ( sprintf ("%.8f", $x0 / $y0 ) );
-
- splice(@$x,1); # keep single element
- return $x;
- }
-
- # wantarray: return (x,rem)
# same length, so make full compare
my $a = 0; my $j = scalar @$x - 1;
splice(@$x,1); # keep single element
$x->[0] = 0; # if $a < 0
$x->[0] = 1 if $a == 0; # $x == $y
- return ($x,$rem);
+ return ($x,$rem) if wantarray;
+ return $x;
}
# $x >= $y, so proceed normally
}
if (length(int($yorg->[-1])) == length(int($x->[-1])))
{
-
- # We take a shortcut here, because the result must be
- # between 1 and MAX_VAL (e.g. one element) and rem is not wanted.
- if (!wantarray)
- {
- # fit's into one Perl scalar, so result can be computed directly
- # cannot use int() here, because it rounds wrongly on some systems
- #$x->[0] = int($x->[-1] / $yorg->[-1]);
-
- # Due to chopping up the number into parts, the two first parts
- # may have only one or two digits. So we use more from the second
- # parts (it always has at least two parts) for more accuracy:
- # Round to 8 digits, then truncate result to integer:
- my $x0 = $x->[-1];
- my $y0 = $yorg->[-1];
- if (length ($x0) < $BASE_LEN) # len($x0) == len($y0)!
- {
- $x0 .= substr('0' x $BASE_LEN . $x->[-2], -$BASE_LEN, $BASE_LEN);
- $x0 = substr($x0,0,$BASE_LEN);
- $y0 .= substr('0' x $BASE_LEN . $yorg->[-2], -$BASE_LEN, $BASE_LEN);
- $y0 = substr($y0,0,$BASE_LEN);
- }
- $x->[0] = int ( sprintf ("%.8f", $x0 / $y0 ) );
-
- splice(@$x,1); # keep single element
- return $x;
- }
-
- # wantarray: return (x,rem)
# same length, so make full compare
my $a = 0; my $j = scalar @$x - 1;
splice(@$x,1); # keep single element
$x->[0] = 0; # if $a < 0
$x->[0] = 1 if $a == 0; # $x == $y
- return ($x,$rem);
+ return ($x,$rem) if wantarray; # including remainder?
+ return $x;
}
# $x >= $y, so proceed normally