This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Comply with the 0x80th commandment
[perl5.git] / lib / Math / BigInt.pm
index 220920e..758d7d8 100644 (file)
@@ -18,10 +18,11 @@ package Math::BigInt;
 my $class = "Math::BigInt";
 require 5.005;
 
-$VERSION = '1.70_01';
-use Exporter;
-@ISA =       qw( Exporter );
-@EXPORT_OK = qw( objectify bgcd blcm); 
+$VERSION = '1.77';
+
+@ISA = qw(Exporter);
+@EXPORT_OK = qw(objectify bgcd blcm); 
+
 # _trap_inf and _trap_nan are internal and should never be accessed from the
 # outside
 use vars qw/$round_mode $accuracy $precision $div_scale $rnd_mode 
@@ -53,14 +54,18 @@ use overload
 '^='   =>      sub { $_[0]->bxor($_[1]); },
 '&='   =>      sub { $_[0]->band($_[1]); },
 '|='   =>      sub { $_[0]->bior($_[1]); },
+
 '**='  =>      sub { $_[0]->bpow($_[1]); },
+'<<='  =>      sub { $_[0]->blsft($_[1]); },
+'>>='  =>      sub { $_[0]->brsft($_[1]); },
 
 # not supported by Perl yet
 '..'   =>      \&_pointpoint,
 
+# we might need '==' and '!=' to get things like "NaN == NaN" right
 '<=>'  =>      sub { $_[2] ?
                       ref($_[0])->bcmp($_[1],$_[0]) : 
-                      $_[0]->bcmp($_[1])},
+                      $_[0]->bcmp($_[1])},
 'cmp'  =>      sub {
          $_[2] ? 
                "$_[1]" cmp $_[0]->bstr() :
@@ -70,7 +75,13 @@ use overload
 'cos'  =>      sub { cos($_[0]->numify()) }, 
 'sin'  =>      sub { sin($_[0]->numify()) }, 
 'exp'  =>      sub { exp($_[0]->numify()) }, 
-'atan2'        =>      sub { atan2($_[0]->numify(),$_[1]) }, 
+'atan2'        =>      sub { $_[2] ?
+                       atan2($_[1],$_[0]->numify()) :
+                       atan2($_[0]->numify(),$_[1]) },
+
+# are not yet overloadable
+#'hex' =>      sub { print "hex"; $_[0]; }, 
+#'oct' =>      sub { print "oct"; $_[0]; }, 
 
 'log'  =>      sub { $_[0]->copy()->blog($_[1]); }, 
 'int'  =>      sub { $_[0]->copy(); }, 
@@ -79,10 +90,10 @@ use overload
 'sqrt'  =>     sub { $_[0]->copy()->bsqrt(); },
 '~'    =>      sub { $_[0]->copy()->bnot(); },
 
-# for sub it is a bit tricky to keep b: b-a => -a+b
+# for subtract it's a bit tricky to not modify b: b-a => -a+b
 '-'    =>      sub { my $c = $_[0]->copy; $_[2] ?
-                   $c->bneg()->badd($_[1]) :
-                   $c->bsub( $_[1]) },
+                       $c->bneg()->badd( $_[1]) :
+                       $c->bsub( $_[1]) },
 '+'    =>      sub { $_[0]->copy()->badd($_[1]); },
 '*'    =>      sub { $_[0]->copy()->bmul($_[1]); },
 
@@ -134,8 +145,8 @@ use overload
 ##############################################################################
 # global constants, flags and accessory
 
-# these are public, but their usage is not recommended, use the accessor
-# methods instead
+# These vars are public, but their direct usage is not recommended, use the
+# accessor methods instead
 
 $round_mode = 'even'; # one of 'even', 'odd', '+inf', '-inf', 'zero' or 'trunc'
 $accuracy   = undef;
@@ -145,20 +156,19 @@ $div_scale  = 40;
 $upgrade = undef;                      # default is no upgrade
 $downgrade = undef;                    # default is no downgrade
 
-# these are internally, and not to be used from the outside
-
-sub MB_NEVER_ROUND () { 0x0001; }
+# These are internally, and not to be used from the outside at all
 
 $_trap_nan = 0;                                # are NaNs ok? set w/ config()
 $_trap_inf = 0;                                # are infs ok? set w/ config()
 my $nan = 'NaN';                       # constants for easier life
 
-my $CALC = 'Math::BigInt::Calc';       # module to do the low level math
-                                       # default is Calc.pm
+my $CALC = 'Math::BigInt::FastCalc';   # module to do the low level math
+                                       # default is FastCalc.pm
 my $IMPORT = 0;                                # was import() called yet?
                                        # used to make require work
 my %WARN;                              # warn only once for low-level libs
 my %CAN;                               # cache for $CALC->can(...)
+my %CALLBACKS;                         # callbacks to notify on lib loads
 my $EMU_LIB = 'Math/BigInt/CalcEmu.pm';        # emulate low-level math
 
 ##############################################################################
@@ -209,8 +219,7 @@ sub upgrade
   # need to set new value?
   if (@_ > 0)
     {
-    my $u = shift;
-    return ${"${class}::upgrade"} = $u;
+    return ${"${class}::upgrade"} = $_[0];
     }
   ${"${class}::upgrade"};
   }
@@ -224,8 +233,7 @@ sub downgrade
   # need to set new value?
   if (@_ > 0)
     {
-    my $u = shift;
-    return ${"${class}::downgrade"} = $u;
+    return ${"${class}::downgrade"} = $_[0];
     }
   ${"${class}::downgrade"};
   }
@@ -242,7 +250,7 @@ sub div_scale
       {
       require Carp; Carp::croak ('div_scale must be greater than zero');
       }
-    ${"${class}::div_scale"} = shift;
+    ${"${class}::div_scale"} = $_[0];
     }
   ${"${class}::div_scale"};
   }
@@ -296,12 +304,12 @@ sub accuracy
     return $a;                         # shortcut
     }
 
-  my $r;
+  my $a;
   # $object->accuracy() or fallback to global
-  $r = $x->{_a} if ref($x);
+  $a = $x->{_a} if ref($x);
   # but don't return global undef, when $x's accuracy is 0!
-  $r = ${"${class}::accuracy"} if !defined $r;
-  $r;
+  $a = ${"${class}::accuracy"} if !defined $a;
+  $a;
   }
 
 sub precision
@@ -342,12 +350,12 @@ sub precision
     return $p;                         # shortcut
     }
 
-  my $r;
+  my $p;
   # $object->precision() or fallback to global
-  $r = $x->{_p} if ref($x);
+  $p = $x->{_p} if ref($x);
   # but don't return global undef, when $x's precision is 0!
-  $r = ${"${class}::precision"} if !defined $r;
-  $r;
+  $p = ${"${class}::precision"} if !defined $p;
+  $p;
   }
 
 sub config
@@ -416,22 +424,34 @@ sub _scale_a
   { 
   # select accuracy parameter based on precedence,
   # used by bround() and bfround(), may return undef for scale (means no op)
-  my ($x,$s,$m,$scale,$mode) = @_;
-  $scale = $x->{_a} if !defined $scale;
-  $scale = $s if (!defined $scale);
-  $mode = $m if !defined $mode;
-  return ($scale,$mode);
+  my ($x,$scale,$mode) = @_;
+
+  $scale = $x->{_a} unless defined $scale;
+
+  no strict 'refs';
+  my $class = ref($x);
+
+  $scale = ${ $class . '::accuracy' } unless defined $scale;
+  $mode = ${ $class . '::round_mode' } unless defined $mode;
+
+  ($scale,$mode);
   }
 
 sub _scale_p
   { 
   # select precision parameter based on precedence,
   # used by bround() and bfround(), may return undef for scale (means no op)
-  my ($x,$s,$m,$scale,$mode) = @_;
-  $scale = $x->{_p} if !defined $scale;
-  $scale = $s if (!defined $scale);
-  $mode = $m if !defined $mode;
-  return ($scale,$mode);
+  my ($x,$scale,$mode) = @_;
+  
+  $scale = $x->{_p} unless defined $scale;
+
+  no strict 'refs';
+  my $class = ref($x);
+
+  $scale = ${ $class . '::precision' } unless defined $scale;
+  $mode = ${ $class . '::round_mode' } unless defined $mode;
+
+  ($scale,$mode);
   }
 
 ##############################################################################
@@ -452,7 +472,7 @@ sub copy
     }
   return unless ref($x); # only for objects
 
-  my $self = {}; bless $self,$c;
+  my $self = bless {}, $c;
 
   $self->{sign} = $x->{sign};
   $self->{value} = $CALC->_copy($x->{value});
@@ -508,11 +528,10 @@ sub new
     }
 
   # handle '+inf', '-inf' first
-  if ($wanted =~ /^[+-]?inf$/)
+  if ($wanted =~ /^[+-]?inf\z/)
     {
-    $self->{value} = $CALC->_zero();
-    $self->{sign} = $wanted; $self->{sign} = '+inf' if $self->{sign} eq 'inf';
-    return $self;
+    $self->{sign} = $wanted;           # set a default sign for bstr()
+    return $self->binf($wanted);
     }
   # split str in m mantissa, e exponent, i integer, f fraction, v value, s sign
   my ($mis,$miv,$mfv,$es,$ev) = _split($wanted);
@@ -643,7 +662,7 @@ sub binf
   if (${"${class}::_trap_inf"})
     {
     require Carp;
-    Carp::croak ("Tried to set $self to +-inf in $class\::binfn()");
+    Carp::croak ("Tried to set $self to +-inf in $class\::binf()");
     }
   $self->import() if $IMPORT == 0;             # make require work
   return if $self->modify('binf');
@@ -667,7 +686,7 @@ sub bzero
   {
   # create a bigint '+0', if given a BigInt, set it to 0
   my $self = shift;
-  $self = $class if !defined $self;
+  $self = __PACKAGE__ if !defined $self;
  
   if (!ref($self))
     {
@@ -708,7 +727,7 @@ sub bzero
 sub bone
   {
   # create a bigint '+1' (or -1 if given sign '-'),
-  # if given a BigInt, set it to +1 or -1, respecively
+  # if given a BigInt, set it to +1 or -1, respectively
   my $self = shift;
   my $sign = shift; $sign = '+' if !defined $sign || $sign ne '-';
   $self = $class if !defined $self;
@@ -758,8 +777,7 @@ sub bsstr
   # (ref to BFLOAT or num_str ) return num_str
   # Convert number from internal format to scientific string format.
   # internal format is always normalized (no leading zeros, "-0E0" => "+0E0")
-  my $x = shift; $class = ref($x) || $x; $x = $class->new(shift) if !ref($x); 
-  # my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_); 
+  my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_); 
 
   if ($x->{sign} !~ /^[+-]$/)
     {
@@ -775,8 +793,7 @@ sub bsstr
 sub bstr 
   {
   # make a string from bigint object
-  my $x = shift; $class = ref($x) || $x; $x = $class->new(shift) if !ref($x); 
-  # my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_); 
+  my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_); 
 
   if ($x->{sign} !~ /^[+-]$/)
     {
@@ -829,9 +846,6 @@ sub _find_round_parameters
   # $r round_mode, if given by caller
   # @args all 'other' arguments (0 for unary, 1 for binary ops)
 
-  # leave bigfloat parts alone
-  return ($self) if exists $self->{_f} && ($self->{_f} & MB_NEVER_ROUND) != 0;
-
   my $c = ref($self);                          # find out class of argument(s)
   no strict 'refs';
 
@@ -889,9 +903,6 @@ sub round
   # $r round_mode, if given by caller
   # @args all 'other' arguments (0 for unary, 1 for binary ops)
 
-  # leave bigfloat parts alone
-  return ($self) if exists $self->{_f} && ($self->{_f} & MB_NEVER_ROUND) != 0;
-
   my $c = ref($self);                          # find out class of argument(s)
   no strict 'refs';
 
@@ -942,7 +953,8 @@ sub round
     {
     $self->bfround($p,$r) if !defined $self->{_p} || $self->{_p} <= $p;
     }
-  $self->bnorm();                      # after round, normalize
+  # bround() or bfround() already callled bnorm() if necc.
+  $self;
   }
 
 sub bnorm
@@ -957,7 +969,7 @@ sub babs
   {
   # (BINT or num_str) return BINT
   # make number absolute, or return absolute BINT from string
-  my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
+  my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
 
   return $x if $x->modify('babs');
   # post-normalized abs for internal use (does nothing for NaN)
@@ -969,12 +981,12 @@ sub bneg
   { 
   # (BINT or num_str) return BINT
   # negate number or make a negated number from string
-  my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
+  my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
   
   return $x if $x->modify('bneg');
 
-  # for +0 dont negate (to have always normalized)
-  $x->{sign} =~ tr/+-/-+/ if !$x->is_zero();   # does nothing for NaN
+  # for +0 dont negate (to have always normalized +0). Does nothing for 'NaN'
+  $x->{sign} =~ tr/+-/-+/ unless ($x->{sign} eq '+' && $CALC->_is_zero($x->{value}));
   $x;
   }
 
@@ -1112,8 +1124,7 @@ sub badd
       $x->{value} = $CALC->_sub($x->{value}, $y->{value}); # abs sub
       }
     }
-  $x->round(@r) if !exists $x->{_f} || $x->{_f} & MB_NEVER_ROUND == 0;
-  $x;
+  $x->round(@r);
   }
 
 sub bsub 
@@ -1134,13 +1145,19 @@ sub bsub
   return $upgrade->new($x)->bsub($upgrade->new($y),@r) if defined $upgrade &&
    ((!$x->isa($self)) || (!$y->isa($self)));
 
-  if ($y->is_zero())
-    { 
-    $x->round(@r) if !exists $x->{_f} || $x->{_f} & MB_NEVER_ROUND == 0;
-    return $x;
-    }
+  return $x->round(@r) if $y->is_zero();
 
+  # To correctly handle the lone special case $x->bsub($x), we note the sign
+  # of $x, then flip the sign from $y, and if the sign of $x did change, too,
+  # then we caught the special case:
+  my $xsign = $x->{sign};
   $y->{sign} =~ tr/+\-/-+/;    # does nothing for NaN
+  if ($xsign ne $x->{sign})
+    {
+    # special case of $x->bsub($x) results in 0
+    return $x->bzero(@r) if $xsign =~ /^[+-]$/;
+    return $x->bnan();          # NaN, -inf, +inf
+    }
   $x->badd($y,@r);             # badd does not leave internal zeros
   $y->{sign} =~ tr/+\-/-+/;    # refix $y (does nothing for NaN)
   $x;                          # already rounded by badd() or no round necc.
@@ -1155,15 +1172,13 @@ sub binc
   if ($x->{sign} eq '+')
     {
     $x->{value} = $CALC->_inc($x->{value});
-    $x->round($a,$p,$r) if !exists $x->{_f} || $x->{_f} & MB_NEVER_ROUND == 0;
-    return $x;
+    return $x->round($a,$p,$r);
     }
   elsif ($x->{sign} eq '-')
     {
     $x->{value} = $CALC->_dec($x->{value});
     $x->{sign} = '+' if $CALC->_is_zero($x->{value}); # -1 +1 => -0 => +0
-    $x->round($a,$p,$r) if !exists $x->{_f} || $x->{_f} & MB_NEVER_ROUND == 0;
-    return $x;
+    return $x->round($a,$p,$r);
     }
   # inf, nan handling etc
   $x->badd($self->bone(),$a,$p,$r);            # badd does round
@@ -1177,12 +1192,12 @@ sub bdec
   
   if ($x->{sign} eq '-')
     {
-    # < 0
+    # x already < 0
     $x->{value} = $CALC->_inc($x->{value});
     } 
   else
     {
-    return $x->badd($self->bone('-'),@r) unless $x->{sign} eq '+'; # inf/NaN
+    return $x->badd($self->bone('-'),@r) unless $x->{sign} eq '+';     # inf or NaN
     # >= 0
     if ($CALC->_is_zero($x->{value}))
       {
@@ -1195,8 +1210,7 @@ sub bdec
       $x->{value} = $CALC->_dec($x->{value});
       }
     }
-  $x->round(@r) if !exists $x->{_f} || $x->{_f} & MB_NEVER_ROUND == 0;
-  $x;
+  $x->round(@r);
   }
 
 sub blog
@@ -1205,11 +1219,11 @@ sub blog
   # $base of $x)
 
   # set up parameters
-  my ($self,$x,$base,@r) = (ref($_[0]),@_);
+  my ($self,$x,$base,@r) = (undef,@_);
   # objectify is costly, so avoid it
   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
     {
-    ($self,$x,$base,@r) = objectify(1,$class,@_);
+    ($self,$x,$base,@r) = objectify(1,ref($x),@_);
     }
   
   return $x if $x->modify('blog');
@@ -1240,7 +1254,7 @@ sub blcm
     }
   else
     {
-    $x = __PACKAGE__->new($y);
+    $x = $class->new($y);
     }
   my $self = ref($x);
   while (@_) 
@@ -1258,7 +1272,7 @@ sub bgcd
   # GCD -- Euclids algorithm, variant C (Knuth Vol 3, pg 341 ff)
 
   my $y = shift;
-  $y = __PACKAGE__->new($y) if !ref($y);
+  $y = $class->new($y) if !ref($y);
   my $self = ref($y);
   my $x = $y->copy()->babs();                  # keep arguments
   return $x->bnan() if $x->{sign} !~ /^[+-]$/; # x NaN?
@@ -1266,9 +1280,9 @@ sub bgcd
   while (@_)
     {
     $y = shift; $y = $self->new($y) if !ref($y);
-    next if $y->is_zero();
     return $x->bnan() if $y->{sign} !~ /^[+-]$/;       # y NaN?
-    $x->{value} = $CALC->_gcd($x->{value},$y->{value}); last if $x->is_one();
+    $x->{value} = $CALC->_gcd($x->{value},$y->{value});
+    last if $CALC->_is_one($x->{value});
     }
   $x;
   }
@@ -1352,8 +1366,11 @@ sub is_positive
   {
   # return true when arg (BINT or num_str) is positive (>= 0)
   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
-  
-  $x->{sign} =~ /^\+/ ? 1 : 0;         # +inf is also positive, but NaN not
+
+  return 1 if $x->{sign} eq '+inf';                    # +inf is positive
+  # 0+ is neither positive nor negative
+  ($x->{sign} eq '+' && !$x->is_zero()) ? 1 : 0;       
   }
 
 sub is_negative
@@ -1361,7 +1378,7 @@ sub is_negative
   # return true when arg (BINT or num_str) is negative (< 0)
   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
   
-  $x->{sign} =~ /^-/ ? 1 : 0;          # -inf is also negative, but NaN not
+  $x->{sign} =~ /^-/ ? 1 : 0;          # -inf is negative, but NaN is not
   }
 
 sub is_int
@@ -1414,8 +1431,7 @@ sub bmul
   $x->{value} = $CALC->_mul($x->{value},$y->{value});  # do actual math
   $x->{sign} = '+' if $CALC->_is_zero($x->{value});    # no -0
 
-  $x->round(@r) if !exists $x->{_f} || $x->{_f} & MB_NEVER_ROUND == 0;
-  $x;
+  $x->round(@r);
   }
 
 sub _div_inf
@@ -1497,7 +1513,7 @@ sub bdiv
     $x->{sign} = '+' if $CALC->_is_zero($x->{value});
     $rem->{_a} = $x->{_a};
     $rem->{_p} = $x->{_p};
-    $x->round(@r) if !exists $x->{_f} || ($x->{_f} & MB_NEVER_ROUND) == 0;
+    $x->round(@r);
     if (! $CALC->_is_zero($rem->{value}))
       {
       $rem->{sign} = $y->{sign};
@@ -1507,15 +1523,14 @@ sub bdiv
       {
       $rem->{sign} = '+';                      # dont leave -0
       }
-    $rem->round(@r) if !exists $rem->{_f} || ($rem->{_f} & MB_NEVER_ROUND) == 0;
+    $rem->round(@r);
     return ($x,$rem);
     }
 
   $x->{value} = $CALC->_div($x->{value},$y->{value});
   $x->{sign} = '+' if $CALC->_is_zero($x->{value});
 
-  $x->round(@r) if !exists $x->{_f} || ($x->{_f} & MB_NEVER_ROUND) == 0;
-  $x;
+  $x->round(@r);
   }
 
 ###############################################################################
@@ -1548,20 +1563,15 @@ sub bmod
   $x->{value} = $CALC->_mod($x->{value},$y->{value});
   if (!$CALC->_is_zero($x->{value}))
     {
-    my $xsign = $x->{sign};
+    $x->{value} = $CALC->_sub($y->{value},$x->{value},1)       # $y-$x
+      if ($x->{sign} ne $y->{sign});
     $x->{sign} = $y->{sign};
-    if ($xsign ne $y->{sign})
-      {
-      my $t = $CALC->_copy($x->{value});               # copy $x
-      $x->{value} = $CALC->_sub($y->{value},$t,1);     # $y-$x
-      }
     }
    else
     {
     $x->{sign} = '+';                          # dont leave -0
     }
-  $x->round(@r) if !exists $x->{_f} || $x->{_f} & MB_NEVER_ROUND == 0;
-  $x;
+  $x->round(@r);
   }
 
 sub bmodinv
@@ -1572,7 +1582,7 @@ sub bmodinv
   # (i.e. their gcd is not one) then NaN is returned.
 
   # set up parameters
-  my ($self,$x,$y,@r) = (ref($_[0]),@_);
+  my ($self,$x,$y,@r) = (undef,@_);
   # objectify is costly, so avoid it
   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
     {
@@ -1635,12 +1645,10 @@ sub bfac
   {
   # (BINT or num_str, BINT or num_str) return BINT
   # compute factorial number from $x, modify $x in place
-  my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
+  my ($self,$x,@r) = ref($_[0]) ? (undef,@_) : objectify(1,@_);
 
-  return $x if $x->modify('bfac');
-  return $x if $x->{sign} eq '+inf';           # inf => inf
-  return $x->bnan() if $x->{sign} ne '+';      # NaN, <0 etc => NaN
+  return $x if $x->modify('bfac') || $x->{sign} eq '+inf';     # inf => inf
+  return $x->bnan() if $x->{sign} ne '+';                      # NaN, <0 etc => NaN
 
   $x->{value} = $CALC->_fac($x->{value});
   $x->round(@r);
@@ -1662,12 +1670,61 @@ sub bpow
 
   return $x if $x->modify('bpow');
 
+  return $x->bnan() if $x->{sign} eq $nan || $y->{sign} eq $nan;
+
+  # inf handling
+  if (($x->{sign} =~ /^[+-]inf$/) || ($y->{sign} =~ /^[+-]inf$/))
+    {
+    if (($x->{sign} =~ /^[+-]inf$/) && ($y->{sign} =~ /^[+-]inf$/))
+      {
+      # +-inf ** +-inf
+      return $x->bnan();
+      }
+    # +-inf ** Y
+    if ($x->{sign} =~ /^[+-]inf/)
+      {
+      # +inf ** 0 => NaN
+      return $x->bnan() if $y->is_zero();
+      # -inf ** -1 => 1/inf => 0
+      return $x->bzero() if $y->is_one('-') && $x->is_negative();
+
+      # +inf ** Y => inf
+      return $x if $x->{sign} eq '+inf';
+
+      # -inf ** Y => -inf if Y is odd
+      return $x if $y->is_odd();
+      return $x->babs();
+      }
+    # X ** +-inf
+
+    # 1 ** +inf => 1
+    return $x if $x->is_one();
+    
+    # 0 ** inf => 0
+    return $x if $x->is_zero() && $y->{sign} =~ /^[+]/;
+
+    # 0 ** -inf => inf
+    return $x->binf() if $x->is_zero();
+
+    # -1 ** -inf => NaN
+    return $x->bnan() if $x->is_one('-') && $y->{sign} =~ /^[-]/;
+
+    # -X ** -inf => 0
+    return $x->bzero() if $x->{sign} eq '-' && $y->{sign} =~ /^[-]/;
+
+    # -1 ** inf => NaN
+    return $x->bnan() if $x->{sign} eq '-';
+
+    # X ** inf => inf
+    return $x->binf() if $y->{sign} =~ /^[+]/;
+    # X ** -inf => 0
+    return $x->bzero();
+    }
+
   return $upgrade->bpow($upgrade->new($x),$y,@r)
    if defined $upgrade && !$y->isa($self);
 
   $r[3] = $y;                                  # no push!
-  return $x if $x->{sign} =~ /^[+-]inf$/;      # -inf/+inf ** x
-  return $x->bnan() if $x->{sign} eq $nan || $y->{sign} eq $nan;
 
   # cases 0 ** Y, X ** 0, X ** 1, 1 ** Y are handled by Calc or Emu
 
@@ -1684,8 +1741,7 @@ sub bpow
   $x->{value} = $CALC->_pow($x->{value},$y->{value});
   $x->{sign} = $new_sign;
   $x->{sign} = '+' if $CALC->_is_zero($y->{value});
-  $x->round(@r) if !exists $x->{_f} || $x->{_f} & MB_NEVER_ROUND == 0;
-  $x;
+  $x->round(@r);
   }
 
 sub blsft 
@@ -1921,7 +1977,7 @@ sub _trailing_zeros
 sub bsqrt
   {
   # calculate square root of $x
-  my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
+  my ($self,$x,@r) = ref($_[0]) ? (undef,@_) : objectify(1,@_);
 
   return $x if $x->modify('bsqrt');
 
@@ -2013,7 +2069,7 @@ sub bfround
   # $n == 0 || $n == 1 => round to integer
   my $x = shift; my $self = ref($x) || $x; $x = $self->new($x) unless ref $x;
 
-  my ($scale,$mode) = $x->_scale_p($x->precision(),$x->round_mode(),@_);
+  my ($scale,$mode) = $x->_scale_p(@_);
 
   return $x if !defined $scale || $x->modify('bfround');       # no-op
 
@@ -2027,24 +2083,22 @@ sub bfround
 
 sub _scan_for_nonzero
   {
-  # internal, used by bround()
-  my ($x,$pad,$xs) = @_;
+  # internal, used by bround() to scan for non-zeros after a '5'
+  my ($x,$pad,$xs,$len) = @_;
  
-  my $len = $x->length();
-  return 0 if $len == 1;               # '5' is trailed by invisible zeros
+  return 0 if $len == 1;               # "5" is trailed by invisible zeros
   my $follow = $pad - 1;
   return 0 if $follow > $len || $follow < 1;
 
-  # since we do not know underlying represention of $x, use decimal string
-  my $r = substr ("$x",-$follow);
-  $r =~ /[^0]/ ? 1 : 0;
+  # use the string form to check whether only '0's follow or not
+  substr ($xs,-$follow) =~ /[^0]/ ? 1 : 0;
   }
 
 sub fround
   {
   # Exists to make life easier for switch between MBF and MBI (should we
   # autoload fxxx() like MBF does for bxxx()?)
-  my $x = shift;
+  my $x = shift; $x = $class->new($x) unless ref $x;
   $x->bround(@_);
   }
 
@@ -2057,9 +2111,8 @@ sub bround
   # do not return $x->bnorm(), but $x
 
   my $x = shift; $x = $class->new($x) unless ref $x;
-  my ($scale,$mode) = $x->_scale_a($x->accuracy(),$x->round_mode(),@_);
-  return $x if !defined $scale;                        # no-op
-  return $x if $x->modify('bround');
+  my ($scale,$mode) = $x->_scale_a(@_);
+  return $x if !defined $scale || $x->modify('bround');        # no-op
   
   if ($x->is_zero() || $scale == 0)
     {
@@ -2087,8 +2140,8 @@ sub bround
   $pad = $len - $scale;
   $pad = abs($scale-1) if $scale < 0;
 
-  # do not use digit(), it is costly for binary => decimal
-
+  # do not use digit(), it is very costly for binary => decimal
+  # getting the entire string is also costly, but we need to do it only once
   my $xs = $CALC->_str($x->{value});
   my $pl = -$pad-1;
 
@@ -2106,7 +2159,7 @@ sub bround
     ($digit_after =~ /[01234]/)                        ||      # round down anyway,
                                                        # 6789 => round up
     ($digit_after eq '5')                      &&      # not 5000...0000
-    ($x->_scan_for_nonzero($pad,$xs) == 0)             &&
+    ($x->_scan_for_nonzero($pad,$xs,$len) == 0)                &&
     (
      ($mode eq 'even') && ($digit_round =~ /[24680]/) ||
      ($mode eq 'odd')  && ($digit_round =~ /[13579]/) ||
@@ -2118,8 +2171,8 @@ sub bround
        
   if (($pad > 0) && ($pad <= $len))
     {
-    substr($xs,-$pad,$pad) = '0' x $pad;
-    $put_back = 1;
+    substr($xs,-$pad,$pad) = '0' x $pad;               # replace with '00...'
+    $put_back = 1;                                     # need to put back
     }
   elsif ($pad > $len)
     {
@@ -2128,7 +2181,7 @@ sub bround
 
   if ($round_up)                                       # what gave test above?
     {
-    $put_back = 1;
+    $put_back = 1;                                     # need to put back
     $pad = $len, $xs = '0' x $pad if $scale < 0;       # tlr: whack 0.51=>1.0  
 
     # we modify directly the string variant instead of creating a number and
@@ -2143,7 +2196,7 @@ sub bround
     $xs = '1'.$xs if $c == 0;
 
     }
-  $x->{value} = $CALC->_new($xs) if $put_back == 1;    # put back in if needed
+  $x->{value} = $CALC->_new($xs) if $put_back == 1;    # put back, if needed
 
   $x->{_a} = $scale if $scale >= 0;
   if ($scale < 0)
@@ -2211,7 +2264,7 @@ sub objectify
   # the first argument is number of args objectify() should look at it will
   # return $count+1 elements, the first will be a classname. This is because
   # overloaded '""' calls bstr($object,undef,undef) and this would result in
-  # useless objects beeing created and thrown away. So we cannot simple loop
+  # useless objects being created and thrown away. So we cannot simple loop
   # over @_. If the given count is 0, all arguments will be used.
  
   # If the second arg is a ref, use it as class.
@@ -2301,6 +2354,18 @@ sub objectify
   @a;
   }
 
+sub _register_callback
+  {
+  my ($class,$callback) = @_;
+
+  if (ref($callback) ne 'CODE')
+    { 
+    require Carp;
+    Carp::croak ("$callback is not a coderef");
+    }
+  $CALLBACKS{$class} = $callback;
+  }
+
 sub import 
   {
   my $self = shift;
@@ -2334,13 +2399,21 @@ sub import
       }
     }
   # any non :constant stuff is handled by our parent, Exporter
-  # even if @_ is empty, to give it a chance 
-  $self->SUPER::import(@a);                    # need it for subclasses
-  $self->export_to_level(1,$self,@a);          # need it for MBF
+  if (@a > 0)
+    {
+    require Exporter;
+    $self->SUPER::import(@a);                  # need it for subclasses
+    $self->export_to_level(1,$self,@a);                # need it for MBF
+    }
 
   # try to load core math lib
   my @c = split /\s*,\s*/,$CALC;
-  push @c,'Calc';                              # if all fail, try this
+  foreach (@c)
+    {
+    $_ =~ tr/a-zA-Z0-9://cd;                   # limit to sane characters
+    }
+  push @c, 'FastCalc', 'Calc';                 # if all fail, try these
   $CALC = '';                                  # signal error
   foreach my $lib (@c)
     {
@@ -2349,8 +2422,8 @@ sub import
     $lib =~ s/\.pm$//;
     if ($] < 5.006)
       {
-      # Perl < 5.6.0 dies with "out of memory!" when eval() and ':constant' is
-      # used in the same script, or eval inside import().
+      # Perl < 5.6.0 dies with "out of memory!" when eval("") and ':constant' is
+      # used in the same script, or eval("") inside import().
       my @parts = split /::/, $lib;             # Math::BigInt => Math BigInt
       my $file = pop @parts; $file .= '.pm';    # BigInt => BigInt.pm
       require File::Spec;
@@ -2401,7 +2474,7 @@ sub import
        {
        if (($WARN{$lib}||0) < 2)
          {
-         my $ver = eval "\$$lib\::VERSION";
+         my $ver = eval "\$$lib\::VERSION" || 'unknown';
          require Carp;
          Carp::carp ("Cannot load outdated $lib v$ver, please upgrade");
          $WARN{$lib} = 2;              # never warn again
@@ -2414,22 +2487,28 @@ sub import
     require Carp;
     Carp::croak ("Couldn't load any math lib, not even 'Calc.pm'");
     }
-  _fill_can_cache();           # for emulating lower math lib functions
-  }
 
-sub _fill_can_cache
-  {
-  # fill $CAN with the results of $CALC->can(...)
+  # notify callbacks
+  foreach my $class (keys %CALLBACKS)
+    {
+    &{$CALLBACKS{$class}}($CALC);
+    }
+
+  # Fill $CAN with the results of $CALC->can(...) for emulating lower math lib
+  # functions
 
   %CAN = ();
-  for my $method (qw/ signed_and or signed_or xor signed_xor /)
+  for my $method (qw/ signed_and signed_or signed_xor /)
     {
     $CAN{$method} = $CALC->can("_$method") ? 1 : 0;
     }
+
+  # import done
   }
 
 sub __from_hex
   {
+  # internal
   # convert a (ref to) big hex string to BigInt, return undef for error
   my $hs = shift;
 
@@ -2451,6 +2530,7 @@ sub __from_hex
 
 sub __from_bin
   {
+  # internal
   # convert a (ref to) big binary string to BigInt, return undef for error
   my $bs = shift;
 
@@ -2470,10 +2550,11 @@ sub __from_bin
 
 sub _split
   {
-  # (ref to num_str) return num_str
-  # internal, take apart a string and return the pieces
-  # strip leading/trailing whitespace, leading zeros, underscore and reject
-  # invalid input
+  # input: num_str; output: undef for invalid or
+  # (\$mantissa_sign,\$mantissa_value,\$mantissa_fraction,\$exp_sign,\$exp_value)
+  # Internal, take apart a string and return the pieces.
+  # Strip leading/trailing whitespace, leading zeros, underscore and reject
+  # invalid input.
   my $x = shift;
 
   # strip white space at front, also extranous leading zeros
@@ -2541,13 +2622,15 @@ sub __lcm
   # does modify first argument
   # LCM
  
-  my $x = shift; my $ty = shift;
+  my ($x,$ty) = @_;
   return $x->bnan() if ($x->{sign} eq $nan) || ($ty->{sign} eq $nan);
-  $x * $ty / bgcd($x,$ty);
+  my $method = ref($x) . '::bgcd';
+  no strict 'refs';
+  $x * $ty / &$method($x,$ty);
   }
 
 ###############################################################################
-# this method return 0 if the object can be modified, or 1 for not
+# this method returns 0 if the object can be modified, or 1 if not.
 # We use a fast constant sub() here, to avoid costly calls. Subclasses
 # may override it with special code (f.i. Math::BigInt::Constant does so)
 
@@ -2556,9 +2639,11 @@ sub modify () { 0; }
 1;
 __END__
 
+=pod
+
 =head1 NAME
 
-Math::BigInt - Arbitrary size integer math package
+Math::BigInt - Arbitrary size integer/float math package
 
 =head1 SYNOPSIS
 
@@ -2598,7 +2683,7 @@ Math::BigInt - Arbitrary size integer math package
   $x->is_inf($sign);   # if $x is +inf, or -inf (sign is default '+')
   $x->is_int();                # if $x is an integer (not a float)
 
-  # comparing and digit/sign extration
+  # comparing and digit/sign extraction
   $x->bcmp($y);                # compare numbers (undef,<0,=0,>0)
   $x->bacmp($y);       # compare absolutely (undef,<0,=0,>0)
   $x->sign();          # return the sign, either +,- or NaN
@@ -2607,7 +2692,7 @@ Math::BigInt - Arbitrary size integer math package
 
   # The following all modify their first argument. If you want to preserve
   # $x, use $z = $x->copy()->bXXX($y); See under L<CAVEATS> for why this is
-  # neccessary when mixing $a = $b assigments with non-overloaded math.
+  # necessary when mixing $a = $b assignments with non-overloaded math.
 
   $x->bzero();         # set $x to 0
   $x->bnan();          # set $x to NaN
@@ -2667,7 +2752,7 @@ Math::BigInt - Arbitrary size integer math package
  
   $x->length();                   # return number of digits in number
   ($xl,$f) = $x->length(); # length of number and length of fraction part,
-                          # latter is always 0 digits long for BigInt's
+                          # latter is always 0 digits long for BigInts
 
   $x->exponent();         # return exponent as BigInt
   $x->mantissa();         # return (signed) mantissa as BigInt
@@ -2677,8 +2762,8 @@ Math::BigInt - Arbitrary size integer math package
   $x->numify();                   # return as scalar (might overflow!)
   
   # conversation to string (do not modify their argument)
-  $x->bstr();             # normalized string
-  $x->bsstr();            # normalized string in scientific notation
+  $x->bstr();             # normalized string (e.g. '3')
+  $x->bsstr();            # norm. string in scientific notation (e.g. '3E0')
   $x->as_hex();                   # as signed hexadecimal string with prefixed 0x
   $x->as_bin();                   # as signed binary string with prefixed 0b
 
@@ -2690,13 +2775,15 @@ Math::BigInt - Arbitrary size integer math package
   $x->accuracy($n);       # set A $x to $n
 
   # Global methods
-  Math::BigInt->precision(); # get/set global P for all BigInt objects
-  Math::BigInt->accuracy();  # get/set global A for all BigInt objects
-  Math::BigInt->config();    # return hash containing configuration
+  Math::BigInt->precision();   # get/set global P for all BigInt objects
+  Math::BigInt->accuracy();    # get/set global A for all BigInt objects
+  Math::BigInt->round_mode();  # get/set global round mode, one of
+                               # 'even', 'odd', '+inf', '-inf', 'zero' or 'trunc'
+  Math::BigInt->config();      # return hash containing configuration
 
 =head1 DESCRIPTION
 
-All operators (inlcuding basic math operations) are overloaded if you
+All operators (including basic math operations) are overloaded if you
 declare your big integers as
 
   $i = new Math::BigInt '123_456_789_123_456_789';
@@ -2736,19 +2823,20 @@ object from the input.
 
 =item Output
 
-Output values are BigInt objects (normalized), except for bstr(), which
-returns a string in normalized form.
+Output values are BigInt objects (normalized), except for the methods which
+return a string (see L<SYNOPSIS>).
+
 Some routines (C<is_odd()>, C<is_even()>, C<is_zero()>, C<is_one()>,
-C<is_nan()>) return true or false, while others (C<bcmp()>, C<bacmp()>)
-return either undef, <0, 0 or >0 and are suited for sort.
+C<is_nan()>, etc.) return true or false, while others (C<bcmp()>, C<bacmp()>)
+return either undef (if NaN is involved), <0, 0 or >0 and are suited for sort.
 
 =back
 
 =head1 METHODS
 
 Each of the methods below (except config(), accuracy() and precision())
-accepts three additional parameters. These arguments $A, $P and $R are
-accuracy, precision and round_mode. Please see the section about
+accepts three additional parameters. These arguments C<$A>, C<$P> and C<$R>
+are C<accuracy>, C<precision> and C<round_mode>. Please see the section about
 L<ACCURACY and PRECISION> for more information.
 
 =head2 config
@@ -2783,7 +2871,7 @@ appropriate information.
                        even
        version         version number of the class you used
                        1.61
-       div_scale       Fallback acccuracy for div
+       div_scale       Fallback accuracy for div
                        40
        trap_nan        If true, traps creation of NaN via croak()
                        1
@@ -2803,11 +2891,26 @@ Example:
 
        $x->accuracy(5);                # local for $x
        CLASS->accuracy(5);             # global for all members of CLASS
-       $A = $x->accuracy();            # read out
-       $A = CLASS->accuracy();         # read out
+                                       # Note: This also applies to new()!
+
+       $A = $x->accuracy();            # read out accuracy that affects $x
+       $A = CLASS->accuracy();         # read out global accuracy
 
 Set or get the global or local accuracy, aka how many significant digits the
-results have. 
+results have. If you set a global accuracy, then this also applies to new()!
+
+Warning! The accuracy I<sticks>, e.g. once you created a number under the
+influence of C<< CLASS->accuracy($A) >>, all results from math operations with
+that number will also be rounded. 
+
+In most cases, you should probably round the results explicitly using one of
+L<round()>, L<bround()> or L<bfround()> or by passing the desired accuracy
+to the math operation as additional parameter:
+
+        my $x = Math::BigInt->new(30000);
+        my $y = Math::BigInt->new(7);
+        print scalar $x->copy()->bdiv($y, 2);          # print 4300
+        print scalar $x->copy()->bdiv($y)->bround(2);  # print 4300
 
 Please see the section about L<ACCURACY AND PRECISION> for further details.
 
@@ -2822,7 +2925,7 @@ represents the accuracy that will be in effect for $x:
 
        $y = Math::BigInt->new(1234567);        # unrounded
        print Math::BigInt->accuracy(4),"\n";   # set 4, print 4
-       $x = Math::BigInt->new(123456);         # will be automatically rounded
+       $x = Math::BigInt->new(123456);         # $x will be automatically rounded!
        print "$x $y\n";                        # '123500 1234567'
        print $x->accuracy(),"\n";              # will be 4
        print $y->accuracy(),"\n";              # also 4, since global is 4
@@ -2837,35 +2940,46 @@ Math::BigInt.
 
 =head2 precision
 
-       $x->precision(-2);              # local for $x, round right of the dot
-       $x->precision(2);               # ditto, but round left of the dot
-       CLASS->accuracy(5);             # global for all members of CLASS
-       CLASS->precision(-5);           # ditto
-       $P = CLASS->precision();        # read out
-       $P = $x->precision();           # read out
+       $x->precision(-2);      # local for $x, round at the second digit right of the dot
+       $x->precision(2);       # ditto, round at the second digit left of the dot
+
+       CLASS->precision(5);    # Global for all members of CLASS
+                               # This also applies to new()!
+       CLASS->precision(-5);   # ditto
 
-Set or get the global or local precision, aka how many digits the result has
-after the dot (or where to round it when passing a positive number). In
-Math::BigInt, passing a negative number precision has no effect since no
-numbers have digits after the dot.
+       $P = CLASS->precision();        # read out global precision 
+       $P = $x->precision();           # read out precision that affects $x
+
+Note: You probably want to use L<accuracy()> instead. With L<accuracy> you
+set the number of digits each result should have, with L<precision> you
+set the place where to round!
+
+C<precision()> sets or gets the global or local precision, aka at which digit
+before or after the dot to round all results. A set global precision also
+applies to all newly created numbers!
+
+In Math::BigInt, passing a negative number precision has no effect since no
+numbers have digits after the dot. In L<Math::BigFloat>, it will round all
+results to P digits after the dot.
 
 Please see the section about L<ACCURACY AND PRECISION> for further details.
 
-Value must be greater than zero. Pass an undef value to disable it:
+Pass an undef value to disable it:
 
        $x->precision(undef);
        Math::BigInt->precision(undef);
 
 Returns the current precision. For C<$x->precision()> it will return either the
 local precision of $x, or if not defined, the global. This means the return
-value represents the accuracy that will be in effect for $x:
+value represents the prevision that will be in effect for $x:
 
        $y = Math::BigInt->new(1234567);        # unrounded
        print Math::BigInt->precision(4),"\n";  # set 4, print 4
        $x = Math::BigInt->new(123456);         # will be automatically rounded
+       print $x;                               # print "120000"!
 
-Note: Works also for subclasses like Math::BigFloat. Each class has it's own
-globals separated from Math::BigInt, but it is possible to subclass
+Note: Works also for subclasses like L<Math::BigFloat>. Each class has its
+own globals separated from Math::BigInt, but it is possible to subclass
 Math::BigInt and make the globals of the subclass aliases to the ones from
 Math::BigInt.
 
@@ -2954,7 +3068,7 @@ If used on an object, it will set it to one:
        $x->is_inf();                   # true if +inf
        $x->is_inf('-');                # true if -inf (sign is default '+')
 
-These methods all test the BigInt for beeing one specific value and return
+These methods all test the BigInt for being one specific value and return
 true or false depending on the input. These are faster than doing something
 like:
 
@@ -2962,16 +3076,16 @@ like:
 
 =head2 is_pos()/is_neg()
        
-       $x->is_pos();                   # true if >= 0
-       $x->is_neg();                   # true if <  0
+       $x->is_pos();                   # true if > 0
+       $x->is_neg();                   # true if < 0
 
 The methods return true if the argument is positive or negative, respectively.
 C<NaN> is neither positive nor negative, while C<+inf> counts as positive, and
-C<-inf> is negative. A C<zero> is positive.
+C<-inf> is negative. A C<zero> is neither positive nor negative.
 
 These methods are only testing the sign, and not the value.
 
-C<is_positive()> and C<is_negative()> are aliase to C<is_pos()> and
+C<is_positive()> and C<is_negative()> are aliases to C<is_pos()> and
 C<is_neg()>, respectively. C<is_positive()> and C<is_negative()> were
 introduced in v1.36, while C<is_pos()> and C<is_neg()> were only introduced
 in v1.68.
@@ -3006,6 +3120,14 @@ Compares $x with $y while ignoring their. Returns -1, 0, 1 or undef.
 
 Return the sign, of $x, meaning either C<+>, C<->, C<-inf>, C<+inf> or NaN.
 
+If you want $x to have a certain sign, use one of the following methods:
+
+       $x->babs();             # '+'
+       $x->babs()->bneg();     # '-'
+       $x->bnan();             # 'NaN'
+       $x->binf();             # '+inf'
+       $x->binf('-');          # '-inf'
+
 =head2 digit
 
        $x->digit($n);          # return the nth digit, counting from right
@@ -3218,7 +3340,7 @@ v1.22, while C<as_int()> was only introduced in v1.68.
 
        $x->bstr();
 
-Returns a normalized string represantation of C<$x>.
+Returns a normalized string representation of C<$x>.
 
 =head2 bsstr
 
@@ -3389,7 +3511,7 @@ versions <= 5.7.2) is like this:
       result has at most max(scale, length(dividend), length(divisor)) digits
     Actual code:
       scale = max(scale, length(dividend)-1,length(divisor)-1);
-      scale += length(divisior) - length(dividend);
+      scale += length(divisor) - length(dividend);
     So for lx = 3, ly = 9, scale = 10, scale will actually be 16 (10+9-3).
     Actually, the 'difference' added to the scale is calculated from the
     number of "significant digits" in dividend and divisor, which is derived
@@ -3428,7 +3550,7 @@ This is how it works now:
   * to find out the current global P, use C<< Math::SomeClass->precision() >>
   * use C<< $x->accuracy() >> respective C<< $x->precision() >> for the local
     setting of C<< $x >>.
-  * Please note that C<< $x->accuracy() >> respecive C<< $x->precision() >>
+  * Please note that C<< $x->accuracy() >> respective C<< $x->precision() >>
     return eventually defined global A or P, when C<< $x >>'s A or P is not
     set.
 
@@ -3474,7 +3596,7 @@ This is how it works now:
     be automatically cleared.
   * If two objects are involved in an operation, and one of them has A in
     effect, and the other P, this results in an error (NaN).
-  * A takes precendence over P (Hint: A comes before P).
+  * A takes precedence over P (Hint: A comes before P).
     If neither of them is defined, nothing is used, i.e. the result will have
     as many digits as it can (with an exception for fdiv/fsqrt) and will not
     be rounded.
@@ -3492,7 +3614,7 @@ This is how it works now:
     + never round (this is the default):
       This is done by setting A and P to undef. No math operation
       will round the result, with fdiv() and fsqrt() as exceptions to guard
-      against overflows. You must explicitely call bround(), bfround() or
+      against overflows. You must explicitly call bround(), bfround() or
       round() (the latter with parameters).
       Note: Once you have rounded a number, the settings will 'stick' on it
       and 'infect' all other numbers engaged in math operations with it, since
@@ -3585,12 +3707,58 @@ This is how it works now:
 
 =back
 
+=head1 Infinity and Not a Number
+
+While BigInt has extensive handling of inf and NaN, certain quirks remain.
+
+=over 2
+
+=item oct()/hex()
+
+These perl routines currently (as of Perl v.5.8.6) cannot handle passed
+inf.
+
+       te@linux:~> perl -wle 'print 2 ** 3333'
+       inf
+       te@linux:~> perl -wle 'print 2 ** 3333 == 2 ** 3333'
+       1
+       te@linux:~> perl -wle 'print oct(2 ** 3333)'
+       0
+       te@linux:~> perl -wle 'print hex(2 ** 3333)'
+       Illegal hexadecimal digit 'i' ignored at -e line 1.
+       0
+
+The same problems occur if you pass them Math::BigInt->binf() objects. Since
+overloading these routines is not possible, this cannot be fixed from BigInt.
+
+=item ==, !=, <, >, <=, >= with NaNs
+
+BigInt's bcmp() routine currently returns undef to signal that a NaN was
+involved in a comparison. However, the overload code turns that into
+either 1 or '' and thus operations like C<< NaN != NaN >> might return
+wrong values.
+
+=item log(-inf)
+
+C<< log(-inf) >> is highly weird. Since log(-x)=pi*i+log(x), then
+log(-inf)=pi*i+inf. However, since the imaginary part is finite, the real
+infinity "overshadows" it, so the number might as well just be infinity.
+However, the result is a complex number, and since BigInt/BigFloat can only
+have real numbers as results, the result is NaN.
+
+=item exp(), cos(), sin(), atan2()
+
+These all might have problems handling infinity right.
+=back
+
 =head1 INTERNALS
 
 The actual numbers are stored as unsigned big integers (with seperate sign).
+
 You should neither care about nor depend on the internal representation; it
-might change without notice. Use only method calls like C<< $x->sign(); >>
-instead relying on the internal hash keys like in C<< $x->{sign}; >>. 
+might change without notice. Use B<ONLY> method calls like C<< $x->sign(); >>
+instead relying on the internal representation.
 
 =head2 MATH LIBRARY
 
@@ -3609,20 +3777,21 @@ Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
        use Math::BigInt lib => 'Foo,Math::BigInt::Bar';
 
 Since Math::BigInt::GMP is in almost all cases faster than Calc (especially in
-cases involving really big numbers, where it is B<much> faster), and there is
+math involving really big numbers, where it is B<much> faster), and there is
 no penalty if Math::BigInt::GMP is not installed, it is a good idea to always
 use the following:
 
        use Math::BigInt lib => 'GMP';
 
 Different low-level libraries use different formats to store the
-numbers. You should not depend on the number having a specific format.
+numbers. You should B<NOT> depend on the number having a specific format
+internally.
 
 See the respective math library module documentation for further details.
 
 =head2 SIGN
 
-The sign is either '+', '-', 'NaN', '+inf' or '-inf' and stored seperately.
+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
@@ -3757,7 +3926,7 @@ more time then the actual addition.
 With a technique called copy-on-write, the cost of copying with overload could
 be minimized or even completely avoided. A test implementation of COW did show
 performance gains for overloaded math, but introduced a performance loss due
-to a constant overhead for all other operatons. So Math::BigInt does currently
+to a constant overhead for all other operations. So Math::BigInt does currently
 not COW.
 
 The rewritten version of this module (vs. v0.01) is slower on certain
@@ -3964,7 +4133,7 @@ Additionally, the following still works:
 
 There is now a C<bsstr()> method to get the string in scientific notation aka
 C<1e+2> instead of C<100>. Be advised that overloaded 'eq' always uses bstr()
-for comparisation, but Perl will represent some numbers as 100 and others
+for comparison, but Perl will represent some numbers as 100 and others
 as 1e+308. If in doubt, convert both arguments to Math::BigInt before 
 comparing them as strings:
 
@@ -3978,10 +4147,13 @@ comparing them as strings:
        $y = Math::BigInt->new($y);
        ok ($x,$y);                     # okay
 
-Alternatively, simple use C<< <=> >> for comparisations, this will get it
+Alternatively, simple use C<< <=> >> for comparisons, this will get it
 always right. There is not yet a way to get a number automatically represented
 as a string that matches exactly the way Perl represents it.
 
+See also the section about L<Infinity and Not a Number> for problems in
+comparing NaNs.
+
 =item int()
 
 C<int()> will return (at least for Perl v5.7.1 and up) another BigInt, not a 
@@ -3992,14 +4164,25 @@ Perl scalar:
        $x = Math::BigFloat->new(123.45);
        $y = int($x);                           # BigInt 123
 
-In all Perl versions you can use C<as_number()> for the same effect:
+In all Perl versions you can use C<as_number()> or C<as_int> for the same
+effect:
 
        $x = Math::BigFloat->new(123.45);
        $y = $x->as_number();                   # BigInt 123
+       $y = $x->as_int();                      # ditto
 
 This also works for other subclasses, like Math::String.
 
-It is yet unlcear whether overloaded int() should return a scalar or a BigInt.
+It is yet unclear whether overloaded int() should return a scalar or a BigInt.
+
+If you want a real Perl scalar, use C<numify()>:
+
+       $y = $x->numify();                      # 123 as scalar
+
+This is seldom necessary, though, because this is done automatically, like
+when you access an array:
+
+       $z = $array[$x];                        # does work automatically
 
 =item length
 
@@ -4020,7 +4203,7 @@ The following will probably not do what you expect:
        print $c->bdiv(10000),"\n";
 
 It prints both quotient and remainder since print calls C<bdiv()> in list
-context. Also, C<bdiv()> will modify $c, so be carefull. You probably want
+context. Also, C<bdiv()> will modify $c, so be careful. You probably want
 to use
        
        print $c / 10000,"\n";
@@ -4049,7 +4232,7 @@ manpage), and the equation
 holds true for any $x and $y, which justifies calling the two return
 values of bdiv() the quotient and remainder. The only exception to this rule
 are when $y == 0 and $x is negative, then the remainder will also be
-negative. See below under "infinity handling" for the reasoning behing this.
+negative. See below under "infinity handling" for the reasoning behind this.
 
 Perl's 'use integer;' changes the behaviour of % and / for scalars, but will
 not change BigInt's way to do things. This is because under 'use integer' Perl
@@ -4153,9 +4336,6 @@ since overload calls C<sub($x,0,1);> instead of C<neg($x)>. The first variant
 needs to preserve $x since it does not know that it later will get overwritten.
 This makes a copy of $x and takes O(N), but $x->bneg() is O(1).
 
-With Copy-On-Write, this issue would be gone, but C-o-W is not implemented
-since it is slower for all other things.
-
 =item Mixing different object types
 
 In Perl you will get a floating point value if you do one of the following:
@@ -4260,11 +4440,11 @@ subclass files and benchmarks.
 =head1 AUTHORS
 
 Original code by Mark Biggar, overloaded interface by Ilya Zakharevich.
-Completely rewritten by Tels http://bloodgate.com in late 2000, 2001 - 2003
-and still at it in 2004.
+Completely rewritten by Tels http://bloodgate.com in late 2000, 2001 - 2004
+and still at it in 2005.
 
 Many people contributed in one or more ways to the final beast, see the file
-CREDITS for an (uncomplete) list. If you miss your name, please drop me a
+CREDITS for an (incomplete) list. If you miss your name, please drop me a
 mail. Thank you!
 
 =cut