my $LOG_2 =
'0.6931471805599453094172321214581765680755001343602552541206800094933936220';
my $LOG_2_A = length($LOG_2)-1;
+my $HALF = '0.5'; # made into an object if necc.
##############################################################################
# the old code had $rnd_mode, so we need to support it, too
### Since $x in the range 0.5 .. 1.5 is MUCH faster, we do a repeated div
### or mul by 2 (maximum times 3, since x < 10 and x > 0.1)
- my $half = $self->new('0.5');
+ $HALF = $self->new($HALF) unless ref($HALF);
+
my $twos = 0; # default: none (0 times)
my $two = $self->new(2);
- while ($x->bacmp($half) <= 0)
+ while ($x->bacmp($HALF) <= 0)
{
$twos--; $x->bmul($two);
}
local $Math::BigInt::upgrade = undef; # should be really parent class vs MBI
# remember sign and make $x positive, since -4 ** (1/2) => -2
- my $sign = 0; $sign = 1 if $x->{sign} eq '-'; $x->babs();
+ my $sign = 0; $sign = 1 if $x->{sign} eq '-'; $x->{sign} = '+';
+
+ my $is_two = 0;
+ if ($y->isa('Math::BigFloat'))
+ {
+ $is_two = ($y->{sign} eq '+' && $MBI->_is_two($y->{_m}) && $MBI->_is_zero($y->{_e}));
+ }
+ else
+ {
+ $is_two = ($y == 2);
+ }
- if ($y->bcmp(2) == 0) # normal square root
+ # normal square root if $y == 2:
+ if ($is_two)
{
$x->bsqrt($scale+4);
}
my $self = ref($x);
# if $y == 0.5, it is sqrt($x)
- return $x->bsqrt($a,$p,$r,$y) if $y->bcmp('0.5') == 0;
+ $HALF = $self->new($HALF) unless ref($HALF);
+ return $x->bsqrt($a,$p,$r,$y) if $y->bcmp($HALF) == 0;
# Using:
# a ** x == e ** (x * ln a)
if ($MBI->_acmp($x->{_e},$z) >= 0)
{
$x->{_e} = $MBI->_sub ($x->{_e}, $z);
+ $x->{_es} = '+' if $MBI->_is_zero($x->{_e});
}
else
{
--- /dev/null
+#!/usr/bin/perl -w
+
+# test the helper math routines in Math::BigFloat
+
+use Test::More;
+use strict;
+
+BEGIN
+ {
+ $| = 1;
+ # to locate the testing files
+ my $location = $0; $location =~ s/_e_math.t//i;
+ if ($ENV{PERL_CORE})
+ {
+ # testing with the core distribution
+ @INC = qw(../lib);
+ }
+ unshift @INC, '../lib';
+ if (-d 't')
+ {
+ chdir 't';
+ require File::Spec;
+ unshift @INC, File::Spec->catdir(File::Spec->updir, $location);
+ }
+ else
+ {
+ unshift @INC, $location;
+ }
+ print "# INC = @INC\n";
+
+ plan tests => 26;
+ }
+
+use Math::BigFloat;
+
+#############################################################################
+# add
+
+my $a = Math::BigInt::Calc->_new("123");
+my $b = Math::BigInt::Calc->_new("321");
+
+my ($x, $xs) = Math::BigFloat::_e_add($a,$b,'+','+');
+is (_str($x,$xs), '+444', 'add two positive numbers');
+is (_str($a,''), '444', 'a modified');
+
+($x,$xs) = _add (123,321,'+','+');
+is (_str($x,$xs), '+444', 'add two positive numbers');
+
+($x,$xs) = _add (123,321,'+','-');
+is (_str($x,$xs), '-198', 'add +x + -y');
+($x,$xs) = _add (123,321,'-','+');
+is (_str($x,$xs), '+198', 'add -x + +y');
+
+($x,$xs) = _add (321,123,'-','+');
+is (_str($x,$xs), '-198', 'add -x + +y');
+($x,$xs) = _add (321,123,'+','-');
+is (_str($x,$xs), '+198', 'add +x + -y');
+
+($x,$xs) = _add (10,1,'+','-');
+is (_str($x,$xs), '+9', 'add 10 + -1');
+($x,$xs) = _add (10,1,'-','+');
+is (_str($x,$xs), '-9', 'add -10 + +1');
+($x,$xs) = _add (1,10,'-','+');
+is (_str($x,$xs), '+9', 'add -1 + 10');
+($x,$xs) = _add (1,10,'+','-');
+is (_str($x,$xs), '-9', 'add 1 + -10');
+
+#############################################################################
+# sub
+
+$a = Math::BigInt::Calc->_new("123");
+$b = Math::BigInt::Calc->_new("321");
+($x, $xs) = Math::BigFloat::_e_sub($b,$a,'+','+');
+is (_str($x,$xs), '+198', 'sub two positive numbers');
+is (_str($b,''), '198', 'a modified');
+
+($x,$xs) = _sub (123,321,'+','-');
+is (_str($x,$xs), '+444', 'sub +x + -y');
+($x,$xs) = _sub (123,321,'-','+');
+is (_str($x,$xs), '-444', 'sub -x + +y');
+
+sub _add
+ {
+ my ($a,$b,$as,$bs) = @_;
+
+ my $aa = Math::BigInt::Calc->_new($a);
+ my $bb = Math::BigInt::Calc->_new($b);
+ my ($x, $xs) = Math::BigFloat::_e_add($aa,$bb,$as,$bs);
+ is (Math::BigInt::Calc->_str($x), Math::BigInt::Calc->_str($aa),
+ 'param0 modified');
+ ($x,$xs);
+ }
+
+sub _sub
+ {
+ my ($a,$b,$as,$bs) = @_;
+
+ my $aa = Math::BigInt::Calc->_new($a);
+ my $bb = Math::BigInt::Calc->_new($b);
+ my ($x, $xs) = Math::BigFloat::_e_sub($aa,$bb,$as,$bs);
+ is (Math::BigInt::Calc->_str($x), Math::BigInt::Calc->_str($aa),
+ 'param0 modified');
+ ($x,$xs);
+ }
+
+sub _str
+ {
+ my ($x,$s) = @_;
+
+ $s . Math::BigInt::Calc->_str($x);
+ }