# _a : accuracy
# _p : precision
-$VERSION = '1.59';
+$VERSION = '1.60';
require 5.006;
require Exporter;
# But we need at least $scale digits, so calculate how many are missing
my $shift = $scale - $digits;
- # That should never happen (we take care of integer guesses above)
- # $shift = 0 if $shift < 0;
+ # This happens if the input had enough digits
+ # (we take care of integer guesses above)
+ $shift = 0 if $shift < 0;
# Multiply in steps of 100, by shifting left two times the "missing" digits
my $s2 = $shift * 2;
return $y->bnan() if ($y->{sign} eq $nan) || ($x->{sign} eq $nan);
- return $upgrade->new($y)->batan2($upgrade->new($x),@r) if defined $upgrade;
-
# Y X
# 0 0 result is 0
# 0 +x result is 0
- return $y->bzero(@r) if $y->is_zero() && $x->{sign} eq '+';
+ # ? inf result is 0
+ return $y->bzero(@r) if ($x->is_inf('+') && !$y->is_inf()) || ($y->is_zero() && $x->{sign} eq '+');
+
+ # Y X
+ # != 0 -inf result is +- pi
+ if ($x->is_inf() || $y->is_inf())
+ {
+ # calculate PI
+ my $pi = $self->bpi(@r);
+ if ($y->is_inf())
+ {
+ # upgrade to BigRat etc.
+ return $upgrade->new($y)->batan2($upgrade->new($x),@r) if defined $upgrade;
+ if ($x->{sign} eq '-inf')
+ {
+ # calculate 3 pi/4
+ $MBI->_mul($pi->{_m}, $MBI->_new(3));
+ $MBI->_div($pi->{_m}, $MBI->_new(4));
+ }
+ elsif ($x->{sign} eq '+inf')
+ {
+ # calculate pi/4
+ $MBI->_div($pi->{_m}, $MBI->_new(4));
+ }
+ else
+ {
+ # calculate pi/2
+ $MBI->_div($pi->{_m}, $MBI->_new(2));
+ }
+ $y->{sign} = substr($y->{sign},0,1); # keep +/-
+ }
+ # modify $y in place
+ $y->{_m} = $pi->{_m};
+ $y->{_e} = $pi->{_e};
+ $y->{_es} = $pi->{_es};
+ # keep the sign of $y
+ return $y;
+ }
+
+ return $upgrade->new($y)->batan2($upgrade->new($x),@r) if defined $upgrade;
# Y X
# 0 -x result is PI
{
# calculate PI
my $pi = $self->bpi(@r);
- # modify $x in place
+ # modify $y in place
$y->{_m} = $pi->{_m};
$y->{_e} = $pi->{_e};
$y->{_es} = $pi->{_es};
# Y X
# +y 0 result is PI/2
# -y 0 result is -PI/2
- if ($y->is_inf() || $x->is_zero())
+ if ($x->is_zero())
{
# calculate PI/2
my $pi = $self->bpi(@r);
- # modify $x in place
+ # modify $y in place
$y->{_m} = $pi->{_m};
$y->{_e} = $pi->{_e};
$y->{_es} = $pi->{_es};
# -y => -PI/2, +y => PI/2
- $y->{sign} = substr($y->{sign},0,1); # +inf => +
$MBI->_div($y->{_m}, $MBI->_new(2));
return $y;
}
{
# 1,1 => PI/4
my $pi_4 = $self->bpi( $scale - 3);
- # modify $x in place
+ # modify $y in place
$y->{_m} = $pi_4->{_m};
$y->{_e} = $pi_4->{_e};
$y->{_es} = $pi_4->{_es};
return $x if $x->modify('as_number');
+ if (!$x->isa('Math::BigFloat'))
+ {
+ # if the object can as_number(), use it
+ return $x->as_number() if $x->can('as_number');
+ # otherwise, get us a float and then a number
+ $x = $x->can('as_float') ? $x->as_float() : $self->new(0+"$x");
+ }
+
my $z = $MBI->_copy($x->{_m});
if ($x->{_es} eq '-') # < 0
{
use Math::BigFloat lib => 'GMP';
+B<Note>: General purpose packages should not be explicit about the library
+to use; let the script author decide which is best.
+
Note: The keyword 'lib' will warn when the requested library could not be
loaded. To suppress the warning use 'try' instead:
use Math::BigFloat try => 'GMP';
-To turn the warning into a die(), use 'only' instead:
+If your script works with huge numbers and Calc is too slow for them,
+you can also for the loading of one of these libraries and if none
+of them can be used, the code will die:
- use Math::BigFloat only => 'GMP';
+ use Math::BigFloat only => 'GMP,Pari';
The following would first try to find Math::BigInt::Foo, then
Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
my $class = "Math::BigInt";
use 5.006;
-$VERSION = '1.88';
+$VERSION = '1.89';
@ISA = qw(Exporter);
@EXPORT_OK = qw(objectify bgcd blcm);
return $y->bnan() if ($y->{sign} eq $nan) || ($x->{sign} eq $nan);
- return $y->bzero() if $y->is_zero() && $x->{sign} eq '+'; # x >= 0
-
- # inf handling
- # +-inf => --PI/2 => +-1
- return $y->bone( substr($y->{sign},0,1) ) if $y->{sign} =~ /^[+-]inf$/;
+ # Y X
+ # != 0 -inf result is +- pi
+ if ($x->is_inf() || $y->is_inf())
+ {
+ # upgrade to BigFloat etc.
+ return $upgrade->new($y)->batan2($upgrade->new($x),@r) if defined $upgrade;
+ if ($y->is_inf())
+ {
+ if ($x->{sign} eq '-inf')
+ {
+ # calculate 3 pi/4 => 2.3.. => 2
+ $y->bone( substr($y->{sign},0,1) );
+ $y->bmul($self->new(2));
+ }
+ elsif ($x->{sign} eq '+inf')
+ {
+ # calculate pi/4 => 0.7 => 0
+ $y->bzero();
+ }
+ else
+ {
+ # calculate pi/2 => 1.5 => 1
+ $y->bone( substr($y->{sign},0,1) );
+ }
+ }
+ else
+ {
+ if ($x->{sign} eq '+inf')
+ {
+ # calculate pi/4 => 0.7 => 0
+ $y->bzero();
+ }
+ else
+ {
+ # PI => 3.1415.. => 3
+ $y->bone( substr($y->{sign},0,1) );
+ $y->bmul($self->new(3));
+ }
+ }
+ return $y;
+ }
return $upgrade->new($y)->batan2($upgrade->new($x),@r) if defined $upgrade;
use Math::BigInt;
- # or make it faster: install (optional) Math::BigInt::GMP
- # and always use (it will fall back to pure Perl if the
- # GMP library is not installed):
+ # or make it faster with huge numbers: install (optional)
+ # Math::BigInt::GMP and always use (it will fall back to
+ # pure Perl if the GMP library is not installed):
+ # (See also the L<MATH LIBRARY> section!)
# will warn if Math::BigInt::GMP cannot be found
use Math::BigInt lib => 'GMP';
# to supress the warning use this:
# use Math::BigInt try => 'GMP';
+ # dies if GMP cannot be loaded:
+ # use Math::BigInt only => 'GMP';
+
my $str = '1234567890';
my @values = (64,74,18);
my $n = 1; my $sign = '-';
Math with the numbers is done (by default) by a module called
C<Math::BigInt::Calc>. This is equivalent to saying:
- use Math::BigInt lib => 'Calc';
+ use Math::BigInt try => 'Calc';
+
+You can change this backend library by using:
-You can change this by using:
+ use Math::BigInt try => 'GMP';
- use Math::BigInt lib => 'BitVect';
+B<Note>: General purpose packages should not be explicit about the library
+to use; let the script author decide which is best.
+
+If your script works with huge numbers and Calc is too slow for them,
+you can also for the loading of one of these libraries and if none
+of them can be used, the code will die:
+
+ use Math::BigInt only => 'GMP,Pari';
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::BigInt lib => 'Foo,Math::BigInt::Bar';
+ use Math::BigInt try => 'Foo,Math::BigInt::Bar';
+
+The library that is loaded last will be used. Note that this can be
+overwritten at any time by loading a different library, and numbers
+constructed with different libraries cannot be used in math operations
+together.
+
+=head3 What library to use?
-Since Math::BigInt::GMP is in almost all cases faster than Calc (especially in
-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:
+B<Note>: General purpose packages should not be explicit about the library
+to use; let the script author decide which is best.
- use Math::BigInt lib => 'GMP';
+L<Math::BigInt::GMP> and L<Math::BigInt::Pari> are in cases involving big
+numbers much faster than Calc, however it is slower when dealing with very
+small numbers (less than about 20 digits) and when converting very large
+numbers to decimal (for instance for printing, rounding, calculating their
+length in decimal etc).
-Different low-level libraries use different formats to store the
-numbers. You should B<NOT> depend on the number having a specific format
+So please select carefully what libary you want to use.
+
+Different low-level libraries use different formats to store the numbers.
+However, you should B<NOT> depend on the number having a specific format
internally.
See the respective math library module documentation for further details.
=head2 Alternative math libraries
-You can use an alternative library to drive Math::BigInt via:
-
- use Math::BigInt lib => 'Module';
-
-See L<MATH LIBRARY> for more information.
+You can use an alternative library to drive Math::BigInt. See the section
+L<MATH LIBRARY> for more information.
For more benchmark results see L<http://bloodgate.com/perl/benchmarks.html>.