GeographicLib  1.50
Math.cpp
Go to the documentation of this file.
1 /**
2  * \file Math.cpp
3  * \brief Implementation for GeographicLib::Math class
4  *
5  * Copyright (c) Charles Karney (2015-2019) <charles@karney.com> and licensed
6  * under the MIT/X11 License. For more information, see
7  * https://geographiclib.sourceforge.io/
8  **********************************************************************/
9 
10 #include <GeographicLib/Math.hpp>
11 
12 #if defined(_MSC_VER)
13 // Squelch warnings about constant conditional expressions
14 # pragma warning (disable: 4127)
15 #endif
16 
17 namespace GeographicLib {
18 
19  using namespace std;
20 
21  void Math::dummy() {
22  GEOGRAPHICLIB_STATIC_ASSERT(GEOGRAPHICLIB_PRECISION >= 1 &&
24  "Bad value of precision");
25  }
26 
27  int Math::digits() {
28 #if GEOGRAPHICLIB_PRECISION != 5
29  return std::numeric_limits<real>::digits;
30 #else
31  return std::numeric_limits<real>::digits();
32 #endif
33  }
34 
35  int Math::set_digits(int ndigits) {
36 #if GEOGRAPHICLIB_PRECISION != 5
37  (void)ndigits;
38 #else
39  mpfr::mpreal::set_default_prec(ndigits >= 2 ? ndigits : 2);
40 #endif
41  return digits();
42  }
43 
45 #if GEOGRAPHICLIB_PRECISION != 5
46  return std::numeric_limits<real>::digits10;
47 #else
48  return std::numeric_limits<real>::digits10();
49 #endif
50  }
51 
53  return
54  digits10() > std::numeric_limits<double>::digits10 ?
55  digits10() - std::numeric_limits<double>::digits10 : 0;
56  }
57 
58  template<typename T> T Math::hypot(T x, T y) {
59 #if GEOGRAPHICLIB_CXX11_MATH
60  using std::hypot; return hypot(x, y);
61 #else
62  x = abs(x); y = abs(y);
63  if (x < y) std::swap(x, y); // Now x >= y >= 0
64  y /= (x != 0 ? x : 1);
65  return x * sqrt(1 + y * y);
66  // For an alternative (square-root free) method see
67  // C. Moler and D. Morrision (1983) https://doi.org/10.1147/rd.276.0577
68  // and A. A. Dubrulle (1983) https://doi.org/10.1147/rd.276.0582
69 #endif
70  }
71 
72  template<typename T> T Math::expm1(T x) {
73 #if GEOGRAPHICLIB_CXX11_MATH
74  using std::expm1; return expm1(x);
75 #else
77  y = exp(x),
78  z = y - 1;
79  // The reasoning here is similar to that for log1p. The expression
80  // mathematically reduces to exp(x) - 1, and the factor z/log(y) = (y -
81  // 1)/log(y) is a slowly varying quantity near y = 1 and is accurately
82  // computed.
83  return abs(x) > 1 ? z : (z == 0 ? x : x * z / log(y));
84 #endif
85  }
86 
87  template<typename T> T Math::log1p(T x) {
88 #if GEOGRAPHICLIB_CXX11_MATH
89  using std::log1p; return log1p(x);
90 #else
92  y = 1 + x,
93  z = y - 1;
94  // Here's the explanation for this magic: y = 1 + z, exactly, and z
95  // approx x, thus log(y)/z (which is nearly constant near z = 0) returns
96  // a good approximation to the true log(1 + x)/x. The multiplication x *
97  // (log(y)/z) introduces little additional error.
98  return z == 0 ? x : x * log(y) / z;
99 #endif
100  }
101 
102  template<typename T> T Math::asinh(T x) {
103 #if GEOGRAPHICLIB_CXX11_MATH
104  using std::asinh; return asinh(x);
105 #else
106  T y = abs(x); // Enforce odd parity
107  y = log1p(y * (1 + y/(hypot(T(1), y) + 1)));
108  return x > 0 ? y : (x < 0 ? -y : x); // asinh(-0.0) = -0.0
109 #endif
110  }
111 
112  template<typename T> T Math::atanh(T x) {
113 #if GEOGRAPHICLIB_CXX11_MATH
114  using std::atanh; return atanh(x);
115 #else
116  T y = abs(x); // Enforce odd parity
117  y = log1p(2 * y/(1 - y))/2;
118  return x > 0 ? y : (x < 0 ? -y : x); // atanh(-0.0) = -0.0
119 #endif
120  }
121 
122  template<typename T> T Math::copysign(T x, T y) {
123 #if GEOGRAPHICLIB_CXX11_MATH
124  using std::copysign; return copysign(x, y);
125 #else
126  // NaN counts as positive
127  return abs(x) * (y < 0 || (y == 0 && 1/y < 0) ? -1 : 1);
128 #endif
129  }
130 
131  template<typename T> T Math::cbrt(T x) {
132 #if GEOGRAPHICLIB_CXX11_MATH
133  using std::cbrt; return cbrt(x);
134 #else
135  T y = pow(abs(x), 1/T(3)); // Return the real cube root
136  return x > 0 ? y : (x < 0 ? -y : x); // cbrt(-0.0) = -0.0
137 #endif
138  }
139 
140  template<typename T> T Math::remainder(T x, T y) {
141 #if GEOGRAPHICLIB_CXX11_MATH
142  using std::remainder; return remainder(x, y);
143 #else
144  y = abs(y); // The result doesn't depend on the sign of y
145  T z = fmod(x, y);
146  if (z == 0)
147  // This shouldn't be necessary. However, before version 14 (2015),
148  // Visual Studio had problems dealing with -0.0. Specifically
149  // VC 10,11,12 and 32-bit compile: fmod(-0.0, 360.0) -> +0.0
150  // python 2.7 on Windows 32-bit machines has the same problem.
151  z = copysign(z, x);
152  else if (2 * abs(z) == y)
153  z -= fmod(x, 2 * y) - z; // Implement ties to even
154  else if (2 * abs(z) > y)
155  z += (z < 0 ? y : -y); // Fold remaining cases to (-y/2, y/2)
156  return z;
157 #endif
158  }
159 
160  template<typename T> T Math::remquo(T x, T y, int* n) {
161  // boost::math::remquo doesn't handle nans correctly
162 #if GEOGRAPHICLIB_CXX11_MATH && GEOGRAPHICLIB_PRECISION <= 3
163  using std::remquo; return remquo(x, y, n);
164 #else
165  T z = remainder(x, y);
166  if (n) {
167  T
168  a = remainder(x, 2 * y),
169  b = remainder(x, 4 * y),
170  c = remainder(x, 8 * y);
171  *n = (a > z ? 1 : (a < z ? -1 : 0));
172  *n += (b > a ? 2 : (b < a ? -2 : 0));
173  *n += (c > b ? 4 : (c < b ? -4 : 0));
174  if (y < 0) *n *= -1;
175  if (y != 0) {
176  if (x/y > 0 && *n <= 0)
177  *n += 8;
178  else if (x/y < 0 && *n >= 0)
179  *n -= 8;
180  }
181  }
182  return z;
183 #endif
184  }
185 
186  template<typename T> T Math::round(T x) {
187 #if GEOGRAPHICLIB_CXX11_MATH
188  using std::round; return round(x);
189 #else
190  // The handling of corner cases is copied from boost; see
191  // https://github.com/boostorg/math/pull/8
192  // with improvements to return -0 when appropriate.
193  if (0 < x && x < T(0.5))
194  return +T(0);
195  else if (0 > x && x > -T(0.5))
196  return -T(0);
197  else if (x > 0) {
198  T t = ceil(x);
199  return t - x > T(0.5) ? t - 1 : t;
200  } else if (x < 0) {
201  T t = floor(x);
202  return x - t > T(0.5) ? t + 1 : t;
203  } else // +/-0 and NaN
204  return x; // Retain sign of 0
205 #endif
206  }
207 
208  template<typename T> long Math::lround(T x) {
209 #if GEOGRAPHICLIB_CXX11_MATH && GEOGRAPHICLIB_PRECISION != 5
210  using std::lround; return lround(x);
211 #else
212  // Default value for overflow + NaN + (x == LONG_MIN)
213  long r = std::numeric_limits<long>::min();
214  x = round(x);
215  if (abs(x) < -T(r)) // Assume T(LONG_MIN) is exact
216  r = long(x);
217  return r;
218 #endif
219  }
220 
221  template<typename T> T Math::fma(T x, T y, T z) {
222 #if GEOGRAPHICLIB_CXX11_MATH
223  using std::fma; return fma(x, y, z);
224 #else
225  return x * y + z;
226 #endif
227  }
228 
229  template<typename T> T Math::sum(T u, T v, T& t) {
230  GEOGRAPHICLIB_VOLATILE T s = u + v;
231  GEOGRAPHICLIB_VOLATILE T up = s - v;
232  GEOGRAPHICLIB_VOLATILE T vpp = s - up;
233  up -= u;
234  vpp -= v;
235  t = -(up + vpp);
236  // u + v = s + t
237  // = round(u + v) + t
238  return s;
239  }
240 
241  template<typename T> T Math::AngRound(T x) {
242  static const T z = 1/T(16);
243  if (x == 0) return 0;
244  GEOGRAPHICLIB_VOLATILE T y = abs(x);
245  // The compiler mustn't "simplify" z - (z - y) to y
246  y = y < z ? z - (z - y) : y;
247  return x < 0 ? -y : y;
248  }
249 
250  template<typename T> void Math::sincosd(T x, T& sinx, T& cosx) {
251  // In order to minimize round-off errors, this function exactly reduces
252  // the argument to the range [-45, 45] before converting it to radians.
253  T r; int q;
254  // N.B. the implementation of remquo in glibc pre 2.22 were buggy. See
255  // https://sourceware.org/bugzilla/show_bug.cgi?id=17569
256  // This was fixed in version 2.22 on 2015-08-05
257  r = remquo(x, T(90), &q); // now abs(r) <= 45
258  r *= degree<T>();
259  // g++ -O turns these two function calls into a call to sincos
260  T s = sin(r), c = cos(r);
261 #if defined(_MSC_VER) && _MSC_VER < 1900
262  // Before version 14 (2015), Visual Studio had problems dealing
263  // with -0.0. Specifically
264  // VC 10,11,12 and 32-bit compile: fmod(-0.0, 360.0) -> +0.0
265  // VC 12 and 64-bit compile: sin(-0.0) -> +0.0
266  // AngNormalize has a similar fix.
267  // python 2.7 on Windows 32-bit machines has the same problem.
268  if (x == 0) s = x;
269 #endif
270  switch (unsigned(q) & 3U) {
271  case 0U: sinx = s; cosx = c; break;
272  case 1U: sinx = c; cosx = -s; break;
273  case 2U: sinx = -s; cosx = -c; break;
274  default: sinx = -c; cosx = s; break; // case 3U
275  }
276  // Set sign of 0 results. -0 only produced for sin(-0)
277  if (x != 0) { sinx += T(0); cosx += T(0); }
278  }
279 
280  template<typename T> T Math::sind(T x) {
281  // See sincosd
282  T r; int q;
283  r = remquo(x, T(90), &q); // now abs(r) <= 45
284  r *= degree<T>();
285  unsigned p = unsigned(q);
286  r = p & 1U ? cos(r) : sin(r);
287  if (p & 2U) r = -r;
288  if (x != 0) r += T(0);
289  return r;
290  }
291 
292  template<typename T> T Math::cosd(T x) {
293  // See sincosd
294  T r; int q;
295  r = remquo(x, T(90), &q); // now abs(r) <= 45
296  r *= degree<T>();
297  unsigned p = unsigned(q + 1);
298  r = p & 1U ? cos(r) : sin(r);
299  if (p & 2U) r = -r;
300  return T(0) + r;
301  }
302 
303  template<typename T> T Math::tand(T x) {
304  static const T overflow = 1 / sq(std::numeric_limits<T>::epsilon());
305  T s, c;
306  sincosd(x, s, c);
307  return c != 0 ? s / c : (s < 0 ? -overflow : overflow);
308  }
309 
310  template<typename T> T Math::atan2d(T y, T x) {
311  // In order to minimize round-off errors, this function rearranges the
312  // arguments so that result of atan2 is in the range [-pi/4, pi/4] before
313  // converting it to degrees and mapping the result to the correct
314  // quadrant.
315  int q = 0;
316  if (abs(y) > abs(x)) { std::swap(x, y); q = 2; }
317  if (x < 0) { x = -x; ++q; }
318  // here x >= 0 and x >= abs(y), so angle is in [-pi/4, pi/4]
319  T ang = atan2(y, x) / degree<T>();
320  switch (q) {
321  // Note that atan2d(-0.0, 1.0) will return -0. However, we expect that
322  // atan2d will not be called with y = -0. If need be, include
323  //
324  // case 0: ang = 0 + ang; break;
325  //
326  // and handle mpfr as in AngRound.
327  case 1: ang = (y >= 0 ? 180 : -180) - ang; break;
328  case 2: ang = 90 - ang; break;
329  case 3: ang = -90 + ang; break;
330  }
331  return ang;
332  }
333 
334  template<typename T> T Math::atand(T x)
335  { return atan2d(x, T(1)); }
336 
337  template<typename T> T Math::eatanhe(T x, T es) {
338  return es > T(0) ? es * atanh(es * x) : -es * atan(es * x);
339  }
340 
341  template<typename T> T Math::taupf(T tau, T es) {
342  T tau1 = hypot(T(1), tau),
343  sig = sinh( eatanhe(tau / tau1, es ) );
344  return hypot(T(1), sig) * tau - sig * tau1;
345  }
346 
347  template<typename T> T Math::tauf(T taup, T es) {
348  const int numit = 5;
349  const T tol = sqrt(numeric_limits<T>::epsilon()) / T(10);
350  T e2m = T(1) - sq(es),
351  // To lowest order in e^2, taup = (1 - e^2) * tau = _e2m * tau; so use
352  // tau = taup/_e2m as a starting guess. (This starting guess is the
353  // geocentric latitude which, to first order in the flattening, is equal
354  // to the conformal latitude.) Only 1 iteration is needed for |lat| <
355  // 3.35 deg, otherwise 2 iterations are needed. If, instead, tau = taup
356  // is used the mean number of iterations increases to 1.99 (2 iterations
357  // are needed except near tau = 0).
358  tau = taup/e2m,
359  stol = tol * max(T(1), abs(taup));
360  // min iterations = 1, max iterations = 2; mean = 1.94
361  for (int i = 0; i < numit || GEOGRAPHICLIB_PANIC; ++i) {
362  T taupa = taupf(tau, es),
363  dtau = (taup - taupa) * (1 + e2m * sq(tau)) /
364  ( e2m * hypot(T(1), tau) * hypot(T(1), taupa) );
365  tau += dtau;
366  if (!(abs(dtau) >= stol))
367  break;
368  }
369  return tau;
370  }
371 
372  template<typename T> bool Math::isfinite(T x) {
373 #if GEOGRAPHICLIB_CXX11_MATH
374  using std::isfinite; return isfinite(x);
375 #else
376 #if defined(_MSC_VER)
377  return abs(x) <= (std::numeric_limits<T>::max)();
378 #else
379  // There's a problem using MPFR C++ 3.6.3 and g++ -std=c++14 (reported on
380  // 2015-05-04) with the parens around std::numeric_limits<T>::max. Of
381  // course, these parens are only needed to deal with Windows stupidly
382  // defining max as a macro. So don't insert the parens on non-Windows
383  // platforms.
384  return abs(x) <= std::numeric_limits<T>::max();
385 #endif
386 #endif
387  }
388 
389  template<typename T> T Math::NaN() {
390 #if defined(_MSC_VER)
391  return std::numeric_limits<T>::has_quiet_NaN ?
392  std::numeric_limits<T>::quiet_NaN() :
393  (std::numeric_limits<T>::max)();
394 #else
395  return std::numeric_limits<T>::has_quiet_NaN ?
396  std::numeric_limits<T>::quiet_NaN() :
397  std::numeric_limits<T>::max();
398 #endif
399  }
400 
401  template<typename T> bool Math::isnan(T x) {
402 #if GEOGRAPHICLIB_CXX11_MATH
403  using std::isnan; return isnan(x);
404 #else
405  return x != x;
406 #endif
407  }
408 
409  template<typename T> T Math::infinity() {
410 #if defined(_MSC_VER)
411  return std::numeric_limits<T>::has_infinity ?
412  std::numeric_limits<T>::infinity() :
413  (std::numeric_limits<T>::max)();
414 #else
415  return std::numeric_limits<T>::has_infinity ?
416  std::numeric_limits<T>::infinity() :
417  std::numeric_limits<T>::max();
418 #endif
419  }
420 
421  /// \cond SKIP
422  // Instantiate
424  Math::hypot<Math::real>(Math::real, Math::real);
425  template Math::real GEOGRAPHICLIB_EXPORT
426  Math::expm1<Math::real>(Math::real);
427  template Math::real GEOGRAPHICLIB_EXPORT
428  Math::log1p<Math::real>(Math::real);
429  template Math::real GEOGRAPHICLIB_EXPORT
430  Math::asinh<Math::real>(Math::real);
431  template Math::real GEOGRAPHICLIB_EXPORT
432  Math::atanh<Math::real>(Math::real);
433  template Math::real GEOGRAPHICLIB_EXPORT
434  Math::cbrt<Math::real>(Math::real);
435  template Math::real GEOGRAPHICLIB_EXPORT
436  Math::remainder<Math::real>(Math::real, Math::real);
437  template Math::real GEOGRAPHICLIB_EXPORT
438  Math::remquo<Math::real>(Math::real, Math::real, int*);
439  template Math::real GEOGRAPHICLIB_EXPORT
440  Math::round<Math::real>(Math::real);
441  template long GEOGRAPHICLIB_EXPORT
442  Math::lround<Math::real>(Math::real);
443  template Math::real GEOGRAPHICLIB_EXPORT
444  Math::copysign<Math::real>(Math::real, Math::real);
445  template Math::real GEOGRAPHICLIB_EXPORT
446  Math::fma<Math::real>(Math::real, Math::real, Math::real);
447  template Math::real GEOGRAPHICLIB_EXPORT
448  Math::sum<Math::real>(Math::real, Math::real, Math::real&);
449  template Math::real GEOGRAPHICLIB_EXPORT
450  Math::AngRound<Math::real>(Math::real);
451  template void GEOGRAPHICLIB_EXPORT
452  Math::sincosd<Math::real>(Math::real, Math::real&, Math::real&);
453  template Math::real GEOGRAPHICLIB_EXPORT
454  Math::sind<Math::real>(Math::real);
455  template Math::real GEOGRAPHICLIB_EXPORT
456  Math::cosd<Math::real>(Math::real);
457  template Math::real GEOGRAPHICLIB_EXPORT
458  Math::tand<Math::real>(Math::real);
459  template Math::real GEOGRAPHICLIB_EXPORT
460  Math::atan2d<Math::real>(Math::real, Math::real);
461  template Math::real GEOGRAPHICLIB_EXPORT
462  Math::atand<Math::real>(Math::real);
463  template Math::real GEOGRAPHICLIB_EXPORT
464  Math::eatanhe<Math::real>(Math::real, Math::real);
465  template Math::real GEOGRAPHICLIB_EXPORT
466  Math::taupf<Math::real>(Math::real, Math::real);
467  template Math::real GEOGRAPHICLIB_EXPORT
468  Math::tauf<Math::real>(Math::real, Math::real);
469  template bool GEOGRAPHICLIB_EXPORT
470  Math::isfinite<Math::real>(Math::real);
471  template Math::real GEOGRAPHICLIB_EXPORT
472  Math::NaN<Math::real>();
473  template bool GEOGRAPHICLIB_EXPORT
474  Math::isnan<Math::real>(Math::real);
475  template Math::real GEOGRAPHICLIB_EXPORT
476  Math::infinity<Math::real>();
477 #if GEOGRAPHICLIB_PRECISION != 2
478  // Always have double versions available
479  template double GEOGRAPHICLIB_EXPORT
480  Math::hypot<double>(double, double);
481  template double GEOGRAPHICLIB_EXPORT
482  Math::expm1<double>(double);
483  template double GEOGRAPHICLIB_EXPORT
484  Math::log1p<double>(double);
485  template double GEOGRAPHICLIB_EXPORT
486  Math::asinh<double>(double);
487  template double GEOGRAPHICLIB_EXPORT
488  Math::atanh<double>(double);
489  template double GEOGRAPHICLIB_EXPORT
490  Math::cbrt<double>(double);
491  template double GEOGRAPHICLIB_EXPORT
492  Math::remainder<double>(double, double);
493  template double GEOGRAPHICLIB_EXPORT
494  Math::remquo<double>(double, double, int*);
495  template double GEOGRAPHICLIB_EXPORT
496  Math::round<double>(double);
497  template long GEOGRAPHICLIB_EXPORT
498  Math::lround<double>(double);
499  template double GEOGRAPHICLIB_EXPORT
500  Math::copysign<double>(double, double);
501  template double GEOGRAPHICLIB_EXPORT
502  Math::fma<double>(double, double, double);
503  template double GEOGRAPHICLIB_EXPORT
504  Math::sum<double>(double, double, double&);
505  template double GEOGRAPHICLIB_EXPORT
506  Math::AngRound<double>(double);
507  template void GEOGRAPHICLIB_EXPORT
508  Math::sincosd<double>(double, double&, double&);
509  template double GEOGRAPHICLIB_EXPORT
510  Math::sind<double>(double);
511  template double GEOGRAPHICLIB_EXPORT
512  Math::cosd<double>(double);
513  template double GEOGRAPHICLIB_EXPORT
514  Math::tand<double>(double);
515  template double GEOGRAPHICLIB_EXPORT
516  Math::atan2d<double>(double, double);
517  template double GEOGRAPHICLIB_EXPORT
518  Math::atand<double>(double);
519  template double GEOGRAPHICLIB_EXPORT
520  Math::eatanhe<double>(double, double);
521  template double GEOGRAPHICLIB_EXPORT
522  Math::taupf<double>(double, double);
523  template double GEOGRAPHICLIB_EXPORT
524  Math::tauf<double>(double, double);
525  template bool GEOGRAPHICLIB_EXPORT
526  Math::isfinite<double>(double);
527  template double GEOGRAPHICLIB_EXPORT
528  Math::NaN<double>();
529  template bool GEOGRAPHICLIB_EXPORT
530  Math::isnan<double>(double);
531  template double GEOGRAPHICLIB_EXPORT
532  Math::infinity<double>();
533 #endif
534 #if GEOGRAPHICLIB_HAVE_LONG_DOUBLE && GEOGRAPHICLIB_PRECISION != 3
535  // And always have long double versions available (as long as long double is
536  // a really different from double).
537  template long double GEOGRAPHICLIB_EXPORT
538  Math::hypot<long double>(long double, long double);
539  template long double GEOGRAPHICLIB_EXPORT
540  Math::expm1<long double>(long double);
541  template long double GEOGRAPHICLIB_EXPORT
542  Math::log1p<long double>(long double);
543  template long double GEOGRAPHICLIB_EXPORT
544  Math::asinh<long double>(long double);
545  template long double GEOGRAPHICLIB_EXPORT
546  Math::atanh<long double>(long double);
547  template long double GEOGRAPHICLIB_EXPORT
548  Math::cbrt<long double>(long double);
549  template long double GEOGRAPHICLIB_EXPORT
550  Math::remainder<long double>(long double, long double);
551  template long double GEOGRAPHICLIB_EXPORT
552  Math::remquo<long double>(long double, long double, int*);
553  template long double GEOGRAPHICLIB_EXPORT
554  Math::round<long double>(long double);
555  template long GEOGRAPHICLIB_EXPORT
556  Math::lround<long double>(long double);
557  template long double GEOGRAPHICLIB_EXPORT
558  Math::copysign<long double>(long double, long double);
559  template long double GEOGRAPHICLIB_EXPORT
560  Math::fma<long double>(long double, long double, long double);
561  template long double GEOGRAPHICLIB_EXPORT
562  Math::sum<long double>(long double, long double, long double&);
563  template long double GEOGRAPHICLIB_EXPORT
564  Math::AngRound<long double>(long double);
565  template void GEOGRAPHICLIB_EXPORT
566  Math::sincosd<long double>(long double, long double&, long double&);
567  template long double GEOGRAPHICLIB_EXPORT
568  Math::sind<long double>(long double);
569  template long double GEOGRAPHICLIB_EXPORT
570  Math::cosd<long double>(long double);
571  template long double GEOGRAPHICLIB_EXPORT
572  Math::tand<long double>(long double);
573  template long double GEOGRAPHICLIB_EXPORT
574  Math::atan2d<long double>(long double, long double);
575  template long double GEOGRAPHICLIB_EXPORT
576  Math::atand<long double>(long double);
577  template long double GEOGRAPHICLIB_EXPORT
578  Math::eatanhe<long double>(long double, long double);
579  template long double GEOGRAPHICLIB_EXPORT
580  Math::taupf<long double>(long double, long double);
581  template long double GEOGRAPHICLIB_EXPORT
582  Math::tauf<long double>(long double, long double);
583  template bool GEOGRAPHICLIB_EXPORT
584  Math::isfinite<long double>(long double);
585  template long double GEOGRAPHICLIB_EXPORT
586  Math::NaN<long double>();
587  template bool GEOGRAPHICLIB_EXPORT
588  Math::isnan<long double>(long double);
589  template long double GEOGRAPHICLIB_EXPORT
590  Math::infinity<long double>();
591 #endif
592  // Also we need int versions for Utility::nummatch
593  template int GEOGRAPHICLIB_EXPORT Math::NaN<int>();
594  template int GEOGRAPHICLIB_EXPORT Math::infinity<int>();
595  /// \endcond
596 
597 } // namespace GeographicLib
static T atand(T x)
Definition: Math.cpp:334
static T tand(T x)
Definition: Math.cpp:303
#define GEOGRAPHICLIB_EXPORT
Definition: Constants.hpp:92
static bool isfinite(T x)
Definition: Math.cpp:372
static T infinity()
Definition: Math.cpp:409
static T log1p(T x)
Definition: Math.cpp:87
static long lround(T x)
Definition: Math.cpp:208
#define GEOGRAPHICLIB_PRECISION
Definition: Math.hpp:57
#define GEOGRAPHICLIB_VOLATILE
Definition: Math.hpp:80
static int extra_digits()
Definition: Math.cpp:52
static T atan2d(T y, T x)
Definition: Math.cpp:310
Header for GeographicLib::Math class.
static int set_digits(int ndigits)
Definition: Math.cpp:35
static T cbrt(T x)
Definition: Math.cpp:131
static T round(T x)
Definition: Math.cpp:186
Namespace for GeographicLib.
Definition: Accumulator.cpp:12
static T NaN()
Definition: Math.cpp:389
static T sum(T u, T v, T &t)
Definition: Math.cpp:229
static T atanh(T x)
Definition: Math.cpp:112
static bool isnan(T x)
Definition: Math.cpp:401
static T asinh(T x)
Definition: Math.cpp:102
void swap(GeographicLib::NearestNeighbor< dist_t, pos_t, distfun_t > &a, GeographicLib::NearestNeighbor< dist_t, pos_t, distfun_t > &b)
static T copysign(T x, T y)
Definition: Math.cpp:122
static T sind(T x)
Definition: Math.cpp:280
static T cosd(T x)
Definition: Math.cpp:292
static T remquo(T x, T y, int *n)
Definition: Math.cpp:160
static T hypot(T x, T y)
Definition: Math.cpp:58
static int digits10()
Definition: Math.cpp:44
static T tauf(T taup, T es)
Definition: Math.cpp:347
static void sincosd(T x, T &sinx, T &cosx)
Definition: Math.cpp:250
static T eatanhe(T x, T es)
Definition: Math.cpp:337
static int digits()
Definition: Math.cpp:27
static T fma(T x, T y, T z)
Definition: Math.cpp:221
static T expm1(T x)
Definition: Math.cpp:72
static T taupf(T tau, T es)
Definition: Math.cpp:341
static T remainder(T x, T y)
Definition: Math.cpp:140
#define GEOGRAPHICLIB_PANIC
Definition: Math.hpp:83
static T AngRound(T x)
Definition: Math.cpp:241