1N/Apackage bignum;
1N/Arequire 5.005;
1N/A
1N/A$VERSION = '0.15';
1N/Ause Exporter;
1N/A@EXPORT_OK = qw( );
1N/A@EXPORT = qw( inf NaN );
1N/A@ISA = qw( Exporter );
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 *{"bignum::$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 return Math::BigFloat->$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 bignum\-\>$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 # some defaults
1N/A my $lib = 'Calc';
1N/A my $upgrade = 'Math::BigFloat';
1N/A my $downgrade = 'Math::BigInt';
1N/A
1N/A my @import = ( ':constant' ); # drive it w/ constant
1N/A my @a = @_; my $l = scalar @_; my $j = 0;
1N/A my ($ver,$trace); # version? trace?
1N/A my ($a,$p); # accuracy, precision
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; $i++;
1N/A }
1N/A elsif ($_[$i] eq 'downgrade')
1N/A {
1N/A # this causes downgrading
1N/A $downgrade = $_[$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; $i++;
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; $i++;
1N/A }
1N/A elsif ($_[$i] =~ /^(a|accuracy)$/)
1N/A {
1N/A $a = $_[$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; $i++;
1N/A }
1N/A elsif ($_[$i] =~ /^(p|precision)$/)
1N/A {
1N/A $p = $_[$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; $i++;
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 { die "unknown option $_[$i]"; }
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 if ($trace)
1N/A {
1N/A require Math::BigFloat::Trace; $class = 'Math::BigFloat::Trace';
1N/A $downgrade = 'Math::BigInt::Trace';
1N/A }
1N/A else
1N/A {
1N/A require Math::BigFloat; $class = 'Math::BigFloat';
1N/A }
1N/A $class->import(':constant','downgrade',$downgrade);
1N/A
1N/A bignum->accuracy($a) if defined $a;
1N/A bignum->precision($p) if defined $p;
1N/A if ($ver)
1N/A {
1N/A print "bignum\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 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/Abignum - Transparent BigNumber support for Perl
1N/A
1N/A=head1 SYNOPSIS
1N/A
1N/A use bignum;
1N/A
1N/A $x = 2 + 4.5,"\n"; # BigFloat 6.5
1N/A print 2 ** 512 * 0.1,"\n"; # really is what you think it is
1N/A print inf * inf,"\n"; # prints inf
1N/A print NaN * 3,"\n"; # prints NaN
1N/A
1N/A=head1 DESCRIPTION
1N/A
1N/AAll operators (including basic math operations) are overloaded. Integer and
1N/Afloating-point constants are created as proper BigInts or BigFloats,
1N/Arespectively.
1N/A
1N/AIf you do
1N/A
1N/A use bignum;
1N/A
1N/Aat the top of your script, Math::BigFloat and Math::BigInt will be loaded
1N/Aand any constant number will be converted to an object (Math::BigFloat for
1N/Afloats like 3.1415 and Math::BigInt for integers like 1234).
1N/A
1N/ASo, the following line:
1N/A
1N/A $x = 1234;
1N/A
1N/Acreates actually a Math::BigInt and stores a reference to in $x.
1N/AThis happens transparently and behind your back, so to speak.
1N/A
1N/AYou can see this with the following:
1N/A
1N/A perl -Mbignum -le 'print ref(1234)'
1N/A
1N/ADon't worry if it says Math::BigInt::Lite, bignum and friends will use Lite
1N/Aif it is installed since it is faster for some operations. It will be
1N/Aautomatically upgraded to BigInt whenever neccessary:
1N/A
1N/A perl -Mbignum -le 'print ref(2**255)'
1N/A
1N/AThis also means it is a bad idea to check for some specific package, since
1N/Athe actual contents of $x might be something unexpected. Due to the
1N/Atransparent way of bignum C<ref()> should not be neccessary, anyway.
1N/A
1N/ASince Math::BigInt and BigFloat also overload the normal math operations,
1N/Athe following line will still work:
1N/A
1N/A perl -Mbignum -le 'print ref(1234+1234)'
1N/A
1N/ASince numbers are actually objects, you can call all the usual methods from
1N/ABigInt/BigFloat on them. This even works to some extent on expressions:
1N/A
1N/A perl -Mbignum -le '$x = 1234; print $x->bdec()'
1N/A perl -Mbignum -le 'print 1234->binc();'
1N/A perl -Mbignum -le 'print 1234->binc->badd(6);'
1N/A perl -Mbignum -le 'print +(1234)->binc()'
1N/A
1N/A(Note that print doesn't do what you expect if the expression starts with
1N/A'(' hence the C<+>)
1N/A
1N/AYou can even chain the operations together as usual:
1N/A
1N/A perl -Mbignum -le 'print 1234->binc->badd(6);'
1N/A 1241
1N/A
1N/AUnder bignum (or bigint or bigrat), Perl will "upgrade" the numbers
1N/Aappropriately. This means that:
1N/A
1N/A perl -Mbignum -le 'print 1234+4.5'
1N/A 1238.5
1N/A
1N/Awill work correctly. These mixed cases don't do always work when using
1N/AMath::BigInt or Math::BigFloat alone, or at least not in the way normal Perl
1N/Ascalars work.
1N/A
1N/AIf you do want to work with large integers like under C<use integer;>, try
1N/AC<use bigint;>:
1N/A
1N/A perl -Mbigint -le 'print 1234.5+4.5'
1N/A 1238
1N/A
1N/AThere is also C<use bigrat;> which gives you big rationals:
1N/A
1N/A perl -Mbigrat -le 'print 1234+4.1'
1N/A 12381/10
1N/A
1N/AThe entire upgrading/downgrading is still experimental and might not work
1N/Aas you expect or may even have bugs.
1N/A
1N/AYou might get errors like this:
1N/A
1N/A Can't use an undefined value as an ARRAY reference at
1N/A /usr/local/lib/perl5/5.8.0/Math/BigInt/Calc.pm line 864
1N/A
1N/AThis means somewhere a routine got a BigFloat/Lite but expected a BigInt (or
1N/Avice versa) and the upgrade/downgrad path was missing. This is a bug, please
1N/Areport it so that we can fix it.
1N/A
1N/AYou might consider using just Math::BigInt or Math::BigFloat, since they
1N/Aallow you finer control over what get's done in which module/space. For
1N/Ainstance, simple loop counters will be Math::BigInts under C<use bignum;> and
1N/Athis is slower than keeping them as Perl scalars:
1N/A
1N/A perl -Mbignum -le 'for ($i = 0; $i < 10; $i++) { print ref($i); }'
1N/A
1N/APlease note the following does not work as expected (prints nothing), since
1N/Aoverloading of '..' is not yet possible in Perl (as of v5.8.0):
1N/A
1N/A perl -Mbignum -le 'for (1..2) { print ref($_); }'
1N/A
1N/A=head2 OPTIONS
1N/A
1N/Abignum recognizes some options that can be passed while loading it via use.
1N/AThe options can (currently) be either a single letter form, or the long form.
1N/AThe following options exist:
1N/A
1N/A=over 2
1N/A
1N/A=item a or accuracy
1N/A
1N/AThis sets the accuracy for all math operations. The argument must be greater
1N/Athan or equal to zero. See Math::BigInt's bround() function for details.
1N/A
1N/A perl -Mbignum=a,50 -le 'print sqrt(20)'
1N/A
1N/A=item p or precision
1N/A
1N/AThis sets the precision for all math operations. The argument can be any
1N/Ainteger. Negative values mean a fixed number of digits after the dot, while
1N/Aa positive value rounds to this digit left from the dot. 0 or 1 mean round to
1N/Ainteger. See Math::BigInt's bfround() function for details.
1N/A
1N/A perl -Mbignum=p,-50 -le 'print sqrt(20)'
1N/A
1N/A=item t or trace
1N/A
1N/AThis enables a trace mode and is primarily for debugging bignum or
1N/AMath::BigInt/Math::BigFloat.
1N/A
1N/A=item l or lib
1N/A
1N/ALoad a different math lib, see L<MATH LIBRARY>.
1N/A
1N/A perl -Mbignum=l,GMP -e 'print 2 ** 512'
1N/A
1N/ACurrently there is no way to specify more than one library on the command
1N/Aline. This will be hopefully fixed soon ;)
1N/A
1N/A=item v or version
1N/A
1N/AThis prints out the name and version of all modules used and then exits.
1N/A
1N/A perl -Mbignum=v -e ''
1N/A
1N/A=head2 METHODS
1N/A
1N/ABeside import() and AUTOLOAD() there are only a few other methods.
1N/A
1N/ASince all numbers are now 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 it possible that the underlying object
1N/Amight 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=over 2
1N/A
1N/A=item inf()
1N/A
1N/AA shortcut to return Math::BigInt->binf(). Usefull because Perl does not always
1N/Ahandle bareword C<inf> properly.
1N/A
1N/A=item NaN()
1N/A
1N/AA shortcut to return Math::BigInt->bnan(). Usefull because Perl does not always
1N/Ahandle bareword C<NaN> properly.
1N/A
1N/A=item upgrade()
1N/A
1N/AReturn the class that numbers are upgraded to, is in fact returning
1N/AC<$Math::BigInt::upgrade>.
1N/A
1N/A=back
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 bignum lib => 'Calc';
1N/A
1N/AYou can change this by using:
1N/A
1N/A use bignum 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 bignum lib => 'Foo,Math::BigInt::Bar';
1N/A
1N/APlease see respective module documentation for further details.
1N/A
1N/A=head2 INTERNAL FORMAT
1N/A
1N/AThe numbers are stored as objects, and their internals might change at anytime,
1N/Aespecially between math operations. The objects also might belong to different
1N/Aclasses, like Math::BigInt, or Math::BigFLoat. Mixing them together, even
1N/Awith normal scalars is not extraordinary, but normal and expected.
1N/A
1N/AYou should not depend on the internal format, all accesses must go through
1N/Aaccessor methods. E.g. looking at $x->{sign} is not a bright idea since there
1N/Ais no guaranty that the object in question has such a hashkey, nor is a hash
1N/Aunderneath at all.
1N/A
1N/A=head2 SIGN
1N/A
1N/AThe sign is either '+', '-', 'NaN', '+inf' or '-inf' and stored seperately.
1N/AYou can access it with the sign() method.
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=head1 MODULES USED
1N/A
1N/AC<bignum> 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
1N/A=head1 EXAMPLES
1N/A
1N/ASome cool command line examples to impress the Python crowd ;)
1N/A
1N/A perl -Mbignum -le 'print sqrt(33)'
1N/A perl -Mbignum -le 'print 2*255'
1N/A perl -Mbignum -le 'print 4.5+2*255'
1N/A perl -Mbignum -le 'print 3/7 + 5/7 + 8/3'
1N/A perl -Mbignum -le 'print 123->is_odd()'
1N/A perl -Mbignum -le 'print log(2)'
1N/A perl -Mbignum -le 'print 2 ** 0.5'
1N/A perl -Mbignum=a,65 -le 'print 2 ** 0.2'
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<bigrat> as in C<perl -Mbigrat -le 'print 1/3+1/4'>.
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, 2003.
1N/A
1N/A=cut