diff options
author | Perl 5 Porters <perl5-porters@africa.nicoh.com> | 1997-04-04 00:00:00 +0000 |
---|---|---|
committer | Chip Salzenberg <chip@atlantic.net> | 1997-04-04 00:00:00 +0000 |
commit | 5cd24f17b72b10f8506d70fba1ec4dd25224c257 (patch) | |
tree | 0016ef5cb000e60fd3ea5ca5acf14ab3fa5a9812 /lib/Math | |
parent | daff0e373f3630eaa9dbded0adcc04185f454487 (diff) | |
download | perl-5cd24f17b72b10f8506d70fba1ec4dd25224c257.tar.gz |
[inseparable changes from match from perl-5.003_97a to perl-5.003_97b]
BUILD PROCESS
Subject: Don't suggest 'Configure -der' in config.sh comments
From: Chip Salzenberg <chip@perl.com>
Files: Configure
CORE LANGUAGE CHANGES
Subject: Make assignment to C<$)> call setgroups()
From: Chip Salzenberg <chip@perl.com>
Files: Configure config_H config_h.SH mg.c plan9/config.plan9 pod/perldelta.pod vms/config.vms win32/config.H win32/config.w32
Subject: Grandfather "$$<digit>" in strings
From: Chip Salzenberg <chip@perl.com>
Files: pod/perldiag.pod toke.c
Subject: Disconnect warn and die hooks _after_ object destruction
From: Chip Salzenberg <chip@perl.com>
Files: perl.c
Subject: Forbid recursive substitutions
From: Chip Salzenberg <chip@perl.com>
Files: cop.h pod/perldelta.pod pod/perldiag.pod pp_ctl.c pp_hot.c
DOCUMENTATION
Subject: Document required module versions
From: Chip Salzenberg <chip@perl.com>
Files: pod/perldelta.pod
LIBRARY AND EXTENSIONS
Subject: Updates to Math::Complex and Math::Trig
From: Jarkko Hietaniemi <Jarkko.Hietaniemi@cc.hut.fi>
Files: lib/Math/Complex.pm lib/Math/Trig.pm pod/perldelta.pod t/lib/complex.t
OTHER CORE CHANGES
Subject: length($') isn't
Date: Mon, 07 Apr 1997 03:30:44 -0400
From: Gurusamy Sarathy <gsar@engin.umich.edu>
Files: mg.c
Msg-ID: 199704070730.DAA07310@aatma.engin.umich.edu
(applied based on p5p patch as commit 645a7cbb1f14932f058231f0a4f808b88ebe8703)
Subject: Fix obscure regex bug related to leading C<.*>
From: Chip Salzenberg <chip@perl.com>
Files: toke.c
Subject: Add warning for glob failure
From: Chip Salzenberg <chip@perl.com>
Files: pod/perldelta.pod pod/perldiag.pod pp_hot.c
Subject: Fix C<perl -V> in presence of local patches
From: Chip Salzenberg <chip@perl.com>
Files: perl.c
Diffstat (limited to 'lib/Math')
-rw-r--r-- | lib/Math/Complex.pm | 119 | ||||
-rw-r--r-- | lib/Math/Trig.pm | 142 |
2 files changed, 138 insertions, 123 deletions
diff --git a/lib/Math/Complex.pm b/lib/Math/Complex.pm index 9000543438..20762bdfa1 100644 --- a/lib/Math/Complex.pm +++ b/lib/Math/Complex.pm @@ -2,7 +2,7 @@ # # Complex numbers and associated mathematical functions # -- Raphael Manfredi, September 1996 -# -- Jarkko Hietaniemi, March 1997 +# -- Jarkko Hietaniemi, March-April 1997 require Exporter; package Math::Complex; @@ -12,7 +12,7 @@ use strict; use vars qw($VERSION @ISA @EXPORT %EXPORT_TAGS $package $display - $pi $i $ilog10 $logn %logn); + $i $logn %logn); @ISA = qw(Exporter); @@ -20,7 +20,7 @@ $VERSION = 1.01; my @trig = qw( pi - tan + sin cos tan csc cosec sec cot cotan asin acos atan acsc acosec asec acot acotan @@ -135,10 +135,16 @@ sub cplxe { # # The number defined as 2 * pi = 360 degrees # -sub pi () { - $pi = 4 * atan2(1, 1) unless $pi; - return $pi; -} + +use constant pi => 4 * atan2(1, 1); + +# +# log2inv +# +# Used in log10(). +# + +use constant log10inv => 1 / log(10); # # i @@ -146,9 +152,10 @@ sub pi () { # The number defined as i*i = -1; # sub i () { - $i = bless {} unless $i; # There can be only one i + return $i if ($i); + $i = bless {}; $i->{'cartesian'} = [0, 1]; - $i->{'polar'} = [1, pi/2]; + $i->{'polar'} = [1, pi/2]; $i->{c_dirty} = 0; $i->{p_dirty} = 0; return $i; @@ -199,9 +206,8 @@ sub update_polar { # sub plus { my ($z1, $z2, $regular) = @_; - $z2 = cplx($z2, 0) unless ref $z2; my ($re1, $im1) = @{$z1->cartesian}; - my ($re2, $im2) = @{$z2->cartesian}; + my ($re2, $im2) = ref $z2 ? @{$z2->cartesian} : ($z2, 0); unless (defined $regular) { $z1->set_cartesian([$re1 + $re2, $im1 + $im2]); return $z1; @@ -216,9 +222,8 @@ sub plus { # sub minus { my ($z1, $z2, $inverted) = @_; - $z2 = cplx($z2, 0) unless ref $z2; my ($re1, $im1) = @{$z1->cartesian}; - my ($re2, $im2) = @{$z2->cartesian}; + my ($re2, $im2) = ref $z2 ? @{$z2->cartesian} : ($z2, 0); unless (defined $inverted) { $z1->set_cartesian([$re1 - $re2, $im1 - $im2]); return $z1; @@ -251,12 +256,19 @@ sub multiply { # Die on division by zero. # sub divbyzero { - warn "$_[0]: Division by zero.\n"; - warn "(Because in the definition of $_[0], $_[1] is 0)\n" - if (defined $_[1]); + my $mess = "$_[0]: Division by zero.\n"; + + if (defined $_[1]) { + $mess .= "(Because in the definition of $_[0], the divisor "; + $mess .= "$_[1] " unless ($_[1] eq '0'); + $mess .= "is 0)\n"; + } + my @up = caller(1); - my $dmess = "Died at $up[1] line $up[2].\n"; - die $dmess; + + $mess .= "Died at $up[1] line $up[2].\n"; + + die $mess; } # @@ -302,9 +314,8 @@ sub power { # sub spaceship { my ($z1, $z2, $inverted) = @_; - $z2 = cplx($z2, 0) unless ref $z2; - my ($re1, $im1) = @{$z1->cartesian}; - my ($re2, $im2) = @{$z2->cartesian}; + my ($re1, $im1) = ref $z1 ? @{$z1->cartesian} : ($z1, 0); + my ($re2, $im2) = ref $z2 ? @{$z2->cartesian} : ($z2, 0); my $sgn = $inverted ? -1 : 1; return $sgn * ($re1 <=> $re2) if $re1 != $re2; return $sgn * ($im1 <=> $im2); @@ -459,8 +470,8 @@ sub exp { sub log { my ($z) = @_; $z = cplx($z, 0) unless ref $z; - my ($r, $t) = @{$z->polar}; my ($x, $y) = @{$z->cartesian}; + my ($r, $t) = @{$z->polar}; $t -= 2 * pi if ($t > pi() and $x < 0); $t += 2 * pi if ($t < -pi() and $x < 0); return (ref $z)->make(log($r), $t); @@ -478,12 +489,13 @@ sub ln { Math::Complex::log(@_) } # # Compute log10(z). # + sub log10 { my ($z) = @_; - my $ilog10 = 1 / log(10) unless defined $ilog10; - return log(cplx($z, 0)) * $ilog10 unless ref $z; + + return log(cplx($z, 0)) * log10inv unless ref $z; my ($r, $t) = @{$z->polar}; - return (ref $z)->make(log($r) * $ilog10, $t * $ilog10); + return (ref $z)->make(log($r) * log10inv, $t * log10inv); } # @@ -506,6 +518,7 @@ sub logn { # sub cos { my ($z) = @_; + $z = cplx($z, 0) unless ref $z; my ($x, $y) = @{$z->cartesian}; my $ey = exp($y); my $ey_1 = 1 / $ey; @@ -520,6 +533,7 @@ sub cos { # sub sin { my ($z) = @_; + $z = cplx($z, 0) unless ref $z; my ($x, $y) = @{$z->cartesian}; my $ey = exp($y); my $ey_1 = 1 / $ey; @@ -618,6 +632,7 @@ sub asin { # sub atan { my ($z) = @_; + $z = cplx($z, 0) unless ref $z; divbyzero "atan($z)", "i - $z" if ($z == i); return i/2*log((i + $z) / (i - $z)); } @@ -629,25 +644,27 @@ sub atan { # sub asec { my ($z) = @_; + divbyzero "asec($z)", $z if ($z == 0); return acos(1 / $z); } # -# acosec +# acsc # # Computes the arc cosecant sec(z) = asin(1 / z). # -sub acosec { +sub acsc { my ($z) = @_; + divbyzero "acsc($z)", $z if ($z == 0); return asin(1 / $z); } # -# acsc +# acosec # -# Alias for acosec(). +# Alias for acsc(). # -sub acsc { Math::Complex::acosec(@_) } +sub acosec { Math::Complex::acsc(@_) } # # acot @@ -656,6 +673,7 @@ sub acsc { Math::Complex::acosec(@_) } # sub acot { my ($z) = @_; + $z = cplx($z, 0) unless ref $z; divbyzero "acot($z)", "$z - i" if ($z == i); return i/-2 * log((i + $z) / ($z - i)); } @@ -674,8 +692,7 @@ sub acotan { Math::Complex::acot(@_) } # sub cosh { my ($z) = @_; - $z = cplx($z, 0) unless ref $z; - my ($x, $y) = @{$z->cartesian}; + my ($x, $y) = ref $z ? @{$z->cartesian} : ($z, 0); my $ex = exp($x); my $ex_1 = 1 / $ex; return ($ex + $ex_1)/2 unless ref $z; @@ -690,8 +707,7 @@ sub cosh { # sub sinh { my ($z) = @_; - $z = cplx($z, 0) unless ref $z; - my ($x, $y) = @{$z->cartesian}; + my ($x, $y) = ref $z ? @{$z->cartesian} : ($z, 0); my $ex = exp($x); my $ex_1 = 1 / $ex; return ($ex - $ex_1)/2 unless ref $z; @@ -768,7 +784,7 @@ sub cotanh { Math::Complex::coth(@_) } # sub acosh { my ($z) = @_; - $z = cplx($z, 0) unless ref $z; # asinh(-2) + $z = cplx($z, 0) unless ref $z; return log($z + sqrt($z*$z - 1)); } @@ -779,7 +795,7 @@ sub acosh { # sub asinh { my ($z) = @_; - $z = cplx($z, 0) unless ref $z; # asinh(-2) + $z = cplx($z, 0) unless ref $z; return log($z + sqrt($z*$z + 1)); } @@ -790,8 +806,8 @@ sub asinh { # sub atanh { my ($z) = @_; - $z = cplx($z, 0) unless ref $z; # atanh(-2) divbyzero 'atanh(1)', "1 - $z" if ($z == 1); + $z = cplx($z, 0) unless ref $z; my $cz = (1 + $z) / (1 - $z); return log($cz) / 2; } @@ -832,8 +848,8 @@ sub acosech { Math::Complex::acsch(@_) } # sub acoth { my ($z) = @_; - $z = cplx($z, 0) unless ref $z; # acoth(-2) divbyzero 'acoth(1)', "$z - 1" if ($z == 1); + $z = cplx($z, 0) unless ref $z; my $cz = (1 + $z) / ($z - 1); return log($cz) / 2; } @@ -852,8 +868,8 @@ sub acotanh { Math::Complex::acoth(@_) } # sub atan2 { my ($z1, $z2, $inverted) = @_; - my ($re1, $im1) = @{$z1->cartesian}; - my ($re2, $im2) = @{$z2->cartesian}; + my ($re1, $im1) = ref $z1 ? @{$z1->cartesian} : ($z1, 0); + my ($re2, $im2) = ref $z2 ? @{$z2->cartesian} : ($z2, 0); my $tan; if (defined $inverted && $inverted) { # atan(z2/z1) return pi * ($re2 > 0 ? 1 : -1) if $re1 == 0 && $im1 == 0; @@ -1341,7 +1357,7 @@ Here are some examples: $k = exp(i * 2*pi/3); print "$j - $k = ", $j - $k, "\n"; -=head1 CAVEATS +=head1 ERRORS DUE TO DIVISION BY ZERO The division (/) and the following functions @@ -1349,6 +1365,8 @@ The division (/) and the following functions sec csc cot + asec + acsc atan acot tanh @@ -1364,13 +1382,22 @@ cannot be computed for all arguments because that would mean dividing by zero. These situations cause fatal runtime errors looking like this cot(0): Division by zero. - (Because in the definition of cot(0), sin(0) is 0) + (Because in the definition of cot(0), the divisor sin(0) is 0) Died at ... +For the C<csc>, C<cot>, C<asec>, C<acsc>, C<csch>, C<coth>, C<asech>, +C<acsch>, the argument cannot be C<0> (zero). For the C<atanh>, +C<acoth>, the argument cannot be C<1> (one). For the C<atan>, C<acot>, +the argument cannot be C<i> (the imaginary unit). For the C<tan>, +C<sec>, C<tanh>, C<sech>, the argument cannot be I<pi/2 + k * pi>, where +I<k> is any integer. + =head1 BUGS -Saying C<use Math::Complex;> exports many mathematical routines in the caller -environment. This is construed as a feature by the Author, actually... ;-) +Saying C<use Math::Complex;> exports many mathematical routines in the +caller environment and even overrides some (C<sin>, C<cos>, C<sqrt>, +C<log>, C<exp>). This is construed as a feature by the Authors, +actually... ;-) The code is not optimized for speed, although we try to use the cartesian form for addition-like operators and the trigonometric form for all @@ -1388,3 +1415,7 @@ operation (for instance) between two overloaded entities. Raphael Manfredi <F<Raphael_Manfredi@grenoble.hp.com>> Jarkko Hietaniemi <F<jhi@iki.fi>> + +=cut + +# eof diff --git a/lib/Math/Trig.pm b/lib/Math/Trig.pm index 7c3570c840..4098f34448 100644 --- a/lib/Math/Trig.pm +++ b/lib/Math/Trig.pm @@ -1,6 +1,7 @@ # # Trigonometric functions, mostly inherited from Math::Complex. # -- Jarkko Hietaniemi, April 1997 +# -- Raphael Manfredi, September 1996 (indirectly: because of Math::Complex) # require Exporter; @@ -12,8 +13,7 @@ use Math::Complex qw(:trig); use vars qw($VERSION $PACKAGE @ISA - @EXPORT - $pi2 $DR $RD $DG $GD $RG $GR); + @EXPORT); @ISA = qw(Exporter); @@ -26,40 +26,13 @@ my @angcnv = qw(rad_to_deg rad_to_grad @EXPORT = (@{$Math::Complex::EXPORT_TAGS{'trig'}}, @angcnv); -sub pi2 () { - $pi2 = 2 * pi unless ($pi2); - $pi2; -} - -sub DR () { - $DR = pi2/360 unless ($DR); - $DR; -} - -sub RD () { - $RD = 360/pi2 unless ($RD); - $RD; -} - -sub DG () { - $DG = 400/360 unless ($DG); - $DG; -} - -sub GD () { - $GD = 360/400 unless ($GD); - $GD; -} - -sub RG () { - $RG = 400/pi2 unless ($RG); - $RG; -} - -sub GR () { - $GR = pi2/400 unless ($GR); - $GR; -} +use constant pi2 => 2 * pi; +use constant DR => pi2/360; +use constant RD => 360/pi2; +use constant DG => 400/360; +use constant GD => 360/400; +use constant RG => 400/pi2; +use constant GR => pi2/400; # # Truncating remainder. @@ -74,29 +47,17 @@ sub remt ($$) { # Angle conversions. # -sub rad_to_deg ($) { - remt(RD * $_[0], 360); -} +sub rad_to_deg ($) { remt(RD * $_[0], 360) } -sub deg_to_rad ($) { - remt(DR * $_[0], pi2); -} +sub deg_to_rad ($) { remt(DR * $_[0], pi2) } -sub grad_to_deg ($) { - remt(GD * $_[0], 360); -} +sub grad_to_deg ($) { remt(GD * $_[0], 360) } -sub deg_to_grad ($) { - remt(DG * $_[0], 400); -} +sub deg_to_grad ($) { remt(DG * $_[0], 400) } -sub rad_to_grad ($) { - remt(RG * $_[0], 400); -} +sub rad_to_grad ($) { remt(RG * $_[0], 400) } -sub grad_to_rad ($) { - remt(GR * $_[0], pi2); -} +sub grad_to_rad ($) { remt(GR * $_[0], pi2) } =head1 NAME @@ -169,7 +130,39 @@ The trigonometric constant B<pi> is also defined. $pi2 = 2 * pi; -=head2 SIMPLE ARGUMENTS, COMPLEX RESULTS +=head2 ERRORS DUE TO DIVISION BY ZERO + +The following functions + + tan + sec + csc + cot + asec + acsc + tanh + sech + csch + coth + atanh + asech + acsch + acoth + +cannot be computed for all arguments because that would mean dividing +by zero. These situations cause fatal runtime errors looking like this + + cot(0): Division by zero. + (Because in the definition of cot(0), the divisor sin(0) is 0) + Died at ... + +For the C<csc>, C<cot>, C<asec>, C<acsc>, C<csch>, C<coth>, C<asech>, +C<acsch>, the argument cannot be C<0> (zero). For the C<atanh>, +C<acoth>, the argument cannot be C<1> (one). For the C<tan>, C<sec>, +C<tanh>, C<sech>, the argument cannot be I<pi/2 + k * pi>, where I<k> is +any integer. + +=head2 SIMPLE (REAL) ARGUMENTS, COMPLEX RESULTS Please note that some of the trigonometric functions can break out from the B<real axis> into the B<complex plane>. For example @@ -193,8 +186,8 @@ should produce something like this (take or leave few last decimals): 1.5707963267949-1.31695789692482i -That is, a complex number with the real part of approximately E<1.571> -and the imaginary part of approximately E<-1.317>. +That is, a complex number with the real part of approximately C<1.571> +and the imaginary part of approximately C<-1.317>. =head1 ANGLE CONVERSIONS @@ -209,33 +202,24 @@ and the imaginary part of approximately E<-1.317>. $gradians = deg_to_grad($degrees); $gradians = rad_to_grad($radians); -The full circle is 2 B<pi> radians or E<360> degrees or E<400> gradians. +The full circle is 2 I<pi> radians or I<360> degrees or I<400> gradians. -=head1 +=head1 BUGS -The following functions +Saying C<use Math::Trig;> exports many mathematical routines in the +caller environment and even overrides some (C<sin>, C<cos>). This is +construed as a feature by the Authors, actually... ;-) - tan - sec - csc - cot - atan - acot - tanh - sech - csch - coth - atanh - asech - acsch - acoth +The code is not optimized for speed, especially because we use +C<Math::Complex> and thus go quite near complex numbers while doing +the computations even when the arguments are not. This, however, +cannot be completely avoided if we want things like C<asin(2)> to give +an answer instead of giving a fatal runtime error. -cannot be computed for all arguments because that would mean dividing -by zero. These situations cause fatal runtime errors looking like this +=head1 AUTHORS - cot(0): Division by zero. - (Because in the definition of cot(0), sin(0) is 0) - Died at ... + Jarkko Hietaniemi <F<jhi@iki.fi>> + Raphael Manfredi <F<Raphael_Manfredi@grenoble.hp.com>> =cut |