Upgrade to Math::Complex 1.54
Rafael Garcia-Suarez [Wed, 16 Apr 2008 13:51:36 +0000 (13:51 +0000)]
p4raw-id: //depot/perl@33698

lib/Math/Complex.pm
lib/Math/Complex.t
lib/Math/Trig.pm
lib/Math/Trig.t

index f424175..523b11c 100644 (file)
@@ -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 @@ BEGIN {
     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 @@ BEGIN {
            '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 @@ BEGIN {
        $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 @@ sub cosh {
        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 @@ sub sinh {
        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 @@ sub cotanh { Math::Complex::coth(@_) }
 #
 # 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 @@ sub acosh {
 #
 # 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 @@ sub asinh {
 #
 # 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 @@ sub atanh {
 #
 # 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 @@ sub asech {
 #
 # 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 @@ sub acosech { Math::Complex::acsch(@_) }
 #
 # 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) = @_;
index 44f8f35..ee02341 100755 (executable)
@@ -13,7 +13,7 @@ BEGIN {
     }
 }
 
-use Math::Complex 1.52;
+use Math::Complex 1.54;
 
 use vars qw($VERSION);
 
index 3197d6f..6d4d949 100644 (file)
@@ -10,14 +10,14 @@ package Math::Trig;
 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 @@ sub great_circle_direction {
     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 @@ sub great_circle_waypoint {
 
     my $theta = atan2($y, $x);
     my $phi   = acos_real($z);
-    
+
     return ($theta, $phi);
 }
 
@@ -221,8 +221,9 @@ sub great_circle_destination {
 
     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 @@ and cotanh/coth are aliases)
 
 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 @@ The result of great_circle_direction is in radians, zero indicating
 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 @@ The midpoint between London and Tokyo being
 
     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
 
index 618cdb7..91f5486 100755 (executable)
@@ -28,8 +28,8 @@ BEGIN {
 
 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 @@ print "# Infinity\n";
 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.