package bigint; use strict; use warnings; use Carp qw< carp croak >; our \$VERSION = '0.63'; use Exporter; our @ISA = qw( Exporter ); our @EXPORT_OK = qw( PI e bpi bexp hex oct ); our @EXPORT = qw( inf NaN ); use overload; use Math::BigInt; my \$obj_class = "Math::BigInt"; ############################################################################## sub accuracy { my \$self = shift; \$obj_class -> accuracy(@_); } sub precision { my \$self = shift; \$obj_class -> precision(@_); } sub round_mode { my \$self = shift; \$obj_class -> round_mode(@_); } sub div_scale { my \$self = shift; \$obj_class -> div_scale(@_); } sub upgrade { my \$self = shift; \$obj_class -> upgrade(@_); } sub downgrade { my \$self = shift; \$obj_class -> downgrade(@_); } sub in_effect { my \$level = shift || 0; my \$hinthash = (caller(\$level))[10]; \$hinthash->{bigint}; } sub _float_constant { my \$str = shift; # We can't pass input directly to new() because of the way it handles the # combination of non-integers with no upgrading. Such cases are by # Math::BigInt returned as NaN, but we truncate to an integer. # See if we can convert the input string to a string using a normalized form # consisting of the significand as a signed integer, the character "e", and # the exponent as a signed integer, e.g., "+0e+0", "+314e-2", and "-1e+3". my \$nstr; if ( # See if it is an octal number. An octal number like '0377' is also # accepted by the functions parsing decimal and hexadecimal numbers, so # handle octal numbers before decimal and hexadecimal numbers. \$str =~ /^0(?:[Oo]|_*[0-7])/ and \$nstr = Math::BigInt -> oct_str_to_dec_flt_str(\$str) or # See if it is decimal number. \$nstr = Math::BigInt -> dec_str_to_dec_flt_str(\$str) or # See if it is a hexadecimal number. Every hexadecimal number has a # prefix, but the functions parsing numbers don't require it, so check # to see if it actually is a hexadecimal number. \$str =~ /^0[Xx]/ and \$nstr = Math::BigInt -> hex_str_to_dec_flt_str(\$str) or # See if it is a binary numbers. Every binary number has a prefix, but # the functions parsing numbers don't require it, so check to see if it # actually is a binary number. \$str =~ /^0[Bb]/ and \$nstr = Math::BigInt -> bin_str_to_dec_flt_str(\$str)) { my \$pos = index(\$nstr, 'e'); my \$expo_sgn = substr(\$nstr, \$pos + 1, 1); my \$sign = substr(\$nstr, 0, 1); my \$mant = substr(\$nstr, 1, \$pos - 1); my \$mant_len = CORE::length(\$mant); my \$expo = substr(\$nstr, \$pos + 2); if (\$expo_sgn eq '-') { my \$upgrade = \$obj_class -> upgrade(); return \$upgrade -> new(\$nstr) if defined \$upgrade; if (\$mant_len <= \$expo) { return \$obj_class -> bzero(); # underflow } else { \$mant = substr \$mant, 0, \$mant_len - \$expo; # truncate return \$obj_class -> new(\$sign . \$mant); } } else { \$mant .= "0" x \$expo; # pad with zeros return \$obj_class -> new(\$sign . \$mant); } } # If we get here, there is a bug in the code above this point. warn "Internal error: unable to handle literal constant '\$str'.", " This is a bug, so please report this to the module author."; return \$obj_class -> bnan(); } ############################################################################# # the following two routines are for "use bigint qw/hex oct/;": use constant LEXICAL => \$] > 5.009004; # Internal function with the same semantics as CORE::hex(). This function is # not used directly, but rather by other front-end functions. sub _hex_core { my \$str = shift; # Strip off, clean, and parse as much as we can from the beginning. my \$x; if (\$str =~ s/ ^ ( 0? [xX] )? ( [0-9a-fA-F]* ( _ [0-9a-fA-F]+ )* ) //x) { my \$chrs = \$2; \$chrs =~ tr/_//d; \$chrs = '0' unless CORE::length \$chrs; \$x = \$obj_class -> from_hex(\$chrs); } else { \$x = \$obj_class -> bzero(); } # Warn about trailing garbage. if (CORE::length(\$str)) { require Carp; Carp::carp(sprintf("Illegal hexadecimal digit '%s' ignored", substr(\$str, 0, 1))); } return \$x; } # Internal function with the same semantics as CORE::oct(). This function is # not used directly, but rather by other front-end functions. sub _oct_core { my \$str = shift; \$str =~ s/^\s*//; # Hexadecimal input. return _hex_core(\$str) if \$str =~ /^0?[xX]/; my \$x; # Binary input. if (\$str =~ /^0?[bB]/) { # Strip off, clean, and parse as much as we can from the beginning. if (\$str =~ s/ ^ ( 0? [bB] )? ( [01]* ( _ [01]+ )* ) //x) { my \$chrs = \$2; \$chrs =~ tr/_//d; \$chrs = '0' unless CORE::length \$chrs; \$x = \$obj_class -> from_bin(\$chrs); } # Warn about trailing garbage. if (CORE::length(\$str)) { require Carp; Carp::carp(sprintf("Illegal binary digit '%s' ignored", substr(\$str, 0, 1))); } return \$x; } # Octal input. Strip off, clean, and parse as much as we can from the # beginning. if (\$str =~ s/ ^ ( 0? [oO] )? ( [0-7]* ( _ [0-7]+ )* ) //x) { my \$chrs = \$2; \$chrs =~ tr/_//d; \$chrs = '0' unless CORE::length \$chrs; \$x = \$obj_class -> from_oct(\$chrs); } # Warn about trailing garbage. CORE::oct() only warns about 8 and 9, but it # is more helpful to warn about all invalid digits. if (CORE::length(\$str)) { require Carp; Carp::carp(sprintf("Illegal octal digit '%s' ignored", substr(\$str, 0, 1))); } return \$x; } { my \$proto = LEXICAL ? '_' : ';\$'; eval ' sub hex(' . \$proto . ') {' . <<'.'; my \$str = @_ ? \$_[0] : \$_; _hex_core(\$str); } . eval ' sub oct(' . \$proto . ') {' . <<'.'; my \$str = @_ ? \$_[0] : \$_; _oct_core(\$str); } . } ############################################################################# # the following two routines are for Perl 5.9.4 or later and are lexical my (\$prev_oct, \$prev_hex, \$overridden); if (LEXICAL) { eval <<'.' } sub _hex(_) { my \$hh = (caller 0)[10]; return \$\$hh{bigint} ? bigint::_hex_core(\$_[0]) : \$\$hh{bignum} ? bignum::_hex_core(\$_[0]) : \$\$hh{bigrat} ? bigrat::_hex_core(\$_[0]) : \$prev_hex ? &\$prev_hex(\$_[0]) : CORE::hex(\$_[0]); } sub _oct(_) { my \$hh = (caller 0)[10]; return \$\$hh{bigint} ? bigint::_oct_core(\$_[0]) : \$\$hh{bignum} ? bignum::_oct_core(\$_[0]) : \$\$hh{bigrat} ? bigrat::_oct_core(\$_[0]) : \$prev_oct ? &\$prev_oct(\$_[0]) : CORE::oct(\$_[0]); } . sub _override { return if \$overridden; \$prev_oct = *CORE::GLOBAL::oct{CODE}; \$prev_hex = *CORE::GLOBAL::hex{CODE}; no warnings 'redefine'; *CORE::GLOBAL::oct = \&_oct; *CORE::GLOBAL::hex = \&_hex; \$overridden = 1; } sub unimport { \$^H{bigint} = undef; # no longer in effect overload::remove_constant('binary', '', 'float', '', 'integer'); } sub import { my \$class = shift; \$^H{bigint} = 1; # we are in effect \$^H{bignum} = undef; \$^H{bigrat} = undef; # for newer Perls always override hex() and oct() with a lexical version: if (LEXICAL) { _override(); } my @import = (); my @a = (); # unrecognized arguments my \$ver; # version? trace? while (@_) { my \$param = shift; # Upgrading. if (\$param eq 'upgrade') { \$class -> upgrade(shift); next; } # Downgrading. if (\$param eq 'downgrade') { \$class -> downgrade(shift); next; } # Accuracy. if (\$param =~ /^a(ccuracy)?\$/) { \$class -> accuracy(shift); next; } # Precision. if (\$param =~ /^p(recision)?\$/) { \$class -> precision(shift); next; } # Rounding mode. if (\$param eq 'round_mode') { \$class -> round_mode(shift); next; } # Backend library. if (\$param =~ /^(l|lib|try|only)\$/) { push @import, \$param eq 'l' ? 'lib' : \$param; push @import, shift() if @_; next; } if (\$param =~ /^(v|version)\$/) { \$ver = 1; next; } if (\$param =~ /^(t|trace)\$/) { \$obj_class .= "::Trace"; eval "require \$obj_class"; die \$@ if \$@; next; } if (\$param =~ /^(PI|e|bexp|bpi|hex|oct)\z/) { push @a, \$param; next; } croak("Unknown option '\$param'"); } \$obj_class -> import(@import); if (\$ver) { printf "%-31s v%s\n", \$class, \$class -> VERSION(); printf " lib => %-23s v%s\n", \$obj_class -> config("lib"), \$obj_class -> config("lib_version"); printf "%-31s v%s\n", \$obj_class, \$obj_class -> VERSION(); exit; } \$class -> export_to_level(1, \$class, @a); # export inf, NaN, etc. overload::constant # This takes care each number written as decimal integer and within the # range of what perl can represent as an integer, e.g., "314", but not # "3141592653589793238462643383279502884197169399375105820974944592307". integer => sub { #printf "Value '%s' handled by the 'integer' sub.\n", \$_[0]; my \$str = shift; return \$obj_class -> new(\$str); }, # This takes care of each number written with a decimal point and/or # using floating point notation, e.g., "3.", "3.0", "3.14e+2" (decimal), # "0b1.101p+2" (binary), "03.14p+2" and "0o3.14p+2" (octal), and # "0x3.14p+2" (hexadecimal). float => sub { #printf "# Value '%s' handled by the 'float' sub.\n", \$_[0]; _float_constant(shift); }, # Take care of each number written as an integer (no decimal point or # exponent) using binary, octal, or hexadecimal notation, e.g., "0b101" # (binary), "0314" and "0o314" (octal), and "0x314" (hexadecimal). binary => sub { #printf "# Value '%s' handled by the 'binary' sub.\n", \$_[0]; my \$str = shift; return \$obj_class -> new(\$str) if \$str =~ /^0[XxBb]/; \$obj_class -> from_oct(\$str); }; } sub inf () { \$obj_class -> binf(); } sub NaN () { \$obj_class -> bnan(); } sub PI () { \$obj_class -> new(3); } sub e () { \$obj_class -> new(2); } sub bpi (\$) { \$obj_class -> new(3); } sub bexp (\$\$) { my \$x = \$obj_class -> new(shift); \$x -> bexp(@_); } 1; __END__ =pod =head1 NAME bigint - transparent big integer support for Perl =head1 SYNOPSIS use bigint; \$x = 2 + 4.5; # Math::BigInt 6 print 2 ** 512; # Math::BigInt 134...096 print inf + 42; # Math::BigInt inf print NaN * 7; # Math::BigInt NaN print hex("0x1234567890123490"); # Perl v5.10.0 or later { no bigint; print 2 ** 256; # a normal Perl scalar now } # for older Perls, import into current package: use bigint qw/hex oct/; print hex("0x1234567890123490"); print oct("01234567890123490"); =head1 DESCRIPTION All numeric literal in the given scope are converted to Math::BigInt objects. Numeric literal that represent non-integers are truncated to an integer. All results of expressions are also truncated to integer. All operators (including basic math operations) except the range operator C<..> are overloaded. Unlike the L pragma, the C pragma creates integers that are only limited in their size by the available memory. So, the following: use bigint; \$x = 1234; creates a Math::BigInt and stores a reference to in \$x. This happens transparently and behind your back, so to speak. You can see this with the following: perl -Mbigint -le 'print ref(1234)' Since numbers are actually objects, you can call all the usual methods from Math::BigFloat on them. This even works to some extent on expressions: perl -Mbigint -le '\$x = 1234; print \$x->bdec()' perl -Mbigint -le 'print 1234->copy()->binc();' perl -Mbigint -le 'print 1234->copy()->binc->badd(6);' perl -Mbigint -le 'print +(1234)->copy()->binc()' (Note that print doesn't do what you expect if the expression starts with '(' hence the C<+>) You can even chain the operations together as usual: perl -Mbigint -le 'print 1234->copy()->binc->badd(6);' 1241 Please note the following does not work as expected (prints nothing), since overloading of '..' is not yet possible in Perl (as of v5.8.0): perl -Mbigint -le 'for (1..2) { print ref(\$_); }' =head2 use integer vs. use bigint There are some difference between C and C. Whereas C is limited to what can be handled as a Perl scalar, C can handle arbitrarily large integers. Also, C does affect assignments to variables and the return value of some functions. C truncates these results to integer: # perl -Minteger -wle 'print 3.2' 3.2 # perl -Minteger -wle 'print 3.2 + 0' 3 # perl -Mbigint -wle 'print 3.2' 3 # perl -Mbigint -wle 'print 3.2 + 0' 3 # perl -Mbigint -wle 'print exp(1) + 0' 2 # perl -Mbigint -wle 'print exp(1)' 2 # perl -Minteger -wle 'print exp(1)' 2.71828182845905 # perl -Minteger -wle 'print exp(1) + 0' 2 In practice this seldom makes a difference for small integers as B of expressions are truncated anyway, but this can, for instance, affect the return value of subroutines: sub three_integer { use integer; return 3.2; } sub three_bigint { use bigint; return 3.2; } print three_integer(), " ", three_bigint(),"\n"; # prints "3.2 3" =head2 Options C recognizes some options that can be passed while loading it via C. The following options exist: =over 4 =item a or accuracy This sets the accuracy for all math operations. The argument must be greater than or equal to zero. See Math::BigInt's bround() method for details. perl -Mbigint=a,2 -le 'print 12345+1' Note that setting precision and accuracy at the same time is not possible. =item p or precision This sets the precision for all math operations. The argument can be any integer. Negative values mean a fixed number of digits after the dot, and are ignored since all operations happen in integer space. A positive value rounds to this digit left from the dot. 0 means round to integer. See Math::BigInt's bfround() method for details. perl -mbigint=p,5 -le 'print 123456789+123' Note that setting precision and accuracy at the same time is not possible. =item t or trace This enables a trace mode and is primarily for debugging. =item l, lib, try, or only Load a different math lib, see L