diff options
author | Steve Hay <steve.m.hay@googlemail.com> | 2015-10-15 14:04:28 +0100 |
---|---|---|
committer | Steve Hay <steve.m.hay@googlemail.com> | 2015-10-15 17:45:00 +0100 |
commit | c287fe329195a77c40b06a322c85083aa5bc220d (patch) | |
tree | b8fe624d4cef2219eb5ec715f18cb1497e198d8f /cpan | |
parent | 212f8d8f96a73d28eefc56db48f8a30c0d6c0088 (diff) | |
download | perl-c287fe329195a77c40b06a322c85083aa5bc220d.tar.gz |
Move bignum from dist/ to cpan/
Also, blead is actually in sync with 0.40, not 0.37.
Diffstat (limited to 'cpan')
27 files changed, 2835 insertions, 0 deletions
diff --git a/cpan/bignum/lib/Math/BigFloat/Trace.pm b/cpan/bignum/lib/Math/BigFloat/Trace.pm new file mode 100644 index 0000000000..6eee9fafff --- /dev/null +++ b/cpan/bignum/lib/Math/BigFloat/Trace.pm @@ -0,0 +1,57 @@ +#!/usr/bin/perl -w + +package Math::BigFloat::Trace; + +require 5.005_02; +use strict; + +use Exporter; +use Math::BigFloat; +use vars qw($VERSION @ISA $PACKAGE @EXPORT_OK + $accuracy $precision $round_mode $div_scale); + +@ISA = qw(Exporter Math::BigFloat); + +$VERSION = '0.40'; + +use overload; # inherit overload from BigFloat + +# Globals +$accuracy = $precision = undef; +$round_mode = 'even'; +$div_scale = 40; + +sub new { + my $proto = shift; + my $class = ref($proto) || $proto; + + my $value = shift; + my $a = $accuracy; + $a = $_[0] if defined $_[0]; + my $p = $precision; + $p = $_[1] if defined $_[1]; + my $self = Math::BigFloat->new($value, $a, $p, $round_mode); + + # remember, downgrading may return a BigInt, so don't meddle with class + # bless $self, $class; + + print "MBF new '$value' => '$self' (", ref($self), ")"; + return $self; +} + +sub import { + print "MBF import ", join(' ', @_); + my $self = shift; + + # we catch the constants, the rest goes go BigFloat + my @a = (); + foreach (@_) { + push @a, $_ if $_ ne ':constant'; + } + overload::constant float => sub { $self->new(shift); }; + + Math::BigFloat->import(@a); # need it for subclasses +# $self->export_to_level(1,$self,@_); # need this ? +} + +1; diff --git a/cpan/bignum/lib/Math/BigInt/Trace.pm b/cpan/bignum/lib/Math/BigInt/Trace.pm new file mode 100644 index 0000000000..6cab46cc3a --- /dev/null +++ b/cpan/bignum/lib/Math/BigInt/Trace.pm @@ -0,0 +1,47 @@ +#!/usr/bin/perl -w + +package Math::BigInt::Trace; + +require 5.005_02; +use strict; + +use Exporter; +use Math::BigInt; +use vars qw($VERSION @ISA $PACKAGE @EXPORT_OK + $accuracy $precision $round_mode $div_scale); + +@ISA = qw(Exporter Math::BigInt); + +$VERSION = '0.40'; + +use overload; # inherit overload from BigInt + +# Globals +$accuracy = $precision = undef; +$round_mode = 'even'; +$div_scale = 40; + +sub new { + my $proto = shift; + my $class = ref($proto) || $proto; + + my $value = shift; + my $a = $accuracy; + $a = $_[0] if defined $_[0]; + my $p = $precision; + $p = $_[1] if defined $_[1]; + my $self = Math::BigInt->new($value, $a, $p, $round_mode); + bless $self, $class; + print "MBI new '$value' => '$self' (", ref($self), ")"; + return $self; +} + +sub import { + print "MBI import ", join(' ', @_); + my $self = shift; + Math::BigInt::import($self, @_); # need it for subclasses +# $self->export_to_level(1, $self, @_); # need this ? + @_ = (); +} + +1; diff --git a/cpan/bignum/lib/bigint.pm b/cpan/bignum/lib/bigint.pm new file mode 100644 index 0000000000..e6481bd54f --- /dev/null +++ b/cpan/bignum/lib/bigint.pm @@ -0,0 +1,705 @@ +package bigint; +use 5.006; + +$VERSION = '0.40'; +use Exporter; +@ISA = qw( Exporter ); +@EXPORT_OK = qw( PI e bpi bexp hex oct ); +@EXPORT = qw( inf NaN ); + +use strict; +use overload; + +############################################################################## + +# These are all alike, and thus faked by AUTOLOAD + +my @faked = qw/round_mode accuracy precision div_scale/; +use vars qw/$VERSION $AUTOLOAD $_lite/; # _lite for testsuite + +sub AUTOLOAD { + my $name = $AUTOLOAD; + + $name =~ s/.*:://; # split package + no strict 'refs'; + foreach my $n (@faked) { + if ($n eq $name) { + *{"bigint::$name"} = + sub { + my $self = shift; + no strict 'refs'; + if (defined $_[0]) { + return Math::BigInt->$name($_[0]); + } + return Math::BigInt->$name(); + }; + return &$name; + } + } + + # delayed load of Carp and avoid recursion + require Carp; + Carp::croak ("Can't call bigint\-\>$name, not a valid method"); +} + +sub upgrade { + $Math::BigInt::upgrade; +} + +sub _binary_constant { + # this takes a binary/hexadecimal/octal constant string and returns it + # as string suitable for new. Basically it converts octal to decimal, and + # passes every thing else unmodified back. + my $string = shift; + + return Math::BigInt->new($string) if $string =~ /^0[bx]/; + + # so it must be an octal constant + Math::BigInt->from_oct($string); +} + +sub _float_constant { + # this takes a floating point constant string and returns it truncated to + # integer. For instance, '4.5' => '4', '1.234e2' => '123' etc + my $float = shift; + + # some simple cases first + return $float if ($float =~ /^[+-]?[0-9]+$/); # '+123','-1','0' etc + return $float + if ($float =~ /^[+-]?[0-9]+\.?[eE]\+?[0-9]+$/); # 123e2, 123.e+2 + return '0' if ($float =~ /^[+-]?[0]*\.[0-9]+$/); # .2, 0.2, -.1 + if ($float =~ /^[+-]?[0-9]+\.[0-9]*$/) { # 1., 1.23, -1.2 etc + $float =~ s/\..*//; + return $float; + } + my ($mis, $miv, $mfv, $es, $ev) = Math::BigInt::_split($float); + return $float if !defined $mis; # doesn't look like a number to me + my $ec = int($$ev); + my $sign = $$mis; + $sign = '' if $sign eq '+'; + if ($$es eq '-') { + # ignore fraction part entirely + if ($ec >= length($$miv)) { # 123.23E-4 + return '0'; + } + return $sign . substr($$miv, 0, length($$miv) - $ec); # 1234.45E-2 = 12 + } + # xE+y + if ($ec >= length($$mfv)) { + $ec -= length($$mfv); + return $sign.$$miv.$$mfv if $ec == 0; # 123.45E+2 => 12345 + return $sign.$$miv.$$mfv.'E'.$ec; # 123.45e+3 => 12345e1 + } + $mfv = substr($$mfv, 0, $ec); + $sign.$$miv.$mfv; # 123.45e+1 => 1234 +} + +sub unimport { + $^H{bigint} = undef; # no longer in effect + overload::remove_constant('binary', '', 'float', '', 'integer'); +} + +sub in_effect { + my $level = shift || 0; + my $hinthash = (caller($level))[10]; + $hinthash->{bigint}; +} + +############################################################################# +# the following two routines are for "use bigint qw/hex oct/;": + +use constant LEXICAL => $] > 5.009004; + +{ + my $proto = LEXICAL ? '_' : ';$'; + eval ' +sub hex(' . $proto . ') {' . <<'.'; + my $i = @_ ? $_[0] : $_; + $i = '0x'.$i unless $i =~ /^0x/; + Math::BigInt->new($i); +} +. + eval ' +sub oct(' . $proto . ') {' . <<'.'; + my $i = @_ ? $_[0] : $_; + # oct() should never fall back to decimal + return Math::BigInt->from_oct($i) if $i =~ s/^(?=0[0-9]|[1-9])/0/; + Math::BigInt->new($i); +} +. +} + +############################################################################# +# 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 $prev_hex ? &$prev_hex($_[0]) : CORE::hex($_[0]) + unless $$hh{bigint}||$$hh{bignum}||$$hh{bigrat}; + my $i = $_[0]; + $i = '0x'.$i unless $i =~ /^0x/; + Math::BigInt->new($i); +} + +sub _oct(_) { + my $hh = (caller 0)[10]; + return $prev_oct ? &$prev_oct($_[0]) : CORE::oct($_[0]) + unless $$hh{bigint}||$$hh{bignum}||$$hh{bigrat}; + my $i = $_[0]; + # oct() should never fall back to decimal + return Math::BigInt->from_oct($i) if $i =~ s/^(?=0[0-9]|[1-9])/0/; + Math::BigInt->new($i); +} +. + +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++; +} + +sub import { + my $self = shift; + + $^H{bigint} = 1; # we are in effect + + # for newer Perls always override hex() and oct() with a lexical version: + if (LEXICAL) { + _override(); + } + # some defaults + my $lib = ''; + my $lib_kind = 'try'; + + my @import = (':constant'); # drive it w/ constant + my @a = @_; + my $l = scalar @_; + my $j = 0; + my ($ver, $trace); # version? trace? + my ($a, $p); # accuracy, precision + for (my $i = 0; $i < $l; $i++, $j++) { + if ($_[$i] =~ /^(l|lib|try|only)$/) { + # this causes a different low lib to take care... + $lib_kind = $1; + $lib_kind = 'lib' if $lib_kind eq 'l'; + $lib = $_[$i + 1] || ''; + my $s = 2; + $s = 1 if @a - $j < 2; # avoid "can not modify non-existent..." + splice @a, $j, $s; + $j -= $s; + $i++; + } elsif ($_[$i] =~ /^(a|accuracy)$/) { + $a = $_[$i + 1]; + my $s = 2; + $s = 1 if @a - $j < 2; # avoid "can not modify non-existent..." + splice @a, $j, $s; + $j -= $s; + $i++; + } elsif ($_[$i] =~ /^(p|precision)$/) { + $p = $_[$i + 1]; + my $s = 2; + $s = 1 if @a - $j < 2; # avoid "can not modify non-existent..." + splice @a, $j, $s; + $j -= $s; + $i++; + } elsif ($_[$i] =~ /^(v|version)$/) { + $ver = 1; + splice @a, $j, 1; + $j--; + } elsif ($_[$i] =~ /^(t|trace)$/) { + $trace = 1; + splice @a, $j, 1; + $j--; + } elsif ($_[$i] !~ /^(PI|e|bpi|bexp|hex|oct)\z/) { + die ("unknown option $_[$i]"); + } + } + my $class; + $_lite = 0; # using M::BI::L ? + if ($trace) { + require Math::BigInt::Trace; + $class = 'Math::BigInt::Trace'; + } else { + # see if we can find Math::BigInt::Lite + if (!defined $a && !defined $p) { # rounding won't work to well + if (eval { require Math::BigInt::Lite; 1 }) { + @import = (); # :constant in Lite, not MBI + Math::BigInt::Lite->import(':constant'); + $_lite = 1; # signal okay + } + } + require Math::BigInt if $_lite == 0; # not already loaded? + $class = 'Math::BigInt'; # regardless of MBIL or not + } + push @import, $lib_kind => $lib if $lib ne ''; + # Math::BigInt::Trace or plain Math::BigInt + $class->import(@import); + + bigint->accuracy($a) if defined $a; + bigint->precision($p) if defined $p; + if ($ver) { + print "bigint\t\t\t v$VERSION\n"; + print "Math::BigInt::Lite\t v$Math::BigInt::Lite::VERSION\n" if $_lite; + print "Math::BigInt\t\t v$Math::BigInt::VERSION"; + my $config = Math::BigInt->config(); + print " lib => $config->{lib} v$config->{lib_version}\n"; + exit; + } + # we take care of floating point constants, since BigFloat isn't available + # and BigInt doesn't like them: + overload::constant float => + sub { + Math::BigInt->new(_float_constant(shift)); + }; + # Take care of octal/hexadecimal constants + overload::constant binary => + sub { + _binary_constant(shift); + }; + + # if another big* was already loaded: + my ($package) = caller(); + + no strict 'refs'; + if (!defined *{"${package}::inf"}) { + $self->export_to_level(1, $self, @a); # export inf and NaN, e and PI + } +} + +sub inf () { Math::BigInt::binf(); } +sub NaN () { Math::BigInt::bnan(); } + +sub PI () { Math::BigInt->new(3); } +sub e () { Math::BigInt->new(2); } +sub bpi ($) { Math::BigInt->new(3); } +sub bexp ($$) { + my $x = Math::BigInt->new($_[0]); + $x->bexp($_[1]); +} + +1; + +__END__ + +=head1 NAME + +bigint - Transparent BigInteger support for Perl + +=head1 SYNOPSIS + + use bigint; + + $x = 2 + 4.5,"\n"; # BigInt 6 + print 2 ** 512,"\n"; # really is what you think it is + print inf + 42,"\n"; # inf + print NaN * 7,"\n"; # NaN + print hex("0x1234567890123490"),"\n"; # Perl v5.10.0 or later + + { + no bigint; + print 2 ** 256,"\n"; # a normal Perl scalar now + } + + # Import into current package: + use bigint qw/hex oct/; + print hex("0x1234567890123490"),"\n"; + print oct("01234567890123490"),"\n"; + +=head1 DESCRIPTION + +All operators (including basic math operations) except the range operator C<..> +are overloaded. Integer constants are created as proper BigInts. + +Floating point constants are truncated to integer. All parts and results of +expressions are also truncated. + +Unlike L<integer>, this pragma creates integer constants that are only +limited in their size by the available memory and CPU time. + +=head2 use integer vs. use bigint + +There is one small difference between C<use integer> and C<use bigint>: the +former will not affect assignments to variables and the return value of +some functions. C<bigint> truncates these results to integer too: + + # 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 makes seldom a difference as B<parts and results> of +expressions will be 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 + +bigint recognizes some options that can be passed while loading it via use. +The options can (currently) be either a single letter form, or the long form. +The following options exist: + +=over 2 + +=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() function 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 <B>ignored</B> since all operations happen in integer space. +A positive value rounds to this digit left from the dot. 0 or 1 mean round to +integer and are ignore like negative values. + +See Math::BigInt's bfround() function for details. + + perl -Mbignum=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 bigint or +Math::BigInt. + +=item hex + +Override the built-in hex() method with a version that can handle big +integers. This overrides it by exporting it to the current package. Under +Perl v5.10.0 and higher, this is not so necessary, as hex() is lexically +overridden in the current scope whenever the bigint pragma is active. + +=item oct + +Override the built-in oct() method with a version that can handle big +integers. This overrides it by exporting it to the current package. Under +Perl v5.10.0 and higher, this is not so necessary, as oct() is lexically +overridden in the current scope whenever the bigint pragma is active. + +=item l, lib, try or only + +Load a different math lib, see L<Math Library>. + + perl -Mbigint=lib,GMP -e 'print 2 ** 512' + perl -Mbigint=try,GMP -e 'print 2 ** 512' + perl -Mbigint=only,GMP -e 'print 2 ** 512' + +Currently there is no way to specify more than one library on the command +line. This means the following does not work: + + perl -Mbignum=l,GMP,Pari -e 'print 2 ** 512' + +This will be hopefully fixed soon ;) + +=item v or version + +This prints out the name and version of all modules used and then exits. + + perl -Mbigint=v + +=back + +=head2 Math Library + +Math with the numbers is done (by default) by a module called +Math::BigInt::Calc. This is equivalent to saying: + + use bigint lib => 'Calc'; + +You can change this by using: + + use bignum lib => 'GMP'; + +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 bigint lib => 'Foo,Math::BigInt::Bar'; + +Using C<lib> warns if none of the specified libraries can be found and +L<Math::BigInt> did fall back to one of the default libraries. +To suppress this warning, use C<try> instead: + + use bignum try => 'GMP'; + +If you want the code to die instead of falling back, use C<only> instead: + + use bignum only => 'GMP'; + +Please see respective module documentation for further details. + +=head2 Internal Format + +The numbers are stored as objects, and their internals might change at anytime, +especially between math operations. The objects also might belong to different +classes, like Math::BigInt, or Math::BigInt::Lite. Mixing them together, even +with normal scalars is not extraordinary, but normal and expected. + +You should not depend on the internal format, all accesses must go through +accessor methods. E.g. looking at $x->{sign} is not a good idea since there +is no guaranty that the object in question has such a hash key, nor is a hash +underneath at all. + +=head2 Sign + +The sign is either '+', '-', 'NaN', '+inf' or '-inf'. +You can access it with the sign() method. + +A sign of 'NaN' is used to represent the result when input arguments are not +numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively +minus infinity. You will get '+inf' when dividing a positive number by 0, and +'-inf' when dividing any negative number by 0. + +=head2 Method calls + +Since all numbers are now objects, you can use all functions that are part of +the BigInt API. You can only use the bxxx() notation, and not the fxxx() +notation, though. + +But a warning is in order. When using the following to make a copy of a number, +only a shallow copy will be made. + + $x = 9; $y = $x; + $x = $y = 7; + +Using the copy or the original with overloaded math is okay, e.g. the +following work: + + $x = 9; $y = $x; + print $x + 1, " ", $y,"\n"; # prints 10 9 + +but calling any method that modifies the number directly will result in +B<both> the original and the copy being destroyed: + + $x = 9; $y = $x; + print $x->badd(1), " ", $y,"\n"; # prints 10 10 + + $x = 9; $y = $x; + print $x->binc(1), " ", $y,"\n"; # prints 10 10 + + $x = 9; $y = $x; + print $x->bmul(2), " ", $y,"\n"; # prints 18 18 + +Using methods that do not modify, but test that the contents works: + + $x = 9; $y = $x; + $z = 9 if $x->is_zero(); # works fine + +See the documentation about the copy constructor and C<=> in overload, as +well as the documentation in BigInt for further details. + +=head2 Methods + +=over 2 + +=item inf() + +A shortcut to return Math::BigInt->binf(). Useful because Perl does not always +handle bareword C<inf> properly. + +=item NaN() + +A shortcut to return Math::BigInt->bnan(). Useful because Perl does not always +handle bareword C<NaN> properly. + +=item e + + # perl -Mbigint=e -wle 'print e' + +Returns Euler's number C<e>, aka exp(1). Note that under bigint, this is +truncated to an integer, and hence simple '2'. + +=item PI + + # perl -Mbigint=PI -wle 'print PI' + +Returns PI. Note that under bigint, this is truncated to an integer, and hence +simple '3'. + +=item bexp() + + bexp($power,$accuracy); + +Returns Euler's number C<e> raised to the appropriate power, to +the wanted accuracy. + +Note that under bigint, the result is truncated to an integer. + +Example: + + # perl -Mbigint=bexp -wle 'print bexp(1,80)' + +=item bpi() + + bpi($accuracy); + +Returns PI to the wanted accuracy. Note that under bigint, this is truncated +to an integer, and hence simple '3'. + +Example: + + # perl -Mbigint=bpi -wle 'print bpi(80)' + +=item upgrade() + +Return the class that numbers are upgraded to, is in fact returning +C<$Math::BigInt::upgrade>. + +=item in_effect() + + use bigint; + + print "in effect\n" if bigint::in_effect; # true + { + no bigint; + print "in effect\n" if bigint::in_effect; # false + } + +Returns true or false if C<bigint> is in effect in the current scope. + +This method only works on Perl v5.9.4 or later. + +=back + +=head1 CAVEATS + +=over 2 + +=item Operator vs literal overloading + +C<bigint> works by overloading handling of integer and floating point +literals, converting them to L<Math::BigInt> objects. + +This means that arithmetic involving only string values or string +literals will be performed using Perl's built-in operators. + +For example: + + use bignum; + my $x = "900000000000000009"; + my $y = "900000000000000007"; + print $x - $y; + +will output C<0> on default 32-bit builds, since C<bigint> never sees +the string literals. To ensure the expression is all treated as +C<Math::BigInt> objects, use a literal number in the expression: + + print +(0+$x) - $y; + +=item ranges + +Perl does not allow overloading of ranges, so you can neither safely use +ranges with bigint endpoints, nor is the iterator variable a bigint. + + use 5.010; + for my $i (12..13) { + for my $j (20..21) { + say $i ** $j; # produces a floating-point number, + # not a big integer + } + } + +=item in_effect() + +This method only works on Perl v5.9.4 or later. + +=item hex()/oct() + +C<bigint> overrides these routines with versions that can also handle +big integer values. Under Perl prior to version v5.9.4, however, this +will not happen unless you specifically ask for it with the two +import tags "hex" and "oct" - and then it will be global and cannot be +disabled inside a scope with "no bigint": + + use bigint qw/hex oct/; + + print hex("0x1234567890123456"); + { + no bigint; + print hex("0x1234567890123456"); + } + +The second call to hex() will warn about a non-portable constant. + +Compare this to: + + use bigint; + + # will warn only under Perl older than v5.9.4 + print hex("0x1234567890123456"); + +=back + +=head1 MODULES USED + +C<bigint> is just a thin wrapper around various modules of the Math::BigInt +family. Think of it as the head of the family, who runs the shop, and orders +the others to do the work. + +The following modules are currently used by bigint: + + Math::BigInt::Lite (for speed, and only if it is loadable) + Math::BigInt + +=head1 EXAMPLES + +Some cool command line examples to impress the Python crowd ;) You might want +to compare them to the results under -Mbignum or -Mbigrat: + + perl -Mbigint -le 'print sqrt(33)' + perl -Mbigint -le 'print 2*255' + perl -Mbigint -le 'print 4.5+2*255' + perl -Mbigint -le 'print 3/7 + 5/7 + 8/3' + perl -Mbigint -le 'print 123->is_odd()' + perl -Mbigint -le 'print log(2)' + perl -Mbigint -le 'print 2 ** 0.5' + perl -Mbigint=a,65 -le 'print 2 ** 0.2' + perl -Mbignum=a,65,l,GMP -le 'print 7 ** 7777' + +=head1 LICENSE + +This program is free software; you may redistribute it and/or modify it under +the same terms as Perl itself. + +=head1 SEE ALSO + +Especially L<bigrat> as in C<perl -Mbigrat -le 'print 1/3+1/4'> and +L<bignum> as in C<perl -Mbignum -le 'print sqrt(2)'>. + +L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well +as L<Math::BigInt::Pari> and L<Math::BigInt::GMP>. + +=head1 AUTHORS + +(C) by Tels L<http://bloodgate.com/> in early 2002 - 2007. + +=cut diff --git a/cpan/bignum/lib/bignum.pm b/cpan/bignum/lib/bignum.pm new file mode 100644 index 0000000000..61f2bca545 --- /dev/null +++ b/cpan/bignum/lib/bignum.pm @@ -0,0 +1,674 @@ +package bignum; +use 5.006; + +$VERSION = '0.40'; +use Exporter; +@ISA = qw( bigint ); +@EXPORT_OK = qw( PI e bexp bpi hex oct ); +@EXPORT = qw( inf NaN ); + +use strict; +use overload; +use bigint (); + +############################################################################## + +BEGIN { + *inf = \&bigint::inf; + *NaN = \&bigint::NaN; + *hex = \&bigint::hex; + *oct = \&bigint::oct; +} + +# These are all alike, and thus faked by AUTOLOAD + +my @faked = qw/round_mode accuracy precision div_scale/; +use vars qw/$VERSION $AUTOLOAD $_lite/; # _lite for testsuite + +sub AUTOLOAD { + my $name = $AUTOLOAD; + + $name =~ s/.*:://; # split package + no strict 'refs'; + foreach my $n (@faked) { + if ($n eq $name) { + *{"bignum::$name"} = + sub { + my $self = shift; + no strict 'refs'; + if (defined $_[0]) { + Math::BigInt->$name($_[0]); + return Math::BigFloat->$name($_[0]); + } + return Math::BigInt->$name(); + }; + return &$name; + } + } + + # delayed load of Carp and avoid recursion + require Carp; + Carp::croak ("Can't call bignum\-\>$name, not a valid method"); +} + +sub unimport { + $^H{bignum} = undef; # no longer in effect + overload::remove_constant('binary', '', 'float', '', 'integer'); +} + +sub in_effect { + my $level = shift || 0; + my $hinthash = (caller($level))[10]; + $hinthash->{bignum}; +} + +############################################################################# + +sub import { + my $self = shift; + + $^H{bignum} = 1; # we are in effect + + # for newer Perls override hex() and oct() with a lexical version: + if ($] > 5.009004) { + bigint::_override(); + } + + # some defaults + my $lib = ''; + my $lib_kind = 'try'; + my $upgrade = 'Math::BigFloat'; + my $downgrade = 'Math::BigInt'; + + my @import = (':constant'); # drive it w/ constant + my @a = @_; + my $l = scalar @_; + my $j = 0; + my ($ver, $trace); # version? trace? + my ($a, $p); # accuracy, precision + for (my $i = 0; $i < $l; $i++, $j++) { + if ($_[$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-existent..." + 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-existent..." + splice @a, $j, $s; + $j -= $s; + $i++; + } elsif ($_[$i] =~ /^(l|lib|try|only)$/) { + # this causes a different low lib to take care... + $lib_kind = $1; + $lib_kind = 'lib' if $lib_kind eq 'l'; + $lib = $_[$i + 1] || ''; + my $s = 2; + $s = 1 if @a - $j < 2; # avoid "can not modify non-existent..." + splice @a, $j, $s; + $j -= $s; + $i++; + } + elsif ($_[$i] =~ /^(a|accuracy)$/) { + $a = $_[$i + 1]; + my $s = 2; + $s = 1 if @a - $j < 2; # avoid "can not modify non-existent..." + splice @a, $j, $s; + $j -= $s; + $i++; + } + elsif ($_[$i] =~ /^(p|precision)$/) { + $p = $_[$i + 1]; + my $s = 2; + $s = 1 if @a - $j < 2; # avoid "can not modify non-existent..." + splice @a, $j, $s; + $j -= $s; + $i++; + } + elsif ($_[$i] =~ /^(v|version)$/) { + $ver = 1; + splice @a, $j, 1; + $j--; + } + elsif ($_[$i] =~ /^(t|trace)$/) { + $trace = 1; + splice @a, $j, 1; + $j--; + } + elsif ($_[$i] !~ /^(PI|e|bexp|bpi|hex|oct)\z/) { + die ("unknown option $_[$i]"); + } + } + my $class; + $_lite = 0; # using M::BI::L ? + if ($trace) { + require Math::BigInt::Trace; + $class = 'Math::BigInt::Trace'; + $upgrade = 'Math::BigFloat::Trace'; + } + else { + # see if we can find Math::BigInt::Lite + if (!defined $a && !defined $p) { # rounding won't work to well + if (eval { require Math::BigInt::Lite; 1 }) { + @import = (); # :constant in Lite, not MBI + Math::BigInt::Lite->import(':constant'); + $_lite = 1; # signal okay + } + } + require Math::BigInt if $_lite == 0; # not already loaded? + $class = 'Math::BigInt'; # regardless of MBIL or not + } + push @import, $lib_kind => $lib if $lib ne ''; + # Math::BigInt::Trace or plain Math::BigInt + $class->import(@import, upgrade => $upgrade); + + if ($trace) { + require Math::BigFloat::Trace; + $class = 'Math::BigFloat::Trace'; + $downgrade = 'Math::BigInt::Trace'; + } + else { + require Math::BigFloat; + $class = 'Math::BigFloat'; + } + $class->import(':constant', 'downgrade', $downgrade); + + bignum->accuracy($a) if defined $a; + bignum->precision($p) if defined $p; + if ($ver) { + print "bignum\t\t\t v$VERSION\n"; + print "Math::BigInt::Lite\t v$Math::BigInt::Lite::VERSION\n" if $_lite; + print "Math::BigInt\t\t v$Math::BigInt::VERSION"; + my $config = Math::BigInt->config(); + print " lib => $config->{lib} v$config->{lib_version}\n"; + print "Math::BigFloat\t\t v$Math::BigFloat::VERSION\n"; + exit; + } + + # Take care of octal/hexadecimal constants + overload::constant binary => + sub { + bigint::_binary_constant(shift); + }; + + # if another big* was already loaded: + my ($package) = caller(); + + no strict 'refs'; + if (!defined *{"${package}::inf"}) { + $self->export_to_level(1, $self, @a); # export inf and NaN + } +} + +sub PI () { Math::BigFloat->new('3.141592653589793238462643383279502884197'); } +sub e () { Math::BigFloat->new('2.718281828459045235360287471352662497757'); } +sub bpi ($) { Math::BigFloat::bpi(@_); } +sub bexp ($$) { + my $x = Math::BigFloat->new($_[0]); + $x->bexp($_[1]); +} + +1; + +__END__ + +=head1 NAME + +bignum - Transparent BigNumber support for Perl + +=head1 SYNOPSIS + + use bignum; + + $x = 2 + 4.5,"\n"; # BigFloat 6.5 + print 2 ** 512 * 0.1,"\n"; # really is what you think it is + print inf * inf,"\n"; # prints inf + print NaN * 3,"\n"; # prints NaN + + { + no bignum; + print 2 ** 256,"\n"; # a normal Perl scalar now + } + + # for older Perls, import into current package: + use bignum qw/hex oct/; + print hex("0x1234567890123490"),"\n"; + print oct("01234567890123490"),"\n"; + +=head1 DESCRIPTION + +All operators (including basic math operations) are overloaded. Integer and +floating-point constants are created as proper BigInts or BigFloats, +respectively. + +If you do + + use bignum; + +at the top of your script, Math::BigFloat and Math::BigInt will be loaded +and any constant number will be converted to an object (Math::BigFloat for +floats like 3.1415 and Math::BigInt for integers like 1234). + +So, the following line: + + $x = 1234; + +creates actually 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 -Mbignum -le 'print ref(1234)' + +Don't worry if it says Math::BigInt::Lite, bignum and friends will use Lite +if it is installed since it is faster for some operations. It will be +automatically upgraded to BigInt whenever necessary: + + perl -Mbignum -le 'print ref(2**255)' + +This also means it is a bad idea to check for some specific package, since +the actual contents of $x might be something unexpected. Due to the +transparent way of bignum C<ref()> should not be necessary, anyway. + +Since Math::BigInt and BigFloat also overload the normal math operations, +the following line will still work: + + perl -Mbignum -le 'print ref(1234+1234)' + +Since numbers are actually objects, you can call all the usual methods from +BigInt/BigFloat on them. This even works to some extent on expressions: + + perl -Mbignum -le '$x = 1234; print $x->bdec()' + perl -Mbignum -le 'print 1234->copy()->binc();' + perl -Mbignum -le 'print 1234->copy()->binc->badd(6);' + perl -Mbignum -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 -Mbignum -le 'print 1234->copy()->binc->badd(6);' + 1241 + +Under bignum (or bigint or bigrat), Perl will "upgrade" the numbers +appropriately. This means that: + + perl -Mbignum -le 'print 1234+4.5' + 1238.5 + +will work correctly. These mixed cases don't do always work when using +Math::BigInt or Math::BigFloat alone, or at least not in the way normal Perl +scalars work. + +If you do want to work with large integers like under C<use integer;>, try +C<use bigint;>: + + perl -Mbigint -le 'print 1234.5+4.5' + 1238 + +There is also C<use bigrat;> which gives you big rationals: + + perl -Mbigrat -le 'print 1234+4.1' + 12381/10 + +The entire upgrading/downgrading is still experimental and might not work +as you expect or may even have bugs. You might get errors like this: + + Can't use an undefined value as an ARRAY reference at + /usr/local/lib/perl5/5.8.0/Math/BigInt/Calc.pm line 864 + +This means somewhere a routine got a BigFloat/Lite but expected a BigInt (or +vice versa) and the upgrade/downgrad path was missing. This is a bug, please +report it so that we can fix it. + +You might consider using just Math::BigInt or Math::BigFloat, since they +allow you finer control over what get's done in which module/space. For +instance, simple loop counters will be Math::BigInts under C<use bignum;> and +this is slower than keeping them as Perl scalars: + + perl -Mbignum -le 'for ($i = 0; $i < 10; $i++) { print ref($i); }' + +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 -Mbignum -le 'for (1..2) { print ref($_); }' + +=head2 Options + +bignum recognizes some options that can be passed while loading it via use. +The options can (currently) be either a single letter form, or the long form. +The following options exist: + +=over 2 + +=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() function for details. + + perl -Mbignum=a,50 -le 'print sqrt(20)' + +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, while +a positive value rounds to this digit left from the dot. 0 or 1 mean round to +integer. See Math::BigInt's bfround() function for details. + + perl -Mbignum=p,-50 -le 'print sqrt(20)' + +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 bignum or +Math::BigInt/Math::BigFloat. + +=item l or lib + +Load a different math lib, see L<Math Library>. + + perl -Mbignum=l,GMP -e 'print 2 ** 512' + +Currently there is no way to specify more than one library on the command +line. This means the following does not work: + + perl -Mbignum=l,GMP,Pari -e 'print 2 ** 512' + +This will be hopefully fixed soon ;) + +=item hex + +Override the built-in hex() method with a version that can handle big +numbers. This overrides it by exporting it to the current package. Under +Perl v5.10.0 and higher, this is not so necessary, as hex() is lexically +overridden in the current scope whenever the bignum pragma is active. + +=item oct + +Override the built-in oct() method with a version that can handle big +numbers. This overrides it by exporting it to the current package. Under +Perl v5.10.0 and higher, this is not so necessary, as oct() is lexically +overridden in the current scope whenever the bigint pragma is active. + +=item v or version + +This prints out the name and version of all modules used and then exits. + + perl -Mbignum=v + +=back + +=head2 Methods + +Beside import() and AUTOLOAD() there are only a few other methods. + +Since all numbers are now objects, you can use all functions that are part of +the BigInt or BigFloat API. It is wise to use only the bxxx() notation, and not +the fxxx() notation, though. This makes it possible that the underlying object +might morph into a different class than BigFloat. + +=head2 Caveats + +But a warning is in order. When using the following to make a copy of a number, +only a shallow copy will be made. + + $x = 9; $y = $x; + $x = $y = 7; + +If you want to make a real copy, use the following: + + $y = $x->copy(); + +Using the copy or the original with overloaded math is okay, e.g. the +following work: + + $x = 9; $y = $x; + print $x + 1, " ", $y,"\n"; # prints 10 9 + +but calling any method that modifies the number directly will result in +B<both> the original and the copy being destroyed: + + $x = 9; $y = $x; + print $x->badd(1), " ", $y,"\n"; # prints 10 10 + + $x = 9; $y = $x; + print $x->binc(1), " ", $y,"\n"; # prints 10 10 + + $x = 9; $y = $x; + print $x->bmul(2), " ", $y,"\n"; # prints 18 18 + +Using methods that do not modify, but test the contents works: + + $x = 9; $y = $x; + $z = 9 if $x->is_zero(); # works fine + +See the documentation about the copy constructor and C<=> in overload, as +well as the documentation in BigInt for further details. + +=over 2 + +=item inf() + +A shortcut to return Math::BigInt->binf(). Useful because Perl does not always +handle bareword C<inf> properly. + +=item NaN() + +A shortcut to return Math::BigInt->bnan(). Useful because Perl does not always +handle bareword C<NaN> properly. + +=item e + + # perl -Mbignum=e -wle 'print e' + +Returns Euler's number C<e>, aka exp(1). + +=item PI() + + # perl -Mbignum=PI -wle 'print PI' + +Returns PI. + +=item bexp() + + bexp($power,$accuracy); + +Returns Euler's number C<e> raised to the appropriate power, to +the wanted accuracy. + +Example: + + # perl -Mbignum=bexp -wle 'print bexp(1,80)' + +=item bpi() + + bpi($accuracy); + +Returns PI to the wanted accuracy. + +Example: + + # perl -Mbignum=bpi -wle 'print bpi(80)' + +=item upgrade() + +Return the class that numbers are upgraded to, is in fact returning +C<$Math::BigInt::upgrade>. + +=item in_effect() + + use bignum; + + print "in effect\n" if bignum::in_effect; # true + { + no bignum; + print "in effect\n" if bignum::in_effect; # false + } + +Returns true or false if C<bignum> is in effect in the current scope. + +This method only works on Perl v5.9.4 or later. + +=back + +=head2 Math Library + +Math with the numbers is done (by default) by a module called +Math::BigInt::Calc. This is equivalent to saying: + + use bignum lib => 'Calc'; + +You can change this by using: + + use bignum lib => 'GMP'; + +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 bignum lib => 'Foo,Math::BigInt::Bar'; + +Please see respective module documentation for further details. + +Using C<lib> warns if none of the specified libraries can be found and +L<Math::BigInt> did fall back to one of the default libraries. +To suppress this warning, use C<try> instead: + + use bignum try => 'GMP'; + +If you want the code to die instead of falling back, use C<only> instead: + + use bignum only => 'GMP'; + +=head2 INTERNAL FORMAT + +The numbers are stored as objects, and their internals might change at anytime, +especially between math operations. The objects also might belong to different +classes, like Math::BigInt, or Math::BigFloat. Mixing them together, even +with normal scalars is not extraordinary, but normal and expected. + +You should not depend on the internal format, all accesses must go through +accessor methods. E.g. looking at $x->{sign} is not a bright idea since there +is no guaranty that the object in question has such a hashkey, nor is a hash +underneath at all. + +=head2 SIGN + +The sign is either '+', '-', 'NaN', '+inf' or '-inf' and stored separately. +You can access it with the sign() method. + +A sign of 'NaN' is used to represent the result when input arguments are not +numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively +minus infinity. You will get '+inf' when dividing a positive number by 0, and +'-inf' when dividing any negative number by 0. + +=head1 CAVEATS + +=over 2 + +=item Operator vs literal overloading + +C<bignum> works by overloading handling of integer and floating point +literals, converting them to L<Math::BigInt> or L<Math::BigFloat> +objects. + +This means that arithmetic involving only string values or string +literals will be performed using Perl's built-in operators. + +For example: + + use bignum; + my $x = "900000000000000009"; + my $y = "900000000000000007"; + print $x - $y; + +will output C<0> on default 32-bit builds, since C<bigrat> never sees +the string literals. To ensure the expression is all treated as +C<Math::BigInt> or C<BigFloat> objects, use a literal number in the +expression: + + print +(0+$x) - $y; + +=item in_effect() + +This method only works on Perl v5.9.4 or later. + +=item hex()/oct() + +C<bigint> overrides these routines with versions that can also handle +big integer values. Under Perl prior to version v5.9.4, however, this +will not happen unless you specifically ask for it with the two +import tags "hex" and "oct" - and then it will be global and cannot be +disabled inside a scope with "no bigint": + + use bigint qw/hex oct/; + + print hex("0x1234567890123456"); + { + no bigint; + print hex("0x1234567890123456"); + } + +The second call to hex() will warn about a non-portable constant. + +Compare this to: + + use bigint; + + # will warn only under older than v5.9.4 + print hex("0x1234567890123456"); + +=back + +=head1 MODULES USED + +C<bignum> is just a thin wrapper around various modules of the Math::BigInt +family. Think of it as the head of the family, who runs the shop, and orders +the others to do the work. + +The following modules are currently used by bignum: + + Math::BigInt::Lite (for speed, and only if it is loadable) + Math::BigInt + Math::BigFloat + +=head1 EXAMPLES + +Some cool command line examples to impress the Python crowd ;) + + perl -Mbignum -le 'print sqrt(33)' + perl -Mbignum -le 'print 2*255' + perl -Mbignum -le 'print 4.5+2*255' + perl -Mbignum -le 'print 3/7 + 5/7 + 8/3' + perl -Mbignum -le 'print 123->is_odd()' + perl -Mbignum -le 'print log(2)' + perl -Mbignum -le 'print exp(1)' + perl -Mbignum -le 'print 2 ** 0.5' + perl -Mbignum=a,65 -le 'print 2 ** 0.2' + perl -Mbignum=a,65,l,GMP -le 'print 7 ** 7777' + +=head1 LICENSE + +This program is free software; you may redistribute it and/or modify it under +the same terms as Perl itself. + +=head1 SEE ALSO + +Especially L<bigrat> as in C<perl -Mbigrat -le 'print 1/3+1/4'>. + +L<Math::BigFloat>, L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well +as L<Math::BigInt::Pari> and L<Math::BigInt::GMP>. + +=head1 AUTHORS + +(C) by Tels L<http://bloodgate.com/> in early 2002 - 2007. + +=cut diff --git a/cpan/bignum/lib/bigrat.pm b/cpan/bignum/lib/bigrat.pm new file mode 100644 index 0000000000..61b6526ab4 --- /dev/null +++ b/cpan/bignum/lib/bigrat.pm @@ -0,0 +1,560 @@ +package bigrat; +use 5.006; + +$VERSION = '0.40'; +require Exporter; +@ISA = qw( bigint ); +@EXPORT_OK = qw( PI e bpi bexp hex oct ); +@EXPORT = qw( inf NaN ); + +use strict; +use overload; +use bigint (); + +############################################################################## + +BEGIN { + *inf = \&bigint::inf; + *NaN = \&bigint::NaN; + *hex = \&bigint::hex; + *oct = \&bigint::oct; +} + +# These are all alike, and thus faked by AUTOLOAD + +my @faked = qw/round_mode accuracy precision div_scale/; +use vars qw/$VERSION $AUTOLOAD $_lite/; # _lite for testsuite + +sub AUTOLOAD { + my $name = $AUTOLOAD; + + $name =~ s/.*:://; # split package + no strict 'refs'; + foreach my $n (@faked) { + if ($n eq $name) { + *{"bigrat::$name"} = + sub { + my $self = shift; + no strict 'refs'; + if (defined $_[0]) { + Math::BigInt->$name($_[0]); + Math::BigFloat->$name($_[0]); + return Math::BigRat->$name($_[0]); + } + return Math::BigInt->$name(); + }; + return &$name; + } + } + + # delayed load of Carp and avoid recursion + require Carp; + Carp::croak ("Can't call bigrat\-\>$name, not a valid method"); +} + +sub unimport { + $^H{bigrat} = undef; # no longer in effect + overload::remove_constant('binary', '', 'float', '', 'integer'); +} + +sub in_effect { + my $level = shift || 0; + my $hinthash = (caller($level))[10]; + $hinthash->{bigrat}; +} + +############################################################################# + +sub import { + my $self = shift; + + # see also bignum->import() for additional comments + + $^H{bigrat} = 1; # we are in effect + + # for newer Perls always override hex() and oct() with a lexical version: + if ($] > 5.009004) { + bigint::_override(); + } + # some defaults + my $lib = ''; + my $lib_kind = 'try'; + my $upgrade = 'Math::BigFloat'; + + my @import = (':constant'); # drive it w/ constant + my @a = @_; + my $l = scalar @_; + my $j = 0; + my ($a, $p); + my ($ver, $trace); # version? trace? + for (my $i = 0; $i < $l ; $i++, $j++) { + if ($_[$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-existent..." + splice @a, $j, $s; + $j -= $s; + } + elsif ($_[$i] =~ /^(l|lib|try|only)$/) { + # this causes a different low lib to take care... + $lib_kind = $1; + $lib_kind = 'lib' if $lib_kind eq 'l'; + $lib = $_[$i + 1] || ''; + my $s = 2; + $s = 1 if @a - $j < 2; # avoid "can not modify non-existent..." + splice @a, $j, $s; + $j -= $s; + $i++; + } + elsif ($_[$i] =~ /^(a|accuracy)$/) { + $a = $_[$i + 1]; + my $s = 2; + $s = 1 if @a - $j < 2; # avoid "can not modify non-existent..." + splice @a, $j, $s; + $j -= $s; + $i++; + } + elsif ($_[$i] =~ /^(p|precision)$/) { + $p = $_[$i + 1]; + my $s = 2; + $s = 1 if @a - $j < 2; # avoid "can not modify non-existent..." + splice @a, $j, $s; + $j -= $s; + $i++; + } + elsif ($_[$i] =~ /^(v|version)$/) { + $ver = 1; + splice @a, $j, 1; + $j--; + } + elsif ($_[$i] =~ /^(t|trace)$/) { + $trace = 1; + splice @a, $j, 1; + $j--; + } + elsif ($_[$i] !~ /^(PI|e|bpi|bexp|hex|oct)\z/) { + die ("unknown option $_[$i]"); + } + } + my $class; + $_lite = 0; # using M::BI::L ? + if ($trace) { + require Math::BigInt::Trace; + $class = 'Math::BigInt::Trace'; + $upgrade = 'Math::BigFloat::Trace'; + } + else { + # see if we can find Math::BigInt::Lite + if (!defined $a && !defined $p) { # rounding won't work to well + if (eval { require Math::BigInt::Lite; 1 }) { + @import = (); # :constant in Lite, not MBI + Math::BigInt::Lite->import(':constant'); + $_lite = 1; # signal okay + } + } + require Math::BigInt if $_lite == 0; # not already loaded? + $class = 'Math::BigInt'; # regardless of MBIL or not + } + push @import, $lib_kind => $lib if $lib ne ''; + # Math::BigInt::Trace or plain Math::BigInt + $class->import(@import, upgrade => $upgrade); + + require Math::BigFloat; + Math::BigFloat->import(upgrade => 'Math::BigRat', ':constant'); + require Math::BigRat; + Math::BigRat->import(@import); + + bigrat->accuracy($a) if defined $a; + bigrat->precision($p) if defined $p; + if ($ver) { + print "bigrat\t\t\t v$VERSION\n"; + print "Math::BigInt::Lite\t v$Math::BigInt::Lite::VERSION\n" if $_lite; + print "Math::BigInt\t\t v$Math::BigInt::VERSION"; + my $config = Math::BigInt->config(); + print " lib => $config->{lib} v$config->{lib_version}\n"; + print "Math::BigFloat\t\t v$Math::BigFloat::VERSION\n"; + print "Math::BigRat\t\t v$Math::BigRat::VERSION\n"; + exit; + } + + # Take care of octal/hexadecimal constants + overload::constant binary => + sub { + bigint::_binary_constant(shift); + }; + + # if another big* was already loaded: + my ($package) = caller(); + + no strict 'refs'; + if (!defined *{"${package}::inf"}) { + $self->export_to_level(1, $self, @a); # export inf and NaN + } +} + +sub PI () { Math::BigFloat->new('3.141592653589793238462643383279502884197'); } +sub e () { Math::BigFloat->new('2.718281828459045235360287471352662497757'); } + +sub bpi ($) { + local $Math::BigFloat::upgrade; + Math::BigFloat::bpi(@_); +} + +sub bexp ($$) { + local $Math::BigFloat::upgrade; + my $x = Math::BigFloat->new($_[0]); + $x->bexp($_[1]); +} + +1; + +__END__ + +=head1 NAME + +bigrat - Transparent BigNumber/BigRational support for Perl + +=head1 SYNOPSIS + + use bigrat; + + print 2 + 4.5,"\n"; # BigFloat 6.5 + print 1/3 + 1/4,"\n"; # produces 7/12 + + { + no bigrat; + print 1/3,"\n"; # 0.33333... + } + + # Import into current package: + use bigrat qw/hex oct/; + print hex("0x1234567890123490"),"\n"; + print oct("01234567890123490"),"\n"; + +=head1 DESCRIPTION + +All operators (including basic math operations) are overloaded. Integer and +floating-point constants are created as proper BigInts or BigFloats, +respectively. + +Other than L<bignum>, this module upgrades to Math::BigRat, meaning that +instead of 2.5 you will get 2+1/2 as output. + +=head2 Modules Used + +C<bigrat> is just a thin wrapper around various modules of the Math::BigInt +family. Think of it as the head of the family, who runs the shop, and orders +the others to do the work. + +The following modules are currently used by bignum: + + Math::BigInt::Lite (for speed, and only if it is loadable) + Math::BigInt + Math::BigFloat + Math::BigRat + +=head2 Math Library + +Math with the numbers is done (by default) by a module called +Math::BigInt::Calc. This is equivalent to saying: + + use bigrat lib => 'Calc'; + +You can change this by using: + + use bignum lib => 'GMP'; + +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 bigrat lib => 'Foo,Math::BigInt::Bar'; + +Using C<lib> warns if none of the specified libraries can be found and +L<Math::BigInt> did fall back to one of the default libraries. +To suppress this warning, use C<try> instead: + + use bignum try => 'GMP'; + +If you want the code to die instead of falling back, use C<only> instead: + + use bignum only => 'GMP'; + +Please see respective module documentation for further details. + +=head2 Sign + +The sign is either '+', '-', 'NaN', '+inf' or '-inf'. + +A sign of 'NaN' is used to represent the result when input arguments are not +numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively +minus infinity. You will get '+inf' when dividing a positive number by 0, and +'-inf' when dividing any negative number by 0. + +=head2 Methods + +Since all numbers are not objects, you can use all functions that are part of +the BigInt or BigFloat API. It is wise to use only the bxxx() notation, and not +the fxxx() notation, though. This makes you independent on the fact that the +underlying object might morph into a different class than BigFloat. + +=over 2 + +=item inf() + +A shortcut to return Math::BigInt->binf(). Useful because Perl does not always +handle bareword C<inf> properly. + +=item NaN() + +A shortcut to return Math::BigInt->bnan(). Useful because Perl does not always +handle bareword C<NaN> properly. + +=item e + + # perl -Mbigrat=e -wle 'print e' + +Returns Euler's number C<e>, aka exp(1). + +=item PI + + # perl -Mbigrat=PI -wle 'print PI' + +Returns PI. + +=item bexp() + + bexp($power,$accuracy); + +Returns Euler's number C<e> raised to the appropriate power, to +the wanted accuracy. + +Example: + + # perl -Mbigrat=bexp -wle 'print bexp(1,80)' + +=item bpi() + + bpi($accuracy); + +Returns PI to the wanted accuracy. + +Example: + + # perl -Mbigrat=bpi -wle 'print bpi(80)' + +=item upgrade() + +Return the class that numbers are upgraded to, is in fact returning +C<$Math::BigInt::upgrade>. + +=item in_effect() + + use bigrat; + + print "in effect\n" if bigrat::in_effect; # true + { + no bigrat; + print "in effect\n" if bigrat::in_effect; # false + } + +Returns true or false if C<bigrat> is in effect in the current scope. + +This method only works on Perl v5.9.4 or later. + +=back + +=head2 MATH LIBRARY + +Math with the numbers is done (by default) by a module called + +=head2 Caveat + +But a warning is in order. When using the following to make a copy of a number, +only a shallow copy will be made. + + $x = 9; $y = $x; + $x = $y = 7; + +If you want to make a real copy, use the following: + + $y = $x->copy(); + +Using the copy or the original with overloaded math is okay, e.g. the +following work: + + $x = 9; $y = $x; + print $x + 1, " ", $y,"\n"; # prints 10 9 + +but calling any method that modifies the number directly will result in +B<both> the original and the copy being destroyed: + + $x = 9; $y = $x; + print $x->badd(1), " ", $y,"\n"; # prints 10 10 + + $x = 9; $y = $x; + print $x->binc(1), " ", $y,"\n"; # prints 10 10 + + $x = 9; $y = $x; + print $x->bmul(2), " ", $y,"\n"; # prints 18 18 + +Using methods that do not modify, but testthe contents works: + + $x = 9; $y = $x; + $z = 9 if $x->is_zero(); # works fine + +See the documentation about the copy constructor and C<=> in overload, as +well as the documentation in BigInt for further details. + +=head2 Options + +bignum recognizes some options that can be passed while loading it via use. +The options can (currently) be either a single letter form, or the long form. +The following options exist: + +=over 2 + +=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() function for details. + + perl -Mbigrat=a,50 -le 'print sqrt(20)' + +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, while +a positive value rounds to this digit left from the dot. 0 or 1 mean round to +integer. See Math::BigInt's bfround() function for details. + + perl -Mbigrat=p,-50 -le 'print sqrt(20)' + +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 bignum or +Math::BigInt/Math::BigFloat. + +=item l or lib + +Load a different math lib, see L<MATH LIBRARY>. + + perl -Mbigrat=l,GMP -e 'print 2 ** 512' + +Currently there is no way to specify more than one library on the command +line. This means the following does not work: + + perl -Mbignum=l,GMP,Pari -e 'print 2 ** 512' + +This will be hopefully fixed soon ;) + +=item hex + +Override the built-in hex() method with a version that can handle big +numbers. This overrides it by exporting it to the current package. Under +Perl v5.10.0 and higher, this is not so necessary, as hex() is lexically +overridden in the current scope whenever the bigrat pragma is active. + +=item oct + +Override the built-in oct() method with a version that can handle big +numbers. This overrides it by exporting it to the current package. Under +Perl v5.10.0 and higher, this is not so necessary, as oct() is lexically +overridden in the current scope whenever the bigrat pragma is active. + +=item v or version + +This prints out the name and version of all modules used and then exits. + + perl -Mbigrat=v + +=back + +=head1 CAVEATS + +=over 2 + +=item Operator vs literal overloading + +C<bigrat> works by overloading handling of integer and floating point +literals, converting them to L<Math::BigInt> or L<Math::BigRat> +objects. + +This means that arithmetic involving only string values or string +literals will be performed using Perl's built-in operators. + +For example: + + use bigrat; + my $x = "900000000000000009"; + my $y = "900000000000000007"; + print $x - $y; + +will output C<0> on default 32-bit builds, since C<bigrat> never sees +the string literals. To ensure the expression is all treated as +C<Math::BigInt> or C<Math::BigRat> objects, use a literal number in +the expression: + + print +(0+$x) - $y; + +=item in_effect() + +This method only works on Perl v5.9.4 or later. + +=item hex()/oct() + +C<bigint> overrides these routines with versions that can also handle +big integer values. Under Perl prior to version v5.9.4, however, this +will not happen unless you specifically ask for it with the two +import tags "hex" and "oct" - and then it will be global and cannot be +disabled inside a scope with "no bigint": + + use bigint qw/hex oct/; + + print hex("0x1234567890123456"); + { + no bigint; + print hex("0x1234567890123456"); + } + +The second call to hex() will warn about a non-portable constant. + +Compare this to: + + use bigint; + + # will warn only under Perl older than v5.9.4 + print hex("0x1234567890123456"); + +=back + +=head1 EXAMPLES + + perl -Mbigrat -le 'print sqrt(33)' + perl -Mbigrat -le 'print 2*255' + perl -Mbigrat -le 'print 4.5+2*255' + perl -Mbigrat -le 'print 3/7 + 5/7 + 8/3' + perl -Mbigrat -le 'print 12->is_odd()'; + perl -Mbignum=l,GMP -le 'print 7 ** 7777' + +=head1 LICENSE + +This program is free software; you may redistribute it and/or modify it under +the same terms as Perl itself. + +=head1 SEE ALSO + +Especially L<bignum>. + +L<Math::BigFloat>, L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well +as L<Math::BigInt::Pari> and L<Math::BigInt::GMP>. + +=head1 AUTHORS + +(C) by Tels L<http://bloodgate.com/> in early 2002 - 2007. + +=cut diff --git a/cpan/bignum/t/big_e_pi.t b/cpan/bignum/t/big_e_pi.t new file mode 100644 index 0000000000..24f0843c41 --- /dev/null +++ b/cpan/bignum/t/big_e_pi.t @@ -0,0 +1,15 @@ +#!/usr/bin/perl -w + +############################################################################### +# test for e() and PI() exports + +use strict; +use Test::More tests => 4; + +use bignum qw/e PI bexp bpi/; + +is (e, "2.718281828459045235360287471352662497757", 'e'); +is (PI, "3.141592653589793238462643383279502884197", 'PI'); + +is (bexp(1,10), "2.718281828", 'e'); +is (bpi(10), "3.141592654", 'PI'); diff --git a/cpan/bignum/t/bigexp.t b/cpan/bignum/t/bigexp.t new file mode 100644 index 0000000000..d9da12cd95 --- /dev/null +++ b/cpan/bignum/t/bigexp.t @@ -0,0 +1,18 @@ +#!/usr/bin/perl -w + +############################################################################### +# test for bug #18025: bignum/bigrat can lead to a number that is both 1 and 0 + +use strict; +use Test::More tests => 4; + +use bignum; + +my $lnev = -7 / (10**17); +my $ev=exp($lnev); + +is( sprintf('%0.5f',$ev) , '1.00000', '($ev) is approx. 1' ); +is( sprintf('%0.5f',1-$ev) , '0.00000', '(1-$ev) is approx. 0' ); +is( sprintf('%0.5f',1-"$ev") , '0.00000', '(1-"$ev") is approx. 0' ); + +cmp_ok( $ev, '!=', 0, '$ev should not equal 0'); diff --git a/cpan/bignum/t/bigint.t b/cpan/bignum/t/bigint.t new file mode 100644 index 0000000000..e2df70e1bd --- /dev/null +++ b/cpan/bignum/t/bigint.t @@ -0,0 +1,102 @@ +#!/usr/bin/perl -w + +############################################################################### + +use Test::More tests => 51; + +use bigint qw/hex oct/; + +############################################################################### +# _constant tests + +foreach (qw/ + 123:123 + 123.4:123 + 1.4:1 + 0.1:0 + -0.1:0 + -1.1:-1 + -123.4:-123 + -123:-123 + 123e2:123e2 + 123e-1:12 + 123e-4:0 + 123e-3:0 + 123.345e-1:12 + 123.456e+2:12345 + 1234.567e+3:1234567 + 1234.567e+4:1234567E1 + 1234.567e+6:1234567E3 + /) + { + my ($x,$y) = split /:/; + print "# Try $x\n"; + is (bigint::_float_constant("$x"),"$y"); + } + +foreach (qw/ + 0100:64 + 0200:128 + 0x100:256 + 0b1001:9 + /) + { + my ($x,$y) = split /:/; + print "# Try $x\n"; + is (bigint::_binary_constant("$x"),"$y"); + } + +############################################################################### +# general tests + +my $x = 5; like (ref($x), qr/^Math::BigInt/); # :constant + +# todo: is (2 + 2.5,4.5); # should still work +# todo: $x = 2 + 3.5; is (ref($x),'Math::BigFloat'); + +$x = 2 ** 255; like (ref($x), qr/^Math::BigInt/); + +is (12->bfac(),479001600); +is (9/4,2); + +is (4.5+4.5,8); # truncate +like (ref(4.5+4.5), qr/^Math::BigInt/); + + +############################################################################### +# accuracy and precision + +is ('bigint'->accuracy(), undef); +is ('bigint'->accuracy(12),12); +is ('bigint'->accuracy(),12); + +is ('bigint'->precision(), undef); +is ('bigint'->precision(12),12); +is ('bigint'->precision(),12); + +is ('bigint'->round_mode(),'even'); +is ('bigint'->round_mode('odd'),'odd'); +is ('bigint'->round_mode(),'odd'); + +############################################################################### +# hex() and oct() + +my $c = 'Math::BigInt'; + +is (ref(hex(1)), $c); +is (ref(hex(0x1)), $c); +is (ref(hex("af")), $c); +is (hex("af"), Math::BigInt->new(0xaf)); +is (ref(hex("0x1")), $c); + +is (ref(oct("0x1")), $c); +is (ref(oct("01")), $c); +is (ref(oct("0b01")), $c); +is (ref(oct("1")), $c); +is (ref(oct(" 1")), $c); +is (ref(oct(" 0x1")), $c); + +is (ref(oct(0x1)), $c); +is (ref(oct(01)), $c); +is (ref(oct(0b01)), $c); +is (ref(oct(1)), $c); diff --git a/cpan/bignum/t/bignum.t b/cpan/bignum/t/bignum.t new file mode 100644 index 0000000000..562564d327 --- /dev/null +++ b/cpan/bignum/t/bignum.t @@ -0,0 +1,74 @@ +#!/usr/bin/perl -w + +############################################################################### + +use strict; +use Test::More tests => 35; + +use bignum qw/oct hex/; + +############################################################################### +# general tests + +my $x = 5; like (ref($x), qr/^Math::BigInt/); # :constant + +is (2 + 2.5,4.5); +$x = 2 + 3.5; is (ref($x),'Math::BigFloat'); +is (2 * 2.1,4.2); +$x = 2 + 2.1; is (ref($x),'Math::BigFloat'); + +$x = 2 ** 255; like (ref($x), qr/^Math::BigInt/); + +# see if Math::BigInt constant and upgrading works +is (Math::BigInt::bsqrt('12'),'3.464101615137754587054892683011744733886'); +is (sqrt(12),'3.464101615137754587054892683011744733886'); + +is (2/3,"0.6666666666666666666666666666666666666667"); + +#is (2 ** 0.5, 'NaN'); # should be sqrt(2); + +is (12->bfac(),479001600); + +# see if Math::BigFloat constant works + +# 0123456789 0123456789 <- default 40 +# 0123456789 0123456789 +is (1/3, '0.3333333333333333333333333333333333333333'); + +############################################################################### +# accuracy and precision + +is (bignum->accuracy(), undef); +is (bignum->accuracy(12),12); +is (bignum->accuracy(),12); + +is (bignum->precision(), undef); +is (bignum->precision(12),12); +is (bignum->precision(),12); + +is (bignum->round_mode(),'even'); +is (bignum->round_mode('odd'),'odd'); +is (bignum->round_mode(),'odd'); + +############################################################################### +# hex() and oct() + +my $c = 'Math::BigInt'; + +is (ref(hex(1)), $c); +is (ref(hex(0x1)), $c); +is (ref(hex("af")), $c); +is (hex("af"), Math::BigInt->new(0xaf)); +is (ref(hex("0x1")), $c); + +is (ref(oct("0x1")), $c); +is (ref(oct("01")), $c); +is (ref(oct("0b01")), $c); +is (ref(oct("1")), $c); +is (ref(oct(" 1")), $c); +is (ref(oct(" 0x1")), $c); + +is (ref(oct(0x1)), $c); +is (ref(oct(01)), $c); +is (ref(oct(0b01)), $c); +is (ref(oct(1)), $c); diff --git a/cpan/bignum/t/bigrat.t b/cpan/bignum/t/bigrat.t new file mode 100644 index 0000000000..7f40d62b09 --- /dev/null +++ b/cpan/bignum/t/bigrat.t @@ -0,0 +1,78 @@ +#!/usr/bin/perl -w + +############################################################################### + +use strict; +use Test::More tests => 40; + +use bigrat qw/oct hex/; + +############################################################################### +# general tests + +my $x = 5; like (ref($x), qr/^Math::BigInt/); # :constant + +# todo: is (2 + 2.5,4.5); # should still work +# todo: $x = 2 + 3.5; is (ref($x),'Math::BigFloat'); + +$x = 2 ** 255; like (ref($x), qr/^Math::BigInt/); + +# see if Math::BigRat constant works +is (1/3, '1/3'); +is (1/4+1/3,'7/12'); +is (5/7+3/7,'8/7'); + +is (3/7+1,'10/7'); +is (3/7+1.1,'107/70'); +is (3/7+3/7,'6/7'); + +is (3/7-1,'-4/7'); +is (3/7-1.1,'-47/70'); +is (3/7-2/7,'1/7'); + +# fails ? +# is (1+3/7,'10/7'); + +is (1.1+3/7,'107/70'); +is (3/7*5/7,'15/49'); +is (3/7 / (5/7),'3/5'); +is (3/7 / 1,'3/7'); +is (3/7 / 1.5,'2/7'); + +############################################################################### +# accuracy and precision + +is (bigrat->accuracy(), undef); +is (bigrat->accuracy(12),12); +is (bigrat->accuracy(),12); + +is (bigrat->precision(), undef); +is (bigrat->precision(12),12); +is (bigrat->precision(),12); + +is (bigrat->round_mode(),'even'); +is (bigrat->round_mode('odd'),'odd'); +is (bigrat->round_mode(),'odd'); + +############################################################################### +# hex() and oct() + +my $c = 'Math::BigInt'; + +is (ref(hex(1)), $c); +is (ref(hex(0x1)), $c); +is (ref(hex("af")), $c); +is (hex("af"), Math::BigInt->new(0xaf)); +is (ref(hex("0x1")), $c); + +is (ref(oct("0x1")), $c); +is (ref(oct("01")), $c); +is (ref(oct("0b01")), $c); +is (ref(oct("1")), $c); +is (ref(oct(" 1")), $c); +is (ref(oct(" 0x1")), $c); + +is (ref(oct(0x1)), $c); +is (ref(oct(01)), $c); +is (ref(oct(0b01)), $c); +is (ref(oct(1)), $c); diff --git a/cpan/bignum/t/bii_e_pi.t b/cpan/bignum/t/bii_e_pi.t new file mode 100644 index 0000000000..b47b4a8d61 --- /dev/null +++ b/cpan/bignum/t/bii_e_pi.t @@ -0,0 +1,16 @@ +#!/usr/bin/perl -w + +############################################################################### +# test for e() and PI() exports + +use strict; +use Test::More tests => 5; + +use bigint qw/e PI bpi bexp/; + +is (e, "2", 'e'); +is (PI, "3", 'PI'); + +is (bexp(1,10), "2", 'e'); +is (bexp(3,10), "20", 'e'); +is (bpi(10), "3", 'PI'); diff --git a/cpan/bignum/t/biinfnan.t b/cpan/bignum/t/biinfnan.t new file mode 100644 index 0000000000..bb9f41f614 --- /dev/null +++ b/cpan/bignum/t/biinfnan.t @@ -0,0 +1,11 @@ +#!/usr/bin/perl -w + +############################################################################### + +use strict; +use Test::More tests => 26; + +use bigint; + +require "t/infnan.inc"; + diff --git a/cpan/bignum/t/bir_e_pi.t b/cpan/bignum/t/bir_e_pi.t new file mode 100644 index 0000000000..f8b347be0c --- /dev/null +++ b/cpan/bignum/t/bir_e_pi.t @@ -0,0 +1,17 @@ +#!/usr/bin/perl -w + +############################################################################### +# test for e() and PI() exports + +use strict; +use Test::More tests => 4; + +use bigrat qw/e PI bexp bpi/; + +is (e, "2.718281828459045235360287471352662497757", 'e'); +is (PI, "3.141592653589793238462643383279502884197", 'PI'); + +# these tests should actually produce big rationals, but this is not yet +# implemented: +is (bexp(1,10), "2.718281828", 'e'); +is (bpi(10), "3.141592654", 'PI'); diff --git a/cpan/bignum/t/bn_lite.t b/cpan/bignum/t/bn_lite.t new file mode 100644 index 0000000000..c2a04cd7d4 --- /dev/null +++ b/cpan/bignum/t/bn_lite.t @@ -0,0 +1,21 @@ +#!/usr/bin/perl -w + +############################################################################### + +use strict; +use Test::More; + +if (eval { require Math::BigInt::Lite; 1 }) + { + plan (tests => 1); + # can use Lite, so let bignum try it + require bignum; bignum->import(); + # can't get to work a ref(1+1) here, presumable because :constant phase + # already done + is ($bignum::_lite,1); + } +else + { + plan skip_all => "no Math::BigInt::Lite"; + } + diff --git a/cpan/bignum/t/bninfnan.t b/cpan/bignum/t/bninfnan.t new file mode 100644 index 0000000000..45f83b98f8 --- /dev/null +++ b/cpan/bignum/t/bninfnan.t @@ -0,0 +1,11 @@ +#!/usr/bin/perl -w + +############################################################################### + +use strict; +use Test::More tests => 26; + +use bignum; + +require "t/infnan.inc"; + diff --git a/cpan/bignum/t/br_lite.t b/cpan/bignum/t/br_lite.t new file mode 100644 index 0000000000..4e75356bc2 --- /dev/null +++ b/cpan/bignum/t/br_lite.t @@ -0,0 +1,21 @@ +#!/usr/bin/perl -w + +############################################################################### + +use strict; +use Test::More; + +if (eval { require Math::BigInt::Lite; 1 }) + { + plan (tests => 1); + # can use Lite, so let bignum try it + require bigrat; bigrat->import(); + # can't get to work a ref(1+1) here, presumable because :constant phase + # already done + is ($bigrat::_lite,1); + } +else + { + plan (skip_all => "no Math::BigInt::Lite"); + } + diff --git a/cpan/bignum/t/brinfnan.t b/cpan/bignum/t/brinfnan.t new file mode 100644 index 0000000000..ce7daa189d --- /dev/null +++ b/cpan/bignum/t/brinfnan.t @@ -0,0 +1,11 @@ +#!/usr/bin/perl -w + +############################################################################### + +use strict; +use Test::More tests => 26; + +use bigrat; + +require "t/infnan.inc"; + diff --git a/cpan/bignum/t/in_effect.t b/cpan/bignum/t/in_effect.t new file mode 100644 index 0000000000..5d09fc172f --- /dev/null +++ b/cpan/bignum/t/in_effect.t @@ -0,0 +1,34 @@ +#!/usr/bin/perl -w + +############################################################################### +# Test in_effect() + +use strict; +use Test::More tests => 9; + +use bigint; +use bignum; +use bigrat; + +can_ok ('bigint', qw/in_effect/); +can_ok ('bignum', qw/in_effect/); +can_ok ('bigrat', qw/in_effect/); + +SKIP: { + skip ('Need at least Perl v5.9.4', 3) if $] < "5.009005"; + + is (bigint::in_effect(), 1, 'bigint in effect'); + is (bignum::in_effect(), 1, 'bignum in effect'); + is (bigrat::in_effect(), 1, 'bigrat in effect'); + } + +{ + no bigint; + no bignum; + no bigrat; + + is (bigint::in_effect(), undef, 'bigint not in effect'); + is (bignum::in_effect(), undef, 'bignum not in effect'); + is (bigrat::in_effect(), undef, 'bigrat not in effect'); +} + diff --git a/cpan/bignum/t/infnan.inc b/cpan/bignum/t/infnan.inc new file mode 100644 index 0000000000..561adc1a70 --- /dev/null +++ b/cpan/bignum/t/infnan.inc @@ -0,0 +1,35 @@ + +use strict; + +my ($x); + +############################################################################### +# inf tests + +$x = 1+inf; like (ref($x), qr/^Math::BigInt/); is ($x->bstr(),'inf'); +$x = 1*inf; like (ref($x), qr/^Math::BigInt/); is ($x->bstr(),'inf'); + +# these don't work without exporting inf() +$x = inf; like (ref($x), qr/^Math::BigInt/); is ($x->bstr(),'inf'); +$x = inf+inf; like (ref($x), qr/^Math::BigInt/); is ($x->bstr(),'inf'); +$x = inf*inf; like (ref($x), qr/^Math::BigInt/); is ($x->bstr(),'inf'); + +############################################################################### +# NaN tests + +$x = 1+NaN; like (ref($x), qr/^Math::BigInt/); is ($x->bstr(),'NaN'); +$x = 1*NaN; like (ref($x), qr/^Math::BigInt/); is ($x->bstr(),'NaN'); + +# these don't work without exporting NaN() +$x = NaN; like (ref($x), qr/^Math::BigInt/); is ($x->bstr(),'NaN'); +$x = NaN+NaN; like (ref($x), qr/^Math::BigInt/); is ($x->bstr(),'NaN'); +$x = NaN*NaN; like (ref($x), qr/^Math::BigInt/); is ($x->bstr(),'NaN'); + +############################################################################### +# mixed tests + +# these don't work without exporting NaN() or inf() +$x = NaN+inf; like (ref($x), qr/^Math::BigInt/); is ($x->bstr(),'NaN'); +$x = NaN*inf; like (ref($x), qr/^Math::BigInt/); is ($x->bstr(),'NaN'); +$x = inf*NaN; like (ref($x), qr/^Math::BigInt/); is ($x->bstr(),'NaN'); + diff --git a/cpan/bignum/t/option_a.t b/cpan/bignum/t/option_a.t new file mode 100644 index 0000000000..1f135626cc --- /dev/null +++ b/cpan/bignum/t/option_a.t @@ -0,0 +1,23 @@ +#!/usr/bin/perl -w + +############################################################################### + +use strict; +use Test::More tests => 4; + +use bignum a => '12'; + +my @C = qw/Math::BigInt Math::BigFloat/; + +foreach my $c (@C) + { + is ($c->accuracy(),12, "$c accuracy = 12"); + } + +bignum->import( accuracy => '23'); + +foreach my $c (@C) + { + is ($c->accuracy(), 23, "$c accuracy = 23"); + } + diff --git a/cpan/bignum/t/option_l.t b/cpan/bignum/t/option_l.t new file mode 100644 index 0000000000..b5eddec154 --- /dev/null +++ b/cpan/bignum/t/option_l.t @@ -0,0 +1,46 @@ +#!/usr/bin/perl -w + +# test the "l", "lib", "try" and "only" options: + +use strict; +use Test::More tests => 19; + +use bignum; + +my @W; +{ +# catch warnings: +require Carp; +no warnings 'redefine'; +*Carp::carp = sub { push @W, $_[0]; }; +} + +my $rc = eval { bignum->import( "l" => "foo" ) }; +is ($@,''); # shouldn't die +is (scalar @W, 1, 'one warning'); +like ($W[0], qr/fallback to Math::/, 'got fallback'); + +$rc = eval { bignum->import( "lib" => "foo" ) }; +is ($@,''); # ditto +is (scalar @W, 2, 'two warnings'); +like ($W[1], qr/fallback to Math::/, 'got fallback'); + +$rc = eval { bignum->import( "try" => "foo" ) }; +is ($@,''); # shouldn't die +$rc = eval { bignum->import( "try" => "foo" ) }; +is ($@,''); # ditto + +$rc = eval { bignum->import( "foo" => "bar" ) }; +like ($@, qr/^Unknown option foo/i, 'died'); # should die + +$rc = eval { bignum->import( "only" => "bar" ) }; +like ($@, qr/fallback disallowed/i, 'died'); # should die + +# test that options are only lowercase (don't see a reason why allow UPPER) + +foreach (qw/L LIB Lib T Trace TRACE V Version VERSION/) + { + $rc = eval { bignum->import( $_ => "bar" ) }; + like ($@, qr/^Unknown option $_/i, 'died'); # should die + } + diff --git a/cpan/bignum/t/option_p.t b/cpan/bignum/t/option_p.t new file mode 100644 index 0000000000..cdc4f4311b --- /dev/null +++ b/cpan/bignum/t/option_p.t @@ -0,0 +1,21 @@ +#!/usr/bin/perl -w + +use strict; +use Test::More tests => 4; + +my @C = qw/Math::BigInt Math::BigFloat/; + +use bignum p => '12'; + +foreach my $c (@C) + { + is ($c->precision(),12, "$c precision = 12"); + } + +bignum->import( p => '42' ); + +foreach my $c (@C) + { + is ($c->precision(),42, "$c precision = 42"); + } + diff --git a/cpan/bignum/t/overrides.t b/cpan/bignum/t/overrides.t new file mode 100644 index 0000000000..84a2ce1924 --- /dev/null +++ b/cpan/bignum/t/overrides.t @@ -0,0 +1,112 @@ +#!perl -w + +# Test behaviour of hex and oct overrides in detail, and also how the three +# modules interact. + +use Test::More tests => 35; + +# For testing that existing CORE::GLOBAL overrides are not clobbered +BEGIN + { + if ($] > 5.009004) + { + no warnings 'syntax'; + *CORE::GLOBAL::hex = sub(_) { ++$hex_called; CORE::hex(@_?$_[0]:$_) }; + *CORE::GLOBAL::oct = sub(_) { ++$oct_called; CORE::oct(@_?$_[0]:$_) }; + } + else + { + *CORE::GLOBAL::hex = sub(;$) { ++$hex_called; CORE::hex(@_?$_[0]:$_) }; + *CORE::GLOBAL::oct = sub(;$) { ++$oct_called; CORE::oct(@_?$_[0]:$_) }; + } + } + +{ + use bigint; + $_ = "20"; + is hex, "32", 'bigint hex override without arguments infers $_'; + is oct, "16", 'bigint oct override without arguments infers $_'; + @_ = 1..20; + is hex(@_), "32", 'bigint hex override provides scalar context'; + is oct(@_), "16", 'bigint oct override provides scalar context'; + SKIP: + { + skip "no lexical hex/oct", 2 unless $] > do { no bigint; 5.009004}; + is ref hex(1), 'Math::BigInt', + 'bigint hex() works when bignum and bigrat are loaded'; + is ref oct(1), 'Math::BigInt', + 'bigint oct() works when bignum and bigrat are loaded'; + } +} +{ + use bignum; + $_ = "20"; + is hex, "32", 'bignum hex override without arguments infers $_'; + is oct, "16", 'bignum oct override without arguments infers $_'; + @_ = 1..20; + is hex(@_), "32", 'bignum hex override provides scalar context'; + is oct(@_), "16", 'bignum oct override provides scalar context'; + SKIP: + { + skip "no lexical hex/oct", 2 unless $] > 5.009004; + is ref hex(1), 'Math::BigInt', + 'bignum hex() works when bigint and bigrat are loaded'; + is ref oct(1), 'Math::BigInt', + 'bignum oct() works when bigint and bigrat are loaded'; + } +} +{ + use bigrat; + $_ = "20"; + is hex, "32", 'bigrat hex override without arguments infers $_'; + is oct, "16", 'bigrat oct override without arguments infers $_'; + @_ = 1..20; + is hex(@_), "32", 'bigrat hex override provides scalar context'; + is oct(@_), "16", 'bigrat oct override provides scalar context'; + SKIP: + { + skip "no lexical hex/oct", 2 unless $] > 5.009004; + is ref hex(1), 'Math::BigInt', + 'bigrat hex() works when bignum and bigint are loaded'; + is ref oct(1), 'Math::BigInt', + 'bigrat oct() works when bignum and bigint are loaded'; + } +} + +$hex_called = 0; +() = hex 0; +is $hex_called, 1, 'existing hex overrides are called'; +$oct_called = 0; +() = oct 0; +is $oct_called, 1, 'existing oct overrides are called'; + +{ + package _importer; + { + use bigint 'hex', 'oct'; + ::is \&hex, \&bigint::hex, 'exported hex function'; + ::is \&oct, \&bigint::oct, 'exported oct function'; + } + ::ok ref hex(), 'exported hex function returns ref outside pragma scope'; + ::ok ref oct(), 'exported oct function returns ref outside pragma scope'; + ::is oct("20"), "16", 'exported oct function works with "decimal"'; + # (used to return 20 because it thought it was decimal) +} +{ + package _importer2; + use bignum 'hex', 'oct'; + ::is \&hex, \&bignum::hex, 'bignum exports hex'; + ::is \&oct, \&bignum::oct, 'bignum exports oct'; + ::is \&hex, \&bigint::hex, 'bignum exports same hex as bigint'; + ::is \&oct, \&bigint::oct, 'bignum exports same oct as bigint'; +} +{ + package _importer3; + use bigrat 'hex', 'oct'; + ::is \&hex, \&bigrat::hex, 'bigrat exports hex'; + ::is \&oct, \&bigrat::oct, 'bigrat exports oct'; + ::is \&hex, \&bigint::hex, 'bigrat exports same hex as bigint'; + ::is \&oct, \&bigint::oct, 'bigrat exports same oct as bigint'; +} +is ref(hex 0), "", 'hex export is not global'; +is ref(oct 0), "", 'oct export is not global'; diff --git a/cpan/bignum/t/ratopt_a.t b/cpan/bignum/t/ratopt_a.t new file mode 100644 index 0000000000..0d18e87031 --- /dev/null +++ b/cpan/bignum/t/ratopt_a.t @@ -0,0 +1,26 @@ +#!/usr/bin/perl -w + +############################################################################### + +use strict; +use Test::More tests => 7; + +my @C = qw/Math::BigInt Math::BigFloat Math::BigRat/; + +# bigrat (bug until v0.15) +use bigrat a => 2; + +foreach my $c (@C) + { + is ($c->accuracy(), 2, "$c accuracy = 2"); + } + +eval { bigrat->import( accuracy => '42') }; + +is ($@, '', 'no error'); + +foreach my $c (@C) + { + is ($c->accuracy(), 42, "$c accuracy = 42"); + } + diff --git a/cpan/bignum/t/scope_f.t b/cpan/bignum/t/scope_f.t new file mode 100644 index 0000000000..ba11f5b0e2 --- /dev/null +++ b/cpan/bignum/t/scope_f.t @@ -0,0 +1,33 @@ +#!/usr/bin/perl -w + +############################################################################### +# Test "no bignum;" and overloading of hex()/oct() for newer Perls + +use strict; +use Test::More tests => 10; + +# no :hex and :oct means these do not get overloaded for older Perls: +use bignum; + +isnt (ref(1), '', 'is in effect'); +isnt (ref(2.0), '', 'is in effect'); +isnt (ref(0x20), '', 'is in effect'); + +SKIP: { + skip ('Need at least Perl v5.9.4', 2) if $] < 5.009004; + + is (ref(hex(9)), 'Math::BigInt', 'hex is overloaded'); + is (ref(oct(07)), 'Math::BigInt', 'oct is overloaded'); + } + +{ + no bignum; + + is (ref(1), '', 'is not in effect'); + is (ref(2.0), '', 'is not in effect'); + is (ref(0x20), '', 'is not in effect'); + + isnt (ref(hex(9)), 'Math::BigInt', 'hex is not overloaded'); + isnt (ref(oct(07)), 'Math::BigInt', 'oct is not overloaded'); +} + diff --git a/cpan/bignum/t/scope_i.t b/cpan/bignum/t/scope_i.t new file mode 100644 index 0000000000..8a11a6b17e --- /dev/null +++ b/cpan/bignum/t/scope_i.t @@ -0,0 +1,34 @@ +#!/usr/bin/perl -w + +############################################################################### +# Test "no bigint;" and overloading of hex()/oct() for newer Perls + +use strict; +use Test::More tests => 10; + +# no :hex and :oct means these do not get overloaded for older Perls: +use bigint; + +isnt (ref(1), '', 'is in effect'); +isnt (ref(2.0), '', 'is in effect'); +isnt (ref(0x20), '', 'is in effect'); + +SKIP: { + skip ('Need at least Perl v5.9.4', 2) if $] < "5.009004"; # quote due to "use bigint;" + + is (ref(hex(9)), 'Math::BigInt', 'hex is overloaded'); + is (ref(oct(07)), 'Math::BigInt', 'oct is overloaded'); + } + +{ + no bigint; + + is (ref(1), '', 'is not in effect'); + is (ref(2.0), '', 'is not in effect'); + is (ref(0x20), '', 'is not in effect'); + + isnt (ref(hex(9)), 'Math::BigInt', 'hex is not overloaded'); + isnt (ref(oct(07)), 'Math::BigInt', 'oct is not overloaded'); + +} + diff --git a/cpan/bignum/t/scope_r.t b/cpan/bignum/t/scope_r.t new file mode 100644 index 0000000000..5cc2117f01 --- /dev/null +++ b/cpan/bignum/t/scope_r.t @@ -0,0 +1,33 @@ +#!/usr/bin/perl -w + +############################################################################### +# Test "no bigrat;" and overloading of hex()/oct() for newer Perls + +use strict; +use Test::More tests => 10; + +# no :hex and :oct means these do not get overloaded for older Perls: +use bigrat; + +isnt (ref(1), '', 'is in effect'); +isnt (ref(2.0), '', 'is in effect'); +isnt (ref(0x20), '', 'is in effect'); + +SKIP: { + skip ('Need at least Perl v5.9.4', 2) if $] < 5.009004; + + is (ref(hex(9)), 'Math::BigInt', 'hex is overloaded'); + is (ref(oct(07)), 'Math::BigInt', 'oct is overloaded'); + } + +{ + no bigrat; + + is (ref(1), '', 'is not in effect'); + is (ref(2.0), '', 'is not in effect'); + is (ref(0x20), '', 'is not in effect'); + + isnt (ref(hex(9)), 'Math::BigInt', 'hex is not overloaded'); + isnt (ref(oct(07)), 'Math::BigInt', 'oct is not overloaded'); +} + |