1#!./perl
2
3#
4# Regression tests for the Math::Trig package
5#
6# The tests here are quite modest as the Math::Complex tests exercise
7# these interfaces quite vigorously.
8#
9# -- Jarkko Hietaniemi, April 1997
10
11BEGIN {
12    if ($ENV{PERL_CORE}) {
13	chdir 't' if -d 't';
14	@INC = '../lib';
15    }
16}
17
18use Math::Trig 1.03;
19
20my $pip2 = pi / 2;
21
22use strict;
23
24use vars qw($x $y $z);
25
26my $eps = 1e-11;
27
28if ($^O eq 'unicos') { # See lib/Math/Complex.pm and t/lib/complex.t.
29    $eps = 1e-10;
30}
31
32sub near ($$;$) {
33    my $e = defined $_[2] ? $_[2] : $eps;
34    print "# near? $_[0] $_[1] $e\n";
35    $_[1] ? (abs($_[0]/$_[1] - 1) < $e) : abs($_[0]) < $e;
36}
37
38print "1..49\n";
39
40$x = 0.9;
41print 'not ' unless (near(tan($x), sin($x) / cos($x)));
42print "ok 1\n";
43
44print 'not ' unless (near(sinh(2), 3.62686040784702));
45print "ok 2\n";
46
47print 'not ' unless (near(acsch(0.1), 2.99822295029797));
48print "ok 3\n";
49
50$x = asin(2);
51print 'not ' unless (ref $x eq 'Math::Complex');
52print "ok 4\n";
53
54# avoid using Math::Complex here
55$x =~ /^([^-]+)(-[^i]+)i$/;
56($y, $z) = ($1, $2);
57print 'not ' unless (near($y,  1.5707963267949) and
58		     near($z, -1.31695789692482));
59print "ok 5\n";
60
61print 'not ' unless (near(deg2rad(90), pi/2));
62print "ok 6\n";
63
64print 'not ' unless (near(rad2deg(pi), 180));
65print "ok 7\n";
66
67use Math::Trig ':radial';
68
69{
70    my ($r,$t,$z) = cartesian_to_cylindrical(1,1,1);
71
72    print 'not ' unless (near($r, sqrt(2)))     and
73	                (near($t, deg2rad(45))) and
74			(near($z, 1));
75    print "ok 8\n";
76
77    ($x,$y,$z) = cylindrical_to_cartesian($r, $t, $z);
78
79    print 'not ' unless (near($x, 1)) and
80	                (near($y, 1)) and
81			(near($z, 1));
82    print "ok 9\n";
83
84    ($r,$t,$z) = cartesian_to_cylindrical(1,1,0);
85
86    print 'not ' unless (near($r, sqrt(2)))     and
87	                (near($t, deg2rad(45))) and
88			(near($z, 0));
89    print "ok 10\n";
90
91    ($x,$y,$z) = cylindrical_to_cartesian($r, $t, $z);
92
93    print 'not ' unless (near($x, 1)) and
94	                (near($y, 1)) and
95			(near($z, 0));
96    print "ok 11\n";
97}
98
99{
100    my ($r,$t,$f) = cartesian_to_spherical(1,1,1);
101
102    print 'not ' unless (near($r, sqrt(3)))     and
103	                (near($t, deg2rad(45))) and
104			(near($f, atan2(sqrt(2), 1)));
105    print "ok 12\n";
106
107    ($x,$y,$z) = spherical_to_cartesian($r, $t, $f);
108
109    print 'not ' unless (near($x, 1)) and
110	                (near($y, 1)) and
111			(near($z, 1));
112    print "ok 13\n";
113
114    ($r,$t,$f) = cartesian_to_spherical(1,1,0);
115
116    print 'not ' unless (near($r, sqrt(2)))     and
117	                (near($t, deg2rad(45))) and
118			(near($f, deg2rad(90)));
119    print "ok 14\n";
120
121    ($x,$y,$z) = spherical_to_cartesian($r, $t, $f);
122
123    print 'not ' unless (near($x, 1)) and
124	                (near($y, 1)) and
125			(near($z, 0));
126    print "ok 15\n";
127}
128
129{
130    my ($r,$t,$z) = cylindrical_to_spherical(spherical_to_cylindrical(1,1,1));
131
132    print 'not ' unless (near($r, 1)) and
133	                (near($t, 1)) and
134			(near($z, 1));
135    print "ok 16\n";
136
137    ($r,$t,$z) = spherical_to_cylindrical(cylindrical_to_spherical(1,1,1));
138
139    print 'not ' unless (near($r, 1)) and
140	                (near($t, 1)) and
141			(near($z, 1));
142    print "ok 17\n";
143}
144
145{
146    use Math::Trig 'great_circle_distance';
147
148    print 'not '
149	unless (near(great_circle_distance(0, 0, 0, pi/2), pi/2));
150    print "ok 18\n";
151
152    print 'not '
153	unless (near(great_circle_distance(0, 0, pi, pi), pi));
154    print "ok 19\n";
155
156    # London to Tokyo.
157    my @L = (deg2rad(-0.5), deg2rad(90 - 51.3));
158    my @T = (deg2rad(139.8),deg2rad(90 - 35.7));
159
160    my $km = great_circle_distance(@L, @T, 6378);
161
162    print 'not ' unless (near($km, 9605.26637021388));
163    print "ok 20\n";
164}
165
166{
167    my $R2D = 57.295779513082320876798154814169;
168
169    sub frac { $_[0] - int($_[0]) }
170
171    my $lotta_radians = deg2rad(1E+20, 1);
172    print "not " unless near($lotta_radians,  1E+20/$R2D);
173    print "ok 21\n";
174
175    my $negat_degrees = rad2deg(-1E20, 1);
176    print "not " unless near($negat_degrees, -1E+20*$R2D);
177    print "ok 22\n";
178
179    my $posit_degrees = rad2deg(-10000, 1);
180    print "not " unless near($posit_degrees, -10000*$R2D);
181    print "ok 23\n";
182}
183
184{
185    use Math::Trig 'great_circle_direction';
186
187    print 'not '
188	unless (near(great_circle_direction(0, 0, 0, pi/2), pi));
189    print "ok 24\n";
190
191# Retired test: Relies on atan2(0, 0), which is not portable.
192#    print 'not '
193#	unless (near(great_circle_direction(0, 0, pi, pi), -pi()/2));
194    print "ok 25\n";
195
196    my @London  = (deg2rad(  -0.167), deg2rad(90 - 51.3));
197    my @Tokyo   = (deg2rad( 139.5),   deg2rad(90 - 35.7));
198    my @Berlin  = (deg2rad ( 13.417), deg2rad(90 - 52.533));
199    my @Paris   = (deg2rad (  2.333), deg2rad(90 - 48.867));
200
201    print 'not '
202	unless (near(rad2deg(great_circle_direction(@London, @Tokyo)),
203		     31.791945393073));
204    print "ok 26\n";
205
206    print 'not '
207	unless (near(rad2deg(great_circle_direction(@Tokyo, @London)),
208		     336.069766430326));
209    print "ok 27\n";
210
211    print 'not '
212	unless (near(rad2deg(great_circle_direction(@Berlin, @Paris)),
213		     246.800348034667));
214
215    print "ok 28\n";
216
217    print 'not '
218	unless (near(rad2deg(great_circle_direction(@Paris, @Berlin)),
219		     58.2079877553156));
220    print "ok 29\n";
221
222    use Math::Trig 'great_circle_bearing';
223
224    print 'not '
225	unless (near(rad2deg(great_circle_bearing(@Paris, @Berlin)),
226		     58.2079877553156));
227    print "ok 30\n";
228
229    use Math::Trig 'great_circle_waypoint';
230    use Math::Trig 'great_circle_midpoint';
231
232    my ($lon, $lat);
233
234    ($lon, $lat) = great_circle_waypoint(@London, @Tokyo, 0.0);
235
236    print 'not ' unless (near($lon, $London[0]));
237    print "ok 31\n";
238
239    print 'not ' unless (near($lat, $pip2 - $London[1]));
240    print "ok 32\n";
241
242    ($lon, $lat) = great_circle_waypoint(@London, @Tokyo, 1.0);
243
244    print 'not ' unless (near($lon, $Tokyo[0]));
245    print "ok 33\n";
246
247    print 'not ' unless (near($lat, $pip2 - $Tokyo[1]));
248    print "ok 34\n";
249
250    ($lon, $lat) = great_circle_waypoint(@London, @Tokyo, 0.5);
251
252    print 'not ' unless (near($lon, 1.55609593577679)); # 89.1577 E
253    print "ok 35\n";
254
255    print 'not ' unless (near($lat, 1.20296099733328)); # 68.9246 N
256    print "ok 36\n";
257
258    ($lon, $lat) = great_circle_midpoint(@London, @Tokyo);
259
260    print 'not ' unless (near($lon, 1.55609593577679)); # 89.1577 E
261    print "ok 37\n";
262
263    print 'not ' unless (near($lat, 1.20296099733328)); # 68.9246 N
264    print "ok 38\n";
265
266    ($lon, $lat) = great_circle_waypoint(@London, @Tokyo, 0.25);
267
268    print 'not ' unless (near($lon, 0.516073562850837)); # 29.5688 E
269    print "ok 39\n";
270
271    print 'not ' unless (near($lat, 1.170565013391510)); # 67.0684 N
272    print "ok 40\n";
273    ($lon, $lat) = great_circle_waypoint(@London, @Tokyo, 0.75);
274
275    print 'not ' unless (near($lon, 2.17494903805952)); # 124.6154 E
276    print "ok 41\n";
277
278    print 'not ' unless (near($lat, 0.952987032741305)); # 54.6021 N
279    print "ok 42\n";
280
281    use Math::Trig 'great_circle_destination';
282
283    my $dir1 = great_circle_direction(@London, @Tokyo);
284    my $dst1 = great_circle_distance(@London,  @Tokyo);
285
286    ($lon, $lat) = great_circle_destination(@London, $dir1, $dst1);
287
288    print 'not ' unless (near($lon, $Tokyo[0]));
289    print "ok 43\n";
290
291    print 'not ' unless (near($lat, $pip2 - $Tokyo[1]));
292    print "ok 44\n";
293
294    my $dir2 = great_circle_direction(@Tokyo, @London);
295    my $dst2 = great_circle_distance(@Tokyo,  @London);
296
297    ($lon, $lat) = great_circle_destination(@Tokyo, $dir2, $dst2);
298
299    print 'not ' unless (near($lon, $London[0]));
300    print "ok 45\n";
301
302    print 'not ' unless (near($lat, $pip2 - $London[1]));
303    print "ok 46\n";
304
305    my $dir3 = (great_circle_destination(@London, $dir1, $dst1))[2];
306
307    print 'not ' unless (near($dir3, 2.69379263839118)); # about 154.343 deg
308    print "ok 47\n";
309
310    my $dir4 = (great_circle_destination(@Tokyo,  $dir2, $dst2))[2];
311
312    print 'not ' unless (near($dir4, 3.6993902625701)); # about 211.959 deg
313    print "ok 48\n";
314
315    print 'not ' unless (near($dst1, $dst2));
316    print "ok 49\n";
317}
318
319# eof
320