This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Math::BigRat 0.22
[perl5.git] / lib / bignum.pm
index 7796d47..9b2ccc9 100644 (file)
@@ -1,17 +1,24 @@
 package bignum;
 use 5.006002;
 
-$VERSION = '0.19';
+$VERSION = '0.22';
 use Exporter;
-@EXPORT_OK     = qw( ); 
+@ISA           = qw( bigint );
+@EXPORT_OK     = qw( PI e bexp bpi ); 
 @EXPORT        = qw( inf NaN ); 
-@ISA           = qw( Exporter );
 
 use strict;
 use overload;
+require bigint;                # no "use" to avoid import being called
 
 ############################################################################## 
 
+BEGIN 
+  {
+  *inf = \&bigint::inf;
+  *NaN = \&bigint::NaN;
+  }
+
 # These are all alike, and thus faked by AUTOLOAD
 
 my @faked = qw/round_mode accuracy precision div_scale/;
@@ -47,37 +54,55 @@ sub AUTOLOAD
   Carp::croak ("Can't call bignum\-\>$name, not a valid method");
   }
 
-sub upgrade
+sub unimport
   {
-  my $self = shift;
-  no strict 'refs';
-#  if (defined $_[0])
-#    {
-#    $Math::BigInt::upgrade = $_[0];
-#    $Math::BigFloat::upgrade = $_[0];
-#    }
-  $Math::BigInt::upgrade;
+  $^H{bignum} = undef;                                 # no longer in effect
+  overload::remove_constant('binary','','float','','integer');
   }
 
-sub _binary_constant
+sub in_effect
   {
-  # 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;
+  my $level = shift || 0;
+  my $hinthash = (caller($level))[10];
+  $hinthash->{bignum};
+  }
 
-  return Math::BigInt->new($string) if $string =~ /^0[bx]/;
+#############################################################################
+# the following two routines are for Perl 5.9.4 or later and are lexical
 
-  # so it must be an octal constant
-  Math::BigInt->from_oct($string);
+sub _hex
+  {
+  return CORE::hex($_[0]) unless in_effect(1);
+  my $i = $_[0];
+  $i = '0x'.$i unless $i =~ /^0x/;
+  Math::BigInt->new($i);
+  }
+
+sub _oct
+  {
+  return CORE::oct($_[0]) unless in_effect(1);
+  my $i = $_[0];
+  return Math::BigInt->from_oct($i) if $i =~ /^0[0-7]/;
+  Math::BigInt->new($i);
   }
 
 sub import 
   {
   my $self = shift;
 
+  $^H{bignum} = 1;                                     # we are in effect
+
+  my ($hex,$oct);
+
+  # for newer Perls override hex() and oct() with a lexical version:
+  if ($] > 5.009003)
+    {
+    $hex = \&_hex;
+    $oct = \&_oct;
+    }
+
   # some defaults
-  my $lib = '';
+  my $lib = ''; my $lib_kind = 'try';
   my $upgrade = 'Math::BigFloat';
   my $downgrade = 'Math::BigInt';
 
@@ -101,9 +126,10 @@ sub import
       my $s = 2; $s = 1 if @a-$j < 2;  # avoid "can not modify non-existant..."
       splice @a, $j, $s; $j -= $s; $i++;
       }
-    elsif ($_[$i] =~ /^(l|lib)$/)
+    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-existant..."
       splice @a, $j, $s; $j -= $s; $i++;
@@ -130,7 +156,20 @@ sub import
       $trace = 1;
       splice @a, $j, 1; $j --;
       }
-    else { die "unknown option $_[$i]"; }
+    elsif ($_[$i] eq 'hex')
+      {
+      splice @a, $j, 1; $j --;
+      $hex = \&bigint::_hex_global;
+      }
+    elsif ($_[$i] eq 'oct')
+      {
+      splice @a, $j, 1; $j --;
+      $oct = \&bigint::_oct_global;
+      }
+    elsif ($_[$i] !~ /^(PI|e|bexp|bpi)\z/)
+      {
+      die ("unknown option $_[$i]");
+      }
     }
   my $class;
   $_lite = 0;                                  # using M::BI::L ?
@@ -155,7 +194,7 @@ sub import
     require Math::BigInt if $_lite == 0;       # not already loaded?
     $class = 'Math::BigInt';                   # regardless of MBIL or not
     }
-  push @import, 'try' => $lib if $lib ne ''; 
+  push @import, $lib_kind => $lib if $lib ne ''; 
   # Math::BigInt::Trace or plain Math::BigInt
   $class->import(@import, upgrade => $upgrade);
 
@@ -184,13 +223,27 @@ sub import
     }
 
   # Take care of octal/hexadecimal constants
-  overload::constant 'binary' => sub { _binary_constant(shift) };
+  overload::constant binary => sub { bigint::_binary_constant(shift) };
 
-  $self->export_to_level(1,$self,@a);          # export inf and NaN
+  # 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
+    }
+  {
+    no warnings 'redefine';
+    *CORE::GLOBAL::oct = $oct if $oct;
+    *CORE::GLOBAL::hex = $hex if $hex;
+  }
   }
 
-sub inf () { Math::BigInt->binf(); }
-sub NaN () { Math::BigInt->bnan(); }
+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;
 
@@ -209,6 +262,16 @@ bignum - Transparent BigNumber support for Perl
   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, note that this will be global:
+  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
@@ -253,16 +316,16 @@ 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->binc();'
-        perl -Mbignum -le 'print 1234->binc->badd(6);'
-        perl -Mbignum -le 'print +(1234)->binc()'
+        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->binc->badd(6);'
+        perl -Mbignum -le 'print 1234->copy()->binc->badd(6);'
         1241
 
 Under bignum (or bigint or bigrat), Perl will "upgrade" the numbers
@@ -287,9 +350,7 @@ There is also C<use bigrat;> which gives you big rationals:
         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:
+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
@@ -356,6 +417,18 @@ line. This means the following does not work:
 
 This will be hopefully fixed soon ;)
 
+=item hex
+
+Override the built-in hex() method with a version that can handle big
+integers. Note that under Perl older than v5.9.4, this will be global
+and cannot be disabled with "no bigint;".
+
+=item oct
+
+Override the built-in oct() method with a version that can handle big
+integers. Note that under Perl older than v5.9.4, this will be global
+and cannot be disabled with "no bigint;".
+
 =item v or version
 
 This prints out the name and version of all modules used and then exits.
@@ -373,7 +446,7 @@ 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 Caveat
+=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.
@@ -403,7 +476,7 @@ B<both> the original and the copy being destroyed:
         $x = 9; $y = $x;
         print $x->bmul(2), " ", $y,"\n";        # prints 18 18
 
-Using methods that do not modify, but testthe contents works:
+Using methods that do not modify, but test the contents works:
 
         $x = 9; $y = $x;
         $z = 9 if $x->is_zero();                # works fine
@@ -423,14 +496,61 @@ handle bareword C<inf> properly.
 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
+=head2 Math Library
 
 Math with the numbers is done (by default) by a module called
 Math::BigInt::Calc. This is equivalent to saying:
@@ -439,7 +559,7 @@ Math::BigInt::Calc. This is equivalent to saying:
 
 You can change this by using:
 
-       use bignum lib => 'BitVect';
+       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:
@@ -448,6 +568,16 @@ Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
 
 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 supress 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,
@@ -470,6 +600,41 @@ 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 CAVAETS
+
+=over 2
+
+=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
@@ -492,6 +657,7 @@ Some cool command line examples to impress the Python crowd ;)
        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'