Re: [PATCH] Math::BigInt v1.87 take 5
Tels [Sun, 27 May 2007 15:54:29 +0000 (15:54 +0000)]
Message-Id: <200705271554.32054@bloodgate.com>

p4raw-id: //depot/perl@31285

lib/Math/BigFloat.pm
lib/Math/BigInt.pm
lib/Math/BigInt/Calc.pm
lib/Math/BigInt/t/bigfltpm.t

index b767766..3158590 100644 (file)
@@ -16,7 +16,7 @@ $VERSION = '1.58';
 require 5.006002;
 
 require Exporter;
-@ISA =       qw(Exporter Math::BigInt);
+@ISA =       qw(Math::BigInt);
 
 use strict;
 # $_trap_inf/$_trap_nan are internal and should never be accessed from outside
@@ -3160,7 +3160,7 @@ These are effectively no-ops.
 =back
 
 All rounding functions take as a second parameter a rounding mode from one of
-the following: 'even', 'odd', '+inf', '-inf', 'zero' or 'trunc'.
+the following: 'even', 'odd', '+inf', '-inf', 'zero', 'trunc' or 'common'.
 
 The default rounding mode is 'even'. By using
 C<< Math::BigFloat->round_mode($round_mode); >> you can get and set the default
@@ -3183,6 +3183,11 @@ C<as_number()>:
 
 =head1 METHODS
 
+Math::BigFloat supports all methods that Math::BigInt supports, except it
+calculates non-integer results when possible. Please see L<Math::BigInt>
+for a full description of each method. Below are just the most important
+differences:
+
 =head2 accuracy
 
         $x->accuracy(5);                # local for $x
@@ -3224,6 +3229,27 @@ 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!
 
+=head2 bexp()
+
+       $x->bexp($accuracy);            # calculate e ** X
+
+Calculates the expression C<e ** $x> where C<e> is Euler's number.
+
+This method was added in v1.82 of Math::BigInt (April 2007).
+
+=head2 bnok()
+
+       $x->bnok($y);              # x over y (binomial coefficient n over k)
+
+Calculates the binomial coefficient n over k, also called the "choose"
+function. The result is equivalent to:
+
+       ( n )      n!
+       | - |  = -------
+       ( k )    k!(n-k)!
+
+This method was added in v1.84 of Math::BigInt (April 2007).
+
 =head1 Autocreating constants
 
 After C<use Math::BigFloat ':constant'> all the floating point constants
@@ -3251,19 +3277,14 @@ Math::BigInt::Calc. This is equivalent to saying:
 
 You can change this by using:
 
-       use Math::BigFloat lib => 'BitVect';
+       use Math::BigFloat 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 Math::BigFloat lib => 'Foo,Math::BigInt::Bar';
 
-Calc.pm uses as internal format an array of elements of some decimal base
-(usually 1e7, but this might be different for some systems) with the least
-significant digit first, while BitVect.pm uses a bit vector of base 2, most
-significant bit first. Other modules might use even different means of
-representing the numbers. See the respective module documentation for further
-details.
+See the respective low-level library documentation for further details.
 
 Please note that Math::BigFloat does B<not> use the denoted library itself,
 but it merely passes the lib argument to Math::BigInt. So, instead of the need
@@ -3283,108 +3304,37 @@ It is also possible to just require Math::BigFloat:
 This will load the necessary things (like BigInt) when they are needed, and
 automatically.
 
-Use the lib, Luke! And see L<Using Math::BigInt::Lite> for more details than
-you ever wanted to know about loading a different library.
+See L<Math::BigInt> for more details than you ever wanted to know about using
+a different low-level library.
 
 =head2 Using Math::BigInt::Lite
 
-It is possible to use L<Math::BigInt::Lite> with Math::BigFloat:
+For backwards compatibility reasons it is still possible to
+request a different storage class for use with Math::BigFloat:
 
-        # 1
         use Math::BigFloat with => 'Math::BigInt::Lite';
 
-There is no need to "use Math::BigInt" or "use Math::BigInt::Lite", but you
-can combine these if you want. For instance, you may want to use
-Math::BigInt objects in your main script, too.
-
-        # 2
-        use Math::BigInt;
-        use Math::BigFloat with => 'Math::BigInt::Lite';
-
-Of course, you can combine this with the C<lib> parameter.
-
-        # 3
-        use Math::BigFloat with => 'Math::BigInt::Lite', lib => 'GMP,Pari';
-
-There is no need for a "use Math::BigInt;" statement, even if you want to
-use Math::BigInt's, since Math::BigFloat will needs Math::BigInt and thus
-always loads it. But if you add it, add it B<before>:
-
-        # 4
-        use Math::BigInt;
-        use Math::BigFloat with => 'Math::BigInt::Lite', lib => 'GMP,Pari';
-
-Notice that the module with the last C<lib> will "win" and thus
-it's lib will be used if the lib is available:
-
-        # 5
-        use Math::BigInt lib => 'Bar,Baz';
-        use Math::BigFloat with => 'Math::BigInt::Lite', lib => 'Foo';
-
-That would try to load Foo, Bar, Baz and Calc (in that order). Or in other
-words, Math::BigFloat will try to retain previously loaded libs when you
-don't specify it onem but if you specify one, it will try to load them.
+However, this request is ignored, as the current code now uses the low-level
+math libary for directly storing the number parts.
 
-Actually, the lib loading order would be "Bar,Baz,Calc", and then
-"Foo,Bar,Baz,Calc", but independent of which lib exists, the result is the
-same as trying the latter load alone, except for the fact that one of Bar or
-Baz might be loaded needlessly in an intermidiate step (and thus hang around
-and waste memory). If neither Bar nor Baz exist (or don't work/compile), they
-will still be tried to be loaded, but this is not as time/memory consuming as
-actually loading one of them. Still, this type of usage is not recommended due
-to these issues.
-
-The old way (loading the lib only in BigInt) still works though:
-
-        # 6
-        use Math::BigInt lib => 'Bar,Baz';
-        use Math::BigFloat;
-
-You can even load Math::BigInt afterwards:
-
-        # 7
-        use Math::BigFloat;
-        use Math::BigInt lib => 'Bar,Baz';
-
-But this has the same problems like #5, it will first load Calc
-(Math::BigFloat needs Math::BigInt and thus loads it) and then later Bar or
-Baz, depending on which of them works and is usable/loadable. Since this
-loads Calc unnec., it is not recommended.
-
-Since it also possible to just require Math::BigFloat, this poses the question
-about what libary this will use:
-
-       require Math::BigFloat;
-       my $x = Math::BigFloat->new(123); $x += 123;
-
-It will use Calc. Please note that the call to import() is still done, but
-only when you use for the first time some Math::BigFloat math (it is triggered
-via any constructor, so the first time you create a Math::BigFloat, the load
-will happen in the background). This means:
-
-       require Math::BigFloat;
-       Math::BigFloat->import ( lib => 'Foo,Bar' );
+=head1 BUGS
 
-would be the same as:
+Please see the file BUGS in the CPAN distribution Math::BigInt for known bugs.
 
-       use Math::BigFloat lib => 'Foo, Bar';
+=head1 CAVEATS
 
-But don't try to be clever to insert some operations in between:
+Do not try to be clever to insert some operations in between switching
+libraries:
 
        require Math::BigFloat;
-       my $x = Math::BigFloat->bone() + 4;             # load BigInt and Calc
+       my $matter = Math::BigFloat->bone() + 4;        # load BigInt and Calc
        Math::BigFloat->import( lib => 'Pari' );        # load Pari, too
-       $x = Math::BigFloat->bone()+4;                  # now use Pari
-
-While this works, it loads Calc needlessly. But maybe you just wanted that?
+       my $anti-matter = Math::BigFloat->bone()+4;     # now use Pari
 
-B<Examples #3 is highly recommended> for daily usage.
+This will create objects with numbers stored in two different backend libraries,
+and B<VERY BAD THINGS> will happen when you use these together:
 
-=head1 BUGS
-
-Please see the file BUGS in the CPAN distribution Math::BigInt for known bugs.
-
-=head1 CAVEATS
+       my $flash_and_bang = $matter + $anti_matter;    # Don't do this!
 
 =over 1
 
index 23454a6..24bac30 100644 (file)
@@ -865,6 +865,10 @@ sub _find_round_parameters
   my $c = ref($self);                          # find out class of argument(s)
   no strict 'refs';
 
+  # convert to normal scalar for speed and correctness in inner parts
+  $a = $a->numify() if defined $a && ref($a);
+  $p = $p->numify() if defined $a && ref($p);
+
   # now pick $a or $p, but only if we have got "arguments"
   if (!defined $a)
     {
@@ -3380,7 +3384,7 @@ and '-inf', respectively. Does nothing for NaN or zero.
 
        $x->babs();
 
-Set the number to it's absolute value, e.g. change the sign from '-' to '+'
+Set the number to its absolute value, e.g. change the sign from '-' to '+'
 and from '-inf' to '+inf', respectively. Does nothing for NaN or positive
 numbers.
 
@@ -3392,7 +3396,7 @@ numbers.
 
        $x->bnot();                     
 
-Two's complement (bit wise not). This is equivalent to
+Two's complement (bitwise not). This is equivalent to
 
        $x->binc()->bneg();
 
@@ -3870,7 +3874,7 @@ This is how it works now:
 
 =item Creating numbers
 
-  * When you create a number, you can give it's desired A or P via:
+  * When you create a number, you can give the desired A or P via:
     $x = Math::BigInt->new($number,$A,$P);
   * Only one of A or P can be defined, otherwise the result is NaN
   * If no A or P is give ($x = Math::BigInt->new($number) form), then the
@@ -3879,7 +3883,7 @@ This is how it works now:
     $x will be what was in effect when $x was created)
   * If given undef for A and P, B<no> rounding will occur, and the globals will
     B<not> be used. This is used by subclasses to create numbers without
-    suffering rounding in the parent. Thus a subclass is able to have it's own
+    suffering rounding in the parent. Thus a subclass is able to have its own
     globals enforced upon creation of a number by using
     C<< $x = Math::BigInt->new($number,undef,undef) >>:
 
@@ -4305,7 +4309,7 @@ needs to merely change the output only needs to overload C<bstr()>.
 All other object methods and overloaded functions can be directly inherited
 from the parent class.
 
-At the very minimum, any subclass will need to provide it's own C<new()> and can
+At the very minimum, any subclass will need to provide its own C<new()> and can
 store additional hash keys in the object. There are also some package globals
 that must be defined, e.g.:
 
@@ -4418,7 +4422,7 @@ Both C<bstr()> and C<bsstr()> as well as automated stringify via overload now
 drop the leading '+'. The old code would return '+3', the new returns '3'.
 This is to be consistent with Perl and to make C<cmp> (especially with
 overloading) to work as you expect. It also solves problems with C<Test.pm>,
-because it's C<ok()> uses 'eq' internally. 
+because its C<ok()> uses 'eq' internally. 
 
 Mark Biggar said, when asked about to drop the '+' altogether, or make only
 C<cmp> work:
index 61bda7d..0dba174 100644 (file)
@@ -1790,13 +1790,11 @@ sub _log_int
     return ($x,undef);
     }
 
-  # this trial multiplication is very fast, even for large counts (like for
-  # 2 ** 1024, since this still requires only 1024 very fast steps
-  # (multiplication of a large number by a very small number is very fast))
   my $x_org = _copy($c,$x);            # preserve x
   splice(@$x,1); $x->[0] = 1;          # keep ref to $x
 
-  # compute int ( length_in_base_10(X) / ( log(base) / log(10) ) )
+  # Compute a guess for the result based on:
+  # $guess = int ( length_in_base_10(X) / ( log(base) / log(10) ) )
   my $len = _len($c,$x_org);
   my $log = log($base->[-1]) / log(10);
 
index 0c32908..69686d0 100755 (executable)
@@ -27,7 +27,7 @@ BEGIN
   print "# INC = @INC\n";
 
   plan tests => 2064
-       + 3;            # own tests
+       + 5;            # own tests
   }
 
 use Math::BigInt lib => 'Calc';
@@ -41,7 +41,14 @@ ok ($class->config()->{class},$class);
 ok ($class->config()->{with}, $CL);
 
 # bug #17447: Can't call method Math::BigFloat->bsub, not a valid method
-my $c = new Math::BigFloat( '123.3' );
+my $c = Math::BigFloat->new( '123.3' );
 ok ($c->fsub(123) eq '0.3', 1); # calling fsub on a BigFloat works
+
+# Bug until BigInt v1.86, the scale wasn't treated as a scalar:
+$c = Math::BigFloat->new('0.008'); my $d = Math::BigFloat->new(3);
+my $e = $c->bdiv(Math::BigFloat->new(3),$d);
+
+ok ($e,'0.00267'); # '0.008 / 3 => 0.0027');
+ok (ref($e->{_e}->[0]), ''); # 'Not a BigInt');
+
 require 'bigfltpm.inc';        # all tests here for sharing