}
return $downgrade->new("$$mis$$miv$$mfv"."E$$es$$ev");
}
-
- # print "mbf new $self->{sign} $self->{_m} e $self->{_e}\n";
+ # print "mbf new $self->{sign} $self->{_m} e $self->{_e} ",ref($self),"\n";
$self->bnorm()->round(@r); # first normalize, then round
}
$self->{_e} = Math::BigInt->bone();
}
+sub isa
+ {
+ my ($self,$class) = @_;
+ return if $class eq 'Math::BigInt'; # we aren't
+ return UNIVERSAL::isa($self,$class);
+ }
+
##############################################################################
# string conversation
# http://www.efunda.com/math/taylor_series/logarithmic.cfm?search_string=log
- # u = x-1, v = x +1
+ # u = x-1, v = x+1
# _ _
- # taylor: | u 1 u^3 1 u^5 |
+ # Taylor: | u 1 u^3 1 u^5 |
# ln (x) = 2 | --- + - * --- + - * --- + ... | x > 0
# |_ v 3 v^3 5 v^5 _|
+ # This takes much more steps to calculate the result:
+ # u = x-1
+ # _ _
+ # Taylor: | u 1 u^2 1 u^3 |
+ # ln (x) = 2 | --- + - * --- + - * --- + ... | x > 1/2
+ # |_ x 2 x^2 3 x^3 _|
+
# we need to limit the accuracy to protect against overflow
my $fallback = 0;
my $scale = 0;
# we also need to disable any set A or P on $x (_find_round_parameters took
# them already into account), since these would interfere, too
delete $x->{_a}; delete $x->{_p};
- # need to disable $upgrade in BigInt, to aoid deep recursion
+ # need to disable $upgrade in BigInt, to avoid deep recursion
local $Math::BigInt::upgrade = undef;
-
- my $v = $x->copy(); $v->binc(); # v = x+1
- $x->bdec(); my $u = $x->copy(); # u = x-1; x = x-1
-
- $x->bdiv($v,$scale); # first term: u/v
-
- my $below = $v->copy();
- my $over = $u->copy();
- $u *= $u; $v *= $v; # u^2, v^2
- $below->bmul($v); # u^3, v^3
- $over->bmul($u);
- my $factor = $self->new(3); my $two = $self->new(2);
-
- my $diff = $self->bone();
- my $limit = $self->new("1E-". ($scale-1)); my $last;
- # print "diff $diff limit $limit\n";
- while ($diff->bcmp($limit) > 0)
- {
- #print "$x $over $below $factor\n";
- $diff = $x->copy()->bsub($last)->babs();
- #print "diff $diff $limit\n";
- $last = $x->copy();
- $x += $over->copy()->bdiv($below->copy()->bmul($factor),$scale);
- $over *= $u; $below *= $v; $factor->badd($two);
- }
- $x->bmul($two);
+
+ my ($case,$limit,$v,$u,$below,$factor,$two,$next,$over,$f);
+
+ if (3 < 5)
+ #if ($x <= Math::BigFloat->new("0.5"))
+ {
+ $case = 0;
+ # print "case $case $x < 0.5\n";
+ $v = $x->copy(); $v->binc(); # v = x+1
+ $x->bdec(); $u = $x->copy(); # u = x-1; x = x-1
+ $x->bdiv($v,$scale); # first term: u/v
+ $below = $v->copy();
+ $over = $u->copy();
+ $u *= $u; $v *= $v; # u^2, v^2
+ $below->bmul($v); # u^3, v^3
+ $over->bmul($u);
+ $factor = $self->new(3); $f = $self->new(2);
+ }
+ #else
+ # {
+ # $case = 1;
+ # print "case 1 $x > 0.5\n";
+ # $v = $x->copy(); # v = x
+ # $u = $x->copy(); $u->bdec(); # u = x-1;
+ # $x->bdec(); $x->bdiv($v,$scale); # first term: x-1/x
+ # $below = $v->copy();
+ # $over = $u->copy();
+ # $below->bmul($v); # u^2, v^2
+ # $over->bmul($u);
+ # $factor = $self->new(2); $f = $self->bone();
+ # }
+ $limit = $self->new("1E-". ($scale-1));
+ #my $steps = 0;
+ 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
+ # anymore, so we stop
+ $next = $over->copy()->bdiv($below->copy()->bmul($factor),$scale);
+ last if $next->bcmp($limit) <= 0;
+ $x->badd($next);
+ # print "step $steps $x\n";
+ # calculate things for the next term
+ $over *= $u; $below *= $v; $factor->badd($f);
+ #$steps++;
+ }
+ $x->bmul(2) if $case == 0;
+ #print "took $steps steps\n";
# shortcut to not run trough _find_round_parameters again
if (defined $params[1])
sub bdiv
{
# (dividend: BFLOAT or num_str, divisor: BFLOAT or num_str) return
- # (BFLOAT,BFLOAT) (quo,rem) or BINT (only rem)
+ # (BFLOAT,BFLOAT) (quo,rem) or BFLOAT (only rem)
my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
return $self->_div_inf($x,$y)
# x== 0 # also: or y == 1 or y == -1
return wantarray ? ($x,$self->bzero()) : $x if $x->is_zero();
- # upgrade
- return $upgrade->bdiv($x,$y,$a,$p,$r) if defined $upgrade;
+ # upgrade ?
+ return $upgrade->bdiv($upgrade->new($x),$y,$a,$p,$r) if defined $upgrade;
# we need to limit the accuracy to protect against overflow
my $fallback = 0;
# promote BigInts and it's subclasses (except when already a BigFloat)
$y = $self->new($y) unless $y->isa('Math::BigFloat');
+ #print "bdiv $y ",ref($y),"\n";
+ # need to disable $upgrade in BigInt, to avoid deep recursion
+ local $Math::BigInt::upgrade = undef; # should be parent class vs MBI
+
# calculate the result to $scale digits and then round it
# a * 10 ** b / c * 10 ** d => a/c * 10 ** (b-d)
$x->{_m}->blsft($scale,10);
}
return ($x,$rem);
}
- return $x;
+ $x;
}
sub bmod
}
# when user set globals, they would interfere with our calculation, so
- # disable then and later re-enable them
+ # disable them and later re-enable them
no strict 'refs';
my $abr = "$self\::accuracy"; my $ab = $$abr; $$abr = undef;
my $pbr = "$self\::precision"; my $pb = $$pbr; $$pbr = undef;
# we also need to disable any set A or P on $x (_find_round_parameters took
# them already into account), since these would interfere, too
delete $x->{_a}; delete $x->{_p};
- # need to disable $upgrade in BigInt, to aoid deep recursion
- local $Math::BigInt::upgrade = undef;
+ # need to disable $upgrade in BigInt, to avoid deep recursion
+ local $Math::BigInt::upgrade = undef; # should be really parent class vs MBI
my $xas = $x->as_number();
my $gs = $xas->copy()->bsqrt(); # some guess
+# print "guess $gs\n";
if (($x->{_e}->{sign} ne '-') # guess can't be accurate if there are
# digits after the dot
&& ($xas->bacmp($gs * $gs) == 0)) # guess hit the nail on the head?
# clear a/p after round, since user did not request it
$x->{_a} = undef; $x->{_p} = undef;
}
+ # re-enable A and P, upgrade is taken care of by "local"
${"$self\::accuracy"} = $ab; ${"$self\::precision"} = $pb;
return $x;
}
my $lx = $x->{_m}->length();
$scale = $lx if $scale < $lx;
my $e = $self->new("1E-$scale"); # make test variable
-# return $x->bnan() if $e->sign() eq 'NaN';
my $y = $x->copy();
my $two = $self->new(2);
$y = $self->new($y) unless $y->isa('Math::BigFloat');
my $rem;
- while ($diff >= $e)
+ while ($diff->bacmp($e) >= 0)
{
+ $rem = $y->copy()->bdiv($gs,$scale);
$rem = $y->copy()->bdiv($gs,$scale)->badd($gs)->bdiv($two,$scale);
- $diff = $rem->copy()->bsub($gs)->babs();
+ $diff = $rem->copy()->bsub($gs);
$gs = $rem->copy();
}
# copy over to modify $x
$x->bnorm()->round(@r);
}
+sub _pow
+ {
+ # Calculate a power where $y is a non-integer, like 2 ** 0.5
+ my ($x,$y,$a,$p,$r) = @_;
+ 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;
+
+ # u = y * ln x
+ # _ _
+ # Taylor: | u u^2 u^3 |
+ # x ** y = 1 + | --- + --- + * ----- + ... |
+ # |_ 1 1*2 1*2*3 _|
+
+ # we need to limit the accuracy to protect against overflow
+ my $fallback = 0;
+ my $scale = 0;
+ my @params = $x->_find_round_parameters($a,$p,$r);
+
+ # no rounding at all, so must use fallback
+ if (scalar @params == 1)
+ {
+ # simulate old behaviour
+ $params[1] = $self->div_scale(); # and round to it as accuracy
+ $scale = $params[1]+4; # at least four more for proper round
+ $params[3] = $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 is not
+ # enough...
+ $scale = abs($params[1] || $params[2]) + 4; # take whatever is defined
+ }
+
+ # when user set globals, they would interfere with our calculation, so
+ # disable then and later re-enable them
+ no strict 'refs';
+ my $abr = "$self\::accuracy"; my $ab = $$abr; $$abr = undef;
+ my $pbr = "$self\::precision"; my $pb = $$pbr; $$pbr = undef;
+ # we also need to disable any set A or P on $x (_find_round_parameters took
+ # them already into account), since these would interfere, too
+ delete $x->{_a}; delete $x->{_p};
+ # need to disable $upgrade in BigInt, to avoid deep recursion
+ local $Math::BigInt::upgrade = undef;
+
+ my ($limit,$v,$u,$below,$factor,$next,$over);
+
+ $u = $x->copy()->blog($scale)->bmul($y);
+ $v = $self->bone(); # 1
+ $factor = $self->new(2); # 2
+ $x->bone(); # first term: 1
+
+ $below = $v->copy();
+ $over = $u->copy();
+
+ $limit = $self->new("1E-". ($scale-1));
+ #my $steps = 0;
+ 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
+ # anymore, so we stop
+ $next = $over->copy()->bdiv($below,$scale);
+ last if $next->bcmp($limit) <= 0;
+ $x->badd($next);
+# print "at $x\n";
+ # calculate things for the next term
+ $over *= $u; $below *= $factor; $factor->binc();
+ #$steps++;
+ }
+
+ # shortcut to not run trough _find_round_parameters again
+ if (defined $params[1])
+ {
+ $x->bround($params[1],$params[3]); # then round accordingly
+ }
+ else
+ {
+ $x->bfround($params[2],$params[3]); # then round accordingly
+ }
+ if ($fallback)
+ {
+ # clear a/p after round, since user did not request it
+ $x->{_a} = undef; $x->{_p} = undef;
+ }
+ # restore globals
+ $$abr = $ab; $$pbr = $pb;
+ $x;
+ }
+
sub bpow
{
# (BFLOAT or num_str, BFLOAT or num_str) return BFLOAT
return $x->bnan() if $x->{sign} eq $nan || $y->{sign} eq $nan;
return $x->bone() if $y->is_zero();
return $x if $x->is_one() || $y->is_one();
- my $y1 = $y->as_number(); # make bigint (trunc)
+
+ return $x->_pow($y,$a,$p,$r) if !$y->is_int(); # non-integer power
+
+ my $y1 = $y->as_number(); # make bigint
# if ($x == -1)
if ($x->{sign} eq '-' && $x->{_m}->is_one() && $x->{_e}->is_zero())
{
my $class = "Math::BigInt";
require 5.005;
-$VERSION = '1.53';
+$VERSION = '1.54';
use Exporter;
@ISA = qw( Exporter );
@EXPORT_OK = qw( objectify _swap bgcd blcm);
# make Class->upgrade() work
my $self = shift;
my $class = ref($self) || $self || __PACKAGE__;
- if (defined $_[0])
+ # need to set new value?
+ if (@_ > 0)
{
my $u = shift;
return ${"${class}::upgrade"} = $u;
# make Class->downgrade() work
my $self = shift;
my $class = ref($self) || $self || __PACKAGE__;
- if (defined $_[0])
+ # need to set new value?
+ if (@_ > 0)
{
my $u = shift;
return ${"${class}::downgrade"} = $u;
# avoid numify-calls by not using || on $wanted!
return $class->bzero($a,$p) if !defined $wanted; # default to 0
- return $class->copy($wanted,$a,$p,$r) if ref($wanted);
+ return $class->copy($wanted,$a,$p,$r)
+ if ref($wanted) && $wanted->isa($class); # MBI or subclass
$class->import() if $IMPORT == 0; # make require work
- my $self = {}; bless $self, $class;
+ my $self = bless {}, $class;
+
+ # shortcut for "normal" numbers
+ if ((!ref $wanted) && ($wanted =~ /^([+-]?)[1-9][0-9]*$/))
+ {
+ $self->{sign} = $1 || '+';
+ my $ref = \$wanted;
+ if ($wanted =~ /^[+-]/)
+ {
+ # remove sign without touching wanted
+ my $t = $wanted; $t =~ s/^[+-]//; $ref = \$t;
+ }
+ $self->{value} = $CALC->_new($ref);
+ no strict 'refs';
+ if ( (defined $a) || (defined $p)
+ || (defined ${"${class}::precision"})
+ || (defined ${"${class}::accuracy"})
+ )
+ {
+ $self->round($a,$p,$r) unless (@_ == 4 && !defined $a && !defined $p);
+ }
+ return $self;
+ }
+
# handle '+inf', '-inf' first
if ($wanted =~ /^[+-]?inf$/)
{
# do not round for new($x,undef,undef) since that is used by MBF to signal
# no rounding
$self->round($a,$p,$r) unless @_ == 4 && !defined $a && !defined $p;
- # print "mbi new $self\n";
- return $self;
+ $self;
}
sub bnan
return $x->{sign} if $x->{sign} !~ /^[+-]$/;
my $num = $CALC->_num($x->{value});
return -$num if $x->{sign} eq '-';
- return $num;
+ $num;
}
##############################################################################
sub sign
{
- # return the sign of the number: +/-/NaN
+ # return the sign of the number: +/-/-inf/+inf/NaN
my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
- return $x->{sign};
+ $x->{sign};
}
sub _find_round_parameters
my ($self,$x,$sign) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
$sign = '' if !defined $sign;
+ return 1 if $sign eq $x->{sign}; # match ("+inf" eq "+inf")
return 0 if $sign !~ /^([+-]|)$/;
if ($sign eq '')
return $x if $x->modify('bmul');
- $r[3] = $y; # no push here
-
return $x->bnan() if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
# inf handling
return $x->binf() if ($x->{sign} =~ /^-/ && $y->{sign} =~ /^-/);
return $x->binf('-');
}
+
+ return $upgrade->bmul($x,$y,@r)
+ if defined $upgrade && $y->isa($upgrade);
+
+ $r[3] = $y; # no push here
$x->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-'; # +1 * +1 or -1 * -1 => +
return $self->_div_inf($x,$y)
if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/) || $y->is_zero());
+ return $upgrade->bdiv($upgrade->new($x),$y,@r)
+ if defined $upgrade && $y->isa($upgrade);
+
$r[3] = $y; # no push!
# 0 / something
my $cmp = $CALC->_acmp($x->{value},$y->{value});
if (($cmp < 0) and (($x->{sign} eq $y->{sign}) or !wantarray))
{
- return $upgrade->bdiv($x,$y,@r) if defined $upgrade;
+ return $upgrade->bdiv($upgrade->new($x),$upgrade->new($y),@r)
+ if defined $upgrade;
return $x->bzero()->round(@r) unless wantarray;
my $t = $x->copy(); # make copy first, because $x->bzero() clobbers $x
return $x unless wantarray;
return ($x->round(@r),$self->bzero(@r));
}
+ return $upgrade->bdiv($upgrade->new($x),$upgrade->new($y),@r)
+ if defined $upgrade;
# calc new sign and in case $y == +/- 1, return $x
my $xsign = $x->{sign}; # keep
my ($self,$x,$y,@r) = objectify(2,@_);
return $x if $x->modify('bpow');
-
+
+ return $upgrade->bpow($upgrade->new($x),$y,@r)
+ if defined $upgrade && $y->isa($upgrade);
+
$r[3] = $y; # no push!
return $x if $x->{sign} =~ /^[+-]inf$/; # -inf/+inf ** x
return $x->bnan() if $x->{sign} eq $nan || $y->{sign} eq $nan;
# $x->unary_op();
return (ref($_[1]),$_[1]) if (@_ == 2) && ($_[0]||0 == 1) && ref($_[1]);
- # $x->binary_op($y);
- #return (ref($_[1]),$_[1],$_[2]) if (@_ == 3) && ($_[0]||0 == 2)
- # && ref($_[1]) && ref($_[2]);
my $count = abs(shift || 0);
- my @a; # resulting array
+ my (@a,$k,$d); # resulting array, temp, and downgrade
if (ref $_[0])
{
# okay, got object as first
$a[0] = $class;
$a[0] = shift if $_[0] =~ /^[A-Z].*::/; # classname as first?
}
+ no strict 'refs';
+ # disable downgrading, because Math::BigFLoat->foo('1.0','2.0') needs floats
+ if (defined ${"$a[0]::downgrade"})
+ {
+ $d = ${"$a[0]::downgrade"};
+ ${"$a[0]::downgrade"} = undef;
+ }
+
# print "Now in objectify, my class is today $a[0]\n";
- my $k;
if ($count == 0)
{
while (@_)
push @a,@_; # return other params, too
}
die "$class objectify needs list context" unless wantarray;
+ ${"$a[0]::downgrade"} = $d;
@a;
}
use vars qw/@ISA $VERSION/;
@ISA = qw(Exporter);
-$VERSION = '0.24';
+$VERSION = '0.25';
# Package to store unsigned big integers in decimal and do math with them
sub _new
{
# (ref to string) return ref to num_array
- # Convert a number from string format to internal base 100000 format.
- # Assumes normalized value as input.
+ # Convert a number from string format (without sign) to internal base
+ # 1ex format. Assumes normalized value as input.
my $d = $_[1];
my $il = length($$d)-1;
# this leaves '00000' instead of int 0 and will be corrected after any op
sub _sub
{
- # (ref to int_num_array, ref to int_num_array)
+ # (ref to int_num_array, ref to int_num_array, swap)
# subtract base 1eX numbers -- stolen from Knuth Vol 2 pg 232, $x > $y
# subtract Y from X (X is always greater/equal!) by modifying x in place
my ($c,$sx,$sy,$s) = @_;
__strip_zeros($sy);
}
+sub _square_use_mul
+ {
+ # compute $x ** 2 or $x * $x in-place and return $x
+ my ($c,$x) = @_;
+
+ # From: Handbook of Applied Cryptography by A. Menezes, P. van Oorschot and
+ # S. Vanstone., Chapter 14
+
+ #14.16 Algorithm Multiple-precision squaring
+ #INPUT: positive integer x = (xt 1 xt 2 ... x1 x0)b.
+ #OUTPUT: x * x = x ** 2 in radix b representation.
+ #1. For i from 0 to (2t - 1) do: wi <- 0.
+ #2. For i from 0 to (t - 1) do the following:
+ # 2.1 (uv)b w2i + xi * xi, w2i v, c u.
+ # 2.2 For j from (i + 1)to (t - 1) do the following:
+ # (uv)b <- wi+j + 2*xj * xi + c, wi+j <- v, c <- u.
+ # 2.3 wi+t <- u.
+ #3. Return((w2t-1 w2t-2 ... w1 w0)b).
+
+# # Note: That description is crap. Half of the symbols are not explained or
+# # used with out beeing set.
+# my $t = scalar @$x; # count
+# my ($c,$i,$j);
+# for ($i = 0; $i < $t; $i++)
+# {
+# $x->[$i] = $x->[$i*2] + $x[$i]*$x[$i];
+# $x->[$i*2] = $x[$i]; $c = $x[$i];
+# for ($j = $i+1; $j < $t; $j++)
+# {
+# $x->[$i] = $x->[$i+$j] + 2 * $x->[$i] * $x->[$j];
+# $x->[$i+$j] = $x[$j]; $c = $x[$i];
+# }
+# $x->[$i+$t] = $x[$i];
+# }
+ $x;
+ }
+
sub _mul_use_mul
{
- # (BINT, BINT) return nothing
+ # (ref to int_num_array, ref to int_num_array)
# multiply two numbers in internal representation
# modifies first arg, second need not be different from first
my ($c,$xv,$yv) = @_;
# since multiplying $x with $x fails, make copy in this case
$yv = [@$xv] if "$xv" eq "$yv"; # same references?
+ # since multiplying $x with $x would fail here, use the faster squaring
+# return _square($c,$xv) if "$xv" eq "$yv"; # same reference?
+
if ($LEN_CONVERT != 0)
{
$c->_to_small($xv); $c->_to_small($yv);
sub _mul_use_div
{
- # (BINT, BINT) return nothing
+ # (ref to int_num_array, ref to int_num_array)
# multiply two numbers in internal representation
# modifies first arg, second need not be different from first
my ($c,$xv,$yv) = @_;
# since multiplying $x with $x fails, make copy in this case
$yv = [@$xv] if "$xv" eq "$yv"; # same references?
+ # since multiplying $x with $x would fail here, use the faster squaring
+# return _square($c,$xv) if "$xv" eq "$yv"; # same reference?
+
if ($LEN_CONVERT != 0)
{
$c->_to_small($xv); $c->_to_small($yv);
# manual way (abort if unequal, good for early ne)
my $j = scalar @$cx - 1;
while ($j >= 0)
- {
- last if ($a = $cx->[$j] - $cy->[$j]); $j--;
- }
+ {
+ last if ($a = $cx->[$j] - $cy->[$j]); $j--;
+ }
+# my $j = scalar @$cx;
+# while (--$j >= 0)
+# {
+# last if ($a = $cx->[$j] - $cy->[$j]);
+# }
return 1 if $a > 0;
return -1 if $a < 0;
0; # equal
}
print "# INC = @INC\n";
- plan tests => 1586;
+ plan tests => 1592;
}
use Math::BigInt lib => 'BareCalc';
}
print "# INC = @INC\n";
- plan tests => 2143;
+ plan tests => 2147;
}
use Math::BigInt lib => 'BareCalc';
$class = "Math::BigInt";
$CL = "Math::BigInt::BareCalc";
-my $version = '1.51'; # for $VERSION tests, match current release (by hand!)
+my $version = '1.54'; # for $VERSION tests, match current release (by hand!)
require 'bigintpm.inc'; # perform same tests as bigintpm
}
print "# INC = @INC\n";
- plan tests => 1586;
+ plan tests => 1592;
}
use Math::BigInt;
my $location = $0; $location =~ s/bigintpm.t//;
unshift @INC, $location; # to locate the testing files
chdir 't' if -d 't';
- plan tests => 2143;
+ plan tests => 2147;
}
use Math::BigInt;
ok (ref($cfg),'HASH');
ok ($cfg->{lib},'Math::BigInt::Calc');
-ok ($cfg->{lib_version},'0.24');
+ok ($cfg->{lib_version},'0.25');
ok ($cfg->{class},'Math::BigInt');
ok ($cfg->{upgrade}||'','');
ok ($cfg->{div_scale},40);
{
$| = 1;
unshift @INC, '../lib'; # for running manually
- my $location = $0; $location =~ s/bigintpm.t//;
+ my $location = $0; $location =~ s/downgrade.t//;
unshift @INC, $location; # to locate the testing files
chdir 't' if -d 't';
- plan tests => 10;
+ plan tests => 12;
}
-use Math::BigInt;
+use Math::BigInt upgrade => 'Math::BigFloat';
use Math::BigFloat downgrade => 'Math::BigInt', upgrade => 'Math::BigInt';
use vars qw ($scale $class $try $x $y $f @args $ans $ans1 $ans1_str $setup
ok (ref(Math::BigFloat->new('-10')),'Math::BigInt');
ok (ref(Math::BigFloat->new('-10.0E1')),'Math::BigInt');
+# disable, otherwise it screws calculations
+Math::BigFloat->upgrade(undef);
+ok (Math::BigFloat->upgrade()||'','');
+
+Math::BigFloat->div_scale(20); # make it a bit faster
+my $x = Math::BigFloat->new(2); # downgrades
+# the following test upgrade for bsqrt() and also makes new() NOT downgrade
+# for the bpow() side
+ok (Math::BigFloat->bpow('2','0.5'),$x->bsqrt());
+
#require 'upgrade.inc'; # all tests here for sharing
}
print "# INC = @INC\n";
- plan tests => 1586
- + 4; # + 4 own tests
+ plan tests => 1592
+ + 6; # + our own tests
}
use Math::BigFloat::Subclass;
require 'bigfltpm.inc'; # perform same tests as bigfltpm
+###############################################################################
# Now do custom tests for Subclass itself
my $ms = $class->new(23);
print "# Missing custom attribute \$ms->{_custom}" if !ok (1, $ms->{_custom});
+# Check that subclass is a Math::BigFloat, but not a Math::Bigint
+ok ($ms->isa('Math::BigFloat'),1);
+ok ($ms->isa('Math::BigInt') || 0,0);
+
use Math::BigFloat;
my $bf = Math::BigFloat->new(23); # same as other
}
print "# INC = @INC\n";
- plan tests => 2143
- + 4; # +4 own tests
+ plan tests => 2147
+ + 5; # +4 own tests
}
use Math::BigInt::Subclass;
require 'bigintpm.inc'; # perform same tests as bigintpm
+###############################################################################
# Now do custom tests for Subclass itself
+
my $ms = $class->new(23);
print "# Missing custom attribute \$ms->{_custom}" if !ok (1, $ms->{_custom});
+# Check that a subclass is still considered a BigInt
+ok ($ms->isa('Math::BigInt'),1);
+
use Math::BigInt;
my $bi = Math::BigInt->new(23); # same as other
BEGIN
{
$| = 1;
- # to locate the testing files
- my $location = $0; $location =~ s/upgrade.t//i;
- if ($ENV{PERL_CORE})
- {
- @INC = qw(../t/lib); # testing with the core distribution
- }
- unshift @INC, '../lib'; # for testing manually
- 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 => 1990
- + 2; # our own tests
+ unshift @INC, '../lib'; # for running manually
+ my $location = $0; $location =~ s/bigintpm.t//;
+ unshift @INC, $location; # to locate the testing files
+ chdir 't' if -d 't';
+ plan tests => 2056
+ + 2; # our own tests
}
use Math::BigInt upgrade => 'Math::BigFloat';