1N/Apackage bigrat;
1N/Arequire 5.005;
1N/A
1N/A$VERSION = '0.06';
1N/Ause Exporter;
1N/A@ISA = qw( Exporter );
1N/A@EXPORT_OK = qw( );
1N/A@EXPORT = qw( inf NaN );
1N/A
1N/Ause strict;
1N/A
1N/A##############################################################################
1N/A
1N/A# These are all alike, and thus faked by AUTOLOAD
1N/A
1N/Amy @faked = qw/round_mode accuracy precision div_scale/;
1N/Ause vars qw/$VERSION $AUTOLOAD $_lite/; # _lite for testsuite
1N/A
1N/Asub AUTOLOAD
1N/A {
1N/A my $name = $AUTOLOAD;
1N/A
1N/A $name =~ s/.*:://; # split package
1N/A no strict 'refs';
1N/A foreach my $n (@faked)
1N/A {
1N/A if ($n eq $name)
1N/A {
1N/A *{"bigrat::$name"} = sub
1N/A {
1N/A my $self = shift;
1N/A no strict 'refs';
1N/A if (defined $_[0])
1N/A {
1N/A Math::BigInt->$name($_[0]);
1N/A Math::BigFloat->$name($_[0]);
1N/A return Math::BigRat->$name($_[0]);
1N/A }
1N/A return Math::BigInt->$name();
1N/A };
1N/A return &$name;
1N/A }
1N/A }
1N/A
1N/A # delayed load of Carp and avoid recursion
1N/A require Carp;
1N/A Carp::croak ("Can't call bigrat\-\>$name, not a valid method");
1N/A }
1N/A
1N/Asub upgrade
1N/A {
1N/A my $self = shift;
1N/A no strict 'refs';
1N/A# if (defined $_[0])
1N/A# {
1N/A# $Math::BigInt::upgrade = $_[0];
1N/A# $Math::BigFloat::upgrade = $_[0];
1N/A# }
1N/A return $Math::BigInt::upgrade;
1N/A }
1N/A
1N/Asub import
1N/A {
1N/A my $self = shift;
1N/A
1N/A # see also bignum->import() for additional comments
1N/A
1N/A # some defaults
1N/A my $lib = 'Calc'; my $upgrade = 'Math::BigFloat';
1N/A
1N/A my @import = ( ':constant' ); # drive it w/ constant
1N/A my @a = @_; my $l = scalar @_; my $j = 0;
1N/A my ($a,$p);
1N/A my ($ver,$trace); # version? trace?
1N/A for ( my $i = 0; $i < $l ; $i++,$j++ )
1N/A {
1N/A if ($_[$i] eq 'upgrade')
1N/A {
1N/A # this causes upgrading
1N/A $upgrade = $_[$i+1]; # or undef to disable
1N/A my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..."
1N/A splice @a, $j, $s; $j -= $s;
1N/A }
1N/A elsif ($_[$i] =~ /^(l|lib)$/)
1N/A {
1N/A # this causes a different low lib to take care...
1N/A $lib = $_[$i+1] || '';
1N/A my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..."
1N/A splice @a, $j, $s; $j -= $s;
1N/A }
1N/A elsif ($_[$i] =~ /^(v|version)$/)
1N/A {
1N/A $ver = 1;
1N/A splice @a, $j, 1; $j --;
1N/A }
1N/A elsif ($_[$i] =~ /^(t|trace)$/)
1N/A {
1N/A $trace = 1;
1N/A splice @a, $j, 1; $j --;
1N/A }
1N/A else
1N/A {
1N/A die ("unknown option $_[$i]");
1N/A }
1N/A }
1N/A my $class;
1N/A $_lite = 0; # using M::BI::L ?
1N/A if ($trace)
1N/A {
1N/A require Math::BigInt::Trace; $class = 'Math::BigInt::Trace';
1N/A $upgrade = 'Math::BigFloat::Trace';
1N/A }
1N/A else
1N/A {
1N/A # see if we can find Math::BigInt::Lite
1N/A if (!defined $a && !defined $p) # rounding won't work to well
1N/A {
1N/A eval 'require Math::BigInt::Lite;';
1N/A if ($@ eq '')
1N/A {
1N/A @import = ( ); # :constant in Lite, not MBI
1N/A Math::BigInt::Lite->import( ':constant' );
1N/A $_lite= 1; # signal okay
1N/A }
1N/A }
1N/A require Math::BigInt if $_lite == 0; # not already loaded?
1N/A $class = 'Math::BigInt'; # regardless of MBIL or not
1N/A }
1N/A # Math::BigInt::Trace or plain Math::BigInt
1N/A $class->import(@import, upgrade => $upgrade, lib => $lib);
1N/A
1N/A require Math::BigFloat;
1N/A Math::BigFloat->import( upgrade => 'Math::BigRat', ':constant' );
1N/A require Math::BigRat;
1N/A if ($ver)
1N/A {
1N/A print "bigrat\t\t\t v$VERSION\n";
1N/A print "Math::BigInt::Lite\t v$Math::BigInt::Lite::VERSION\n" if $_lite;
1N/A print "Math::BigInt\t\t v$Math::BigInt::VERSION";
1N/A my $config = Math::BigInt->config();
1N/A print " lib => $config->{lib} v$config->{lib_version}\n";
1N/A print "Math::BigFloat\t\t v$Math::BigFloat::VERSION\n";
1N/A print "Math::BigRat\t\t v$Math::BigRat::VERSION\n";
1N/A exit;
1N/A }
1N/A $self->export_to_level(1,$self,@a); # export inf and NaN
1N/A }
1N/A
1N/Asub inf () { Math::BigInt->binf(); }
1N/Asub NaN () { Math::BigInt->bnan(); }
1N/A
1N/A1;
1N/A
1N/A__END__
1N/A
1N/A=head1 NAME
1N/A
1N/Abigrat - Transparent BigNumber/BigRational support for Perl
1N/A
1N/A=head1 SYNOPSIS
1N/A
1N/A use bigrat;
1N/A
1N/A $x = 2 + 4.5,"\n"; # BigFloat 6.5
1N/A print 1/3 + 1/4,"\n"; # produces 7/12
1N/A
1N/A=head1 DESCRIPTION
1N/A
1N/AAll operators (inlcuding basic math operations) are overloaded. Integer and
1N/Afloating-point constants are created as proper BigInts or BigFloats,
1N/Arespectively.
1N/A
1N/AOther than L<bignum>, this module upgrades to Math::BigRat, meaning that
1N/Ainstead of 2.5 you will get 2+1/2 as output.
1N/A
1N/A=head2 MODULES USED
1N/A
1N/AC<bigrat> is just a thin wrapper around various modules of the Math::BigInt
1N/Afamily. Think of it as the head of the family, who runs the shop, and orders
1N/Athe others to do the work.
1N/A
1N/AThe following modules are currently used by bignum:
1N/A
1N/A Math::BigInt::Lite (for speed, and only if it is loadable)
1N/A Math::BigInt
1N/A Math::BigFloat
1N/A Math::BigRat
1N/A
1N/A=head2 MATH LIBRARY
1N/A
1N/AMath with the numbers is done (by default) by a module called
1N/AMath::BigInt::Calc. This is equivalent to saying:
1N/A
1N/A use bigrat lib => 'Calc';
1N/A
1N/AYou can change this by using:
1N/A
1N/A use bigrat lib => 'BitVect';
1N/A
1N/AThe following would first try to find Math::BigInt::Foo, then
1N/AMath::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
1N/A
1N/A use bigrat lib => 'Foo,Math::BigInt::Bar';
1N/A
1N/APlease see respective module documentation for further details.
1N/A
1N/A=head2 SIGN
1N/A
1N/AThe sign is either '+', '-', 'NaN', '+inf' or '-inf' and stored seperately.
1N/A
1N/AA sign of 'NaN' is used to represent the result when input arguments are not
1N/Anumbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively
1N/Aminus infinity. You will get '+inf' when dividing a positive number by 0, and
1N/A'-inf' when dividing any negative number by 0.
1N/A
1N/A=head2 METHODS
1N/A
1N/ASince all numbers are not objects, you can use all functions that are part of
1N/Athe BigInt or BigFloat API. It is wise to use only the bxxx() notation, and not
1N/Athe fxxx() notation, though. This makes you independed on the fact that the
1N/Aunderlying object might morph into a different class than BigFloat.
1N/A
1N/A=head2 CAVEAT
1N/A
1N/ABut a warning is in order. When using the following to make a copy of a number,
1N/Aonly a shallow copy will be made.
1N/A
1N/A $x = 9; $y = $x;
1N/A $x = $y = 7;
1N/A
1N/AUsing the copy or the original with overloaded math is okay, e.g. the
1N/Afollowing work:
1N/A
1N/A $x = 9; $y = $x;
1N/A print $x + 1, " ", $y,"\n"; # prints 10 9
1N/A
1N/Abut calling any method that modifies the number directly will result in
1N/AB<both> the original and the copy beeing destroyed:
1N/A
1N/A $x = 9; $y = $x;
1N/A print $x->badd(1), " ", $y,"\n"; # prints 10 10
1N/A
1N/A $x = 9; $y = $x;
1N/A print $x->binc(1), " ", $y,"\n"; # prints 10 10
1N/A
1N/A $x = 9; $y = $x;
1N/A print $x->bmul(2), " ", $y,"\n"; # prints 18 18
1N/A
1N/AUsing methods that do not modify, but testthe contents works:
1N/A
1N/A $x = 9; $y = $x;
1N/A $z = 9 if $x->is_zero(); # works fine
1N/A
1N/ASee the documentation about the copy constructor and C<=> in overload, as
1N/Awell as the documentation in BigInt for further details.
1N/A
1N/A=head1 EXAMPLES
1N/A
1N/A perl -Mbigrat -le 'print sqrt(33)'
1N/A perl -Mbigrat -le 'print 2*255'
1N/A perl -Mbigrat -le 'print 4.5+2*255'
1N/A perl -Mbigrat -le 'print 3/7 + 5/7 + 8/3'
1N/A perl -Mbigrat -le 'print 12->is_odd()';
1N/A
1N/A=head1 LICENSE
1N/A
1N/AThis program is free software; you may redistribute it and/or modify it under
1N/Athe same terms as Perl itself.
1N/A
1N/A=head1 SEE ALSO
1N/A
1N/AEspecially L<bignum>.
1N/A
1N/AL<Math::BigFloat>, L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well
1N/Aas L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and L<Math::BigInt::GMP>.
1N/A
1N/A=head1 AUTHORS
1N/A
1N/A(C) by Tels L<http://bloodgate.com/> in early 2002.
1N/A
1N/A=cut