# _n : numeraotr (value = _n/_d)
# _a : accuracy
# _p : precision
-# _f : flags, used by MBR to flag parts of a rational as untouchable
# You should not look at the innards of a BigRat - use the methods for this.
package Math::BigRat;
-require 5.005_03;
+# anythig older is untested, and unlikely to work
+use 5.006;
use strict;
-require Exporter;
use Math::BigFloat;
use vars qw($VERSION @ISA $upgrade $downgrade
$accuracy $precision $round_mode $div_scale $_trap_nan $_trap_inf);
-@ISA = qw(Exporter Math::BigFloat);
+@ISA = qw(Math::BigFloat);
-$VERSION = '0.13';
+$VERSION = '0.21';
use overload; # inherit overload from Math::BigFloat
# Math::BigInt::config->('lib'); (there is always only one library loaded)
*_e_add = \&Math::BigFloat::_e_add;
*_e_sub = \&Math::BigFloat::_e_sub;
+ *as_int = \&as_number;
+ *is_pos = \&is_positive;
+ *is_neg = \&is_negative;
}
##############################################################################
my $nan = 'NaN';
my $class = 'Math::BigRat';
-my $IMPORT = 0;
sub isa
{
# create a Math::BigRat
my $class = shift;
- my ($n,$d) = shift;
+ my ($n,$d) = @_;
my $self = { }; bless $self,$class;
- # input like (BigInt,BigInt) or (BigFloat,BigFloat) not handled yet
-
+ # input like (BigInt) or (BigFloat):
if ((!defined $d) && (ref $n) && (!$n->isa('Math::BigRat')))
{
if ($n->isa('Math::BigFloat'))
if ($n->isa('Math::BigInt'))
{
# TODO: trap NaN, inf
- $self->{_n} = $MBI->_copy($n->{value}); # "mantissa" = $n
+ $self->{_n} = $MBI->_copy($n->{value}); # "mantissa" = N
$self->{_d} = $MBI->_one(); # d => 1
$self->{sign} = $n->{sign};
}
{
# TODO: trap NaN, inf
$self->{sign} = '+'; $self->{sign} = '-' if $$n < 0;
- $self->{_n} = $MBI->_new(abs($$n)); # "mantissa" = $n
+ $self->{_n} = $MBI->_new(abs($$n)); # "mantissa" = N
$self->{_d} = $MBI->_one(); # d => 1
}
return $self->bnorm(); # normalize (120/1 => 12/10)
}
+
+ # input like (BigInt,BigInt) or (BigLite,BigLite):
+ if (ref($d) && ref($n))
+ {
+ # do N first (for $self->{sign}):
+ if ($n->isa('Math::BigInt'))
+ {
+ # TODO: trap NaN, inf
+ $self->{_n} = $MBI->_copy($n->{value}); # "mantissa" = N
+ $self->{sign} = $n->{sign};
+ }
+ elsif ($n->isa('Math::BigInt::Lite'))
+ {
+ # TODO: trap NaN, inf
+ $self->{sign} = '+'; $self->{sign} = '-' if $$n < 0;
+ $self->{_n} = $MBI->_new(abs($$n)); # "mantissa" = $n
+ }
+ else
+ {
+ require Carp;
+ Carp::croak(ref($n) . " is not a recognized object format for Math::BigRat->new");
+ }
+ # now D:
+ if ($d->isa('Math::BigInt'))
+ {
+ # TODO: trap NaN, inf
+ $self->{_d} = $MBI->_copy($d->{value}); # "mantissa" = D
+ # +/+ or -/- => +, +/- or -/+ => -
+ $self->{sign} = $d->{sign} ne $self->{sign} ? '-' : '+';
+ }
+ elsif ($d->isa('Math::BigInt::Lite'))
+ {
+ # TODO: trap NaN, inf
+ $self->{_d} = $MBI->_new(abs($$d)); # "mantissa" = D
+ my $ds = '+'; $ds = '-' if $$d < 0;
+ # +/+ or -/- => +, +/- or -/+ => -
+ $self->{sign} = $ds ne $self->{sign} ? '-' : '+';
+ }
+ else
+ {
+ require Carp;
+ Carp::croak(ref($d) . " is not a recognized object format for Math::BigRat->new");
+ }
+ return $self->bnorm(); # normalize (120/1 => 12/10)
+ }
return $n->copy() if ref $n; # already a BigRat
if (!defined $n)
my $nf = Math::BigFloat->new($n,undef,undef);
$self->{sign} = '+';
return $self->bnan() if $nf->is_nan();
+
$self->{_n} = $MBI->_copy( $nf->{_m} ); # get mantissa
# now correct $self->{_n} due to $n
$self->{_d} = $MBI->_copy( $f->{_m} );
# calculate the difference between nE and dE
- # XXX TODO: check that exponent() makes a copy to avoid copy()
- my $diff_e = $nf->exponent()->copy()->bsub( $f->exponent);
+ my $diff_e = $nf->exponent()->bsub( $f->exponent);
if ($diff_e->is_negative())
{
# < 0: mul d with it
$self->{sign} = '+'; # no sign => '+'
$self->{_n} = undef;
$self->{_d} = undef;
- if ($n =~ /^([+-]?)0*(\d+)\z/) # first part ok?
+ if ($n =~ /^([+-]?)0*([0-9]+)\z/) # first part ok?
{
$self->{sign} = $1 || '+'; # no sign => '+'
$self->{_n} = $MBI->_new($2 || 0);
}
- if ($d =~ /^([+-]?)0*(\d+)\z/) # second part ok?
+ if ($d =~ /^([+-]?)0*([0-9]+)\z/) # second part ok?
{
$self->{sign} =~ tr/+-/-+/ if ($1 || '') eq '-'; # negate if second part neg.
$self->{_d} = $MBI->_new($2 || 0);
{
$d = Math::BigInt->new($d,undef,undef) unless ref $d;
$n = Math::BigInt->new($n,undef,undef) unless ref $n;
-
+
if ($n->{sign} =~ /^[+-]$/ && $d->{sign} =~ /^[+-]$/)
{
# both parts are ok as integers (wierd things like ' 1e0'
else
{
# for simple forms, use $MBI directly
- if ($n =~ /^([+-]?)0*(\d+)\z/)
+ if ($n =~ /^([+-]?)0*([0-9]+)\z/)
{
$self->{sign} = $1 || '+';
$self->{_n} = $MBI->_new($2 || 0);
sub copy
{
- my ($c,$x);
- if (@_ > 1)
- {
- # if two arguments, the first one is the class to "swallow" subclasses
- ($c,$x) = @_;
- }
- else
+ # if two arguments, the first one is the class to "swallow" subclasses
+ my ($c,$x) = @_;
+
+ if (scalar @_ == 1)
{
- $x = shift;
+ $x = $_[0];
$c = ref($x);
}
return unless ref($x); # only for objects
sub config
{
# return (later set?) configuration data as hash ref
- my $class = shift || 'Math::BigFloat';
+ my $class = shift || 'Math::BigRat';
+
+ if (@_ == 1 && ref($_[0]) ne 'HASH')
+ {
+ my $cfg = $class->SUPER::config();
+ return $cfg->{$_[0]};
+ }
my $cfg = $class->SUPER::config(@_);
sub bsstr
{
- my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
+ my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
if ($x->{sign} !~ /^[+-]$/) # inf, NaN etc
{
sub bnorm
{
# reduce the number to the shortest form
- my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
+ my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
# Both parts must be objects of whatever we are using today.
- # Second check because Calc.pm has ARRAY res as unblessed objects.
- if (ref($x->{_n}) ne $MBI && ref($x->{_n}) ne 'ARRAY')
+ if ( my $c = $MBI->_check($x->{_n}) )
{
- require Carp; Carp::croak ("n is not $MBI but (".ref($x->{_n}).') in bnorm()');
+ require Carp; Carp::croak ("n did not pass the self-check ($c) in bnorm()");
}
- if (ref($x->{_d}) ne $MBI && ref($x->{_d}) ne 'ARRAY')
+ if ( my $c = $MBI->_check($x->{_d}) )
{
- require Carp; Carp::croak ("d is not $MBI but (".ref($x->{_d}).') in bnorm()');
+ require Carp; Carp::croak ("d did not pass the self-check ($c) in bnorm()");
}
# no normalize for NaN, inf etc.
}
##############################################################################
+# sign manipulation
+
+sub bneg
+ {
+ # (BRAT or num_str) return BRAT
+ # negate number or make a negated number from string
+ my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
+
+ return $x if $x->modify('bneg');
+
+ # for +0 dont negate (to have always normalized +0). Does nothing for 'NaN'
+ $x->{sign} =~ tr/+-/-+/ unless ($x->{sign} eq '+' && $MBI->_is_zero($x->{_n}));
+ $x;
+ }
+
+##############################################################################
# special values
sub _bnan
{
require Carp;
my $class = ref($self);
+ # "$self" below will stringify the object, this blows up if $self is a
+ # partial object (happens under trap_nan), so fix it beforehand
+ $self->{_d} = $MBI->_zero() unless defined $self->{_d};
+ $self->{_n} = $MBI->_zero() unless defined $self->{_n};
Carp::croak ("Tried to set $self to NaN in $class\::_bnan()");
}
$self->{_n} = $MBI->_zero();
{
require Carp;
my $class = ref($self);
+ # "$self" below will stringify the object, this blows up if $self is a
+ # partial object (happens under trap_nan), so fix it beforehand
+ $self->{_d} = $MBI->_zero() unless defined $self->{_d};
+ $self->{_n} = $MBI->_zero() unless defined $self->{_n};
Carp::croak ("Tried to set $self to inf in $class\::_binf()");
}
$self->{_n} = $MBI->_zero();
# 4 3 4*3 12
# we do not compute the gcd() here, but simple do:
- # 5 7 5*3 + 7*4 41
+ # 5 7 5*3 + 7*4 43
# - + - = --------- = --
# 4 3 4*3 12
# and bnorm() will then take care of the rest
+ # 5 * 3
$x->{_n} = $MBI->_mul( $x->{_n}, $y->{_d});
+ # 7 * 4
my $m = $MBI->_mul( $MBI->_copy( $y->{_n} ), $x->{_d} );
+ # 5 * 3 + 7 * 4
($x->{_n}, $x->{sign}) = _e_add( $x->{_n}, $m, $x->{sign}, $y->{sign});
+ # 4 * 3
$x->{_d} = $MBI->_mul( $x->{_d}, $y->{_d});
- # normalize and round
+ # normalize result, and possible round
$x->bnorm()->round(@r);
}
$x->_new_from_float( $x->_as_float()->blog(Math::BigFloat->new("$y"),@r) );
}
+sub bexp
+ {
+ # 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,$class,@_);
+ }
+
+ return $x->binf() if $x->{sign} eq '+inf';
+ return $x->bzero() if $x->{sign} eq '-inf';
+
+ # we need to limit the accuracy to protect against overflow
+ my $fallback = 0;
+ my ($scale,@params);
+ ($x,@params) = $x->_find_round_parameters($a,$p,$r);
+
+ # also takes care of the "error in _find_round_parameters?" case
+ return $x if $x->{sign} eq 'NaN';
+
+ # no rounding at all, so must use fallback
+ if (scalar @params == 0)
+ {
+ # simulate old behaviour
+ $params[0] = $self->div_scale(); # and round to it as accuracy
+ $params[1] = undef; # P = undef
+ $scale = $params[0]+4; # at least four more for proper round
+ $params[2] = $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's not enough...
+ $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined
+ }
+
+ return $x->bone(@params) if $x->is_zero();
+
+ # See the comments in Math::BigFloat on how this algorithm works.
+ # Basically we calculate A and B (where B is faculty(N)) so that A/B = e
+
+ my $x_org = $x->copy();
+ if ($scale <= 75)
+ {
+ # set $x directly from a cached string form
+ $x->{_n} = $MBI->_new("90933395208605785401971970164779391644753259799242");
+ $x->{_d} = $MBI->_new("33452526613163807108170062053440751665152000000000");
+ $x->{sign} = '+';
+ }
+ else
+ {
+ # compute A and B so that e = A / B.
+
+ # After some terms we end up with this, so we use it as a starting point:
+ my $A = $MBI->_new("90933395208605785401971970164779391644753259799242");
+ my $F = $MBI->_new(42); my $step = 42;
+
+ # Compute how many steps we need to take to get $A and $B sufficiently big
+ my $steps = Math::BigFloat::_len_to_steps($scale - 4);
+# print STDERR "# Doing $steps steps for ", $scale-4, " digits\n";
+ while ($step++ <= $steps)
+ {
+ # calculate $a * $f + 1
+ $A = $MBI->_mul($A, $F);
+ $A = $MBI->_inc($A);
+ # increment f
+ $F = $MBI->_inc($F);
+ }
+ # compute $B as factorial of $steps (this is faster than doing it manually)
+ my $B = $MBI->_fac($MBI->_new($steps));
+
+# print "A ", $MBI->_str($A), "\nB ", $MBI->_str($B), "\n";
+
+ $x->{_n} = $A;
+ $x->{_d} = $B;
+ $x->{sign} = '+';
+ }
+
+ # $x contains now an estimate of e, with some surplus digits, so we can round
+ if (!$x_org->is_one())
+ {
+ # raise $x to the wanted power and round it in one step:
+ $x->bpow($x_org, @params);
+ }
+ else
+ {
+ # else just round the already computed result
+ delete $x->{_a}; delete $x->{_p};
+ # shortcut to not run through _find_round_parameters again
+ if (defined $params[0])
+ {
+ $x->bround($params[0],$params[2]); # then round accordingly
+ }
+ else
+ {
+ $x->bfround($params[1],$params[2]); # then round accordingly
+ }
+ }
+ if ($fallback)
+ {
+ # clear a/p after round, since user did not request it
+ delete $x->{_a}; delete $x->{_p};
+ }
+
+ $x;
+ }
+
+sub bnok
+ {
+ # set up parameters
+ my ($self,$x,$y,@r) = (ref($_[0]),@_);
+
+ # objectify is costly, so avoid it
+ if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
+ {
+ ($self,$x,$y,@r) = objectify(2,$class,@_);
+ }
+
+ # do it with floats
+ $x->_new_from_float( $x->_as_float()->bnok(Math::BigFloat->new("$y"),@r) );
+ }
+
sub _float_from_part
{
my $x = shift;
sub numify
{
# convert 17/8 => float (aka 2.125)
- my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
+ my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
return $x->bstr() if $x->{sign} !~ /^[+-]$/; # inf, NaN, etc
# N/1 => N
- return $MBI->_num($x->{_n}) if $MBI->_is_one($x->{_d});
+ my $neg = ''; $neg = '-' if $x->{sign} eq '-';
+ return $neg . $MBI->_num($x->{_n}) if $MBI->_is_one($x->{_d});
- # N/D
- my $neg = 1; $neg = -1 if $x->{sign} ne '+';
- $neg * $MBI->_num($x->{_n}) / $MBI->_num($x->{_d}); # return sign * N/D
+ $x->_as_float()->numify() + 0.0;
}
sub as_number
{
my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
- return Math::BigInt->new($x) if $x->{sign} !~ /^[+-]$/; # NaN, inf etc
+ # NaN, inf etc
+ return Math::BigInt->new($x->{sign}) if $x->{sign} !~ /^[+-]$/;
my $u = Math::BigInt->bzero();
$u->{sign} = $x->{sign};
$s . $MBI->_as_hex($x->{_n});
}
+sub as_oct
+ {
+ my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
+
+ return $x unless $x->is_int();
+
+ my $s = $x->{sign}; $s = '' if $s eq '+';
+ $s . $MBI->_as_oct($x->{_n});
+ }
+
+##############################################################################
+
+sub from_hex
+ {
+ my $class = shift;
+
+ $class->new(@_);
+ }
+
+sub from_bin
+ {
+ my $class = shift;
+
+ $class->new(@_);
+ }
+
+sub from_oct
+ {
+ my $class = shift;
+
+ my @parts;
+ for my $c (@_)
+ {
+ push @parts, Math::BigInt->from_oct($c);
+ }
+ $class->new ( @parts );
+ }
+
+##############################################################################
+# import
+
sub import
{
my $self = shift;
my $l = scalar @_;
my $lib = ''; my @a;
- $IMPORT++;
+ my $try = 'try';
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); };
}
# elsif ($_[$i] eq 'upgrade')
# {
# # this causes upgrading
-# $upgrade = $_[$i+1]; # or undef to disable
+# $upgrade = $_[$i+1]; # or undef to disable
# $i++;
# }
elsif ($_[$i] eq 'downgrade')
{
# this causes downgrading
- $downgrade = $_[$i+1]; # or undef to disable
+ $downgrade = $_[$i+1]; # or undef to disable
$i++;
}
- elsif ($_[$i] eq 'lib')
+ elsif ($_[$i] =~ /^(lib|try|only)\z/)
{
- $lib = $_[$i+1] || ''; # default Calc
+ $lib = $_[$i+1] || ''; # default Calc
+ $try = $1; # lib, try or only
$i++;
}
elsif ($_[$i] eq 'with')
{
- $MBI = $_[$i+1] || 'Math::BigInt'; # default Math::BigInt
+ # this argument is no longer used
+ #$MBI = $_[$i+1] || 'Math::BigInt::Calc'; # default Math::BigInt::Calc
$i++;
}
else
push @a, $_[$i];
}
}
- # let use Math::BigInt lib => 'GMP'; use Math::BigRat; still work
- my $mbilib = eval { Math::BigInt->config()->{lib} };
- if ((defined $mbilib) && ($MBI eq 'Math::BigInt'))
- {
- # MBI already loaded
- $MBI->import('lib',"$lib,$mbilib", 'objectify');
- }
- else
- {
- # MBI not loaded, or not with "Math::BigInt"
- $lib .= ",$mbilib" if defined $mbilib;
+ require Math::BigInt;
- 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
+ # let use Math::BigInt lib => 'GMP'; use Math::BigRat; still have GMP
+ if ($lib ne '')
+ {
+ my @c = split /\s*,\s*/, $lib;
+ foreach (@c)
{
- my $rc = "use $MBI lib => '$lib', 'objectify';";
- eval $rc;
+ $_ =~ tr/a-zA-Z0-9://cd; # limit to sane characters
}
+ $lib = join(",", @c);
}
- if ($@)
- {
- require Carp; Carp::croak ("Couldn't load $MBI: $! $@");
- }
+ my @import = ('objectify');
+ push @import, $try => $lib if $lib ne '';
+
+ # MBI already loaded, so feed it our lib arguments
+ Math::BigInt->import( @import );
$MBI = Math::BigFloat->config()->{lib};
+
+ # register us with MBI to get notified of future lib changes
+ Math::BigInt::_register_callback( $self, sub { $MBI = $_[0]; } );
- # any non :constant stuff is handled by our parent, Exporter
- # even if @_ is empty, to give it a chance
+ # any non :constant stuff is handled by our parent, Exporter (loaded
+ # by Math::BigFloat, even if @_ is empty, to give it a chance
$self->SUPER::import(@a); # for subclasses
$self->export_to_level(1,$self,@a); # need this, too
}
=head1 NAME
-Math::BigRat - arbitrarily big rational numbers
+Math::BigRat - Arbitrary big rational numbers
=head1 SYNOPSIS
=head1 DESCRIPTION
Math::BigRat complements Math::BigInt and Math::BigFloat by providing support
-for arbitrarily big rational numbers.
+for arbitrary big rational numbers.
=head2 MATH LIBRARY
-Math with the numbers is done (by default) by a module called
-Math::BigInt::Calc. This is equivalent to saying:
-
- use Math::BigRat lib => 'Calc';
+You can change the underlying module that does the low-level
+math operations by using:
-You can change this by using:
+ use Math::BigRat try => 'GMP';
- use Math::BigRat lib => 'BitVect';
+Note: This needs Math::BigInt::GMP installed.
The following would first try to find Math::BigInt::Foo, then
Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
- use Math::BigRat lib => 'Foo,Math::BigInt::Bar';
+ use Math::BigRat try => 'Foo,Math::BigInt::Bar';
+
+If you want to get warned when the fallback occurs, replace "try" with
+"lib":
-Calc.pm uses as internal format an array of elements of some decimal base
-(usually 1e7, but this might be different for some systems) with the least
-significant digit first, while BitVect.pm uses a bit vector of base 2, most
-significant bit first. Other modules might use even different means of
-representing the numbers. See the respective module documentation for further
-details.
+ use Math::BigRat lib => 'Foo,Math::BigInt::Bar';
-Currently the following replacement libraries exist, search for them at CPAN:
+If you want the code to die instead, replace "try" with
+"only":
- Math::BigInt::BitVect
- Math::BigInt::GMP
- Math::BigInt::Pari
- Math::BigInt::FastCalc
+ use Math::BigRat only => 'Foo,Math::BigInt::Bar';
=head1 METHODS
-Any methods not listed here are dervied from Math::BigFloat (or
+Any methods not listed here are derived from Math::BigFloat (or
Math::BigInt), so make sure you check these two modules for further
information.
$x = Math::BigRat->new(Math::BigFloat->new('3.1')); # BigFloat
$x = Math::BigRat->new(Math::BigInt::Lite->new('2')); # BigLite
+ # You can also give D and N as different objects:
+ $x = Math::BigRat->new(
+ Math::BigInt->new(-123),
+ Math::BigInt->new(7),
+ ); # => -123/7
+
=head2 numerator()
$n = $x->numerator();
Return a list consisting of (signed) numerator and (unsigned) denominator as
BigInts.
-=head2 as_number()
+=head2 numify()
+
+ my $y = $x->numify();
+
+Returns the object as a scalar. This will lose some data if the object
+cannot be represented by a normal Perl scalar (integer or float), so
+use as_int() instead.
+
+This routine is automatically used whenever a scalar is required:
+
+ my $x = Math::BigRat->new('3/1');
+ @array = (1,2,3);
+ $y = $array[$x]; # set $y to 3
+
+=head2 as_int()/as_number()
$x = Math::BigRat->new('13/7');
- print $x->as_number(),"\n"; # '1'
+ print $x->as_int(),"\n"; # '1'
+
+Returns a copy of the object as BigInt, truncated to an integer.
+
+C<as_number()> is an alias for C<as_int()>.
+
+=head2 as_hex()
+
+ $x = Math::BigRat->new('13');
+ print $x->as_hex(),"\n"; # '0xd'
+
+Returns the BigRat as hexadecimal string. Works only for integers.
-Returns a copy of the object as BigInt trunced it to integer.
+=head2 as_bin()
+
+ $x = Math::BigRat->new('13');
+ print $x->as_bin(),"\n"; # '0x1101'
+
+Returns the BigRat as binary string. Works only for integers.
+
+=head2 as_oct()
+
+ $x = Math::BigRat->new('13');
+ print $x->as_oct(),"\n"; # '015'
+
+Returns the BigRat as octal string. Works only for integers.
+
+=head2 from_hex()/from_bin()/from_oct()
+
+ my $h = Math::BigRat->from_hex('0x10');
+ my $b = Math::BigRat->from_bin('0b10000000');
+ my $o = Math::BigRat->from_oct('020');
+
+Create a BigRat from an hexadecimal, binary or octal number
+in string form.
+
+=head2 length()
+
+ $len = $x->length();
+
+Return the length of $x in digitis for integer values.
+
+=head2 digit()
+
+ print Math::BigRat->new('123/1')->digit(1); # 1
+ print Math::BigRat->new('123/1')->digit(-1); # 3
+
+Return the N'ths digit from X when X is an integer value.
+
+=head2 bnorm()
+
+ $x->bnorm();
+
+Reduce the number to the shortest form. This routine is called
+automatically whenever it is needed.
=head2 bfac()
Works currently only for integers.
-=head2 blog()
-
-Is not yet implemented.
-
=head2 bround()/round()/bfround()
Are not yet implemented.
Set $x to the remainder of the division of $x by $y.
+=head2 bneg()
+
+ $x->bneg();
+
+Used to negate the object in-place.
+
=head2 is_one()
print "$x is 1\n" if $x->is_one();
Return true if $x is exactly zero, otherwise false.
-=head2 is_positive()
+=head2 is_pos()/is_positive()
print "$x is >= 0\n" if $x->is_positive();
Return true if $x is positive (greater than or equal to zero), otherwise
false. Please note that '+inf' is also positive, while 'NaN' and '-inf' aren't.
-=head2 is_negative()
+C<is_positive()> is an alias for C<is_pos()>.
+
+=head2 is_neg()/is_negative()
print "$x is < 0\n" if $x->is_negative();
Return true if $x is negative (smaller than zero), otherwise false. Please
note that '-inf' is also negative, while 'NaN' and '+inf' aren't.
+C<is_negative()> is an alias for C<is_neg()>.
+
=head2 is_int()
print "$x is an integer\n" if $x->is_int();
Calculate the square root of $x.
-=head2 config
+=head2 broot()
+
+ $x->broot($n);
+
+Calculate the N'th root of $x.
+
+=head2 badd()/bmul()/bsub()/bdiv()/bdec()/binc()
+
+Please see the documentation in L<Math::BigInt>.
+
+=head2 copy()
+
+ my $z = $x->copy();
+
+Makes a deep copy of the object.
+
+Please see the documentation in L<Math::BigInt> for further details.
+
+=head2 bstr()/bsstr()
+
+ my $x = Math::BigInt->new('8/4');
+ print $x->bstr(),"\n"; # prints 1/2
+ print $x->bsstr(),"\n"; # prints 1/2
+
+Return a string representating this object.
+
+=head2 bacmp()/bcmp()
+
+Used to compare numbers.
+
+Please see the documentation in L<Math::BigInt> for further details.
+
+=head2 blsft()/brsft()
+
+Used to shift numbers left/right.
+
+Please see the documentation in L<Math::BigInt> for further details.
+
+=head2 bpow()
+
+ $x->bpow($y);
+
+Compute $x ** $y.
+
+Please see the documentation in L<Math::BigInt> for further details.
+
+=head2 bexp()
+
+ $x->bexp($accuracy); # calculate e ** X
+
+Calculates two integers A and B so that A/B is equal to C<e ** $x>, where C<e> is
+Euler's number.
+
+This method was added in v0.20 of Math::BigRat (May 2007).
+
+See also L<blog()>.
+
+=head2 bnok()
+
+ $x->bnok($y); # x over y (binomial coefficient n over k)
+
+Calculates the binomial coefficient n over k, also called the "choose"
+function. The result is equivalent to:
+
+ ( n ) n!
+ | - | = -------
+ ( k ) k!(n-k)!
+
+This method was added in v0.20 of Math::BigRat (May 2007).
+
+=head2 config()
use Data::Dumper;
undef
round_mode RW Global round mode
even
- div_scale RW Fallback acccuracy for div
+ div_scale RW Fallback accuracy for div
40
trap_nan RW Trap creation of NaN (undef = no)
undef
=head1 AUTHORS
-(C) by Tels L<http://bloodgate.com/> 2001, 2002, 2003, 2004.
+(C) by Tels L<http://bloodgate.com/> 2001 - 2007.
=cut