diff options
Diffstat (limited to 'lib/Math/BigFloat.pm')
-rw-r--r-- | lib/Math/BigFloat.pm | 92 |
1 files changed, 71 insertions, 21 deletions
diff --git a/lib/Math/BigFloat.pm b/lib/Math/BigFloat.pm index d47b5f1f2a..33cf3d12a3 100644 --- a/lib/Math/BigFloat.pm +++ b/lib/Math/BigFloat.pm @@ -21,7 +21,7 @@ use File::Spec; use strict; use vars qw/$AUTOLOAD $accuracy $precision $div_scale $round_mode $rnd_mode/; -use vars qw/$upgrade $downgrade $MBI/; +use vars qw/$upgrade $downgrade/; my $class = "Math::BigFloat"; use overload @@ -49,8 +49,8 @@ $div_scale = 40; $upgrade = undef; $downgrade = undef; -$MBI = 'Math::BigInt'; # the package we are using for our private parts - # changable by use Math::BigFloat with => 'package' +my $MBI = 'Math::BigInt'; # the package we are using for our private parts + # changable by use Math::BigFloat with => 'package' ############################################################################## # the old code had $rnd_mode, so we need to support it, too @@ -204,6 +204,24 @@ sub isa UNIVERSAL::isa($self,$class); } +sub config + { + # return (later set?) configuration data as hash ref + my $class = shift || 'Math::BigFloat'; + + my $cfg = $MBI->config(); + + no strict 'refs'; + $cfg->{class} = $class; + $cfg->{with} = $MBI; + foreach ( + qw/upgrade downgrade precision accuracy round_mode VERSION div_scale/) + { + $cfg->{lc($_)} = ${"${class}::$_"}; + }; + $cfg; + } + ############################################################################## # string conversation @@ -440,6 +458,9 @@ sub badd return $x; } + return $upgrade->badd($x,$y,$a,$p,$r) if defined $upgrade && + ((!$x->isa($self)) || (!$y->isa($self))); + # speed: no add for 0+y or x+0 return $x->bround($a,$p,$r) if $y->is_zero(); # x+0 if ($x->is_zero()) # 0+y @@ -784,6 +805,9 @@ sub bmul } # handle result = 0 return $x->bzero() if $x->is_zero() || $y->is_zero(); + + return $upgrade->bmul($x,$y,$a,$p,$r) if defined $upgrade && + ((!$x->isa($self)) || (!$y->isa($self))); # aEb * cEd = (a*c)E(b+d) $x->{_m}->bmul($y->{_m}); @@ -1655,52 +1679,78 @@ sub parts sub import { my $self = shift; - my $l = scalar @_; my $j = 0; my @a = @_; - my $lib = ''; - for ( my $i = 0; $i < $l ; $i++, $j++) + my $l = scalar @_; + my $lib = ''; my @a; + for ( my $i = 0; $i < $l ; $i++) { +# print "at $_[$i] (",$_[$i+1]||'undef',")\n"; if ( $_[$i] eq ':constant' ) { # this rest causes overlord er load to step in # print "overload @_\n"; overload::constant float => sub { $self->new(shift); }; - splice @a, $j, 1; $j--; } elsif ($_[$i] eq 'upgrade') { # this causes upgrading $upgrade = $_[$i+1]; # or undef to disable - my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..." - splice @a, $j, $s; $j -= $s; + $i++; } elsif ($_[$i] eq 'downgrade') { # this causes downgrading $downgrade = $_[$i+1]; # or undef to disable - my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..." - splice @a, $j, $s; $j -= $s; + $i++; } elsif ($_[$i] eq 'lib') { $lib = $_[$i+1] || ''; # default Calc - my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..." - splice @a, $j, $s; $j -= $s; + $i++; } elsif ($_[$i] eq 'with') { $MBI = $_[$i+1] || 'Math::BigInt'; # default Math::BigInt - my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..." - splice @a, $j, $s; $j -= $s; + $i++; + } + else + { + push @a, $_[$i]; } } - my @parts = split /::/, $MBI; # Math::BigInt => Math BigInt - my $file = pop @parts; $file .= '.pm'; # BigInt => BigInt.pm - $file = File::Spec->catdir (@parts, $file); +# print "mbf @a\n"; + # let use Math::BigInt lib => 'GMP'; use Math::BigFloat; still work my $mbilib = eval { Math::BigInt->config()->{lib} }; - $lib .= ",$mbilib" if defined $mbilib; - require $file; - $MBI->import ( lib => $lib, 'objectify' ); + if ((defined $mbilib) && ($MBI eq 'Math::BigInt')) + { + # MBI already loaded + $MBI->import('lib',"$lib,$mbilib", 'objectify'); + } + else + { + # MBI not loaded, or with ne "Math::BigInt" + $lib .= ",$mbilib" if defined $mbilib; + +# my @parts = split /::/, $MBI; # Math::BigInt => Math BigInt +# my $file = pop @parts; $file .= '.pm'; # BigInt => BigInt.pm +# $file = File::Spec->catfile (@parts, $file); + + if ($] < 5.006) + { + # Perl < 5.6.0 dies with "out of memory!" when eval() and ':constant' is + # used in the same script, or eval inside import(). + my @parts = split /::/, $MBI; # Math::BigInt => Math BigInt + my $file = pop @parts; $file .= '.pm'; # BigInt => BigInt.pm + $file = File::Spec->catfile (@parts, $file); + eval { require $file; $MBI->import( lib => '$lib', 'objectify' ); } + } + else + { + my $rc = "use $MBI lib => '$lib', 'objectify';"; + eval $rc; + } + } + die ("Couldn't load $MBI: $! $@") if $@; # any non :constant stuff is handled by our parent, Exporter # even if @_ is empty, to give it a chance |