Change 33821 by [EMAIL PROTECTED] on 2008/05/11 11:19:32
Integrate:
[ 33666]
Subject: [PATCH] Math::BigRat 0.22
From: Tels <[EMAIL PROTECTED]>
Date: Mon, 7 Apr 2008 21:27:30 +0200
Message-Id: <[EMAIL PROTECTED]>
[ 33698]
Upgrade to Math::Complex 1.54
[ 33715]
Upgrade to Math::BigInt v1.89
[ 33772]
Upgrade to bignum-0.23
Affected files ...
... //depot/maint-5.10/perl/MANIFEST#21 integrate
... //depot/maint-5.10/perl/lib/Math/BigFloat.pm#2 integrate
... //depot/maint-5.10/perl/lib/Math/BigInt.pm#2 integrate
... //depot/maint-5.10/perl/lib/Math/BigInt/t/bare_mbf.t#2 integrate
... //depot/maint-5.10/perl/lib/Math/BigInt/t/bare_mbi.t#2 integrate
... //depot/maint-5.10/perl/lib/Math/BigInt/t/bigfltpm.inc#2 integrate
... //depot/maint-5.10/perl/lib/Math/BigInt/t/bigfltpm.t#2 integrate
... //depot/maint-5.10/perl/lib/Math/BigInt/t/bigintpm.inc#2 integrate
... //depot/maint-5.10/perl/lib/Math/BigInt/t/bigintpm.t#2 integrate
... //depot/maint-5.10/perl/lib/Math/BigInt/t/calling.t#2 integrate
... //depot/maint-5.10/perl/lib/Math/BigInt/t/const_mbf.t#2 integrate
... //depot/maint-5.10/perl/lib/Math/BigInt/t/constant.t#2 integrate
... //depot/maint-5.10/perl/lib/Math/BigInt/t/mbimbf.t#2 integrate
... //depot/maint-5.10/perl/lib/Math/BigInt/t/sub_mbf.t#2 integrate
... //depot/maint-5.10/perl/lib/Math/BigInt/t/sub_mbi.t#2 integrate
... //depot/maint-5.10/perl/lib/Math/BigInt/t/with_sub.t#2 integrate
... //depot/maint-5.10/perl/lib/Math/BigRat.pm#2 integrate
... //depot/maint-5.10/perl/lib/Math/BigRat/t/biglog.t#2 integrate
... //depot/maint-5.10/perl/lib/Math/BigRat/t/bigrat.t#2 integrate
... //depot/maint-5.10/perl/lib/Math/BigRat/t/bigroot.t#2 integrate
... //depot/maint-5.10/perl/lib/Math/BigRat/t/hang.t#1 branch
... //depot/maint-5.10/perl/lib/Math/Complex.pm#5 integrate
... //depot/maint-5.10/perl/lib/Math/Complex.t#5 integrate
... //depot/maint-5.10/perl/lib/Math/Trig.pm#5 integrate
... //depot/maint-5.10/perl/lib/Math/Trig.t#5 integrate
... //depot/maint-5.10/perl/lib/bigint.pm#2 integrate
... //depot/maint-5.10/perl/lib/bignum.pm#2 integrate
... //depot/maint-5.10/perl/lib/bigrat.pm#2 integrate
Differences ...
==== //depot/maint-5.10/perl/MANIFEST#21 (text) ====
Index: perl/MANIFEST
--- perl/MANIFEST#20~33801~ 2008-05-10 06:34:11.000000000 -0700
+++ perl/MANIFEST 2008-05-11 04:19:32.000000000 -0700
@@ -2118,6 +2118,7 @@
lib/Math/BigRat/t/bigrat.t Math::BigRat test
lib/Math/BigRat/t/bigratup.t test under $Math::BigInt::upgrade
lib/Math/BigRat/t/bigroot.t Math::BigRat test
+lib/Math/BigRat/t/hang.t Math::BigRat test for bug #34584 - hang
in exp()
lib/Math/BigRat/t/requirer.t see if require works properly
lib/Math/BigRat/t/trap.t see if trap_nan and trap_inf work
lib/Math/Complex.pm A Complex package
==== //depot/maint-5.10/perl/lib/Math/BigFloat.pm#2 (text) ====
Index: perl/lib/Math/BigFloat.pm
--- perl/lib/Math/BigFloat.pm#1~32694~ 2007-12-22 01:23:09.000000000 -0800
+++ perl/lib/Math/BigFloat.pm 2008-05-11 04:19:32.000000000 -0700
@@ -12,7 +12,7 @@
# _a : accuracy
# _p : precision
-$VERSION = '1.59';
+$VERSION = '1.60';
require 5.006;
require Exporter;
@@ -2142,8 +2142,9 @@
# 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;
@@ -2846,12 +2847,49 @@
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
@@ -2859,7 +2897,7 @@
{
# 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};
@@ -2870,16 +2908,15 @@
# 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;
}
@@ -2918,7 +2955,7 @@
{
# 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};
@@ -3639,6 +3676,14 @@
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
{
@@ -4146,14 +4191,19 @@
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:
==== //depot/maint-5.10/perl/lib/Math/BigInt.pm#2 (text) ====
Index: perl/lib/Math/BigInt.pm
--- perl/lib/Math/BigInt.pm#1~32694~ 2007-12-22 01:23:09.000000000 -0800
+++ perl/lib/Math/BigInt.pm 2008-05-11 04:19:32.000000000 -0700
@@ -18,7 +18,7 @@
my $class = "Math::BigInt";
use 5.006;
-$VERSION = '1.88';
+$VERSION = '1.89';
@ISA = qw(Exporter);
@EXPORT_OK = qw(objectify bgcd blcm);
@@ -3000,11 +3000,47 @@
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;
@@ -3056,9 +3092,10 @@
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';
@@ -3066,6 +3103,9 @@
# 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 = '-';
@@ -4390,26 +4430,46 @@
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.
@@ -4571,11 +4631,8 @@
=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>.
==== //depot/maint-5.10/perl/lib/Math/BigInt/t/bare_mbf.t#2 (text) ====
Index: perl/lib/Math/BigInt/t/bare_mbf.t
--- perl/lib/Math/BigInt/t/bare_mbf.t#1~32694~ 2007-12-22 01:23:09.000000000
-0800
+++ perl/lib/Math/BigInt/t/bare_mbf.t 2008-05-11 04:19:32.000000000 -0700
@@ -27,7 +27,7 @@
}
print "# INC = @INC\n";
- plan tests => 2292;
+ plan tests => 2308;
}
use Math::BigFloat lib => 'BareCalc';
==== //depot/maint-5.10/perl/lib/Math/BigInt/t/bare_mbi.t#2 (text) ====
Index: perl/lib/Math/BigInt/t/bare_mbi.t
--- perl/lib/Math/BigInt/t/bare_mbi.t#1~32694~ 2007-12-22 01:23:09.000000000
-0800
+++ perl/lib/Math/BigInt/t/bare_mbi.t 2008-05-11 04:19:32.000000000 -0700
@@ -26,7 +26,7 @@
}
print "# INC = @INC\n";
- plan tests => 3257;
+ plan tests => 3273;
}
use Math::BigInt lib => 'BareCalc';
==== //depot/maint-5.10/perl/lib/Math/BigInt/t/bigfltpm.inc#2 (text) ====
Index: perl/lib/Math/BigInt/t/bigfltpm.inc
--- perl/lib/Math/BigInt/t/bigfltpm.inc#1~32694~ 2007-12-22
01:23:09.000000000 -0800
+++ perl/lib/Math/BigInt/t/bigfltpm.inc 2008-05-11 04:19:32.000000000 -0700
@@ -450,6 +450,14 @@
1:NaN:10:NaN
inf:1:14:1.5707963267949
-inf:1:14:-1.5707963267949
+0:-inf:14:3.1415926535898
+-1:-inf:14:-3.1415926535898
+1:-inf:14:3.1415926535898
+0:inf:14:0
+inf:-inf:14:2.3561944901923
+-inf:-inf:14:-2.3561944901923
+inf:+inf:14:0.7853981633974
+-inf:+inf:14:-0.7853981633974
1:5:13:0.1973955598499
1:5:14:0.19739555984988
0:0:10:0
==== //depot/maint-5.10/perl/lib/Math/BigInt/t/bigfltpm.t#2 (xtext) ====
Index: perl/lib/Math/BigInt/t/bigfltpm.t
--- perl/lib/Math/BigInt/t/bigfltpm.t#1~32694~ 2007-12-22 01:23:09.000000000
-0800
+++ perl/lib/Math/BigInt/t/bigfltpm.t 2008-05-11 04:19:32.000000000 -0700
@@ -26,7 +26,7 @@
}
print "# INC = @INC\n";
- plan tests => 2292
+ plan tests => 2308
+ 5; # own tests
}
==== //depot/maint-5.10/perl/lib/Math/BigInt/t/bigintpm.inc#2 (text) ====
Index: perl/lib/Math/BigInt/t/bigintpm.inc
--- perl/lib/Math/BigInt/t/bigintpm.inc#1~32694~ 2007-12-22
01:23:09.000000000 -0800
+++ perl/lib/Math/BigInt/t/bigintpm.inc 2008-05-11 04:19:32.000000000 -0700
@@ -2304,6 +2304,15 @@
1:NaN:10:NaN
inf:1:14:1
-inf:1:14:-1
+0:-inf:14:3
+-1:-inf:14:-3
+1:-inf:14:3
+0:inf:14:0
+inf:-inf:14:2
+-inf:-inf:14:-2
+# +- 0.78....
+inf:+inf:14:0
+-inf:+inf:14:0
1:5:13:0
1:5:14:0
0:0:10:0
==== //depot/maint-5.10/perl/lib/Math/BigInt/t/bigintpm.t#2 (xtext) ====
Index: perl/lib/Math/BigInt/t/bigintpm.t
--- perl/lib/Math/BigInt/t/bigintpm.t#1~32694~ 2007-12-22 01:23:09.000000000
-0800
+++ perl/lib/Math/BigInt/t/bigintpm.t 2008-05-11 04:19:32.000000000 -0700
@@ -10,7 +10,7 @@
my $location = $0; $location =~ s/bigintpm.t//;
unshift @INC, $location; # to locate the testing files
chdir 't' if -d 't';
- plan tests => 3257 + 6;
+ plan tests => 3273 + 6;
}
use Math::BigInt lib => 'Calc';
==== //depot/maint-5.10/perl/lib/Math/BigInt/t/calling.t#2 (text) ====
Index: perl/lib/Math/BigInt/t/calling.t
--- perl/lib/Math/BigInt/t/calling.t#1~32694~ 2007-12-22 01:23:09.000000000
-0800
+++ perl/lib/Math/BigInt/t/calling.t 2008-05-11 04:19:32.000000000 -0700
@@ -32,11 +32,6 @@
print "# INC = @INC\n";
my $tests = 160;
plan tests => $tests;
- if ($] < 5.006)
- {
- for (1..$tests) { skip (1,'Not supported on older Perls'); }
- exit;
- }
}
package Math::BigInt::Test;
==== //depot/maint-5.10/perl/lib/Math/BigInt/t/const_mbf.t#2 (text) ====
Index: perl/lib/Math/BigInt/t/const_mbf.t
--- perl/lib/Math/BigInt/t/const_mbf.t#1~32694~ 2007-12-22 01:23:09.000000000
-0800
+++ perl/lib/Math/BigInt/t/const_mbf.t 2008-05-11 04:19:32.000000000 -0700
@@ -29,11 +29,6 @@
print "# INC = @INC\n";
plan tests => 2;
- if ($] < 5.006)
- {
- for (1..2) { skip (1,'Not supported on older Perls'); }
- exit;
- }
}
use Math::BigFloat ':constant';
==== //depot/maint-5.10/perl/lib/Math/BigInt/t/constant.t#2 (text) ====
Index: perl/lib/Math/BigInt/t/constant.t
--- perl/lib/Math/BigInt/t/constant.t#1~32694~ 2007-12-22 01:23:09.000000000
-0800
+++ perl/lib/Math/BigInt/t/constant.t 2008-05-11 04:19:32.000000000 -0700
@@ -27,11 +27,6 @@
print "# INC = @INC\n";
plan tests => 7;
- if ($] < 5.006)
- {
- for (1..7) { skip (1,'Not supported on older Perls'); }
- exit;
- }
}
use Math::BigInt ':constant';
==== //depot/maint-5.10/perl/lib/Math/BigInt/t/mbimbf.t#2 (text) ====
Index: perl/lib/Math/BigInt/t/mbimbf.t
--- perl/lib/Math/BigInt/t/mbimbf.t#1~32694~ 2007-12-22 01:23:09.000000000
-0800
+++ perl/lib/Math/BigInt/t/mbimbf.t 2008-05-11 04:19:32.000000000 -0700
@@ -32,7 +32,7 @@
print "# INC = @INC\n";
plan tests => 684
- + 23; # own tests
+ + 26; # own tests
}
use Math::BigInt 1.70;
@@ -100,3 +100,11 @@
$x = $x->blog(Math::BigInt->new(10));
ok ($x,2);
+
+# bug until v1.88 for sqrt() with enough digits
+for my $i (80,88,100)
+ {
+ $x = Math::BigFloat->new("1." . ("0" x $i) . "1");
+ $x = $x->bsqrt;
+ ok ($x, 1);
+ }
==== //depot/maint-5.10/perl/lib/Math/BigInt/t/sub_mbf.t#2 (xtext) ====
Index: perl/lib/Math/BigInt/t/sub_mbf.t
--- perl/lib/Math/BigInt/t/sub_mbf.t#1~32694~ 2007-12-22 01:23:09.000000000
-0800
+++ perl/lib/Math/BigInt/t/sub_mbf.t 2008-05-11 04:19:32.000000000 -0700
@@ -26,7 +26,7 @@
}
print "# INC = @INC\n";
- plan tests => 2292
+ plan tests => 2308
+ 6; # + our own tests
}
==== //depot/maint-5.10/perl/lib/Math/BigInt/t/sub_mbi.t#2 (xtext) ====
Index: perl/lib/Math/BigInt/t/sub_mbi.t
--- perl/lib/Math/BigInt/t/sub_mbi.t#1~32694~ 2007-12-22 01:23:09.000000000
-0800
+++ perl/lib/Math/BigInt/t/sub_mbi.t 2008-05-11 04:19:32.000000000 -0700
@@ -26,7 +26,7 @@
}
print "# INC = @INC\n";
- plan tests => 3257
+ plan tests => 3273
+ 5; # +5 own tests
}
==== //depot/maint-5.10/perl/lib/Math/BigInt/t/with_sub.t#2 (text) ====
Index: perl/lib/Math/BigInt/t/with_sub.t
--- perl/lib/Math/BigInt/t/with_sub.t#1~32694~ 2007-12-22 01:23:09.000000000
-0800
+++ perl/lib/Math/BigInt/t/with_sub.t 2008-05-11 04:19:32.000000000 -0700
@@ -28,7 +28,7 @@
}
print "# INC = @INC\n";
- plan tests => 2292
+ plan tests => 2308
+ 1;
}
==== //depot/maint-5.10/perl/lib/Math/BigRat.pm#2 (text) ====
Index: perl/lib/Math/BigRat.pm
--- perl/lib/Math/BigRat.pm#1~32694~ 2007-12-22 01:23:09.000000000 -0800
+++ perl/lib/Math/BigRat.pm 2008-05-11 04:19:32.000000000 -0700
@@ -23,7 +23,7 @@
@ISA = qw(Math::BigFloat);
-$VERSION = '0.21';
+$VERSION = '0.22';
use overload; # inherit overload from Math::BigFloat
@@ -937,6 +937,13 @@
return $x->round(@r) if $x->is_zero(); # 0**y => 0 (if not y <= 0)
+ # shortcut if y == 1/N (is then sqrt() respective broot())
+ if ($MBI->_is_one($y->{_n}))
+ {
+ return $x->bsqrt(@r) if $MBI->_is_two($y->{_d}); # 1/2 => sqrt
+ return $x->broot($MBI->_str($y->{_d}),@r); # 1/N => root(N)
+ }
+
# shortcut y/1 (and/or x/1)
if ($MBI->_is_one($y->{_d}))
{
@@ -974,21 +981,18 @@
return $x->round(@r);
}
- # regular calculation (this is wrong for d/e ** f/g)
- my $pow2 = $self->bone();
- my $y1 = $MBI->_div ( $MBI->_copy($y->{_n}), $y->{_d});
- my $two = $MBI->_two();
-
- while (!$MBI->_is_one($y1))
- {
- $pow2->bmul($x) if $MBI->_is_odd($y1);
- $MBI->_div($y1, $two);
- $x->bmul($x);
- }
- $x->bmul($pow2) unless $pow2->is_one();
- # n ** -x => 1/n ** x
- ($x->{_d},$x->{_n}) = ($x->{_n},$x->{_d}) if $y->{sign} eq '-';
- $x->bnorm()->round(@r);
+# print STDERR "# $x $y\n";
+
+ # otherwise:
+
+ # n/d n ______________
+ # a/b = -\/ (a/b) ** d
+
+ # (a/b) ** n == (a ** n) / (b ** n)
+ $MBI->_pow($x->{_n}, $y->{_n} );
+ $MBI->_pow($x->{_d}, $y->{_n} );
+
+ return $x->broot($MBI->_str($y->{_d}),@r); # n/d => root(n)
}
sub blog
@@ -1020,21 +1024,21 @@
sub bexp
{
# set up parameters
- my ($self,$x,$y,$a,$p,$r) = (ref($_[0]),@_);
+ my ($self,$x,$y,@r) = (ref($_[0]),@_);
# objectify is costly, so avoid it
if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
{
- ($self,$x,$y,$a,$p,$r) = objectify(2,$class,@_);
+ ($self,$x,$y,@r) = objectify(2,$class,@_);
}
- return $x->binf() if $x->{sign} eq '+inf';
- return $x->bzero() if $x->{sign} eq '-inf';
+ return $x->binf(@r) if $x->{sign} eq '+inf';
+ return $x->bzero(@r) if $x->{sign} eq '-inf';
# we need to limit the accuracy to protect against overflow
my $fallback = 0;
my ($scale,@params);
- ($x,@params) = $x->_find_round_parameters($a,$p,$r);
+ ($x,@params) = $x->_find_round_parameters(@r);
# also takes care of the "error in _find_round_parameters?" case
return $x if $x->{sign} eq 'NaN';
@@ -1043,11 +1047,11 @@
if (scalar @params == 0)
{
# simulate old behaviour
- $params[0] = $self->div_scale(); # and round to it as accuracy
- $params[1] = undef; # P = undef
- $scale = $params[0]+4; # at least four more for proper round
- $params[2] = $r; # round mode by caller or undef
- $fallback = 1; # to clear a/p afterwards
+ $params[0] = $self->div_scale(); # and round to it as accuracy
+ $params[1] = undef; # P = undef
+ $scale = $params[0]+4; # at least four more for proper round
+ $params[2] = $r[2]; # round mode by caller or undef
+ $fallback = 1; # to clear a/p afterwards
}
else
{
@@ -1165,7 +1169,7 @@
if ($a != 0 || !$MBI->_is_one($x->{_d}))
{
# n/d
- return Math::BigFloat->new($x->{sign} . $MBI->_str($x->{_n}))->bdiv(
$MBI->_str($x->{_d}), $x->accuracy());
+ return scalar Math::BigFloat->new($x->{sign} .
$MBI->_str($x->{_n}))->bdiv( $MBI->_str($x->{_d}), $x->accuracy());
}
# just n
Math::BigFloat->new($x->{sign} . $MBI->_str($x->{_n}));
@@ -1187,7 +1191,7 @@
}
# do it with floats
- $x->_new_from_float( $x->_as_float()->broot($y,@r) );
+ $x->_new_from_float( $x->_as_float()->broot($y->_as_float(),@r)
)->bnorm()->bround(@r);
}
sub bmodpow
@@ -1418,6 +1422,28 @@
$u;
}
+sub as_float
+ {
+ # return N/D as Math::BigFloat
+
+ # set up parameters
+ my ($self,$x,@r) = (ref($_[0]),@_);
+ # objectify is costly, so avoid it
+ ($self,$x,@r) = objectify(1,$class,@_) unless ref $_[0];
+
+ # NaN, inf etc
+ return Math::BigFloat->new($x->{sign}) if $x->{sign} !~ /^[+-]$/;
+
+ my $u = Math::BigFloat->bzero();
+ $u->{sign} = $x->{sign};
+ # n
+ $u->{_m} = $MBI->_copy($x->{_n});
+ $u->{_e} = $MBI->_zero();
+ $u->bdiv( $MBI->_str($x->{_d}), @r);
+ # return $u
+ $u;
+ }
+
sub as_bin
{
my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
@@ -1655,7 +1681,7 @@
Returns the object as a scalar. This will lose some data if the object
cannot be represented by a normal Perl scalar (integer or float), so
-use as_int() instead.
+use L<as_int()> or L<as_float()> instead.
This routine is automatically used whenever a scalar is required:
@@ -1672,6 +1698,19 @@
C<as_number()> is an alias for C<as_int()>.
+=head2 as_float()
+
+ $x = Math::BigRat->new('13/7');
+ print $x->as_float(),"\n"; # '1'
+
+ $x = Math::BigRat->new('2/3');
+ print $x->as_float(5),"\n"; # '0.66667'
+
+Returns a copy of the object as BigFloat, preserving the
+accuracy as wanted, or the default of 40 digits.
+
+This method was added in v0.22 of Math::BigRat (April 2008).
+
=head2 as_hex()
$x = Math::BigRat->new('13');
@@ -1933,6 +1972,10 @@
works only for values that a marked with a C<RW> above, anything else is
read-only.
+=head2 objectify()
+
+This is an internal routine that turns scalars into objects.
+
=head1 BUGS
Some things are not yet implemented, or only implemented half-way:
@@ -1969,6 +2012,6 @@
=head1 AUTHORS
-(C) by Tels L<http://bloodgate.com/> 2001 - 2007.
+(C) by Tels L<http://bloodgate.com/> 2001 - 2008.
=cut
==== //depot/maint-5.10/perl/lib/Math/BigRat/t/biglog.t#2 (text) ====
Index: perl/lib/Math/BigRat/t/biglog.t
--- perl/lib/Math/BigRat/t/biglog.t#1~32694~ 2007-12-22 01:23:09.000000000
-0800
+++ perl/lib/Math/BigRat/t/biglog.t 2008-05-11 04:19:32.000000000 -0700
@@ -28,7 +28,7 @@
}
print "# INC = @INC\n";
- plan tests => 14;
+ plan tests => 17;
}
use Math::BigRat;
@@ -66,18 +66,18 @@
'90933395208605785401971970164779391644753259799242' . '/' .
'33452526613163807108170062053440751665152000000000',
'bexp(1)');
-#is ($cl->new(2)->bexp(40), $cl->new(1)->bexp(45)->bpow(2,40), 'bexp(2)');
+is ($cl->new(2)->bexp(1,40), $cl->new(1)->bexp(1,45)->bpow(2,40), 'bexp(2)');
-#is ($cl->new("12.5")->bexp(61), $cl->new(1)->bexp(65)->bpow(12.5,61),
'bexp(12.5)');
+is ($cl->new("12.5")->bexp(1,61), $cl->new(1)->bexp(1,65)->bpow(12.5,61),
'bexp(12.5)');
#############################################################################
# test bexp() with big values (non-cached)
-#is ($cl->new(1)->bexp(100),
-#
'2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427',
-# 'bexp(100)');
+is ($cl->new(1)->bexp(1,100)->as_float(100),
+
'2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427',
+ 'bexp(100)');
-is ($cl->new("12.5")->bexp(91), $cl->new(1)->bexp(95)->bpow(12.5,91),
+is ($cl->new("12.5")->bexp(1,91), $cl->new(1)->bexp(1,95)->bpow(12.5,91),
'bexp(12.5) to 91 digits');
#############################################################################
==== //depot/maint-5.10/perl/lib/Math/BigRat/t/bigrat.t#2 (xtext) ====
Index: perl/lib/Math/BigRat/t/bigrat.t
--- perl/lib/Math/BigRat/t/bigrat.t#1~32694~ 2007-12-22 01:23:09.000000000
-0800
+++ perl/lib/Math/BigRat/t/bigrat.t 2008-05-11 04:19:32.000000000 -0700
@@ -8,7 +8,7 @@
$| = 1;
chdir 't' if -d 't';
unshift @INC, '../lib'; # for running manually
- plan tests => 193;
+ plan tests => 198;
}
# basic testing of Math::BigRat
@@ -197,8 +197,8 @@
$x = $cr->new('1/3'); $z = $x->bpow('4/1'); ok ($x,'1/81');
$x = $cr->new('2/3'); $z = $x->bpow('4/1'); ok ($x,'16/81');
-# XXX todo:
-#$x = $cr->new('2/3'); $z = $x->bpow('5/3'); ok ($x,'32/81 ???');
+$x = $cr->new('2/3'); $z = $x->bpow('5/3');
+ok ($x,
'31797617848703662994667839220546583581/62500000000000000000000000000000000000');
##############################################################################
# bfac
@@ -279,7 +279,7 @@
# square root with exact result
$x = $cr->new('1.44');
-ok ($x->copy()->broot(2), '12/10');
+ok ($x->copy()->broot(2), '6/5');
ok (ref($x->copy()->broot(2)), $cr);
# log with exact result
@@ -312,6 +312,19 @@
ok ($x, '64', 'from_oct');
##############################################################################
+# as_float()
+
+$x = Math::BigRat->new('1/2'); my $f = $x->as_float();
+
+ok ($x, '1/2', '$x unmodified');
+ok ($f, '0.5', 'as_float(0.5)');
+
+$x = Math::BigRat->new('2/3'); $f = $x->as_float(5);
+
+ok ($x, '2/3', '$x unmodified');
+ok ($f, '0.66667', 'as_float(2/3,5)');
+
+##############################################################################
# done
1;
==== //depot/maint-5.10/perl/lib/Math/BigRat/t/bigroot.t#2 (text) ====
Index: perl/lib/Math/BigRat/t/bigroot.t
--- perl/lib/Math/BigRat/t/bigroot.t#1~32694~ 2007-12-22 01:23:09.000000000
-0800
+++ perl/lib/Math/BigRat/t/bigroot.t 2008-05-11 04:19:32.000000000 -0700
@@ -34,7 +34,7 @@
}
print "# INC = @INC\n";
- plan tests => 4 * 2;
+ plan tests => 8 * 2;
}
use Math::BigFloat;
@@ -46,11 +46,10 @@
# 2 ** 240 =
# 1766847064778384329583297500742918515827483896875618958121606201292619776
-# takes way too long
-#test_broot ('2','240', 8, undef, '1073741824');
-#test_broot ('2','240', 9, undef,
'106528681.3099908308759836475139583940127');
-#test_broot ('2','120', 9, undef,
'10321.27324073880096577298929482324664787');
-#test_broot ('2','120', 17, undef,
'133.3268493632747279600707813049418888729');
+test_broot ('2','240', 8, undef, '1073741824');
+test_broot ('2','240', 9, undef,
'106528681.3099908308759836475139583940127');
+test_broot ('2','120', 9, undef,
'10321.27324073880096577298929482324664787');
+test_broot ('2','120', 17, undef,
'133.3268493632747279600707813049418888729');
test_broot ('2','120', 8, undef, '32768');
test_broot ('2','60', 8, undef, '181.0193359837561662466161566988413540569');
==== //depot/maint-5.10/perl/lib/Math/BigRat/t/hang.t#1 (text) ====
Index: perl/lib/Math/BigRat/t/hang.t
--- /dev/null 2008-05-07 15:08:24.549929899 -0700
+++ perl/lib/Math/BigRat/t/hang.t 2008-05-11 04:19:32.000000000 -0700
@@ -0,0 +1,27 @@
+#!/usr/bin/perl -w
+
+# test for bug #34584: hang in exp(1/2)
+
+use strict;
+use Test::More;
+
+BEGIN
+ {
+ $| = 1;
+ chdir 't' if -d 't';
+ unshift @INC, '../lib'; # for running manually
+ plan tests => 1;
+ }
+
+use Math::BigRat;
+
+my $result = Math::BigRat->new('1/2')->bexp();
+
+is ("$result",
"9535900335500879457687887524133067574481/5783815921445270815783609372070483523265",
+ "exp(1/2) worked");
+
+##############################################################################
+# done
+
+1;
+
==== //depot/maint-5.10/perl/lib/Math/Complex.pm#5 (text) ====
Index: perl/lib/Math/Complex.pm
--- perl/lib/Math/Complex.pm#4~33512~ 2008-03-13 10:55:54.000000000 -0700
+++ perl/lib/Math/Complex.pm 2008-05-11 04:19:32.000000000 -0700
@@ -7,9 +7,9 @@
package Math::Complex;
-use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $Inf);
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $Inf $ExpInf);
-$VERSION = 1.52;
+$VERSION = 1.54;
use Config;
@@ -38,6 +38,7 @@
if ($^O eq 'unicosmk') {
$Inf = $DBL_MAX;
} else {
+ local $SIG{FPE} = { };
local $!;
# We do want an arithmetic overflow, Inf INF inf Infinity.
for my $t (
@@ -50,7 +51,6 @@
'INFINITY',
'1e99999',
) {
- local $SIG{FPE} = { };
local $^W = 0;
my $i = eval "$t+1.0";
if (defined $i && $i > $BIGGER_THAN_THIS) {
@@ -61,6 +61,7 @@
$Inf = $DBL_MAX unless defined $Inf; # Oh well, close enough.
die "Math::Complex: Could not get Infinity"
unless $Inf > $BIGGER_THAN_THIS;
+ $ExpInf = exp(99999);
}
# print "# On this machine, Inf = '$Inf'\n";
}
@@ -1101,7 +1102,7 @@
my $ex;
unless (ref $z) {
$ex = CORE::exp($z);
- return $ex ? ($ex + 1/$ex)/2 : Inf();
+ return $ex ? ($ex == $ExpInf ? Inf() : ($ex + 1/$ex)/2) : Inf();
}
my ($x, $y) = @{$z->_cartesian};
$ex = CORE::exp($x);
@@ -1121,7 +1122,7 @@
unless (ref $z) {
return 0 if $z == 0;
$ex = CORE::exp($z);
- return $ex ? ($ex - 1/$ex)/2 : -Inf();
+ return $ex ? ($ex == $ExpInf ? Inf() : ($ex - 1/$ex)/2) : -Inf();
}
my ($x, $y) = @{$z->_cartesian};
my $cy = CORE::cos($y);
@@ -1203,7 +1204,7 @@
#
# acosh
#
-# Computes the arc hyperbolic cosine acosh(z) = log(z + sqrt(z*z-1)).
+# Computes the area/inverse hyperbolic cosine acosh(z) = log(z + sqrt(z*z-1)).
#
sub acosh {
my ($z) = @_;
@@ -1231,7 +1232,7 @@
#
# asinh
#
-# Computes the arc hyperbolic sine asinh(z) = log(z + sqrt(z*z+1))
+# Computes the area/inverse hyperbolic sine asinh(z) = log(z + sqrt(z*z+1))
#
sub asinh {
my ($z) = @_;
@@ -1251,7 +1252,7 @@
#
# atanh
#
-# Computes the arc hyperbolic tangent atanh(z) = 1/2 log((1+z) / (1-z)).
+# Computes the area/inverse hyperbolic tangent atanh(z) = 1/2 log((1+z) /
(1-z)).
#
sub atanh {
my ($z) = @_;
@@ -1267,7 +1268,7 @@
#
# asech
#
-# Computes the hyperbolic arc secant asech(z) = acosh(1 / z).
+# Computes the area/inverse hyperbolic secant asech(z) = acosh(1 / z).
#
sub asech {
my ($z) = @_;
@@ -1278,7 +1279,7 @@
#
# acsch
#
-# Computes the hyperbolic arc cosecant acsch(z) = asinh(1 / z).
+# Computes the area/inverse hyperbolic cosecant acsch(z) = asinh(1 / z).
#
sub acsch {
my ($z) = @_;
@@ -1296,7 +1297,7 @@
#
# acoth
#
-# Computes the arc hyperbolic cotangent acoth(z) = 1/2 log((1+z) / (z-1)).
+# Computes the area/inverse hyperbolic cotangent acoth(z) = 1/2 log((1+z) /
(z-1)).
#
sub acoth {
my ($z) = @_;
==== //depot/maint-5.10/perl/lib/Math/Complex.t#5 (xtext) ====
Index: perl/lib/Math/Complex.t
--- perl/lib/Math/Complex.t#4~33512~ 2008-03-13 10:55:54.000000000 -0700
+++ perl/lib/Math/Complex.t 2008-05-11 04:19:32.000000000 -0700
@@ -13,7 +13,7 @@
}
}
-use Math::Complex 1.52;
+use Math::Complex 1.54;
use vars qw($VERSION);
==== //depot/maint-5.10/perl/lib/Math/Trig.pm#5 (text) ====
Index: perl/lib/Math/Trig.pm
--- perl/lib/Math/Trig.pm#4~33512~ 2008-03-13 10:55:54.000000000 -0700
+++ perl/lib/Math/Trig.pm 2008-05-11 04:19:32.000000000 -0700
@@ -10,14 +10,14 @@
use 5.005;
use strict;
-use Math::Complex 1.51;
+use Math::Complex 1.54;
use Math::Complex qw(:trig :pi);
use vars qw($VERSION $PACKAGE @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
@ISA = qw(Exporter);
-$VERSION = 1.16;
+$VERSION = 1.18;
my @angcnv = qw(rad2deg rad2grad
deg2rad deg2grad
@@ -181,7 +181,7 @@
return rad2rad($direction);
}
-*great_circle_bearing = \&great_circle_direction;
+*great_circle_bearing = \&great_circle_direction;
sub great_circle_waypoint {
my ( $theta0, $phi0, $theta1, $phi1, $point ) = @_;
@@ -208,7 +208,7 @@
my $theta = atan2($y, $x);
my $phi = acos_real($z);
-
+
return ($theta, $phi);
}
@@ -221,8 +221,9 @@
my $lat0 = pip2 - $phi0;
- my $phi1 = asin_real(sin($lat0)*cos($dst) +
+ my $phi1 = asin_real(sin($lat0)*cos($dst) +
cos($lat0)*sin($dst)*cos($dir0));
+
my $theta1 = $theta0 + atan2(sin($dir0)*sin($dst)*cos($lat0),
cos($dst)-sin($lat0)*sin($phi1));
@@ -308,12 +309,12 @@
B<csch>, B<cosech>, B<sech>, B<coth>, B<cotanh>
-The arcus (also known as the inverse) functions of the hyperbolic
+The area (also known as the inverse) functions of the hyperbolic
sine, cosine, and tangent
B<asinh>, B<acosh>, B<atanh>
-The arcus cofunctions of the hyperbolic sine, cosine, and tangent
+The area cofunctions of the hyperbolic sine, cosine, and tangent
(acsch/acosech and acoth/acotanh are aliases)
B<acsch>, B<acosech>, B<asech>, B<acoth>, B<acotanh>
@@ -589,18 +590,22 @@
straight north, pi or -pi straight south, pi/2 straight west, and
-pi/2 straight east.
+=head2 great_circle_destination
+
You can inversely compute the destination if you know the
starting point, direction, and distance:
-=head2 great_circle_destination
-
use Math::Trig 'great_circle_destination';
- # thetad and phid are the destination coordinates,
- # dird is the final direction at the destination.
+ # $diro is the original direction,
+ # for example from great_circle_bearing().
+ # $distance is the angular distance in radians,
+ # for example from great_circle_distance().
+ # $thetad and $phid are the destination coordinates,
+ # $dird is the final direction at the destination.
($thetad, $phid, $dird) =
- great_circle_destination($theta, $phi, $direction, $distance);
+ great_circle_destination($theta, $phi, $diro, $distance);
or the midpoint if you know the end points:
@@ -668,7 +673,18 @@
my @M = great_circle_midpoint(@L, @T);
-or about 68.93N 89.16E, in the frozen wastes of Siberia.
+or about 69 N 89 E, in the frozen wastes of Siberia.
+
+B<NOTE>: you B<cannot> get from A to B like this:
+
+ Dist = great_circle_distance(A, B)
+ Dir = great_circle_direction(A, B)
+ C = great_circle_destination(A, Dist, Dir)
+
+and expect C to be B, because the bearing constantly changes when
+going from A to B (except in some special case like the meridians or
+the circles of latitudes) and in great_circle_destination() one gives
+a constant bearing to follow.
=head2 CAVEAT FOR GREAT CIRCLE FORMULAS
==== //depot/maint-5.10/perl/lib/Math/Trig.t#5 (xtext) ====
Index: perl/lib/Math/Trig.t
--- perl/lib/Math/Trig.t#4~33512~ 2008-03-13 10:55:54.000000000 -0700
+++ perl/lib/Math/Trig.t 2008-05-11 04:19:32.000000000 -0700
@@ -28,8 +28,8 @@
plan(tests => 153);
-use Math::Trig 1.16;
-use Math::Trig 1.16 qw(:pi Inf);
+use Math::Trig 1.18;
+use Math::Trig 1.18 qw(:pi Inf);
my $pip2 = pi / 2;
@@ -312,7 +312,7 @@
my $BigDouble = 1e40;
# E.g. netbsd-alpha core dumps on Inf arith without this.
-local $SIG{FPE} = { };
+local $SIG{FPE} = sub { };
ok(Inf() > $BigDouble); # This passes in netbsd-alpha.
ok(Inf() + $BigDouble > $BigDouble); # This coredumps in netbsd-alpha.
==== //depot/maint-5.10/perl/lib/bigint.pm#2 (text) ====
Index: perl/lib/bigint.pm
--- perl/lib/bigint.pm#1~32694~ 2007-12-22 01:23:09.000000000 -0800
+++ perl/lib/bigint.pm 2008-05-11 04:19:32.000000000 -0700
@@ -1,7 +1,7 @@
package bigint;
-use 5.006002;
+use 5.006;
-$VERSION = '0.22';
+$VERSION = '0.23';
use Exporter;
@ISA = qw( Exporter );
@EXPORT_OK = qw( PI e bpi bexp );
==== //depot/maint-5.10/perl/lib/bignum.pm#2 (text) ====
Index: perl/lib/bignum.pm
--- perl/lib/bignum.pm#1~32694~ 2007-12-22 01:23:09.000000000 -0800
+++ perl/lib/bignum.pm 2008-05-11 04:19:32.000000000 -0700
@@ -1,7 +1,7 @@
package bignum;
-use 5.006002;
+use 5.006;
-$VERSION = '0.22';
+$VERSION = '0.23';
use Exporter;
@ISA = qw( bigint );
@EXPORT_OK = qw( PI e bexp bpi );
==== //depot/maint-5.10/perl/lib/bigrat.pm#2 (text) ====
Index: perl/lib/bigrat.pm
--- perl/lib/bigrat.pm#1~32694~ 2007-12-22 01:23:09.000000000 -0800
+++ perl/lib/bigrat.pm 2008-05-11 04:19:32.000000000 -0700
@@ -1,7 +1,7 @@
package bigrat;
-use 5.006002;
+use 5.006;
-$VERSION = '0.22';
+$VERSION = '0.23';
require Exporter;
@ISA = qw( bigint );
@EXPORT_OK = qw( PI e bpi bexp );
End of Patch.