This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
v5.8.8: File::Temp.pm (_gettemp): ignore dir -w test on Cygwin
[perl5.git] / lib / bignum.pm
index d9d73bb..9b2ccc9 100644 (file)
@@ -1,17 +1,24 @@
 package bignum;
 use 5.006002;
 
-$VERSION = '0.21_02';
+$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,35 +54,53 @@ 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_kind = 'try';
   my $upgrade = 'Math::BigFloat';
@@ -131,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 ?
@@ -185,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) };
+
+  # if another big* was already loaded:
+  my ($package) = caller();
 
-  $self->export_to_level(1,$self,@a);          # export inf and NaN
+  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;
 
@@ -210,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
@@ -254,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
@@ -288,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
@@ -357,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.
@@ -374,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.
@@ -404,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
@@ -424,11 +496,58 @@ 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
@@ -481,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