From: Tels Date: Sun, 27 May 2007 15:54:29 +0000 (+0000) Subject: Re: [PATCH] Math::BigInt v1.87 take 5 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=86b762011e902edec7ae61d0884c0d4fab62cfeb;p=p5sagit%2Fp5-mst-13.2.git Re: [PATCH] Math::BigInt v1.87 take 5 Message-Id: <200705271554.32054@bloodgate.com> p4raw-id: //depot/perl@31285 --- diff --git a/lib/Math/BigFloat.pm b/lib/Math/BigFloat.pm index b767766..3158590 100644 --- a/lib/Math/BigFloat.pm +++ b/lib/Math/BigFloat.pm @@ -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: =head1 METHODS +Math::BigFloat supports all methods that Math::BigInt supports, except it +calculates non-integer results when possible. Please see L +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 instead. With L you set the number of digits each result should have, with L you set the place where to round! +=head2 bexp() + + $x->bexp($accuracy); # calculate e ** X + +Calculates the expression C where C 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 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 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 for more details than -you ever wanted to know about loading a different library. +See L 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 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 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: - - # 4 - use Math::BigInt; - use Math::BigFloat with => 'Math::BigInt::Lite', lib => 'GMP,Pari'; - -Notice that the module with the last C 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 for daily usage. +This will create objects with numbers stored in two different backend libraries, +and B 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 diff --git a/lib/Math/BigInt.pm b/lib/Math/BigInt.pm index 23454a6..24bac30 100644 --- a/lib/Math/BigInt.pm +++ b/lib/Math/BigInt.pm @@ -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 rounding will occur, and the globals will B 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. 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 and can +At the very minimum, any subclass will need to provide its own C 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 and C 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 (especially with overloading) to work as you expect. It also solves problems with C, -because it's C uses 'eq' internally. +because its C uses 'eq' internally. Mark Biggar said, when asked about to drop the '+' altogether, or make only C work: diff --git a/lib/Math/BigInt/Calc.pm b/lib/Math/BigInt/Calc.pm index 61bda7d..0dba174 100644 --- a/lib/Math/BigInt/Calc.pm +++ b/lib/Math/BigInt/Calc.pm @@ -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); diff --git a/lib/Math/BigInt/t/bigfltpm.t b/lib/Math/BigInt/t/bigfltpm.t index 0c32908..69686d0 100755 --- a/lib/Math/BigInt/t/bigfltpm.t +++ b/lib/Math/BigInt/t/bigfltpm.t @@ -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