Fortran library for Geodesics 2.1
Loading...
Searching...
No Matches
geodesic.for
Go to the documentation of this file.
1* The subroutines in this files are documented at
2* https://geographiclib.sourceforge.io/Fortran/doc/index.html
3*
4*> @file geodesic.for
5*! @brief Implementation of geodesic routines in Fortran
6*!
7*! This is a Fortran implementation of the geodesic algorithms described
8*! in
9*! - C. F. F. Karney,
10*! <a href="https://doi.org/10.1007/s00190-012-0578-z">
11*! Algorithms for geodesics</a>,
12*! J. Geodesy <b>87</b>, 43--55 (2013);
13*! DOI: <a href="https://doi.org/10.1007/s00190-012-0578-z">
14*! 10.1007/s00190-012-0578-z</a>;
15*! <a href=
16*! "https://geographiclib.sourceforge.io/geod-addenda.html">
17*! addenda</a>.
18*! .
19*! The principal advantages of these algorithms over previous ones
20*! (e.g., Vincenty, 1975) are
21*! - accurate to round off for |<i>f</i>| &lt; 1/50;
22*! - the solution of the inverse problem is always found;
23*! - differential and integral properties of geodesics are computed.
24*!
25*! The shortest path between two points on the ellipsoid at (\e lat1, \e
26*! lon1) and (\e lat2, \e lon2) is called the geodesic. Its length is
27*! \e s12 and the geodesic from point 1 to point 2 has forward azimuths
28*! \e azi1 and \e azi2 at the two end points.
29*!
30*! Traditionally two geodesic problems are considered:
31*! - the direct problem -- given \e lat1, \e lon1, \e s12, and \e azi1,
32*! determine \e lat2, \e lon2, and \e azi2. This is solved by the
33*! subroutine direct().
34*! - the inverse problem -- given \e lat1, \e lon1, \e lat2, \e lon2,
35*! determine \e s12, \e azi1, and \e azi2. This is solved by the
36*! subroutine invers().
37*!
38*! The ellipsoid is specified by its equatorial radius \e a (typically
39*! in meters) and flattening \e f. The routines are accurate to round
40*! off with double precision arithmetic provided that |<i>f</i>| &lt;
41*! 1/50; for the WGS84 ellipsoid, the errors are less than 15
42*! nanometers. (Reasonably accurate results are obtained for |<i>f</i>|
43*! &lt; 1/5.) For a prolate ellipsoid, specify \e f &lt; 0.
44*!
45*! The routines also calculate several other quantities of interest
46*! - \e SS12 is the area between the geodesic from point 1 to point 2
47*! and the equator; i.e., it is the area, measured counter-clockwise,
48*! of the geodesic quadrilateral with corners (\e lat1,\e lon1), (0,\e
49*! lon1), (0,\e lon2), and (\e lat2,\e lon2).
50*! - \e m12, the reduced length of the geodesic is defined such that if
51*! the initial azimuth is perturbed by \e dazi1 (radians) then the
52*! second point is displaced by \e m12 \e dazi1 in the direction
53*! perpendicular to the geodesic. On a curved surface the reduced
54*! length obeys a symmetry relation, \e m12 + \e m21 = 0. On a flat
55*! surface, we have \e m12 = \e s12.
56*! - \e MM12 and \e MM21 are geodesic scales. If two geodesics are
57*! parallel at point 1 and separated by a small distance \e dt, then
58*! they are separated by a distance \e MM12 \e dt at point 2. \e MM21
59*! is defined similarly (with the geodesics being parallel to one
60*! another at point 2). On a flat surface, we have \e MM12 = \e MM21
61*! = 1.
62*! - \e a12 is the arc length on the auxiliary sphere. This is a
63*! construct for converting the problem to one in spherical
64*! trigonometry. \e a12 is measured in degrees. The spherical arc
65*! length from one equator crossing to the next is always 180&deg;.
66*!
67*! If points 1, 2, and 3 lie on a single geodesic, then the following
68*! addition rules hold:
69*! - \e s13 = \e s12 + \e s23
70*! - \e a13 = \e a12 + \e a23
71*! - \e SS13 = \e SS12 + \e SS23
72*! - \e m13 = \e m12 \e MM23 + \e m23 \e MM21
73*! - \e MM13 = \e MM12 \e MM23 &minus; (1 &minus; \e MM12 \e MM21) \e
74*! m23 / \e m12
75*! - \e MM31 = \e MM32 \e MM21 &minus; (1 &minus; \e MM23 \e MM32) \e
76*! m12 / \e m23
77*!
78*! The shortest distance returned by the solution of the inverse problem
79*! is (obviously) uniquely defined. However, in a few special cases
80*! there are multiple azimuths which yield the same shortest distance.
81*! Here is a catalog of those cases:
82*! - \e lat1 = &minus;\e lat2 (with neither point at a pole). If \e
83*! azi1 = \e azi2, the geodesic is unique. Otherwise there are two
84*! geodesics and the second one is obtained by setting [\e azi1, \e
85*! azi2] &rarr; [\e azi2, \e azi1], [\e MM12, \e MM21] &rarr; [\e
86*! MM21, \e MM12], \e SS12 &rarr; &minus;\e SS12. (This occurs when
87*! the longitude difference is near &plusmn;180&deg; for oblate
88*! ellipsoids.)
89*! - \e lon2 = \e lon1 &plusmn; 180&deg; (with neither point at a pole).
90*! If \e azi1 = 0&deg; or &plusmn;180&deg;, the geodesic is unique.
91*! Otherwise there are two geodesics and the second one is obtained by
92*! setting [\e azi1, \e azi2] &rarr; [&minus;\e azi1, &minus;\e azi2],
93*! \e SS12 &rarr; &minus;\e SS12. (This occurs when \e lat2 is near
94*! &minus;\e lat1 for prolate ellipsoids.)
95*! - Points 1 and 2 at opposite poles. There are infinitely many
96*! geodesics which can be generated by setting [\e azi1, \e azi2]
97*! &rarr; [\e azi1, \e azi2] + [\e d, &minus;\e d], for arbitrary \e
98*! d. (For spheres, this prescription applies when points 1 and 2 are
99*! antipodal.)
100*! - \e s12 = 0 (coincident points). There are infinitely many
101*! geodesics which can be generated by setting [\e azi1, \e azi2]
102*! &rarr; [\e azi1, \e azi2] + [\e d, \e d], for arbitrary \e d.
103*!
104*! These routines are a simple transcription of the corresponding C++
105*! classes in <a href="https://geographiclib.sourceforge.io">
106*! GeographicLib</a>. Because of the limitations of Fortran 77, the
107*! classes have been replaced by simple subroutines with no attempt to
108*! save "state" across subroutine calls. Most of the internal comments
109*! have been retained. However, in the process of transcription some
110*! documentation has been lost and the documentation for the C++
111*! classes, GeographicLib::Geodesic, GeographicLib::GeodesicLine, and
112*! GeographicLib::PolygonAreaT, should be consulted. The C++ code
113*! remains the "reference implementation". Think twice about
114*! restructuring the internals of the Fortran code since this may make
115*! porting fixes from the C++ code more difficult.
116*!
117*! Copyright (c) Charles Karney (2012-2025) <karney@alum.mit.edu> and
118*! licensed under the MIT/X11 License. For more information, see
119*! https://geographiclib.sourceforge.io/
120
121*> Solve the direct geodesic problem
122*!
123*! @param[in] a the equatorial radius (meters).
124*! @param[in] f the flattening of the ellipsoid. Setting \e f = 0 gives
125*! a sphere. Negative \e f gives a prolate ellipsoid.
126*! @param[in] lat1 latitude of point 1 (degrees).
127*! @param[in] lon1 longitude of point 1 (degrees).
128*! @param[in] azi1 azimuth at point 1 (degrees).
129*! @param[in] s12a12 if \e arcmode is not set, this is the distance
130*! from point 1 to point 2 (meters); otherwise it is the arc
131*! length from point 1 to point 2 (degrees); it can be negative.
132*! @param[in] flags a bitor'ed combination of the \e arcmode and \e
133*! unroll flags.
134*! @param[out] lat2 latitude of point 2 (degrees).
135*! @param[out] lon2 longitude of point 2 (degrees).
136*! @param[out] azi2 (forward) azimuth at point 2 (degrees).
137*! @param[in] omask a bitor'ed combination of mask values
138*! specifying which of the following parameters should be set.
139*! @param[out] a12s12 if \e arcmode is not set, this is the arc length
140*! from point 1 to point 2 (degrees); otherwise it is the distance
141*! from point 1 to point 2 (meters).
142*! @param[out] m12 reduced length of geodesic (meters).
143*! @param[out] MM12 geodesic scale of point 2 relative to point 1
144*! (dimensionless).
145*! @param[out] MM21 geodesic scale of point 1 relative to point 2
146*! (dimensionless).
147*! @param[out] SS12 area under the geodesic (meters<sup>2</sup>).
148*!
149*! \e flags is an integer in [0, 4) whose binary bits are interpreted
150*! as follows
151*! - 1 the \e arcmode flag
152*! - 2 the \e unroll flag
153*! .
154*! If \e arcmode is not set, \e s12a12 is \e s12 and \e a12s12 is \e
155*! a12; otherwise, \e s12a12 is \e a12 and \e a12s12 is \e s12. It \e
156*! unroll is not set, the value \e lon2 returned is in the range
157*! [&minus;180&deg;, 180&deg;]; if unroll is set, the longitude variable
158*! is "unrolled" so that \e lon2 &minus; \e lon1 indicates how many
159*! times and in what sense the geodesic encircles the ellipsoid.
160*!
161*! \e omask is an integer in [0, 16) whose binary bits are interpreted
162*! as follows
163*! - 1 return \e a12
164*! - 2 return \e m12
165*! - 4 return \e MM12 and \e MM21
166*! - 8 return \e SS12
167*!
168*! \e lat1 should be in the range [&minus;90&deg;, 90&deg;]. The value
169*! \e azi2 returned is in the range [&minus;180&deg;, 180&deg;].
170*!
171*! If either point is at a pole, the azimuth is defined by keeping the
172*! longitude fixed, writing \e lat = \e lat = &plusmn;(90&deg; &minus;
173*! &epsilon;), and taking the limit &epsilon; &rarr; 0+. An arc length
174*! greater that 180&deg; signifies a geodesic which is not a shortest
175*! path. (For a prolate ellipsoid, an additional condition is necessary
176*! for a shortest path: the longitudinal extent must not exceed of
177*! 180&deg;.)
178*!
179*! Example of use:
180*! \include geoddirect.for
181
182 subroutine direct(a, f, lat1, lon1, azi1, s12a12, flags,
183 + lat2, lon2, azi2, omask, a12s12, m12, MM12, MM21, SS12)
184* input
185 double precision a, f, lat1, lon1, azi1, s12a12
186 integer flags, omask
187* output
188 double precision lat2, lon2, azi2
189* optional output
190 double precision a12s12, m12, MM12, MM21, SS12
191
192 integer ord, nC1, nC1p, nC2, nA3, nA3x, nC3, nC3x, nC4, nC4x
193 parameter(ord = 6, nc1 = ord, nc1p = ord,
194 + nc2 = ord, na3 = ord, na3x = na3,
195 + nc3 = ord, nc3x = (nc3 * (nc3 - 1)) / 2,
196 + nc4 = ord, nc4x = (nc4 * (nc4 + 1)) / 2)
197 double precision A3x(0:nA3x-1), C3x(0:nC3x-1), C4x(0:nC4x-1),
198 + c1a(nc1), c1pa(nc1p), c2a(nc2), c3a(nc3-1), c4a(0:nc4-1)
199
200 double precision atanhx, hypotx,
201 + angnm, angrnd, trgsum, a1m1f, a2m1f, a3f, atn2dx, latfix
202 logical arcmod, unroll, arcp, redlp, scalp, areap
203 double precision e2, f1, ep2, n, b, c2,
204 + salp0, calp0, k2, eps,
205 + salp1, calp1, ssig1, csig1, cbet1, sbet1, dn1, somg1, comg1,
206 + salp2, calp2, ssig2, csig2, sbet2, cbet2, dn2, somg2, comg2,
207 + ssig12, csig12, salp12, calp12, omg12, lam12, lon12,
208 + sig12, stau1, ctau1, tau12, t, s, c, serr, e,
209 + a1m1, a2m1, a3c, a4, ab1, ab2,
210 + b11, b12, b21, b22, b31, b41, b42, j12
211
212 double precision dblmin, dbleps, pi, degree, tiny,
213 + tol0, tol1, tol2, tolb, xthrsh
214 integer digits, maxit1, maxit2
215 logical init
216 common /geocom/ dblmin, dbleps, pi, degree, tiny,
217 + tol0, tol1, tol2, tolb, xthrsh, digits, maxit1, maxit2, init
218
219 if (.not.init) call geoini
220
221 e2 = f * (2 - f)
222 ep2 = e2 / (1 - e2)
223 f1 = 1 - f
224 n = f / (2 - f)
225 b = a * f1
226 c2 = 0
227
228 arcmod = mod(flags/1, 2) .eq. 1
229 unroll = mod(flags/2, 2) .eq. 1
230
231 arcp = mod(omask/1, 2) .eq. 1
232 redlp = mod(omask/2, 2) .eq. 1
233 scalp = mod(omask/4, 2) .eq. 1
234 areap = mod(omask/8, 2) .eq. 1
235
236 if (areap) then
237 if (e2 .eq. 0) then
238 c2 = a**2
239 else if (e2 .gt. 0) then
240 c2 = (a**2 + b**2 * atanhx(sqrt(e2)) / sqrt(e2)) / 2
241 else
242 c2 = (a**2 + b**2 * atan(sqrt(abs(e2))) / sqrt(abs(e2))) / 2
243 end if
244 end if
245
246 call a3cof(n, a3x)
247 call c3cof(n, c3x)
248 if (areap) call c4cof(n, c4x)
249
250* Guard against underflow in salp0
251 call sncsdx(angrnd(azi1), salp1, calp1)
252
253 call sncsdx(angrnd(latfix(lat1)), sbet1, cbet1)
254 sbet1 = f1 * sbet1
255 call norm2x(sbet1, cbet1)
256* Ensure cbet1 = +dbleps at poles
257 cbet1 = max(tiny, cbet1)
258 dn1 = sqrt(1 + ep2 * sbet1**2)
259
260* Evaluate alp0 from sin(alp1) * cos(bet1) = sin(alp0),
261* alp0 in [0, pi/2 - |bet1|]
262 salp0 = salp1 * cbet1
263* Alt: calp0 = hypot(sbet1, calp1 * cbet1). The following
264* is slightly better (consider the case salp1 = 0).
265 calp0 = hypotx(calp1, salp1 * sbet1)
266* Evaluate sig with tan(bet1) = tan(sig1) * cos(alp1).
267* sig = 0 is nearest northward crossing of equator.
268* With bet1 = 0, alp1 = pi/2, we have sig1 = 0 (equatorial line).
269* With bet1 = pi/2, alp1 = -pi, sig1 = pi/2
270* With bet1 = -pi/2, alp1 = 0 , sig1 = -pi/2
271* Evaluate omg1 with tan(omg1) = sin(alp0) * tan(sig1).
272* With alp0 in (0, pi/2], quadrants for sig and omg coincide.
273* No atan2(0,0) ambiguity at poles since cbet1 = +dbleps.
274* With alp0 = 0, omg1 = 0 for alp1 = 0, omg1 = pi for alp1 = pi.
275 ssig1 = sbet1
276 somg1 = salp0 * sbet1
277 if (sbet1 .ne. 0 .or. calp1 .ne. 0) then
278 csig1 = cbet1 * calp1
279 else
280 csig1 = 1
281 end if
282 comg1 = csig1
283* sig1 in (-pi, pi]
284 call norm2x(ssig1, csig1)
285* norm2x(somg1, comg1); -- don't need to normalize!
286
287 k2 = calp0**2 * ep2
288 eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2)
289
290 a1m1 = a1m1f(eps)
291 call c1f(eps, c1a)
292 b11 = trgsum(.true., ssig1, csig1, c1a, nc1)
293 s = sin(b11)
294 c = cos(b11)
295* tau1 = sig1 + B11
296 stau1 = ssig1 * c + csig1 * s
297 ctau1 = csig1 * c - ssig1 * s
298* Not necessary because C1pa reverts C1a
299* B11 = -TrgSum(true, stau1, ctau1, C1pa, nC1p)
300
301 if (.not. arcmod) call c1pf(eps, c1pa)
302
303 if (redlp .or. scalp) then
304 a2m1 = a2m1f(eps)
305 call c2f(eps, c2a)
306 b21 = trgsum(.true., ssig1, csig1, c2a, nc2)
307 else
308* Suppress bogus warnings about unitialized variables
309 a2m1 = 0
310 b21 = 0
311 end if
312
313 call c3f(eps, c3x, c3a)
314 a3c = -f * salp0 * a3f(eps, a3x)
315 b31 = trgsum(.true., ssig1, csig1, c3a, nc3-1)
316
317 if (areap) then
318 call c4f(eps, c4x, c4a)
319* Multiplier = a^2 * e^2 * cos(alpha0) * sin(alpha0)
320 a4 = a**2 * calp0 * salp0 * e2
321 b41 = trgsum(.false., ssig1, csig1, c4a, nc4)
322 else
323* Suppress bogus warnings about unitialized variables
324 a4 = 0
325 b41 = 0
326 end if
327
328 if (arcmod) then
329* Interpret s12a12 as spherical arc length
330 sig12 = s12a12 * degree
331 call sncsdx(s12a12, ssig12, csig12)
332* Suppress bogus warnings about unitialized variables
333 b12 = 0
334 else
335* Interpret s12a12 as distance
336 tau12 = s12a12 / (b * (1 + a1m1))
337 s = sin(tau12)
338 c = cos(tau12)
339* tau2 = tau1 + tau12
340 b12 = - trgsum(.true.,
341 + stau1 * c + ctau1 * s, ctau1 * c - stau1 * s, c1pa, nc1p)
342 sig12 = tau12 - (b12 - b11)
343 ssig12 = sin(sig12)
344 csig12 = cos(sig12)
345 if (abs(f) .gt. 0.01d0) then
346* Reverted distance series is inaccurate for |f| > 1/100, so correct
347* sig12 with 1 Newton iteration. The following table shows the
348* approximate maximum error for a = WGS_a() and various f relative to
349* GeodesicExact.
350* erri = the error in the inverse solution (nm)
351* errd = the error in the direct solution (series only) (nm)
352* errda = the error in the direct solution (series + 1 Newton) (nm)
353*
354* f erri errd errda
355* -1/5 12e6 1.2e9 69e6
356* -1/10 123e3 12e6 765e3
357* -1/20 1110 108e3 7155
358* -1/50 18.63 200.9 27.12
359* -1/100 18.63 23.78 23.37
360* -1/150 18.63 21.05 20.26
361* 1/150 22.35 24.73 25.83
362* 1/100 22.35 25.03 25.31
363* 1/50 29.80 231.9 30.44
364* 1/20 5376 146e3 10e3
365* 1/10 829e3 22e6 1.5e6
366* 1/5 157e6 3.8e9 280e6
367 ssig2 = ssig1 * csig12 + csig1 * ssig12
368 csig2 = csig1 * csig12 - ssig1 * ssig12
369 b12 = trgsum(.true., ssig2, csig2, c1a, nc1)
370 serr = (1 + a1m1) * (sig12 + (b12 - b11)) - s12a12 / b
371 sig12 = sig12 - serr / sqrt(1 + k2 * ssig2**2)
372 ssig12 = sin(sig12)
373 csig12 = cos(sig12)
374* Update B12 below
375 end if
376 end if
377
378* sig2 = sig1 + sig12
379 ssig2 = ssig1 * csig12 + csig1 * ssig12
380 csig2 = csig1 * csig12 - ssig1 * ssig12
381 dn2 = sqrt(1 + k2 * ssig2**2)
382 if (arcmod .or. abs(f) .gt. 0.01d0)
383 + b12 = trgsum(.true., ssig2, csig2, c1a, nc1)
384 ab1 = (1 + a1m1) * (b12 - b11)
385
386* sin(bet2) = cos(alp0) * sin(sig2)
387 sbet2 = calp0 * ssig2
388* Alt: cbet2 = hypot(csig2, salp0 * ssig2)
389 cbet2 = hypotx(salp0, calp0 * csig2)
390 if (cbet2 .eq. 0) then
391* I.e., salp0 = 0, csig2 = 0. Break the degeneracy in this case
392 cbet2 = tiny
393 csig2 = cbet2
394 end if
395* tan(omg2) = sin(alp0) * tan(sig2)
396* No need to normalize
397 somg2 = salp0 * ssig2
398 comg2 = csig2
399* tan(alp0) = cos(sig2)*tan(alp2)
400* No need to normalize
401 salp2 = salp0
402 calp2 = calp0 * csig2
403* East or west going?
404 e = sign(1d0, salp0)
405* omg12 = omg2 - omg1
406 if (unroll) then
407 omg12 = e * (sig12
408 + - (atan2( ssig2, csig2) - atan2( ssig1, csig1))
409 + + (atan2(e * somg2, comg2) - atan2(e * somg1, comg1)))
410 else
411 omg12 = atan2(somg2 * comg1 - comg2 * somg1,
412 + comg2 * comg1 + somg2 * somg1)
413 end if
414
415 lam12 = omg12 + a3c *
416 + ( sig12 + (trgsum(.true., ssig2, csig2, c3a, nc3-1)
417 + - b31))
418 lon12 = lam12 / degree
419 if (unroll) then
420 lon2 = lon1 + lon12
421 else
422 lon2 = angnm(angnm(lon1) + angnm(lon12))
423 end if
424 lat2 = atn2dx(sbet2, f1 * cbet2)
425 azi2 = atn2dx(salp2, calp2)
426
427 if (redlp .or. scalp) then
428 b22 = trgsum(.true., ssig2, csig2, c2a, nc2)
429 ab2 = (1 + a2m1) * (b22 - b21)
430 j12 = (a1m1 - a2m1) * sig12 + (ab1 - ab2)
431 end if
432* Add parens around (csig1 * ssig2) and (ssig1 * csig2) to ensure
433* accurate cancellation in the case of coincident points.
434 if (redlp) m12 = b * ((dn2 * (csig1 * ssig2) -
435 + dn1 * (ssig1 * csig2)) - csig1 * csig2 * j12)
436 if (scalp) then
437 t = k2 * (ssig2 - ssig1) * (ssig2 + ssig1) / (dn1 + dn2)
438 mm12 = csig12 + (t * ssig2 - csig2 * j12) * ssig1 / dn1
439 mm21 = csig12 - (t * ssig1 - csig1 * j12) * ssig2 / dn2
440 end if
441
442 if (areap) then
443 b42 = trgsum(.false., ssig2, csig2, c4a, nc4)
444 if (calp0 .eq. 0 .or. salp0 .eq. 0) then
445* alp12 = alp2 - alp1, used in atan2 so no need to normalize
446 salp12 = salp2 * calp1 - calp2 * salp1
447 calp12 = calp2 * calp1 + salp2 * salp1
448 else
449* tan(alp) = tan(alp0) * sec(sig)
450* tan(alp2-alp1) = (tan(alp2) -tan(alp1)) / (tan(alp2)*tan(alp1)+1)
451* = calp0 * salp0 * (csig1-csig2) / (salp0^2 + calp0^2 * csig1*csig2)
452* If csig12 > 0, write
453* csig1 - csig2 = ssig12 * (csig1 * ssig12 / (1 + csig12) + ssig1)
454* else
455* csig1 - csig2 = csig1 * (1 - csig12) + ssig12 * ssig1
456* No need to normalize
457 if (csig12 .le. 0) then
458 salp12 = csig1 * (1 - csig12) + ssig12 * ssig1
459 else
460 salp12 = ssig12 * (csig1 * ssig12 / (1 + csig12) + ssig1)
461 end if
462 salp12 = calp0 * salp0 * salp12
463 calp12 = salp0**2 + calp0**2 * csig1 * csig2
464 end if
465 ss12 = c2 * atan2(salp12, calp12) + a4 * (b42 - b41)
466 end if
467
468 if (arcp) then
469 if (arcmod) then
470 a12s12 = b * ((1 + a1m1) * sig12 + ab1)
471 else
472 a12s12 = sig12 / degree
473 end if
474 end if
475
476 return
477 end
478
479*> Solve the inverse geodesic problem.
480*!
481*! @param[in] a the equatorial radius (meters).
482*! @param[in] f the flattening of the ellipsoid. Setting \e f = 0 gives
483*! a sphere. Negative \e f gives a prolate ellipsoid.
484*! @param[in] lat1 latitude of point 1 (degrees).
485*! @param[in] lon1 longitude of point 1 (degrees).
486*! @param[in] lat2 latitude of point 2 (degrees).
487*! @param[in] lon2 longitude of point 2 (degrees).
488*! @param[out] s12 distance from point 1 to point 2 (meters).
489*! @param[out] azi1 azimuth at point 1 (degrees).
490*! @param[out] azi2 (forward) azimuth at point 2 (degrees).
491*! @param[in] omask a bitor'ed combination of mask values
492*! specifying which of the following parameters should be set.
493*! @param[out] a12 arc length from point 1 to point 2 (degrees).
494*! @param[out] m12 reduced length of geodesic (meters).
495*! @param[out] MM12 geodesic scale of point 2 relative to point 1
496*! (dimensionless).
497*! @param[out] MM21 geodesic scale of point 1 relative to point 2
498*! (dimensionless).
499*! @param[out] SS12 area under the geodesic (meters<sup>2</sup>).
500*!
501*! \e omask is an integer in [0, 16) whose binary bits are interpreted
502*! as follows
503*! - 1 return \e a12
504*! - 2 return \e m12
505*! - 4 return \e MM12 and \e MM21
506*! - 8 return \e SS12
507*!
508*! \e lat1 and \e lat2 should be in the range [&minus;90&deg;, 90&deg;].
509*! The values of \e azi1 and \e azi2 returned are in the range
510*! [&minus;180&deg;, 180&deg;].
511*!
512*! If either point is at a pole, the azimuth is defined by keeping the
513*! longitude fixed, writing \e lat = &plusmn;(90&deg; &minus;
514*! &epsilon;), and taking the limit &epsilon; &rarr; 0+.
515*!
516*! The solution to the inverse problem is found using Newton's method.
517*! If this fails to converge (this is very unlikely in geodetic
518*! applications but does occur for very eccentric ellipsoids), then the
519*! bisection method is used to refine the solution.
520*!
521*! Example of use:
522*! \include geodinverse.for
523
524 subroutine invers(a, f, lat1, lon1, lat2, lon2,
525 + s12, azi1, azi2, omask, a12, m12, MM12, MM21, SS12)
526* input
527 double precision a, f, lat1, lon1, lat2, lon2
528 integer omask
529* output
530 double precision s12, azi1, azi2
531* optional output
532 double precision a12, m12, MM12, MM21, SS12
533
534 integer ord, nA3, nA3x, nC3, nC3x, nC4, nC4x, nC
535 parameter (ord = 6, na3 = ord, na3x = na3,
536 + nc3 = ord, nc3x = (nc3 * (nc3 - 1)) / 2,
537 + nc4 = ord, nc4x = (nc4 * (nc4 + 1)) / 2,
538 + nc = ord)
539 double precision A3x(0:nA3x-1), C3x(0:nC3x-1), C4x(0:nC4x-1),
540 + Ca(nC)
541
542 double precision atanhx, hypotx,
543 + AngDif, AngRnd, TrgSum, Lam12f, InvSta, atn2dx, LatFix
544 integer latsgn, lonsgn, swapp, numit
545 logical arcp, redlp, scalp, areap, merid, tripn, tripb
546
547 double precision e2, f1, ep2, n, b, c2,
548 + lat1x, lat2x, salp0, calp0, k2, eps,
549 + salp1, calp1, ssig1, csig1, cbet1, sbet1, dbet1, dn1,
550 + salp2, calp2, ssig2, csig2, sbet2, cbet2, dbet2, dn2,
551 + slam12, clam12, salp12, calp12, omg12, lam12, lon12, lon12s,
552 + salp1a, calp1a, salp1b, calp1b,
553 + dalp1, sdalp1, cdalp1, nsalp1, alp12, somg12, comg12, domg12,
554 + sig12, v, dv, dnm, dummy,
555 + a4, b41, b42, s12x, m12x, a12x, sdomg12, cdomg12
556
557 double precision dblmin, dbleps, pi, degree, tiny,
558 + tol0, tol1, tol2, tolb, xthrsh
559 integer digits, maxit1, maxit2, lmask
560 logical init
561 common /geocom/ dblmin, dbleps, pi, degree, tiny,
562 + tol0, tol1, tol2, tolb, xthrsh, digits, maxit1, maxit2, init
563
564 if (.not.init) call geoini
565
566 f1 = 1 - f
567 e2 = f * (2 - f)
568 ep2 = e2 / f1**2
569 n = f / ( 2 - f)
570 b = a * f1
571 c2 = 0
572
573 arcp = mod(omask/1, 2) .eq. 1
574 redlp = mod(omask/2, 2) .eq. 1
575 scalp = mod(omask/4, 2) .eq. 1
576 areap = mod(omask/8, 2) .eq. 1
577 if (scalp) then
578 lmask = 16 + 2 + 4
579 else
580 lmask = 16 + 2
581 end if
582
583 if (areap) then
584 if (e2 .eq. 0) then
585 c2 = a**2
586 else if (e2 .gt. 0) then
587 c2 = (a**2 + b**2 * atanhx(sqrt(e2)) / sqrt(e2)) / 2
588 else
589 c2 = (a**2 + b**2 * atan(sqrt(abs(e2))) / sqrt(abs(e2))) / 2
590 end if
591 end if
592
593 call a3cof(n, a3x)
594 call c3cof(n, c3x)
595 if (areap) call c4cof(n, c4x)
596
597* Compute longitude difference (AngDiff does this carefully). Result is
598* in [-180, 180] but -180 is only for west-going geodesics. 180 is for
599* east-going and meridional geodesics.
600* If very close to being on the same half-meridian, then make it so.
601 lon12 = angdif(lon1, lon2, lon12s)
602* Make longitude difference positive.
603 lonsgn = int(sign(1d0, lon12))
604 lon12 = lonsgn * lon12
605 lon12s = lonsgn * lon12s
606 lam12 = lon12 * degree
607* Calculate sincos of lon12 + error (this applies AngRound internally).
608 call sncsde(lon12, lon12s, slam12, clam12)
609* the supplementary longitude difference
610 lon12s = (180 - lon12) - lon12s
611
612* If really close to the equator, treat as on equator.
613 lat1x = angrnd(latfix(lat1))
614 lat2x = angrnd(latfix(lat2))
615* Swap points so that point with higher (abs) latitude is point 1
616* If one latitude is a nan, then it becomes lat1.
617 if (abs(lat1x) .lt. abs(lat2x) .or. lat2x .ne. lat2x) then
618 swapp = -1
619 else
620 swapp = 1
621 end if
622 if (swapp .lt. 0) then
623 lonsgn = -lonsgn
624 call swap(lat1x, lat2x)
625 end if
626* Make lat1 <= 0
627 latsgn = int(sign(1d0, -lat1x))
628 lat1x = lat1x * latsgn
629 lat2x = lat2x * latsgn
630* Now we have
631*
632* 0 <= lon12 <= 180
633* -90 <= lat1 <= 0
634* lat1 <= lat2 <= -lat1
635*
636* longsign, swapp, latsgn register the transformation to bring the
637* coordinates to this canonical form. In all cases, 1 means no change
638* was made. We make these transformations so that there are few cases
639* to check, e.g., on verifying quadrants in atan2. In addition, this
640* enforces some symmetries in the results returned.
641
642 call sncsdx(lat1x, sbet1, cbet1)
643 sbet1 = f1 * sbet1
644 call norm2x(sbet1, cbet1)
645* Ensure cbet1 = +dbleps at poles
646 cbet1 = max(tiny, cbet1)
647
648 call sncsdx(lat2x, sbet2, cbet2)
649 sbet2 = f1 * sbet2
650 call norm2x(sbet2, cbet2)
651* Ensure cbet2 = +dbleps at poles
652 cbet2 = max(tiny, cbet2)
653
654* If cbet1 < -sbet1, then cbet2 - cbet1 is a sensitive measure of the
655* |bet1| - |bet2|. Alternatively (cbet1 >= -sbet1), abs(sbet2) + sbet1
656* is a better measure. This logic is used in assigning calp2 in
657* Lambda12. Sometimes these quantities vanish and in that case we force
658* bet2 = +/- bet1 exactly. An example where is is necessary is the
659* inverse problem 48.522876735459 0 -48.52287673545898293
660* 179.599720456223079643 which failed with Visual Studio 10 (Release and
661* Debug)
662
663 if (cbet1 .lt. -sbet1) then
664 if (cbet2 .eq. cbet1) sbet2 = sign(sbet1, sbet2)
665 else
666 if (abs(sbet2) .eq. -sbet1) cbet2 = cbet1
667 end if
668
669 dn1 = sqrt(1 + ep2 * sbet1**2)
670 dn2 = sqrt(1 + ep2 * sbet2**2)
671
672* Suppress bogus warnings about unitialized variables
673 a12x = 0
674 merid = lat1x .eq. -90 .or. slam12 .eq. 0
675
676 if (merid) then
677
678* Endpoints are on a single full meridian, so the geodesic might lie on
679* a meridian.
680
681* Head to the target longitude
682 calp1 = clam12
683 salp1 = slam12
684* At the target we're heading north
685 calp2 = 1
686 salp2 = 0
687
688* tan(bet) = tan(sig) * cos(alp)
689 ssig1 = sbet1
690 csig1 = calp1 * cbet1
691 ssig2 = sbet2
692 csig2 = calp2 * cbet2
693
694* sig12 = sig2 - sig1
695 sig12 = atan2(max(0d0, csig1 * ssig2 - ssig1 * csig2) + 0d0,
696 + csig1 * csig2 + ssig1 * ssig2)
697 call lengs(n, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
698 + cbet1, cbet2, lmask,
699 + s12x, m12x, dummy, mm12, mm21, ep2, ca)
700
701* Add the check for sig12 since zero length geodesics might yield m12 <
702* 0. Test case was
703*
704* echo 20.001 0 20.001 0 | GeodSolve -i
705*
706* In fact, we will have sig12 > pi/2 for meridional geodesic which is
707* not a shortest path.
708 if (sig12 .lt. tol2 .or. m12x .ge. 0) then
709 if (sig12 .lt. 3 * tiny .or.
710 + (sig12 .lt. tol0 .and.
711 + (s12x .lt. 0 .or. m12x .lt. 0))) then
712* Prevent negative s12 or m12 for short lines
713 sig12 = 0
714 m12x = 0
715 s12x = 0
716 end if
717 m12x = m12x * b
718 s12x = s12x * b
719 a12x = sig12 / degree
720 else
721* m12 < 0, i.e., prolate and too close to anti-podal
722 merid = .false.
723 end if
724 end if
725
726 omg12 = 0
727* somg12 = 2 marks that it needs to be calculated
728 somg12 = 2
729 comg12 = 0
730 if (.not. merid .and. sbet1 .eq. 0 .and.
731 + (f .le. 0 .or. lon12s .ge. f * 180)) then
732
733* Geodesic runs along equator
734 calp1 = 0
735 calp2 = 0
736 salp1 = 1
737 salp2 = 1
738 s12x = a * lam12
739 sig12 = lam12 / f1
740 omg12 = sig12
741 m12x = b * sin(sig12)
742 if (scalp) then
743 mm12 = cos(sig12)
744 mm21 = mm12
745 end if
746 a12x = lon12 / f1
747 else if (.not. merid) then
748* Now point1 and point2 belong within a hemisphere bounded by a
749* meridian and geodesic is neither meridional or equatorial.
750
751* Figure a starting point for Newton's method
752 sig12 = invsta(sbet1, cbet1, dn1, sbet2, cbet2, dn2, lam12,
753 + slam12, clam12, f, a3x, salp1, calp1, salp2, calp2, dnm, ca)
754
755 if (sig12 .ge. 0) then
756* Short lines (InvSta sets salp2, calp2, dnm)
757 s12x = sig12 * b * dnm
758 m12x = dnm**2 * b * sin(sig12 / dnm)
759 if (scalp) then
760 mm12 = cos(sig12 / dnm)
761 mm21 = mm12
762 end if
763 a12x = sig12 / degree
764 omg12 = lam12 / (f1 * dnm)
765 else
766
767* Newton's method. This is a straightforward solution of f(alp1) =
768* lambda12(alp1) - lam12 = 0 with one wrinkle. f(alp) has exactly one
769* root in the interval (0, pi) and its derivative is positive at the
770* root. Thus f(alp) is positive for alp > alp1 and negative for alp <
771* alp1. During the course of the iteration, a range (alp1a, alp1b) is
772* maintained which brackets the root and with each evaluation of
773* f(alp) the range is shrunk, if possible. Newton's method is
774* restarted whenever the derivative of f is negative (because the new
775* value of alp1 is then further from the solution) or if the new
776* estimate of alp1 lies outside (0,pi); in this case, the new starting
777* guess is taken to be (alp1a + alp1b) / 2.
778
779* Bracketing range
780 salp1a = tiny
781 calp1a = 1
782 salp1b = tiny
783 calp1b = -1
784 tripn = .false.
785 tripb = .false.
786 do 10 numit = 0, maxit2
787* the WGS84 test set: mean = 1.47, sd = 1.25, max = 16
788* WGS84 and random input: mean = 2.85, sd = 0.60
789 v = lam12f(sbet1, cbet1, dn1, sbet2, cbet2, dn2,
790 + salp1, calp1, slam12, clam12, f, a3x, c3x, salp2, calp2,
791 + sig12, ssig1, csig1, ssig2, csig2,
792 + eps, domg12, numit .lt. maxit1, dv, ca)
793* Reversed test to allow escape with NaNs
794 if (tripn) then
795 dummy = 8
796 else
797 dummy = 1
798 end if
799 if (tripb .or. .not. (abs(v) .ge. dummy * tol0) .or.
800 + numit .eq. maxit2) go to 20
801* Update bracketing values
802 if (v .gt. 0 .and. (numit .gt. maxit1 .or.
803 + calp1/salp1 .gt. calp1b/salp1b)) then
804 salp1b = salp1
805 calp1b = calp1
806 else if (v .lt. 0 .and. (numit .gt. maxit1 .or.
807 + calp1/salp1 .lt. calp1a/salp1a)) then
808 salp1a = salp1
809 calp1a = calp1
810 end if
811 if (numit .lt. maxit1 .and. dv .gt. 0) then
812 dalp1 = -v/dv
813 if (abs(dalp1) .lt. pi) then
814 sdalp1 = sin(dalp1)
815 cdalp1 = cos(dalp1)
816 nsalp1 = salp1 * cdalp1 + calp1 * sdalp1
817 if (nsalp1 .gt. 0) then
818 calp1 = calp1 * cdalp1 - salp1 * sdalp1
819 salp1 = nsalp1
820 call norm2x(salp1, calp1)
821* In some regimes we don't get quadratic convergence because
822* slope -> 0. So use convergence conditions based on dbleps
823* instead of sqrt(dbleps).
824 tripn = abs(v) .le. 16 * tol0
825 go to 10
826 end if
827 end if
828 end if
829* Either dv was not positive or updated value was outside legal
830* range. Use the midpoint of the bracket as the next estimate.
831* This mechanism is not needed for the WGS84 ellipsoid, but it does
832* catch problems with more eccentric ellipsoids. Its efficacy is
833* such for the WGS84 test set with the starting guess set to alp1 =
834* 90deg:
835* the WGS84 test set: mean = 5.21, sd = 3.93, max = 24
836* WGS84 and random input: mean = 4.74, sd = 0.99
837 salp1 = (salp1a + salp1b)/2
838 calp1 = (calp1a + calp1b)/2
839 call norm2x(salp1, calp1)
840 tripn = .false.
841 tripb = abs(salp1a - salp1) + (calp1a - calp1) .lt. tolb
842 + .or. abs(salp1 - salp1b) + (calp1 - calp1b) .lt. tolb
843 10 continue
844 20 continue
845 call lengs(eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
846 + cbet1, cbet2, lmask,
847 + s12x, m12x, dummy, mm12, mm21, ep2, ca)
848 m12x = m12x * b
849 s12x = s12x * b
850 a12x = sig12 / degree
851 if (areap) then
852 sdomg12 = sin(domg12)
853 cdomg12 = cos(domg12)
854 somg12 = slam12 * cdomg12 - clam12 * sdomg12
855 comg12 = clam12 * cdomg12 + slam12 * sdomg12
856 end if
857 end if
858 end if
859
860* Convert -0 to 0
861 s12 = 0 + s12x
862 if (redlp) m12 = 0 + m12x
863
864 if (areap) then
865* From Lambda12: sin(alp1) * cos(bet1) = sin(alp0)
866 salp0 = salp1 * cbet1
867 calp0 = hypotx(calp1, salp1 * sbet1)
868 if (calp0 .ne. 0 .and. salp0 .ne. 0) then
869* From Lambda12: tan(bet) = tan(sig) * cos(alp)
870 ssig1 = sbet1
871 csig1 = calp1 * cbet1
872 ssig2 = sbet2
873 csig2 = calp2 * cbet2
874 k2 = calp0**2 * ep2
875 eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2)
876* Multiplier = a^2 * e^2 * cos(alpha0) * sin(alpha0).
877 a4 = a**2 * calp0 * salp0 * e2
878 call norm2x(ssig1, csig1)
879 call norm2x(ssig2, csig2)
880 call c4f(eps, c4x, ca)
881 b41 = trgsum(.false., ssig1, csig1, ca, nc4)
882 b42 = trgsum(.false., ssig2, csig2, ca, nc4)
883 ss12 = a4 * (b42 - b41)
884 else
885* Avoid problems with indeterminate sig1, sig2 on equator
886 ss12 = 0
887 end if
888
889 if (.not. merid .and. somg12 .eq. 2) then
890 somg12 = sin(omg12)
891 comg12 = cos(omg12)
892 end if
893
894 if (.not. merid .and. comg12 .ge. 0.7071d0
895 + .and. sbet2 - sbet1 .lt. 1.75d0) then
896* Use tan(Gamma/2) = tan(omg12/2)
897* * (tan(bet1/2)+tan(bet2/2))/(1+tan(bet1/2)*tan(bet2/2))
898* with tan(x/2) = sin(x)/(1+cos(x))
899 domg12 = 1 + comg12
900 dbet1 = 1 + cbet1
901 dbet2 = 1 + cbet2
902 alp12 = 2 * atan2(somg12 * (sbet1 * dbet2 + sbet2 * dbet1),
903 + domg12 * ( sbet1 * sbet2 + dbet1 * dbet2 ) )
904 else
905* alp12 = alp2 - alp1, used in atan2 so no need to normalize
906 salp12 = salp2 * calp1 - calp2 * salp1
907 calp12 = calp2 * calp1 + salp2 * salp1
908* The right thing appears to happen if alp1 = +/-180 and alp2 = 0, viz
909* salp12 = -0 and alp12 = -180. However this depends on the sign
910* being attached to 0 correctly. The following ensures the correct
911* behavior.
912 if (salp12 .eq. 0 .and. calp12 .lt. 0) then
913 salp12 = tiny * calp1
914 calp12 = -1
915 end if
916 alp12 = atan2(salp12, calp12)
917 end if
918 ss12 = ss12 + c2 * alp12
919 ss12 = ss12 * swapp * lonsgn * latsgn
920* Convert -0 to 0
921 ss12 = 0 + ss12
922 end if
923
924* Convert calp, salp to azimuth accounting for lonsgn, swapp, latsgn.
925 if (swapp .lt. 0) then
926 call swap(salp1, salp2)
927 call swap(calp1, calp2)
928 if (scalp) call swap(mm12, mm21)
929 end if
930
931 salp1 = salp1 * swapp * lonsgn
932 calp1 = calp1 * swapp * latsgn
933 salp2 = salp2 * swapp * lonsgn
934 calp2 = calp2 * swapp * latsgn
935
936 azi1 = atn2dx(salp1, calp1)
937 azi2 = atn2dx(salp2, calp2)
938
939 if (arcp) a12 = a12x
940
941 return
942 end
943
944*> Determine the area of a geodesic polygon
945*!
946*! @param[in] a the equatorial radius (meters).
947*! @param[in] f the flattening of the ellipsoid. Setting \e f = 0 gives
948*! a sphere. Negative \e f gives a prolate ellipsoid.
949*! @param[in] lats an array of the latitudes of the vertices (degrees).
950*! @param[in] lons an array of the longitudes of the vertices (degrees).
951*! @param[in] n the number of vertices.
952*! @param[out] AA the (signed) area of the polygon (meters<sup>2</sup>).
953*! @param[out] PP the perimeter of the polygon.
954*!
955*! \e lats should be in the range [&minus;90&deg;, 90&deg;].
956*!
957*! Arbitrarily complex polygons are allowed. In the case of
958*! self-intersecting polygons the area is accumulated "algebraically",
959*! e.g., the areas of the 2 loops in a figure-8 polygon will partially
960*! cancel. There's no need to "close" the polygon by repeating the
961*! first vertex. The area returned is signed with counter-clockwise
962*! traversal being treated as positive.
963
964 subroutine area(a, f, lats, lons, n, AA, PP)
965* input
966 integer n
967 double precision a, f, lats(n), lons(n)
968* output
969 double precision AA, PP
970
971 integer i, omask, cross, trnsit
972 double precision s12, azi1, azi2, dummy, SS12, b, e2, c2, area0,
973 + atanhx, aacc(2), pacc(2)
974
975 double precision dblmin, dbleps, pi, degree, tiny,
976 + tol0, tol1, tol2, tolb, xthrsh
977 integer digits, maxit1, maxit2
978 logical init
979 common /geocom/ dblmin, dbleps, pi, degree, tiny,
980 + tol0, tol1, tol2, tolb, xthrsh, digits, maxit1, maxit2, init
981
982 omask = 8
983 call accini(aacc)
984 call accini(pacc)
985 cross = 0
986 do 10 i = 0, n-1
987 call invers(a, f, lats(i+1), lons(i+1),
988 + lats(mod(i+1,n)+1), lons(mod(i+1,n)+1),
989 + s12, azi1, azi2, omask, dummy, dummy, dummy, dummy, ss12)
990 call accadd(pacc, s12)
991 call accadd(aacc, -ss12)
992 cross = cross + trnsit(lons(i+1), lons(mod(i+1,n)+1))
993 10 continue
994 pp = pacc(1)
995 b = a * (1 - f)
996 e2 = f * (2 - f)
997 if (e2 .eq. 0) then
998 c2 = a**2
999 else if (e2 .gt. 0) then
1000 c2 = (a**2 + b**2 * atanhx(sqrt(e2)) / sqrt(e2)) / 2
1001 else
1002 c2 = (a**2 + b**2 * atan(sqrt(abs(e2))) / sqrt(abs(e2))) / 2
1003 end if
1004 area0 = 4 * pi * c2
1005 call accrem(aacc, area0)
1006 if (mod(abs(cross), 2) .eq. 1) then
1007 if (aacc(1) .lt. 0) then
1008 call accadd(aacc, +area0/2)
1009 else
1010 call accadd(aacc, -area0/2)
1011 end if
1012 end if
1013 if (aacc(1) .gt. area0/2) then
1014 call accadd(aacc, -area0)
1015 else if (aacc(1) .le. -area0/2) then
1016 call accadd(aacc, +area0)
1017 end if
1018 aa = aacc(1)
1019
1020 return
1021 end
1022
1023*> Return the version numbers for this package.
1024*!
1025*! @param[out] major the major version number.
1026*! @param[out] minor the minor version number.
1027*! @param[out] patch the patch number.
1028*!
1029*! This subroutine was added with version 1.44.
1030
1031 subroutine geover(major, minor, patch)
1032* output
1033 integer major, minor, patch
1034
1035 major = 2
1036 minor = 1
1037 patch = 0
1038
1039 return
1040 end
1041
1042*> Initialize some constants.
1043*!
1044*! This routine is called by the main geodesic routines to initialize
1045*! some constants, so usually there's no need for it to be called
1046*! explicitly. However, if accessing some of the other routines, it may
1047*! need to be called first.
1048
1049 subroutine geoini
1050 double precision dblmin, dbleps, pi, degree, tiny,
1051 + tol0, tol1, tol2, tolb, xthrsh
1052 integer digits, maxit1, maxit2
1053 logical init
1054 common /geocom/ dblmin, dbleps, pi, degree, tiny,
1055 + tol0, tol1, tol2, tolb, xthrsh, digits, maxit1, maxit2, init
1056
1057 digits = 53
1058 dblmin = 0.5d0**1022
1059 dbleps = 0.5d0**(digits-1)
1060
1061 pi = atan2(0d0, -1d0)
1062 degree = pi/180
1063* This is about cbrt(dblmin). With other implementations, sqrt(dblmin)
1064* is used. The larger value is used here to avoid complaints about a
1065* IEEE_UNDERFLOW_FLAG IEEE_DENORMAL signal. This is triggered when
1066* invers is called with points at opposite poles.
1067 tiny = 0.5d0**((1022+1)/3)
1068 tol0 = dbleps
1069* Increase multiplier in defn of tol1 from 100 to 200 to fix inverse
1070* case 52.784459512564 0 -52.784459512563990912 179.634407464943777557
1071* which otherwise failed for Visual Studio 10 (Release and Debug)
1072 tol1 = 200 * tol0
1073 tol2 = sqrt(tol0)
1074* Check on bisection interval
1075 tolb = tol0
1076 xthrsh = 1000 * tol2
1077 maxit1 = 20
1078 maxit2 = maxit1 + digits + 10
1079
1080 init = .true.
1081
1082 return
1083 end
1084
1085*> @cond SKIP
1086
1087 block data geodat
1088 double precision dblmin, dbleps, pi, degree, tiny,
1089 + tol0, tol1, tol2, tolb, xthrsh
1090 integer digits, maxit1, maxit2
1091 logical init
1092 data init /.false./
1093 common /geocom/ dblmin, dbleps, pi, degree, tiny,
1094 + tol0, tol1, tol2, tolb, xthrsh, digits, maxit1, maxit2, init
1095 end
1096
1097 subroutine lengs(eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
1098 + cbet1, cbet2, omask,
1099 + s12b, m12b, m0, MM12, MM21, ep2, Ca)
1100* input
1101 double precision eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
1102 + cbet1, cbet2, ep2
1103 integer omask
1104* optional output
1105 double precision s12b, m12b, m0, MM12, MM21
1106* temporary storage
1107 double precision Ca(*)
1108
1109 integer ord, nC1, nC2
1110 parameter (ord = 6, nc1 = ord, nc2 = ord)
1111
1112 double precision A1m1f, A2m1f, TrgSum
1113 double precision m0x, J12, A1, A2, B1, B2, csig12, t, Cb(nC2)
1114 logical distp, redlp, scalp
1115 integer l
1116
1117* Return m12b = (reduced length)/b; also calculate s12b = distance/b,
1118* and m0 = coefficient of secular term in expression for reduced length.
1119
1120 distp = (mod(omask/16, 2) .eq. 1)
1121 redlp = (mod(omask/2, 2) .eq. 1)
1122 scalp = (mod(omask/4, 2) .eq. 1)
1123
1124* Suppress compiler warnings
1125 m0x = 0
1126 j12 = 0
1127 a1 = 0
1128 a2 = 0
1129 if (distp .or. redlp .or. scalp) then
1130 a1 = a1m1f(eps)
1131 call c1f(eps, ca)
1132 if (redlp .or. scalp) then
1133 a2 = a2m1f(eps)
1134 call c2f(eps, cb)
1135 m0x = a1 - a2
1136 a2 = 1 + a2
1137 end if
1138 a1 = 1 + a1
1139 end if
1140 if (distp) then
1141 b1 = trgsum(.true., ssig2, csig2, ca, nc1) -
1142 + trgsum(.true., ssig1, csig1, ca, nc1)
1143* Missing a factor of b
1144 s12b = a1 * (sig12 + b1)
1145 if (redlp .or. scalp) then
1146 b2 = trgsum(.true., ssig2, csig2, cb, nc2) -
1147 + trgsum(.true., ssig1, csig1, cb, nc2)
1148 j12 = m0x * sig12 + (a1 * b1 - a2 * b2)
1149 end if
1150 else if (redlp .or. scalp) then
1151* Assume here that nC1 >= nC2
1152 do 10 l = 1, nc2
1153 cb(l) = a1 * ca(l) - a2 * cb(l)
1154 10 continue
1155 j12 = m0x * sig12 + (trgsum(.true., ssig2, csig2, cb, nc2) -
1156 + trgsum(.true., ssig1, csig1, cb, nc2))
1157 end if
1158 if (redlp) then
1159 m0 = m0x
1160* Missing a factor of b.
1161* Add parens around (csig1 * ssig2) and (ssig1 * csig2) to ensure
1162* accurate cancellation in the case of coincident points.
1163 m12b = dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) -
1164 + csig1 * csig2 * j12
1165 else
1166 m12b = 0
1167 end if
1168 if (scalp) then
1169 csig12 = csig1 * csig2 + ssig1 * ssig2
1170 t = ep2 * (cbet1 - cbet2) * (cbet1 + cbet2) / (dn1 + dn2)
1171 mm12 = csig12 + (t * ssig2 - csig2 * j12) * ssig1 / dn1
1172 mm21 = csig12 - (t * ssig1 - csig1 * j12) * ssig2 / dn2
1173 end if
1174
1175 return
1176 end
1177
1178 double precision function astrd(x, y)
1179* Solve k^4+2*k^3-(x^2+y^2-1)*k^2-2*y^2*k-y^2 = 0 for positive root k.
1180* This solution is adapted from Geocentric::Reverse.
1181* input
1182 double precision x, y
1183
1184 double precision cbrt
1185 double precision k, p, q, r, S, r2, r3, disc, u,
1186 + t3, t, ang, v, uv, w
1187
1188 p = x**2
1189 q = y**2
1190 r = (p + q - 1) / 6
1191 if ( .not. (q .eq. 0 .and. r .lt. 0) ) then
1192* Avoid possible division by zero when r = 0 by multiplying equations
1193* for s and t by r^3 and r, resp.
1194* S = r^3 * s
1195 s = p * q / 4
1196 r2 = r**2
1197 r3 = r * r2
1198* The discriminant of the quadratic equation for T3. This is zero on
1199* the evolute curve p^(1/3)+q^(1/3) = 1
1200 disc = s * (s + 2 * r3)
1201 u = r
1202 if (disc .ge. 0) then
1203 t3 = s + r3
1204* Pick the sign on the sqrt to maximize abs(T3). This minimizes loss
1205* of precision due to cancellation. The result is unchanged because
1206* of the way the T is used in definition of u.
1207* T3 = (r * t)^3
1208 if (t3 .lt. 0) then
1209 disc = -sqrt(disc)
1210 else
1211 disc = sqrt(disc)
1212 end if
1213 t3 = t3 + disc
1214* N.B. cbrt always returns the real root. cbrt(-8) = -2.
1215* T = r * t
1216 t = cbrt(t3)
1217* T can be zero; but then r2 / T -> 0.
1218 if (t .ne. 0) u = u + t + r2 / t
1219 else
1220* T is complex, but the way u is defined the result is real.
1221 ang = atan2(sqrt(-disc), -(s + r3))
1222* There are three possible cube roots. We choose the root which
1223* avoids cancellation. Note that disc < 0 implies that r < 0.
1224 u = u + 2 * r * cos(ang / 3)
1225 end if
1226* guaranteed positive
1227 v = sqrt(u**2 + q)
1228* Avoid loss of accuracy when u < 0.
1229* u+v, guaranteed positive
1230 if (u .lt. 0) then
1231 uv = q / (v - u)
1232 else
1233 uv = u + v
1234 end if
1235* positive?
1236 w = (uv - q) / (2 * v)
1237* Rearrange expression for k to avoid loss of accuracy due to
1238* subtraction. Division by 0 not possible because uv > 0, w >= 0.
1239* guaranteed positive
1240 k = uv / (sqrt(uv + w**2) + w)
1241 else
1242* q == 0 && r <= 0
1243* y = 0 with |x| <= 1. Handle this case directly.
1244* for y small, positive root is k = abs(y)/sqrt(1-x^2)
1245 k = 0
1246 end if
1247 astrd = k
1248
1249 return
1250 end
1251
1252 double precision function invsta(sbet1, cbet1, dn1,
1253 + sbet2, cbet2, dn2, lam12, slam12, clam12, f, A3x,
1254 + salp1, calp1, salp2, calp2, dnm,
1255 + Ca)
1256* Return a starting point for Newton's method in salp1 and calp1
1257* (function value is -1). If Newton's method doesn't need to be used,
1258* return also salp2, calp2, and dnm and function value is sig12.
1259* input
1260 double precision sbet1, cbet1, dn1, sbet2, cbet2, dn2,
1261 + lam12, slam12, clam12, f, A3x(*)
1262* output
1263 double precision salp1, calp1, salp2, calp2, dnm
1264* temporary
1265 double precision Ca(*)
1266
1267 double precision hypotx, A3f, Astrd
1268 logical shortp
1269 double precision f1, e2, ep2, n, etol2, k2, eps, sig12,
1270 + sbet12, cbet12, sbt12a, omg12, somg12, comg12, ssig12, csig12,
1271 + x, y, lamscl, betscl, cbt12a, bt12a, m12b, m0, dummy,
1272 + k, omg12a, sbetm2, lam12x
1273
1274 double precision dblmin, dbleps, pi, degree, tiny,
1275 + tol0, tol1, tol2, tolb, xthrsh
1276 integer digits, maxit1, maxit2
1277 logical init
1278 common /geocom/ dblmin, dbleps, pi, degree, tiny,
1279 + tol0, tol1, tol2, tolb, xthrsh, digits, maxit1, maxit2, init
1280
1281 f1 = 1 - f
1282 e2 = f * (2 - f)
1283 ep2 = e2 / (1 - e2)
1284 n = f / (2 - f)
1285* The sig12 threshold for "really short". Using the auxiliary sphere
1286* solution with dnm computed at (bet1 + bet2) / 2, the relative error in
1287* the azimuth consistency check is sig12^2 * abs(f) * min(1, 1-f/2) / 2.
1288* (Error measured for 1/100 < b/a < 100 and abs(f) >= 1/1000. For a
1289* given f and sig12, the max error occurs for lines near the pole. If
1290* the old rule for computing dnm = (dn1 + dn2)/2 is used, then the error
1291* increases by a factor of 2.) Setting this equal to epsilon gives
1292* sig12 = etol2. Here 0.1 is a safety factor (error decreased by 100)
1293* and max(0.001, abs(f)) stops etol2 getting too large in the nearly
1294* spherical case.
1295 etol2 = 0.1d0 * tol2 /
1296 + sqrt( max(0.001d0, abs(f)) * min(1d0, 1 - f/2) / 2 )
1297
1298* Return value
1299 sig12 = -1
1300* bet12 = bet2 - bet1 in [0, pi); bt12a = bet2 + bet1 in (-pi, 0]
1301 sbet12 = sbet2 * cbet1 - cbet2 * sbet1
1302 cbet12 = cbet2 * cbet1 + sbet2 * sbet1
1303 sbt12a = sbet2 * cbet1 + cbet2 * sbet1
1304
1305 shortp = cbet12 .ge. 0 .and. sbet12 .lt. 0.5d0 .and.
1306 + cbet2 * lam12 .lt. 0.5d0
1307
1308 if (shortp) then
1309 sbetm2 = (sbet1 + sbet2)**2
1310* sin((bet1+bet2)/2)^2
1311* = (sbet1 + sbet2)^2 / ((sbet1 + sbet2)^2 + (cbet1 + cbet2)^2)
1312 sbetm2 = sbetm2 / (sbetm2 + (cbet1 + cbet2)**2)
1313 dnm = sqrt(1 + ep2 * sbetm2)
1314 omg12 = lam12 / (f1 * dnm)
1315 somg12 = sin(omg12)
1316 comg12 = cos(omg12)
1317 else
1318 somg12 = slam12
1319 comg12 = clam12
1320 end if
1321
1322 salp1 = cbet2 * somg12
1323 if (comg12 .ge. 0) then
1324 calp1 = sbet12 + cbet2 * sbet1 * somg12**2 / (1 + comg12)
1325 else
1326 calp1 = sbt12a - cbet2 * sbet1 * somg12**2 / (1 - comg12)
1327 end if
1328
1329 ssig12 = hypotx(salp1, calp1)
1330 csig12 = sbet1 * sbet2 + cbet1 * cbet2 * comg12
1331
1332 if (shortp .and. ssig12 .lt. etol2) then
1333* really short lines
1334 salp2 = cbet1 * somg12
1335 if (comg12 .ge. 0) then
1336 calp2 = somg12**2 / (1 + comg12)
1337 else
1338 calp2 = 1 - comg12
1339 end if
1340 calp2 = sbet12 - cbet1 * sbet2 * calp2
1341 call norm2x(salp2, calp2)
1342* Set return value
1343 sig12 = atan2(ssig12, csig12)
1344 else if (abs(n) .gt. 0.1d0 .or. csig12 .ge. 0 .or.
1345 + ssig12 .ge. 6 * abs(n) * pi * cbet1**2) then
1346* Nothing to do, zeroth order spherical approximation is OK
1347 continue
1348 else
1349* lam12 - pi
1350 lam12x = atan2(-slam12, -clam12)
1351* Scale lam12 and bet2 to x, y coordinate system where antipodal point
1352* is at origin and singular point is at y = 0, x = -1.
1353 if (f .ge. 0) then
1354* x = dlong, y = dlat
1355 k2 = sbet1**2 * ep2
1356 eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2)
1357 lamscl = f * cbet1 * a3f(eps, a3x) * pi
1358 betscl = lamscl * cbet1
1359 x = lam12x / lamscl
1360 y = sbt12a / betscl
1361 else
1362* f < 0: x = dlat, y = dlong
1363 cbt12a = cbet2 * cbet1 - sbet2 * sbet1
1364 bt12a = atan2(sbt12a, cbt12a)
1365* In the case of lon12 = 180, this repeats a calculation made in
1366* Inverse.
1367 call lengs(n, pi + bt12a,
1368 + sbet1, -cbet1, dn1, sbet2, cbet2, dn2, cbet1, cbet2, 2,
1369 + dummy, m12b, m0, dummy, dummy, ep2, ca)
1370 x = -1 + m12b / (cbet1 * cbet2 * m0 * pi)
1371 if (x .lt. -0.01d0) then
1372 betscl = sbt12a / x
1373 else
1374 betscl = -f * cbet1**2 * pi
1375 end if
1376 lamscl = betscl / cbet1
1377 y = lam12x / lamscl
1378 end if
1379
1380 if (y .gt. -tol1 .and. x .gt. -1 - xthrsh) then
1381* strip near cut
1382 if (f .ge. 0) then
1383 salp1 = min(1d0, -x)
1384 calp1 = - sqrt(1 - salp1**2)
1385 else
1386 if (x .gt. -tol1) then
1387 calp1 = 0
1388 else
1389 calp1 = 1
1390 end if
1391 calp1 = max(calp1, x)
1392 salp1 = sqrt(1 - calp1**2)
1393 end if
1394 else
1395* Estimate alp1, by solving the astroid problem.
1396*
1397* Could estimate alpha1 = theta + pi/2, directly, i.e.,
1398* calp1 = y/k; salp1 = -x/(1+k); for f >= 0
1399* calp1 = x/(1+k); salp1 = -y/k; for f < 0 (need to check)
1400*
1401* However, it's better to estimate omg12 from astroid and use
1402* spherical formula to compute alp1. This reduces the mean number of
1403* Newton iterations for astroid cases from 2.24 (min 0, max 6) to 2.12
1404* (min 0 max 5). The changes in the number of iterations are as
1405* follows:
1406*
1407* change percent
1408* 1 5
1409* 0 78
1410* -1 16
1411* -2 0.6
1412* -3 0.04
1413* -4 0.002
1414*
1415* The histogram of iterations is (m = number of iterations estimating
1416* alp1 directly, n = number of iterations estimating via omg12, total
1417* number of trials = 148605):
1418*
1419* iter m n
1420* 0 148 186
1421* 1 13046 13845
1422* 2 93315 102225
1423* 3 36189 32341
1424* 4 5396 7
1425* 5 455 1
1426* 6 56 0
1427*
1428* Because omg12 is near pi, estimate work with omg12a = pi - omg12
1429 k = astrd(x, y)
1430 if (f .ge. 0) then
1431 omg12a = -x * k/(1 + k)
1432 else
1433 omg12a = -y * (1 + k)/k
1434 end if
1435 omg12a = lamscl * omg12a
1436 somg12 = sin(omg12a)
1437 comg12 = -cos(omg12a)
1438* Update spherical estimate of alp1 using omg12 instead of lam12
1439 salp1 = cbet2 * somg12
1440 calp1 = sbt12a - cbet2 * sbet1 * somg12**2 / (1 - comg12)
1441 end if
1442 end if
1443* Sanity check on starting guess. Backwards check allows NaN through.
1444 if (.not. (salp1 .le. 0)) then
1445 call norm2x(salp1, calp1)
1446 else
1447 salp1 = 1
1448 calp1 = 0
1449 end if
1450 invsta = sig12
1451
1452 return
1453 end
1454
1455 double precision function lam12f(sbet1, cbet1, dn1,
1456 + sbet2, cbet2, dn2, salp1, calp1, slm120, clm120, f, A3x, C3x,
1457 + salp2, calp2, sig12, ssig1, csig1, ssig2, csig2, eps,
1458 + domg12, diffp, dlam12, Ca)
1459* input
1460 double precision sbet1, cbet1, dn1, sbet2, cbet2, dn2,
1461 + salp1, calp1, slm120, clm120, f, A3x(*), C3x(*)
1462 logical diffp
1463* output
1464 double precision salp2, calp2, sig12, ssig1, csig1, ssig2, csig2,
1465 + eps, domg12
1466* optional output
1467 double precision dlam12
1468* temporary
1469 double precision Ca(*)
1470
1471 integer ord, nC3
1472 parameter(ord = 6, nc3 = ord)
1473
1474 double precision hypotx, A3f, TrgSum
1475
1476 double precision f1, e2, ep2, salp0, calp0,
1477 + somg1, comg1, somg2, comg2, somg12, comg12,
1478 + lam12, eta, b312, k2, dummy
1479
1480 double precision dblmin, dbleps, pi, degree, tiny,
1481 + tol0, tol1, tol2, tolb, xthrsh
1482 integer digits, maxit1, maxit2
1483 logical init
1484 common /geocom/ dblmin, dbleps, pi, degree, tiny,
1485 + tol0, tol1, tol2, tolb, xthrsh, digits, maxit1, maxit2, init
1486
1487 f1 = 1 - f
1488 e2 = f * (2 - f)
1489 ep2 = e2 / (1 - e2)
1490* Break degeneracy of equatorial line. This case has already been
1491* handled.
1492 if (sbet1 .eq. 0 .and. calp1 .eq. 0) calp1 = -tiny
1493
1494* sin(alp1) * cos(bet1) = sin(alp0)
1495 salp0 = salp1 * cbet1
1496* calp0 > 0
1497 calp0 = hypotx(calp1, salp1 * sbet1)
1498
1499* tan(bet1) = tan(sig1) * cos(alp1)
1500* tan(omg1) = sin(alp0) * tan(sig1) = tan(omg1)=tan(alp1)*sin(bet1)
1501 ssig1 = sbet1
1502 somg1 = salp0 * sbet1
1503 csig1 = calp1 * cbet1
1504 comg1 = csig1
1505 call norm2x(ssig1, csig1)
1506* norm2x(somg1, comg1); -- don't need to normalize!
1507
1508* Enforce symmetries in the case abs(bet2) = -bet1. Need to be careful
1509* about this case, since this can yield singularities in the Newton
1510* iteration.
1511* sin(alp2) * cos(bet2) = sin(alp0)
1512 if (cbet2 .ne. cbet1) then
1513 salp2 = salp0 / cbet2
1514 else
1515 salp2 = salp1
1516 end if
1517* calp2 = sqrt(1 - sq(salp2))
1518* = sqrt(sq(calp0) - sq(sbet2)) / cbet2
1519* and subst for calp0 and rearrange to give (choose positive sqrt
1520* to give alp2 in [0, pi/2]).
1521 if (cbet2 .ne. cbet1 .or. abs(sbet2) .ne. -sbet1) then
1522 if (cbet1 .lt. -sbet1) then
1523 calp2 = (cbet2 - cbet1) * (cbet1 + cbet2)
1524 else
1525 calp2 = (sbet1 - sbet2) * (sbet1 + sbet2)
1526 end if
1527 calp2 = sqrt((calp1 * cbet1)**2 + calp2) / cbet2
1528 else
1529 calp2 = abs(calp1)
1530 end if
1531* tan(bet2) = tan(sig2) * cos(alp2)
1532* tan(omg2) = sin(alp0) * tan(sig2).
1533 ssig2 = sbet2
1534 somg2 = salp0 * sbet2
1535 csig2 = calp2 * cbet2
1536 comg2 = csig2
1537 call norm2x(ssig2, csig2)
1538* norm2x(somg2, comg2); -- don't need to normalize!
1539
1540* sig12 = sig2 - sig1, limit to [0, pi]
1541 sig12 = atan2(max(0d0, csig1 * ssig2 - ssig1 * csig2) + 0d0,
1542 + csig1 * csig2 + ssig1 * ssig2)
1543
1544* omg12 = omg2 - omg1, limit to [0, pi]
1545 somg12 = max(0d0, comg1 * somg2 - somg1 * comg2) + 0d0
1546 comg12 = comg1 * comg2 + somg1 * somg2
1547* eta = omg12 - lam120
1548 eta = atan2(somg12 * clm120 - comg12 * slm120,
1549 + comg12 * clm120 + somg12 * slm120)
1550 k2 = calp0**2 * ep2
1551 eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2)
1552 call c3f(eps, c3x, ca)
1553 b312 = (trgsum(.true., ssig2, csig2, ca, nc3-1) -
1554 + trgsum(.true., ssig1, csig1, ca, nc3-1))
1555 domg12 = -f * a3f(eps, a3x) * salp0 * (sig12 + b312)
1556 lam12 = eta + domg12
1557
1558 if (diffp) then
1559 if (calp2 .eq. 0) then
1560 dlam12 = - 2 * f1 * dn1 / sbet1
1561 else
1562 call lengs(eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
1563 + cbet1, cbet2, 2,
1564 + dummy, dlam12, dummy, dummy, dummy, ep2, ca)
1565 dlam12 = dlam12 * f1 / (calp2 * cbet2)
1566 end if
1567 end if
1568 lam12f = lam12
1569
1570 return
1571 end
1572
1573 double precision function a3f(eps, A3x)
1574* Evaluate A3
1575 integer ord, nA3, nA3x
1576 parameter(ord = 6, na3 = ord, na3x = na3)
1577
1578* input
1579 double precision eps
1580* output
1581 double precision A3x(0: nA3x-1)
1582
1583 double precision polval
1584 A3f = polval(na3 - 1, a3x, eps)
1585
1586 return
1587 end
1588
1589 subroutine c3f(eps, C3x, c)
1590* Evaluate C3 coeffs
1591* Elements c[1] thru c[nC3-1] are set
1592 integer ord, nC3, nC3x
1593 parameter(ord = 6, nc3 = ord, nc3x = (nc3 * (nc3 - 1)) / 2)
1594
1595* input
1596 double precision eps, C3x(0:nC3x-1)
1597* output
1598 double precision c(nC3-1)
1599
1600 integer o, m, l
1601 double precision mult, polval
1602
1603 mult = 1
1604 o = 0
1605 do 10 l = 1, nc3 - 1
1606 m = nc3 - l - 1
1607 mult = mult * eps
1608 c(l) = mult * polval(m, c3x(o), eps)
1609 o = o + m + 1
1610 10 continue
1611
1612 return
1613 end
1614
1615 subroutine c4f(eps, C4x, c)
1616* Evaluate C4
1617* Elements c[0] thru c[nC4-1] are set
1618 integer ord, nC4, nC4x
1619 parameter(ord = 6, nc4 = ord, nc4x = (nc4 * (nc4 + 1)) / 2)
1620
1621* input
1622 double precision eps, C4x(0:nC4x-1)
1623*output
1624 double precision c(0:nC4-1)
1625
1626 integer o, m, l
1627 double precision mult, polval
1628
1629 mult = 1
1630 o = 0
1631 do 10 l = 0, nc4 - 1
1632 m = nc4 - l - 1
1633 c(l) = mult * polval(m, c4x(o), eps)
1634 o = o + m + 1
1635 mult = mult * eps
1636 10 continue
1637
1638 return
1639 end
1640
1641 double precision function a1m1f(eps)
1642* The scale factor A1-1 = mean value of (d/dsigma)I1 - 1
1643* input
1644 double precision eps
1645
1646 double precision t
1647 integer ord, nA1, o, m
1648 parameter(ord = 6, na1 = ord)
1649 double precision polval, coeff(nA1/2 + 2)
1650 data coeff /1, 4, 64, 0, 256/
1651
1652 o = 1
1653 m = na1/2
1654 t = polval(m, coeff(o), eps**2) / coeff(o + m + 1)
1655 a1m1f = (t + eps) / (1 - eps)
1656
1657 return
1658 end
1659
1660 subroutine c1f(eps, c)
1661* The coefficients C1[l] in the Fourier expansion of B1
1662 integer ord, nC1
1663 parameter(ord = 6, nc1 = ord)
1664
1665* input
1666 double precision eps
1667* output
1668 double precision c(nC1)
1669
1670 double precision eps2, d
1671 integer o, m, l
1672 double precision polval, coeff((nC1**2 + 7*nC1 - 2*(nC1/2))/4)
1673 data coeff /
1674 + -1, 6, -16, 32,
1675 + -9, 64, -128, 2048,
1676 + 9, -16, 768,
1677 + 3, -5, 512,
1678 + -7, 1280,
1679 + -7, 2048/
1680
1681 eps2 = eps**2
1682 d = eps
1683 o = 1
1684 do 10 l = 1, nc1
1685 m = (nc1 - l) / 2
1686 c(l) = d * polval(m, coeff(o), eps2) / coeff(o + m + 1)
1687 o = o + m + 2
1688 d = d * eps
1689 10 continue
1690
1691 return
1692 end
1693
1694 subroutine c1pf(eps, c)
1695* The coefficients C1p[l] in the Fourier expansion of B1p
1696 integer ord, nC1p
1697 parameter(ord = 6, nc1p = ord)
1698
1699* input
1700 double precision eps
1701* output
1702 double precision c(nC1p)
1703
1704 double precision eps2, d
1705 integer o, m, l
1706 double precision polval, coeff((nC1p**2 + 7*nC1p - 2*(nC1p/2))/4)
1707 data coeff /
1708 + 205, -432, 768, 1536,
1709 + 4005, -4736, 3840, 12288,
1710 + -225, 116, 384,
1711 + -7173, 2695, 7680,
1712 + 3467, 7680,
1713 + 38081, 61440/
1714
1715 eps2 = eps**2
1716 d = eps
1717 o = 1
1718 do 10 l = 1, nc1p
1719 m = (nc1p - l) / 2
1720 c(l) = d * polval(m, coeff(o), eps2) / coeff(o + m + 1)
1721 o = o + m + 2
1722 d = d * eps
1723 10 continue
1724
1725 return
1726 end
1727
1728* The scale factor A2-1 = mean value of (d/dsigma)I2 - 1
1729 double precision function a2m1f(eps)
1730* input
1731 double precision eps
1732
1733 double precision t
1734 integer ord, nA2, o, m
1735 parameter(ord = 6, na2 = ord)
1736 double precision polval, coeff(nA2/2 + 2)
1737 data coeff /-11, -28, -192, 0, 256/
1738
1739 o = 1
1740 m = na2/2
1741 t = polval(m, coeff(o), eps**2) / coeff(o + m + 1)
1742 a2m1f = (t - eps) / (1 + eps)
1743
1744 return
1745 end
1746
1747 subroutine c2f(eps, c)
1748* The coefficients C2[l] in the Fourier expansion of B2
1749 integer ord, nC2
1750 parameter(ord = 6, nc2 = ord)
1751
1752* input
1753 double precision eps
1754* output
1755 double precision c(nC2)
1756
1757 double precision eps2, d
1758 integer o, m, l
1759 double precision polval, coeff((nC2**2 + 7*nC2 - 2*(nC2/2))/4)
1760 data coeff /
1761 + 1, 2, 16, 32,
1762 + 35, 64, 384, 2048,
1763 + 15, 80, 768,
1764 + 7, 35, 512,
1765 + 63, 1280,
1766 + 77, 2048/
1767
1768 eps2 = eps**2
1769 d = eps
1770 o = 1
1771 do 10 l = 1, nc2
1772 m = (nc2 - l) / 2
1773 c(l) = d * polval(m, coeff(o), eps2) / coeff(o + m + 1)
1774 o = o + m + 2
1775 d = d * eps
1776 10 continue
1777
1778 return
1779 end
1780
1781 subroutine a3cof(n, A3x)
1782* The scale factor A3 = mean value of (d/dsigma)I3
1783 integer ord, nA3, nA3x
1784 parameter(ord = 6, na3 = ord, na3x = na3)
1785
1786* input
1787 double precision n
1788* output
1789 double precision A3x(0:nA3x-1)
1790
1791 integer o, m, k, j
1792 double precision polval, coeff((nA3**2 + 7*nA3 - 2*(nA3/2))/4)
1793 data coeff /
1794 + -3, 128,
1795 + -2, -3, 64,
1796 + -1, -3, -1, 16,
1797 + 3, -1, -2, 8,
1798 + 1, -1, 2,
1799 + 1, 1/
1800
1801 o = 1
1802 k = 0
1803 do 10 j = na3 - 1, 0, -1
1804 m = min(na3 - j - 1, j)
1805 a3x(k) = polval(m, coeff(o), n) / coeff(o + m + 1)
1806 k = k + 1
1807 o = o + m + 2
1808 10 continue
1809
1810 return
1811 end
1812
1813 subroutine c3cof(n, C3x)
1814* The coefficients C3[l] in the Fourier expansion of B3
1815 integer ord, nC3, nC3x
1816 parameter(ord = 6, nc3 = ord, nc3x = (nc3 * (nc3 - 1)) / 2)
1817
1818* input
1819 double precision n
1820* output
1821 double precision C3x(0:nC3x-1)
1822
1823 integer o, m, l, j, k
1824 double precision polval,
1825 + coeff(((nc3-1)*(nc3**2 + 7*nc3 - 2*(nc3/2)))/8)
1826 data coeff /
1827 + 3, 128,
1828 + 2, 5, 128,
1829 + -1, 3, 3, 64,
1830 + -1, 0, 1, 8,
1831 + -1, 1, 4,
1832 + 5, 256,
1833 + 1, 3, 128,
1834 + -3, -2, 3, 64,
1835 + 1, -3, 2, 32,
1836 + 7, 512,
1837 + -10, 9, 384,
1838 + 5, -9, 5, 192,
1839 + 7, 512,
1840 + -14, 7, 512,
1841 + 21, 2560/
1842
1843 o = 1
1844 k = 0
1845 do 20 l = 1, nc3 - 1
1846 do 10 j = nc3 - 1, l, -1
1847 m = min(nc3 - j - 1, j)
1848 c3x(k) = polval(m, coeff(o), n) / coeff(o + m + 1)
1849 k = k + 1
1850 o = o + m + 2
1851 10 continue
1852 20 continue
1853
1854 return
1855 end
1856
1857 subroutine c4cof(n, C4x)
1858* The coefficients C4[l] in the Fourier expansion of I4
1859 integer ord, nC4, nC4x
1860 parameter(ord = 6, nc4 = ord, nc4x = (nc4 * (nc4 + 1)) / 2)
1861
1862* input
1863 double precision n
1864* output
1865 double precision C4x(0:nC4x-1)
1866
1867 integer o, m, l, j, k
1868 double precision polval, coeff((nC4 * (nC4 + 1) * (nC4 + 5)) / 6)
1869 data coeff /
1870 + 97, 15015, 1088, 156, 45045, -224, -4784, 1573, 45045,
1871 + -10656, 14144, -4576, -858, 45045,
1872 + 64, 624, -4576, 6864, -3003, 15015,
1873 + 100, 208, 572, 3432, -12012, 30030, 45045,
1874 + 1, 9009, -2944, 468, 135135, 5792, 1040, -1287, 135135,
1875 + 5952, -11648, 9152, -2574, 135135,
1876 + -64, -624, 4576, -6864, 3003, 135135,
1877 + 8, 10725, 1856, -936, 225225, -8448, 4992, -1144, 225225,
1878 + -1440, 4160, -4576, 1716, 225225,
1879 + -136, 63063, 1024, -208, 105105,
1880 + 3584, -3328, 1144, 315315,
1881 + -128, 135135, -2560, 832, 405405, 128, 99099/
1882
1883 o = 1
1884 k = 0
1885 do 20 l = 0, nc4 - 1
1886 do 10 j = nc4 - 1, l, -1
1887 m = nc4 - j - 1
1888 c4x(k) = polval(m, coeff(o), n) / coeff(o + m + 1)
1889 k = k + 1
1890 o = o + m + 2
1891 10 continue
1892 20 continue
1893
1894 return
1895 end
1896
1897 double precision function sumx(u, v, t)
1898* input
1899 double precision u, v
1900* output
1901 double precision t
1902
1903 double precision up, vpp
1904 sumx = u + v
1905 up = sumx - v
1906 vpp = sumx - up
1907 up = up - u
1908 vpp = vpp - v
1909 if (sumx .eq. 0) then
1910 t = sumx
1911 else
1912 t = 0d0 - (up + vpp)
1913 end if
1914
1915 return
1916 end
1917
1918 double precision function remx(x, y)
1919* the remainder function but not worrying how ties are handled
1920* y must be positive
1921* input
1922 double precision x, y
1923
1924 remx = mod(x, y)
1925 if (remx .lt. -y/2) then
1926 remx = remx + y
1927 else if (remx .gt. +y/2) then
1928 remx = remx - y
1929 end if
1930
1931 return
1932 end
1933
1934 double precision function angnm(x)
1935* input
1936 double precision x
1937
1938 double precision remx
1939 angnm = remx(x, 360d0)
1940 if (abs(angnm) .eq. 180) then
1941 angnm = sign(180d0, x)
1942 end if
1943
1944 return
1945 end
1946
1947 double precision function latfix(x)
1948* input
1949 double precision x
1950
1951 latfix = x
1952 if (.not. (abs(x) .gt. 90)) return
1953* concoct a NaN
1954 latfix = sqrt(90 - abs(x))
1955
1956 return
1957 end
1958
1959 double precision function angdif(x, y, e)
1960* Compute y - x. x and y must both lie in [-180, 180]. The result is
1961* equivalent to computing the difference exactly, reducing it to (-180,
1962* 180] and rounding the result. Note that this prescription allows -180
1963* to be returned (e.g., if x is tiny and negative and y = 180). The
1964* error in the difference is returned in e
1965* input
1966 double precision x, y
1967* output
1968 double precision e
1969
1970 double precision d, t, sumx, remx
1971 d = sumx(remx(-x, 360d0), remx(y, 360d0), t)
1972 d = sumx(remx(d, 360d0), t, e)
1973 if (d .eq. 0 .or. abs(d) .eq. 180) then
1974 if (e .eq. 0) then
1975 d = sign(d, y - x)
1976 else
1977 d = sign(d, -e)
1978 end if
1979 end if
1980 angdif = d
1981
1982 return
1983 end
1984
1985 double precision function angrnd(x)
1986* The makes the smallest gap in x = 1/16 - nextafter(1/16, 0) = 1/2^57
1987* for reals = 0.7 pm on the earth if x is an angle in degrees. (This is
1988* about 1000 times more resolution than we get with angles around 90
1989* degrees.) We use this to avoid having to deal with near singular
1990* cases when x is non-zero but tiny (e.g., 1.0e-200).
1991* input
1992 double precision x
1993
1994 double precision y, z
1995 z = 1/16d0
1996 y = abs(x)
1997* The compiler mustn't "simplify" z - (z - y) to y
1998 if (y .lt. z) y = z - (z - y)
1999 angrnd = sign(y, x)
2000
2001 return
2002 end
2003
2004 subroutine swap(x, y)
2005* input/output
2006 double precision x, y
2007
2008 double precision z
2009 z = x
2010 x = y
2011 y = z
2012
2013 return
2014 end
2015
2016 double precision function hypotx(x, y)
2017* input
2018 double precision x, y
2019
2020* With Fortran 2008, this becomes: hypotx = hypot(x, y)
2021 hypotx = sqrt(x**2 + y**2)
2022
2023 return
2024 end
2025
2026 subroutine norm2x(x, y)
2027* input/output
2028 double precision x, y
2029
2030 double precision hypotx, r
2031 r = hypotx(x, y)
2032 x = x/r
2033 y = y/r
2034
2035 return
2036 end
2037
2038 double precision function log1px(x)
2039* input
2040 double precision x
2041
2042 double precision y, z
2043 y = 1 + x
2044 z = y - 1
2045 if (z .eq. 0) then
2046 log1px = x
2047 else
2048 log1px = x * log(y) / z
2049 end if
2050
2051 return
2052 end
2053
2054 double precision function atanhx(x)
2055* input
2056 double precision x
2057
2058* With Fortran 2008, this becomes: atanhx = atanh(x)
2059 double precision log1px, y
2060 y = abs(x)
2061 y = log1px(2 * y/(1 - y))/2
2062 atanhx = sign(y, x)
2063
2064 return
2065 end
2066
2067 double precision function cbrt(x)
2068* input
2069 double precision x
2070
2071 cbrt = sign(abs(x)**(1/3d0), x)
2072
2073 return
2074 end
2075
2076 double precision function trgsum(sinp, sinx, cosx, c, n)
2077* Evaluate
2078* y = sinp ? sum(c[i] * sin( 2*i * x), i, 1, n) :
2079* sum(c[i] * cos((2*i-1) * x), i, 1, n)
2080* using Clenshaw summation.
2081* Approx operation count = (n + 5) mult and (2 * n + 2) add
2082* input
2083 logical sinp
2084 integer n
2085 double precision sinx, cosx, c(n)
2086
2087 double precision ar, y0, y1
2088 integer n2, k
2089
2090* 2 * cos(2 * x)
2091 ar = 2 * (cosx - sinx) * (cosx + sinx)
2092* accumulators for sum
2093 if (mod(n, 2) .eq. 1) then
2094 y0 = c(n)
2095 n2 = n - 1
2096 else
2097 y0 = 0
2098 n2 = n
2099 end if
2100 y1 = 0
2101* Now n2 is even
2102 do 10 k = n2, 2, -2
2103* Unroll loop x 2, so accumulators return to their original role
2104 y1 = ar * y0 - y1 + c(k)
2105 y0 = ar * y1 - y0 + c(k-1)
2106 10 continue
2107 if (sinp) then
2108* sin(2 * x) * y0
2109 trgsum = 2 * sinx * cosx * y0
2110 else
2111* cos(x) * (y0 - y1)
2112 trgsum = cosx * (y0 - y1)
2113 end if
2114
2115 return
2116 end
2117
2118 integer function trnsit(lon1, lon2)
2119* input
2120 double precision lon1, lon2
2121
2122 double precision lon1x, lon2x, lon12, AngNm, AngDif, e
2123 lon12 = angdif(lon1, lon2, e)
2124 lon1x = angnm(lon1)
2125 lon2x = angnm(lon2)
2126 if (lon12 .gt. 0 .and. ((lon1x .lt. 0 .and. lon2x .ge. 0) .or.
2127 + (lon1x .gt. 0 .and. lon2x .eq. 0))) then
2128 trnsit = 1
2129 else if (lon12 .lt. 0 .and. lon1x .ge. 0 .and. lon2x .lt. 0) then
2130 trnsit = -1
2131 else
2132 trnsit = 0
2133 end if
2134
2135 return
2136 end
2137
2138 subroutine accini(s)
2139* Initialize an accumulator; this is an array with two elements.
2140* input/output
2141 double precision s(2)
2142
2143 s(1) = 0
2144 s(2) = 0
2145
2146 return
2147 end
2148
2149 subroutine accadd(s, y)
2150* Add y to an accumulator.
2151* input
2152 double precision y
2153* input/output
2154 double precision s(2)
2155
2156 double precision z, u, sumx
2157 z = sumx(y, s(2), u)
2158 s(1) = sumx(z, s(1), s(2))
2159 if (s(1) .eq. 0) then
2160 s(1) = u
2161 else
2162 s(2) = s(2) + u
2163 end if
2164
2165 return
2166 end
2167
2168 subroutine accrem(s, y)
2169* Reduce s to [-y/2, y/2].
2170* input
2171 double precision y
2172* input/output
2173 double precision s(2)
2174
2175 double precision remx
2176 s(1) = remx(s(1), y)
2177 call accadd(s, 0d0)
2178
2179 return
2180 end
2181
2182 subroutine sncsdx(x, sinx, cosx)
2183* Compute sin(x) and cos(x) with x in degrees
2184* input
2185 double precision x
2186* input/output
2187 double precision sinx, cosx
2188
2189 double precision dblmin, dbleps, pi, degree, tiny,
2190 + tol0, tol1, tol2, tolb, xthrsh
2191 integer digits, maxit1, maxit2
2192 logical init
2193 common /geocom/ dblmin, dbleps, pi, degree, tiny,
2194 + tol0, tol1, tol2, tolb, xthrsh, digits, maxit1, maxit2, init
2195
2196 double precision d, r, s, c
2197 integer q
2198 d = mod(x, 360d0)
2199 q = nint(d / 90)
2200 d = d - 90 * q
2201 r = d * degree
2202 s = sin(r)
2203 c = cos(r)
2204 if (abs(d) .eq. 45d0) then
2205 c = sqrt(0.5d0)
2206 s = sign(s, r)
2207 else if (abs(d) .eq. 30d0) then
2208 c = sqrt(0.75d0)
2209 s = sign(0.5d0, r)
2210 end if
2211 q = mod(q + 4, 4)
2212 if (q .eq. 0) then
2213 sinx = s
2214 cosx = c
2215 else if (q .eq. 1) then
2216 sinx = c
2217 cosx = -s
2218 else if (q .eq. 2) then
2219 sinx = -s
2220 cosx = -c
2221 else
2222* q .eq. 3
2223 sinx = -c
2224 cosx = s
2225 end if
2226
2227 if (sinx .eq. 0) then
2228 sinx = sign(sinx, x)
2229 end if
2230 cosx = 0d0 + cosx
2231
2232 return
2233 end
2234
2235 subroutine sncsde(x, t, sinx, cosx)
2236* Compute sin(x+t) and cos(x+t) with x in degrees
2237* input
2238 double precision x, t
2239* input/output
2240 double precision sinx, cosx
2241
2242 double precision dblmin, dbleps, pi, degree, tiny,
2243 + tol0, tol1, tol2, tolb, xthrsh, angrnd
2244 integer digits, maxit1, maxit2
2245 logical init
2246 common /geocom/ dblmin, dbleps, pi, degree, tiny,
2247 + tol0, tol1, tol2, tolb, xthrsh, digits, maxit1, maxit2, init
2248
2249 double precision d, r, s, c
2250 integer q
2251 d = mod(x, 360d0)
2252 q = nint(d / 90)
2253 d = d - 90 * q
2254 d = angrnd(d + t)
2255 r = d * degree
2256 s = sin(r)
2257 c = cos(r)
2258 if (abs(d) .eq. 45d0) then
2259 c = sqrt(0.5d0)
2260 s = sign(s, r)
2261 else if (abs(d) .eq. 30d0) then
2262 c = sqrt(0.75d0)
2263 s = sign(0.5d0, r)
2264 end if
2265 q = mod(q + 4, 4)
2266 if (q .eq. 0) then
2267 sinx = s
2268 cosx = c
2269 else if (q .eq. 1) then
2270 sinx = c
2271 cosx = -s
2272 else if (q .eq. 2) then
2273 sinx = -s
2274 cosx = -c
2275 else
2276* q .eq. 3
2277 sinx = -c
2278 cosx = s
2279 end if
2280
2281 if (sinx .eq. 0) then
2282 sinx = sign(sinx, x+t)
2283 end if
2284 cosx = 0d0 + cosx
2285
2286 return
2287 end
2288
2289 double precision function atn2dx(y, x)
2290* input
2291 double precision x, y
2292
2293 double precision dblmin, dbleps, pi, degree, tiny,
2294 + tol0, tol1, tol2, tolb, xthrsh
2295 integer digits, maxit1, maxit2
2296 logical init
2297 common /geocom/ dblmin, dbleps, pi, degree, tiny,
2298 + tol0, tol1, tol2, tolb, xthrsh, digits, maxit1, maxit2, init
2299
2300 double precision xx, yy
2301 integer q
2302 if (abs(y) .gt. abs(x)) then
2303 xx = y
2304 yy = x
2305 q = 2
2306 else
2307 xx = x
2308 yy = y
2309 q = 0
2310 end if
2311 if (xx .lt. 0) then
2312 xx = -xx
2313 q = q + 1
2314 end if
2315 atn2dx = atan2(yy, xx) / degree
2316 if (q .eq. 1) then
2317 atn2dx = sign(180d0, y) - atn2dx
2318 else if (q .eq. 2) then
2319 atn2dx = 90 - atn2dx
2320 else if (q .eq. 3) then
2321 atn2dx = -90 + atn2dx
2322 end if
2323
2324 return
2325 end
2326
2327 double precision function polval(N, p, x)
2328* input
2329 integer N
2330 double precision p(0:N), x
2331
2332 integer i
2333 if (N .lt. 0) then
2334 polval = 0
2335 else
2336 polval = p(0)
2337 end if
2338 do 10 i = 1, n
2339 polval = polval * x + p(i)
2340 10 continue
2341
2342 return
2343 end
2344
2345* Table of name abbreviations to conform to the 6-char limit and
2346* potential name conflicts.
2347* A3coeff A3cof
2348* C3coeff C3cof
2349* C4coeff C4cof
2350* AngNormalize AngNm
2351* AngDiff AngDif
2352* AngRound AngRnd
2353* arcmode arcmod
2354* Astroid Astrd
2355* betscale betscl
2356* lamscale lamscl
2357* cbet12a cbt12a
2358* sbet12a sbt12a
2359* epsilon dbleps
2360* realmin dblmin
2361* geodesic geod
2362* inverse invers
2363* InverseStart InvSta
2364* Lambda12 Lam12f
2365* latsign latsgn
2366* lonsign lonsgn
2367* Lengths Lengs
2368* meridian merid
2369* outmask omask
2370* shortline shortp
2371* norm norm2x
2372* SinCosSeries TrgSum
2373* xthresh xthrsh
2374* transit trnsit
2375* polyval polval
2376* LONG_UNROLL unroll
2377* sincosd sncsdx
2378* sincosde sncsde
2379* atan2d atn2dx
2380*> @endcond