package Math::BigFloat;
#
-# Mike grinned. 'Two down, infinity to go' - Mike Nostrus in Before and After
+# Mike grinned. 'Two down, infinity to go' - Mike Nostrus in 'Before and After'
#
# The following hash values are internally used:
# _p: precision
# _f: flags, used to signal MBI not to touch our private parts
-$VERSION = '1.31';
+$VERSION = '1.38';
require 5.005;
use Exporter;
-use File::Spec;
-# use Math::BigInt;
-@ISA = qw( Exporter Math::BigInt);
+@ISA = qw(Exporter Math::BigInt);
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
$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
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
return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN
return 'inf'; # +inf
}
- my $sign = $x->{_e}->{sign}; $sign = '' if $sign eq '-';
- my $sep = 'e'.$sign;
- $x->{_m}->bstr().$sep.$x->{_e}->bstr();
+ my $esign = $x->{_e}->{sign}; $esign = '' if $esign eq '-';
+ my $sep = 'e'.$esign;
+ my $sign = $x->{sign}; $sign = '' if $sign eq '+';
+ $sign . $x->{_m}->bstr() . $sep . $x->{_e}->bstr();
}
sub numify
{
# Compares 2 values. Returns one of undef, <0, =0, >0. (suitable for sort)
# (BFLOAT or num_str, BFLOAT or num_str) return cond_code
- my ($self,$x,$y) = objectify(2,@_);
+
+ # set up parameters
+ my ($self,$x,$y) = (ref($_[0]),@_);
+ # objectify is costly, so avoid it
+ if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
+ {
+ ($self,$x,$y) = objectify(2,@_);
+ }
+
+ return $upgrade->bcmp($x,$y) if defined $upgrade &&
+ ((!$x->isa($self)) || (!$y->isa($self)));
if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
{
# Compares 2 values, ignoring their signs.
# Returns one of undef, <0, =0, >0. (suitable for sort)
# (BFLOAT or num_str, BFLOAT or num_str) return cond_code
- my ($self,$x,$y) = objectify(2,@_);
+
+ # set up parameters
+ my ($self,$x,$y) = (ref($_[0]),@_);
+ # objectify is costly, so avoid it
+ if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
+ {
+ ($self,$x,$y) = objectify(2,@_);
+ }
+
+ return $upgrade->bacmp($x,$y) if defined $upgrade &&
+ ((!$x->isa($self)) || (!$y->isa($self)));
# handle +-inf and NaN's
if ($x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/)
{
# add second arg (BFLOAT or string) to first (BFLOAT) (modifies first)
# return result as BFLOAT
- my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
- #print "mbf badd $x $y\n";
+ # set up parameters
+ my ($self,$x,$y,$a,$p,$r) = (ref($_[0]),@_);
+ # objectify is costly, so avoid it
+ if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
+ {
+ ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
+ }
+
# inf and NaN handling
if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
{
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
{
# (BigFloat or num_str, BigFloat or num_str) return BigFloat
# subtract second arg from first, modify first
- my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
+
+ # set up parameters
+ my ($self,$x,$y,$a,$p,$r) = (ref($_[0]),@_);
+ # objectify is costly, so avoid it
+ if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
+ {
+ ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
+ }
if ($y->is_zero()) # still round for not adding zero
{
{
# simulate old behaviour
$params[1] = $self->div_scale(); # and round to it as accuracy
+ $params[0] = undef;
$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
return $x->bzero(@params) if $x->is_one();
return $x->bnan() if $x->{sign} ne '+' || $x->is_zero();
- #return $x->bone('+',@params) if $x->bcmp($base) == 0;
+ return $x->bone('+',@params) if $x->bcmp($base) == 0;
# 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;
$next = $over->copy()->bdiv($below->copy()->bmul($factor),$scale);
last if $next->bcmp($limit) <= 0;
$x->badd($next);
- # print "step $steps $x\n";
+ # print "step $x\n";
# calculate things for the next term
$over *= $u; $below *= $v; $factor->badd($f);
#$steps++;
{
# multiply two numbers -- stolen from Knuth Vol 2 pg 233
# (BINT or num_str, BINT or num_str) return BINT
- my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
+
+ # set up parameters
+ my ($self,$x,$y,$a,$p,$r) = (ref($_[0]),@_);
+ # objectify is costly, so avoid it
+ if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
+ {
+ ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
+ }
return $x->bnan() if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
}
# 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});
{
# (dividend: BFLOAT or num_str, divisor: BFLOAT or num_str) return
# (BFLOAT,BFLOAT) (quo,rem) or BFLOAT (only rem)
- my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
+
+ # set up parameters
+ my ($self,$x,$y,$a,$p,$r) = (ref($_[0]),@_);
+ # objectify is costly, so avoid it
+ if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
+ {
+ ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
+ }
return $self->_div_inf($x,$y)
if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/) || $y->is_zero());
# 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
# shortcut to not run trough _find_round_parameters again
if (defined $params[1])
{
+ $x->{_a} = undef; # clear before round
$x->bround($params[1],$params[3]); # then round accordingly
}
else
{
+ $x->{_p} = undef; # clear before round
$x->bfround($params[2],$params[3]); # then round accordingly
}
if ($fallback)
sub bmod
{
# (dividend: BFLOAT or num_str, divisor: BFLOAT or num_str) return reminder
- my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
+
+ # set up parameters
+ my ($self,$x,$y,$a,$p,$r) = (ref($_[0]),@_);
+ # objectify is costly, so avoid it
+ if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
+ {
+ ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
+ }
if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
{
my ($d,$re) = $self->SUPER::_div_inf($x,$y);
- return $re->round($a,$p,$r,$y);
+ $x->{sign} = $re->{sign};
+ $x->{_e} = $re->{_e};
+ $x->{_m} = $re->{_m};
+ return $x->round($a,$p,$r,$y);
}
return $x->bnan() if $x->is_zero() && $y->is_zero();
return $x if $y->is_zero();
my @params = $x->_find_round_parameters($a,$p,$r);
# no rounding at all, so must use fallback
- if (scalar @params == 1)
+ if ((scalar @params == 1) ||
+ (!defined($params[1] || $params[2])))
{
# simulate old behaviour
$params[1] = $self->div_scale(); # and round to it as accuracy
{
# 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
+ $scale = abs($params[1] || $params[2]) + 4; # take whatever is defined
}
# when user set globals, they would interfere with our calculation, so
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?
${"$self\::accuracy"} = $ab; ${"$self\::precision"} = $pb;
return $x;
}
- $gs = $self->new( $gs ); # BigInt to BigFloat
-
- my $lx = $x->{_m}->length();
- $scale = $lx if $scale < $lx;
- my $e = $self->new("1E-$scale"); # make test variable
-
- my $y = $x->copy();
- my $two = $self->new(2);
- my $diff = $e;
- # promote BigInts and it's subclasses (except when already a BigFloat)
- $y = $self->new($y) unless $y->isa('Math::BigFloat');
+
+ # sqrt(2) = 1.4 because sqrt(2*100) = 1.4*10; so we can increase the accuracy
+ # of the result by multipyling the input by 100 and then divide the integer
+ # result of sqrt(input) by 10. Rounding afterwards returns the real result.
+ # this will transform 123.456 (in $x) into 123456 (in $y1)
+ my $y1 = $x->{_m}->copy();
+ # We now make sure that $y1 has the same odd or even number of digits than
+ # $x had. So when _e of $x is odd, we must shift $y1 by one digit left,
+ # because we always must multiply by steps of 100 (sqrt(100) is 10) and not
+ # 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).
+ $y1->bmul(10) if $x->{_e}->is_odd();
+ # now calculate how many digits the result of sqrt(y1) would have
+ my $digits = int($y1->length() / 2);
+ # but we need at least $scale digits, so calculate how many are missing
+ my $shift = $scale - $digits;
+ # that should never happen (we take care of integer guesses above)
+ # $shift = 0 if $shift < 0;
+ # multiply in steps of 100, by shifting left two times the "missing" digits
+ $y1->blsft($shift*2,10);
+ # now take the square root and truncate to integer
+ $y1->bsqrt();
+ # By "shifting" $y1 right (by creating a negative _e) we calculate the final
+ # result, which is than later rounded to the desired scale.
+ $x->{_m} = $y1;
+ # gs->length() is the number of digits before the dot. Since gs is always
+ # truncated (9.99 => 9), it is always right (if gs was rounded, it would be
+ # '10' and thus gs->length() == 2, which would be wrong).
+ $x->{_e} = $MBI->new(- $y1->length() + $gs->length());
- my $rem;
- 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);
- $gs = $rem->copy();
- }
- # copy over to modify $x
- $x->{_m} = $rem->{_m}; $x->{_e} = $rem->{_e};
-
# shortcut to not run trough _find_round_parameters again
if (defined $params[1])
{
if (($x->{sign} ne '+') || # inf, NaN, <0 etc => NaN
($x->{_e}->{sign} ne '+')); # digits after dot?
- return $x->bone(@r) if $x->is_zero() || $x->is_one(); # 0 or 1 => 1
+ return $x->bone('+',@r) if $x->is_zero() || $x->is_one(); # 0 or 1 => 1
# use BigInt's bfac() for faster calc
$x->{_m}->blsft($x->{_e},10); # un-norm m
}
# 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;
{
$x->bsqrt(); $x->bmul($xc); $d->bdec(); # 1
}
- print "at $x\n";
}
# assume fraction ends in 1
$x->bsqrt(); # 1
}
# 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;
# compute power of two numbers, second arg is used as integer
# modifies first argument
- my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
+ # set up parameters
+ my ($self,$x,$y,$a,$p,$r) = (ref($_[0]),@_);
+ # objectify is costly, so avoid it
+ if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
+ {
+ ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
+ }
return $x if $x->{sign} =~ /^[+-]inf$/;
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();
- return $x->_pow2($y,$a,$p,$r) if !$y->is_int(); # non-integer power
+ return $x->_pow($y,$a,$p,$r) if !$y->is_int(); # non-integer power
my $y1 = $y->as_number(); # make bigint
# if ($x == -1)
return $x;
}
return $x if $x->{sign} !~ /^[+-]$/;
- # print "MBF bfround $x to scale $scale mode $mode\n";
# don't round if x already has lower precision
return $x if (defined $x->{_p} && $x->{_p} < 0 && $scale < $x->{_p});
$x->{_a} = undef; # and clear A
if ($scale < 0)
{
- # print "bfround scale $scale e $x->{_e}\n";
# round right from the '.'
- return $x if $x->{_e} >= 0; # nothing to round
+
+ return $x if $x->{_e}->{sign} eq '+'; # e >= 0 => nothing to round
+
$scale = -$scale; # positive for simplicity
my $len = $x->{_m}->length(); # length of mantissa
- my $dad = -$x->{_e}; # digits after dot
+
+ # the following poses a restriction on _e, but if _e is bigger than a
+ # scalar, you got other problems (memory etc) anyway
+ my $dad = -($x->{_e}->numify()); # digits after dot
my $zad = 0; # zeros after dot
- $zad = -$len-$x->{_e} if ($x->{_e} < -$len);# for 0.00..00xxx style
+ $zad = $dad - $len if (-$dad < -$len); # for 0.00..00xxx style
+
#print "scale $scale dad $dad zad $zad len $len\n";
-
# number bsstr len zad dad
# 0.123 123e-3 3 0 3
# 0.0123 123e-4 3 1 4
$scale = $dbd+$scale;
}
}
- # print "round to $x->{_m} to $scale\n";
}
else
{
+ # round left from the '.'
+
# 123 => 100 means length(123) = 3 - $scale (2) => 1
my $dbt = $x->{_m}->length();
# digits before dot
- my $dbd = $dbt + $x->{_e};
+ my $dbd = $dbt + $x->{_e}->numify();
# should be the same, so treat it as this
$scale = 1 if $scale == 0;
# shortcut if already integer
{
$scale = $dbd - $scale;
}
-
}
- # print "using $scale for $x->{_m} with '$mode'\n";
# pass sign to bround for rounding modes '+inf' and '-inf'
$x->{_m}->{sign} = $x->{sign};
$x->{_m}->bround($scale,$mode);
# if $x has digits after dot
if ($x->{_e}->{sign} eq '-')
{
- #$x->{_m}->brsft(-$x->{_e},10);
- #$x->{_e}->bzero();
- #$x-- if $x->{sign} eq '-';
-
$x->{_e}->{sign} = '+'; # negate e
$x->{_m}->brsft($x->{_e},10); # cut off digits after dot
$x->{_e}->bzero(); # trunc/norm
sub brsft
{
- # shift right by $y (divide by power of 2)
- my ($self,$x,$y,$n,$a,$p,$r) = objectify(2,@_);
+ # shift right by $y (divide by power of $n)
+
+ # set up parameters
+ my ($self,$x,$y,$n,$a,$p,$r) = (ref($_[0]),@_);
+ # objectify is costly, so avoid it
+ if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
+ {
+ ($self,$x,$y,$n,$a,$p,$r) = objectify(2,@_);
+ }
return $x if $x->modify('brsft');
return $x if $x->{sign} !~ /^[+-]$/; # nan, +inf, -inf
- $n = 2 if !defined $n; $n = Math::BigFloat->new($n);
- $x->bdiv($n ** $y,$a,$p,$r,$y);
+ $n = 2 if !defined $n; $n = $self->new($n);
+ $x->bdiv($n->bpow($y),$a,$p,$r,$y);
}
sub blsft
{
- # shift right by $y (divide by power of 2)
- my ($self,$x,$y,$n,$a,$p,$r) = objectify(2,@_);
+ # shift left by $y (multiply by power of $n)
+
+ # set up parameters
+ my ($self,$x,$y,$n,$a,$p,$r) = (ref($_[0]),@_);
+ # objectify is costly, so avoid it
+ if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
+ {
+ ($self,$x,$y,$n,$a,$p,$r) = objectify(2,@_);
+ }
- return $x if $x->modify('brsft');
+ return $x if $x->modify('blsft');
return $x if $x->{sign} !~ /^[+-]$/; # nan, +inf, -inf
- $n = 2 if !defined $n; $n = Math::BigFloat->new($n);
- $x->bmul($n ** $y,$a,$p,$r,$y);
+ $n = 2 if !defined $n; $n = $self->new($n);
+ $x->bmul($n->bpow($y),$a,$p,$r,$y);
}
###############################################################################
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++)
{
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);
+
# 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;
+ $lib =~ s/^,//; # don't leave empty
+ 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
+ require File::Spec;
+ $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
}
##############################################################################
-# internal calculation routines
+
+sub as_hex
+ {
+ # return number as hexadecimal string (only for integers defined)
+ my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
+
+ return $x->bstr() if $x->{sign} !~ /^[+-]$/; # inf, nan etc
+ return '0x0' if $x->is_zero();
+
+ return 'NaN' if $x->{_e}->{sign} ne '+'; # how to do 1e-1 in hex!?
+
+ my $z = $x->{_m}->copy();
+ if (!$x->{_e}->is_zero()) # > 0
+ {
+ $z->blsft($x->{_e},10);
+ }
+ $z->{sign} = $x->{sign};
+ $z->as_hex();
+ }
+
+sub as_bin
+ {
+ # return number as binary digit string (only for integers defined)
+ my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
+
+ return $x->bstr() if $x->{sign} !~ /^[+-]$/; # inf, nan etc
+ return '0b0' if $x->is_zero();
+
+ return 'NaN' if $x->{_e}->{sign} ne '+'; # how to do 1e-1 in hex!?
+
+ my $z = $x->{_m}->copy();
+ if (!$x->{_e}->is_zero()) # > 0
+ {
+ $z->blsft($x->{_e},10);
+ }
+ $z->{sign} = $x->{sign};
+ $z->as_bin();
+ }
sub as_number
{
$x->length(); # number of digits (w/o sign and '.')
($l,$f) = $x->length(); # number of digits, and length of fraction
+ $x->precision(); # return P of $x (or global, if P of $x undef)
+ $x->precision($n); # set P of $x to $n
+ $x->accuracy(); # return A of $x (or global, if A of $x undef)
+ $x->accuracy($n); # set A $x to $n
+
+ Math::BigFloat->precision(); # get/set global P for all BigFloat objects
+ Math::BigFloat->accuracy(); # get/set global A for all BigFloat objects
+
=head1 DESCRIPTION
All operators (inlcuding basic math operations) are overloaded if you