added patch for overloading constants, made PERL_OBJECT-aware
[p5sagit/p5-mst-13.2.git] / lib / Math / BigInt.pm
index 68856ae..bbd15e4 100644 (file)
@@ -36,6 +36,12 @@ sub stringify { "${$_[0]}" }
 sub numify { 0 + "${$_[0]}" }  # Not needed, additional overhead
                                # comparing to direct compilation based on
                                # stringify
+sub import {
+  shift;
+  return unless @_;
+  die "unknown import: @_" unless @_ == 1 and $_[0] eq ':constant';
+  overload::constant integer => sub {Math::BigInt->new(shift)};
+}
 
 $zero = 0;
 
@@ -106,13 +112,23 @@ sub bcmp { #(num_str, num_str) return cond_code
 
 sub cmp { # post-normalized compare for internal use
     local($cx, $cy) = @_;
-    $cx cmp $cy
-    &&
-    (
-       ord($cy) <=> ord($cx)
-       ||
-       ($cx cmp ',') * (length($cy) <=> length($cx) || $cy cmp $cx)
-    );
+    
+    return 0 if ($cx eq $cy);
+
+    local($sx, $sy) = (substr($cx, 0, 1), substr($cy, 0, 1));
+    local($ld);
+
+    if ($sx eq '+') {
+      return  1 if ($sy eq '-' || $cy eq '+0');
+      $ld = length($cx) - length($cy);
+      return $ld if ($ld);
+      return $cx cmp $cy;
+    } else { # $sx eq '-'
+      return -1 if ($sy eq '+');
+      $ld = length($cy) - length($cx);
+      return $ld if ($ld);
+      return $cy cmp $cx;
+    }
 }
 
 sub badd { #(num_str, num_str) return num_str
@@ -161,11 +177,11 @@ sub add { #(int_num_array, int_num_array) return int_num_array
     $car = 0;
     for $x (@x) {
        last unless @y || $car;
-       $x -= 1e5 if $car = (($x += shift(@y) + $car) >= 1e5);
+       $x -= 1e5 if $car = (($x += (@y ? shift(@y) : 0) + $car) >= 1e5) ? 1 : 0;
     }
     for $y (@y) {
        last unless $car;
-       $y -= 1e5 if $car = (($y += $car) >= 1e5);
+       $y -= 1e5 if $car = (($y += $car) >= 1e5) ? 1 : 0;
     }
     (@x, @y, $car);
 }
@@ -175,8 +191,8 @@ sub sub { #(int_num_array, int_num_array) return int_num_array
     local(*sx, *sy) = @_;
     $bar = 0;
     for $sx (@sx) {
-       last unless @y || $bar;
-       $sx += 1e5 if $bar = (($sx -= shift(@sy) + $bar) < 0);
+       last unless @sy || $bar;
+       $sx += 1e5 if $bar = (($sx -= (@sy ? shift(@sy) : 0) + $bar) < 0);
     }
     @sx;
 }
@@ -204,7 +220,7 @@ sub mul { #(*int_num_array, *int_num_array) return int_num_array
     for $x (@x) {
       ($car, $cty) = (0, $[);
       for $y (@y) {
-       $prod = $x * $y + $prod[$cty] + $car;
+       $prod = $x * $y + ($prod[$cty] || 0) + $car;
        $prod[$cty++] =
          $prod - ($car = int($prod * 1e-5)) * 1e5;
       }
@@ -374,6 +390,19 @@ are not numbers, as well as the result of dividing by zero.
    '1 23 456 7890'                 canonical value '+1234567890'
 
 
+=head1 Autocreating constants
+
+After C<use Math::BigInt ':constant'> all the integer decimal constants
+in the given scope are converted to C<Math::BigInt>.  This convertion
+happens at compile time.
+
+In particular
+
+  perl -MMath::BigInt=:constant -e 'print 2**100'
+
+print the integer value of C<2**100>.  Note that without convertion of 
+constants the expression 2**100 will be calculatted as floating point number.
+
 =head1 BUGS
 
 The current version of this module is a preliminary version of the