Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / devtools / v8plus / lib / perl5 / 5.8.8 / Math / Trig.pm
CommitLineData
920dae64
AT
1#
2# Trigonometric functions, mostly inherited from Math::Complex.
3# -- Jarkko Hietaniemi, since April 1997
4# -- Raphael Manfredi, September 1996 (indirectly: because of Math::Complex)
5#
6
7require Exporter;
8package Math::Trig;
9
10use 5.006;
11use strict;
12
13use Math::Complex 1.35;
14use Math::Complex qw(:trig);
15
16our($VERSION, $PACKAGE, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
17
18@ISA = qw(Exporter);
19
20$VERSION = 1.03;
21
22my @angcnv = qw(rad2deg rad2grad
23 deg2rad deg2grad
24 grad2rad grad2deg);
25
26@EXPORT = (@{$Math::Complex::EXPORT_TAGS{'trig'}},
27 @angcnv);
28
29my @rdlcnv = qw(cartesian_to_cylindrical
30 cartesian_to_spherical
31 cylindrical_to_cartesian
32 cylindrical_to_spherical
33 spherical_to_cartesian
34 spherical_to_cylindrical);
35
36my @greatcircle = qw(
37 great_circle_distance
38 great_circle_direction
39 great_circle_bearing
40 great_circle_waypoint
41 great_circle_midpoint
42 great_circle_destination
43 );
44
45my @pi = qw(pi2 pip2 pip4);
46
47@EXPORT_OK = (@rdlcnv, @greatcircle, @pi);
48
49# See e.g. the following pages:
50# http://www.movable-type.co.uk/scripts/LatLong.html
51# http://williams.best.vwh.net/avform.htm
52
53%EXPORT_TAGS = ('radial' => [ @rdlcnv ],
54 'great_circle' => [ @greatcircle ],
55 'pi' => [ @pi ]);
56
57sub pi2 () { 2 * pi }
58sub pip2 () { pi / 2 }
59sub pip4 () { pi / 4 }
60
61sub DR () { pi2/360 }
62sub RD () { 360/pi2 }
63sub DG () { 400/360 }
64sub GD () { 360/400 }
65sub RG () { 400/pi2 }
66sub GR () { pi2/400 }
67
68#
69# Truncating remainder.
70#
71
72sub remt ($$) {
73 # Oh yes, POSIX::fmod() would be faster. Possibly. If it is available.
74 $_[0] - $_[1] * int($_[0] / $_[1]);
75}
76
77#
78# Angle conversions.
79#
80
81sub rad2rad($) { remt($_[0], pi2) }
82
83sub deg2deg($) { remt($_[0], 360) }
84
85sub grad2grad($) { remt($_[0], 400) }
86
87sub rad2deg ($;$) { my $d = RD * $_[0]; $_[1] ? $d : deg2deg($d) }
88
89sub deg2rad ($;$) { my $d = DR * $_[0]; $_[1] ? $d : rad2rad($d) }
90
91sub grad2deg ($;$) { my $d = GD * $_[0]; $_[1] ? $d : deg2deg($d) }
92
93sub deg2grad ($;$) { my $d = DG * $_[0]; $_[1] ? $d : grad2grad($d) }
94
95sub rad2grad ($;$) { my $d = RG * $_[0]; $_[1] ? $d : grad2grad($d) }
96
97sub grad2rad ($;$) { my $d = GR * $_[0]; $_[1] ? $d : rad2rad($d) }
98
99sub cartesian_to_spherical {
100 my ( $x, $y, $z ) = @_;
101
102 my $rho = sqrt( $x * $x + $y * $y + $z * $z );
103
104 return ( $rho,
105 atan2( $y, $x ),
106 $rho ? acos( $z / $rho ) : 0 );
107}
108
109sub spherical_to_cartesian {
110 my ( $rho, $theta, $phi ) = @_;
111
112 return ( $rho * cos( $theta ) * sin( $phi ),
113 $rho * sin( $theta ) * sin( $phi ),
114 $rho * cos( $phi ) );
115}
116
117sub spherical_to_cylindrical {
118 my ( $x, $y, $z ) = spherical_to_cartesian( @_ );
119
120 return ( sqrt( $x * $x + $y * $y ), $_[1], $z );
121}
122
123sub cartesian_to_cylindrical {
124 my ( $x, $y, $z ) = @_;
125
126 return ( sqrt( $x * $x + $y * $y ), atan2( $y, $x ), $z );
127}
128
129sub cylindrical_to_cartesian {
130 my ( $rho, $theta, $z ) = @_;
131
132 return ( $rho * cos( $theta ), $rho * sin( $theta ), $z );
133}
134
135sub cylindrical_to_spherical {
136 return ( cartesian_to_spherical( cylindrical_to_cartesian( @_ ) ) );
137}
138
139sub great_circle_distance {
140 my ( $theta0, $phi0, $theta1, $phi1, $rho ) = @_;
141
142 $rho = 1 unless defined $rho; # Default to the unit sphere.
143
144 my $lat0 = pip2 - $phi0;
145 my $lat1 = pip2 - $phi1;
146
147 return $rho *
148 acos(cos( $lat0 ) * cos( $lat1 ) * cos( $theta0 - $theta1 ) +
149 sin( $lat0 ) * sin( $lat1 ) );
150}
151
152sub great_circle_direction {
153 my ( $theta0, $phi0, $theta1, $phi1 ) = @_;
154
155 my $distance = &great_circle_distance;
156
157 my $lat0 = pip2 - $phi0;
158 my $lat1 = pip2 - $phi1;
159
160 my $direction =
161 acos((sin($lat1) - sin($lat0) * cos($distance)) /
162 (cos($lat0) * sin($distance)));
163
164 $direction = pi2 - $direction
165 if sin($theta1 - $theta0) < 0;
166
167 return rad2rad($direction);
168}
169
170*great_circle_bearing = \&great_circle_direction;
171
172sub great_circle_waypoint {
173 my ( $theta0, $phi0, $theta1, $phi1, $point ) = @_;
174
175 $point = 0.5 unless defined $point;
176
177 my $d = great_circle_distance( $theta0, $phi0, $theta1, $phi1 );
178
179 return undef if $d == pi;
180
181 my $sd = sin($d);
182
183 return ($theta0, $phi0) if $sd == 0;
184
185 my $A = sin((1 - $point) * $d) / $sd;
186 my $B = sin( $point * $d) / $sd;
187
188 my $lat0 = pip2 - $phi0;
189 my $lat1 = pip2 - $phi1;
190
191 my $x = $A * cos($lat0) * cos($theta0) + $B * cos($lat1) * cos($theta1);
192 my $y = $A * cos($lat0) * sin($theta0) + $B * cos($lat1) * sin($theta1);
193 my $z = $A * sin($lat0) + $B * sin($lat1);
194
195 my $theta = atan2($y, $x);
196 my $phi = atan2($z, sqrt($x*$x + $y*$y));
197
198 return ($theta, $phi);
199}
200
201sub great_circle_midpoint {
202 great_circle_waypoint(@_[0..3], 0.5);
203}
204
205sub great_circle_destination {
206 my ( $theta0, $phi0, $dir0, $dst ) = @_;
207
208 my $lat0 = pip2 - $phi0;
209
210 my $phi1 = asin(sin($lat0)*cos($dst)+cos($lat0)*sin($dst)*cos($dir0));
211 my $theta1 = $theta0 + atan2(sin($dir0)*sin($dst)*cos($lat0),
212 cos($dst)-sin($lat0)*sin($phi1));
213
214 my $dir1 = great_circle_bearing($theta1, $phi1, $theta0, $phi0) + pi;
215
216 $dir1 -= pi2 if $dir1 > pi2;
217
218 return ($theta1, $phi1, $dir1);
219}
220
2211;
222
223__END__
224=pod
225
226=head1 NAME
227
228Math::Trig - trigonometric functions
229
230=head1 SYNOPSIS
231
232 use Math::Trig;
233
234 $x = tan(0.9);
235 $y = acos(3.7);
236 $z = asin(2.4);
237
238 $halfpi = pi/2;
239
240 $rad = deg2rad(120);
241
242 # Import constants pi2, pip2, pip4 (2*pi, pi/2, pi/4).
243 use Math::Trig ':pi';
244
245 # Import the conversions between cartesian/spherical/cylindrical.
246 use Math::Trig ':radial';
247
248 # Import the great circle formulas.
249 use Math::Trig ':great_circle';
250
251=head1 DESCRIPTION
252
253C<Math::Trig> defines many trigonometric functions not defined by the
254core Perl which defines only the C<sin()> and C<cos()>. The constant
255B<pi> is also defined as are a few convenience functions for angle
256conversions, and I<great circle formulas> for spherical movement.
257
258=head1 TRIGONOMETRIC FUNCTIONS
259
260The tangent
261
262=over 4
263
264=item B<tan>
265
266=back
267
268The cofunctions of the sine, cosine, and tangent (cosec/csc and cotan/cot
269are aliases)
270
271B<csc>, B<cosec>, B<sec>, B<sec>, B<cot>, B<cotan>
272
273The arcus (also known as the inverse) functions of the sine, cosine,
274and tangent
275
276B<asin>, B<acos>, B<atan>
277
278The principal value of the arc tangent of y/x
279
280B<atan2>(y, x)
281
282The arcus cofunctions of the sine, cosine, and tangent (acosec/acsc
283and acotan/acot are aliases)
284
285B<acsc>, B<acosec>, B<asec>, B<acot>, B<acotan>
286
287The hyperbolic sine, cosine, and tangent
288
289B<sinh>, B<cosh>, B<tanh>
290
291The cofunctions of the hyperbolic sine, cosine, and tangent (cosech/csch
292and cotanh/coth are aliases)
293
294B<csch>, B<cosech>, B<sech>, B<coth>, B<cotanh>
295
296The arcus (also known as the inverse) functions of the hyperbolic
297sine, cosine, and tangent
298
299B<asinh>, B<acosh>, B<atanh>
300
301The arcus cofunctions of the hyperbolic sine, cosine, and tangent
302(acsch/acosech and acoth/acotanh are aliases)
303
304B<acsch>, B<acosech>, B<asech>, B<acoth>, B<acotanh>
305
306The trigonometric constant B<pi> is also defined.
307
308$pi2 = 2 * B<pi>;
309
310=head2 ERRORS DUE TO DIVISION BY ZERO
311
312The following functions
313
314 acoth
315 acsc
316 acsch
317 asec
318 asech
319 atanh
320 cot
321 coth
322 csc
323 csch
324 sec
325 sech
326 tan
327 tanh
328
329cannot be computed for all arguments because that would mean dividing
330by zero or taking logarithm of zero. These situations cause fatal
331runtime errors looking like this
332
333 cot(0): Division by zero.
334 (Because in the definition of cot(0), the divisor sin(0) is 0)
335 Died at ...
336
337or
338
339 atanh(-1): Logarithm of zero.
340 Died at...
341
342For the C<csc>, C<cot>, C<asec>, C<acsc>, C<acot>, C<csch>, C<coth>,
343C<asech>, C<acsch>, the argument cannot be C<0> (zero). For the
344C<atanh>, C<acoth>, the argument cannot be C<1> (one). For the
345C<atanh>, C<acoth>, the argument cannot be C<-1> (minus one). For the
346C<tan>, C<sec>, C<tanh>, C<sech>, the argument cannot be I<pi/2 + k *
347pi>, where I<k> is any integer. atan2(0, 0) is undefined.
348
349=head2 SIMPLE (REAL) ARGUMENTS, COMPLEX RESULTS
350
351Please note that some of the trigonometric functions can break out
352from the B<real axis> into the B<complex plane>. For example
353C<asin(2)> has no definition for plain real numbers but it has
354definition for complex numbers.
355
356In Perl terms this means that supplying the usual Perl numbers (also
357known as scalars, please see L<perldata>) as input for the
358trigonometric functions might produce as output results that no more
359are simple real numbers: instead they are complex numbers.
360
361The C<Math::Trig> handles this by using the C<Math::Complex> package
362which knows how to handle complex numbers, please see L<Math::Complex>
363for more information. In practice you need not to worry about getting
364complex numbers as results because the C<Math::Complex> takes care of
365details like for example how to display complex numbers. For example:
366
367 print asin(2), "\n";
368
369should produce something like this (take or leave few last decimals):
370
371 1.5707963267949-1.31695789692482i
372
373That is, a complex number with the real part of approximately C<1.571>
374and the imaginary part of approximately C<-1.317>.
375
376=head1 PLANE ANGLE CONVERSIONS
377
378(Plane, 2-dimensional) angles may be converted with the following functions.
379
380 $radians = deg2rad($degrees);
381 $radians = grad2rad($gradians);
382
383 $degrees = rad2deg($radians);
384 $degrees = grad2deg($gradians);
385
386 $gradians = deg2grad($degrees);
387 $gradians = rad2grad($radians);
388
389The full circle is 2 I<pi> radians or I<360> degrees or I<400> gradians.
390The result is by default wrapped to be inside the [0, {2pi,360,400}[ circle.
391If you don't want this, supply a true second argument:
392
393 $zillions_of_radians = deg2rad($zillions_of_degrees, 1);
394 $negative_degrees = rad2deg($negative_radians, 1);
395
396You can also do the wrapping explicitly by rad2rad(), deg2deg(), and
397grad2grad().
398
399=head1 RADIAL COORDINATE CONVERSIONS
400
401B<Radial coordinate systems> are the B<spherical> and the B<cylindrical>
402systems, explained shortly in more detail.
403
404You can import radial coordinate conversion functions by using the
405C<:radial> tag:
406
407 use Math::Trig ':radial';
408
409 ($rho, $theta, $z) = cartesian_to_cylindrical($x, $y, $z);
410 ($rho, $theta, $phi) = cartesian_to_spherical($x, $y, $z);
411 ($x, $y, $z) = cylindrical_to_cartesian($rho, $theta, $z);
412 ($rho_s, $theta, $phi) = cylindrical_to_spherical($rho_c, $theta, $z);
413 ($x, $y, $z) = spherical_to_cartesian($rho, $theta, $phi);
414 ($rho_c, $theta, $z) = spherical_to_cylindrical($rho_s, $theta, $phi);
415
416B<All angles are in radians>.
417
418=head2 COORDINATE SYSTEMS
419
420B<Cartesian> coordinates are the usual rectangular I<(x, y, z)>-coordinates.
421
422Spherical coordinates, I<(rho, theta, pi)>, are three-dimensional
423coordinates which define a point in three-dimensional space. They are
424based on a sphere surface. The radius of the sphere is B<rho>, also
425known as the I<radial> coordinate. The angle in the I<xy>-plane
426(around the I<z>-axis) is B<theta>, also known as the I<azimuthal>
427coordinate. The angle from the I<z>-axis is B<phi>, also known as the
428I<polar> coordinate. The North Pole is therefore I<0, 0, rho>, and
429the Gulf of Guinea (think of the missing big chunk of Africa) I<0,
430pi/2, rho>. In geographical terms I<phi> is latitude (northward
431positive, southward negative) and I<theta> is longitude (eastward
432positive, westward negative).
433
434B<BEWARE>: some texts define I<theta> and I<phi> the other way round,
435some texts define the I<phi> to start from the horizontal plane, some
436texts use I<r> in place of I<rho>.
437
438Cylindrical coordinates, I<(rho, theta, z)>, are three-dimensional
439coordinates which define a point in three-dimensional space. They are
440based on a cylinder surface. The radius of the cylinder is B<rho>,
441also known as the I<radial> coordinate. The angle in the I<xy>-plane
442(around the I<z>-axis) is B<theta>, also known as the I<azimuthal>
443coordinate. The third coordinate is the I<z>, pointing up from the
444B<theta>-plane.
445
446=head2 3-D ANGLE CONVERSIONS
447
448Conversions to and from spherical and cylindrical coordinates are
449available. Please notice that the conversions are not necessarily
450reversible because of the equalities like I<pi> angles being equal to
451I<-pi> angles.
452
453=over 4
454
455=item cartesian_to_cylindrical
456
457 ($rho, $theta, $z) = cartesian_to_cylindrical($x, $y, $z);
458
459=item cartesian_to_spherical
460
461 ($rho, $theta, $phi) = cartesian_to_spherical($x, $y, $z);
462
463=item cylindrical_to_cartesian
464
465 ($x, $y, $z) = cylindrical_to_cartesian($rho, $theta, $z);
466
467=item cylindrical_to_spherical
468
469 ($rho_s, $theta, $phi) = cylindrical_to_spherical($rho_c, $theta, $z);
470
471Notice that when C<$z> is not 0 C<$rho_s> is not equal to C<$rho_c>.
472
473=item spherical_to_cartesian
474
475 ($x, $y, $z) = spherical_to_cartesian($rho, $theta, $phi);
476
477=item spherical_to_cylindrical
478
479 ($rho_c, $theta, $z) = spherical_to_cylindrical($rho_s, $theta, $phi);
480
481Notice that when C<$z> is not 0 C<$rho_c> is not equal to C<$rho_s>.
482
483=back
484
485=head1 GREAT CIRCLE DISTANCES AND DIRECTIONS
486
487You can compute spherical distances, called B<great circle distances>,
488by importing the great_circle_distance() function:
489
490 use Math::Trig 'great_circle_distance';
491
492 $distance = great_circle_distance($theta0, $phi0, $theta1, $phi1, [, $rho]);
493
494The I<great circle distance> is the shortest distance between two
495points on a sphere. The distance is in C<$rho> units. The C<$rho> is
496optional, it defaults to 1 (the unit sphere), therefore the distance
497defaults to radians.
498
499If you think geographically the I<theta> are longitudes: zero at the
500Greenwhich meridian, eastward positive, westward negative--and the
501I<phi> are latitudes: zero at the North Pole, northward positive,
502southward negative. B<NOTE>: this formula thinks in mathematics, not
503geographically: the I<phi> zero is at the North Pole, not at the
504Equator on the west coast of Africa (Bay of Guinea). You need to
505subtract your geographical coordinates from I<pi/2> (also known as 90
506degrees).
507
508 $distance = great_circle_distance($lon0, pi/2 - $lat0,
509 $lon1, pi/2 - $lat1, $rho);
510
511The direction you must follow the great circle (also known as I<bearing>)
512can be computed by the great_circle_direction() function:
513
514 use Math::Trig 'great_circle_direction';
515
516 $direction = great_circle_direction($theta0, $phi0, $theta1, $phi1);
517
518(Alias 'great_circle_bearing' is also available.)
519The result is in radians, zero indicating straight north, pi or -pi
520straight south, pi/2 straight west, and -pi/2 straight east.
521
522You can inversely compute the destination if you know the
523starting point, direction, and distance:
524
525 use Math::Trig 'great_circle_destination';
526
527 # thetad and phid are the destination coordinates,
528 # dird is the final direction at the destination.
529
530 ($thetad, $phid, $dird) =
531 great_circle_destination($theta, $phi, $direction, $distance);
532
533or the midpoint if you know the end points:
534
535 use Math::Trig 'great_circle_midpoint';
536
537 ($thetam, $phim) =
538 great_circle_midpoint($theta0, $phi0, $theta1, $phi1);
539
540The great_circle_midpoint() is just a special case of
541
542 use Math::Trig 'great_circle_waypoint';
543
544 ($thetai, $phii) =
545 great_circle_waypoint($theta0, $phi0, $theta1, $phi1, $way);
546
547Where the $way is a value from zero ($theta0, $phi0) to one ($theta1,
548$phi1). Note that antipodal points (where their distance is I<pi>
549radians) do not have waypoints between them (they would have an an
550"equator" between them), and therefore C<undef> is returned for
551antipodal points. If the points are the same and the distance
552therefore zero and all waypoints therefore identical, the first point
553(either point) is returned.
554
555The thetas, phis, direction, and distance in the above are all in radians.
556
557You can import all the great circle formulas by
558
559 use Math::Trig ':great_circle';
560
561Notice that the resulting directions might be somewhat surprising if
562you are looking at a flat worldmap: in such map projections the great
563circles quite often do not look like the shortest routes-- but for
564example the shortest possible routes from Europe or North America to
565Asia do often cross the polar regions.
566
567=head1 EXAMPLES
568
569To calculate the distance between London (51.3N 0.5W) and Tokyo
570(35.7N 139.8E) in kilometers:
571
572 use Math::Trig qw(great_circle_distance deg2rad);
573
574 # Notice the 90 - latitude: phi zero is at the North Pole.
575 sub NESW { deg2rad($_[0]), deg2rad(90 - $_[1]) }
576 my @L = NESW( -0.5, 51.3);
577 my @T = NESW(139.8, 35.7);
578 my $km = great_circle_distance(@L, @T, 6378); # About 9600 km.
579
580The direction you would have to go from London to Tokyo (in radians,
581straight north being zero, straight east being pi/2).
582
583 use Math::Trig qw(great_circle_direction);
584
585 my $rad = great_circle_direction(@L, @T); # About 0.547 or 0.174 pi.
586
587The midpoint between London and Tokyo being
588
589 use Math::Trig qw(great_circle_midpoint);
590
591 my @M = great_circle_midpoint(@L, @T);
592
593or about 68.11N 24.74E, in the Finnish Lapland.
594
595=head2 CAVEAT FOR GREAT CIRCLE FORMULAS
596
597The answers may be off by few percentages because of the irregular
598(slightly aspherical) form of the Earth. The errors are at worst
599about 0.55%, but generally below 0.3%.
600
601=head1 BUGS
602
603Saying C<use Math::Trig;> exports many mathematical routines in the
604caller environment and even overrides some (C<sin>, C<cos>). This is
605construed as a feature by the Authors, actually... ;-)
606
607The code is not optimized for speed, especially because we use
608C<Math::Complex> and thus go quite near complex numbers while doing
609the computations even when the arguments are not. This, however,
610cannot be completely avoided if we want things like C<asin(2)> to give
611an answer instead of giving a fatal runtime error.
612
613Do not attempt navigation using these formulas.
614
615=head1 AUTHORS
616
617Jarkko Hietaniemi <F<jhi@iki.fi>> and
618Raphael Manfredi <F<Raphael_Manfredi@pobox.com>>.
619
620=cut
621
622# eof