GeographicLib  1.52
Math.hpp
Go to the documentation of this file.
1 /**
2  * \file Math.hpp
3  * \brief Header for GeographicLib::Math class
4  *
5  * Copyright (c) Charles Karney (2008-2020) <charles@karney.com> and licensed
6  * under the MIT/X11 License. For more information, see
7  * https://geographiclib.sourceforge.io/
8  **********************************************************************/
9 
10 // Constants.hpp includes Math.hpp. Place this include outside Math.hpp's
11 // include guard to enforce this ordering.
13 
14 #if !defined(GEOGRAPHICLIB_MATH_HPP)
15 #define GEOGRAPHICLIB_MATH_HPP 1
16 
17 #if !defined(GEOGRAPHICLIB_WORDS_BIGENDIAN)
18 # define GEOGRAPHICLIB_WORDS_BIGENDIAN 0
19 #endif
20 
21 #if !defined(GEOGRAPHICLIB_HAVE_LONG_DOUBLE)
22 # define GEOGRAPHICLIB_HAVE_LONG_DOUBLE 0
23 #endif
24 
25 #if !defined(GEOGRAPHICLIB_PRECISION)
26 /**
27  * The precision of floating point numbers used in %GeographicLib. 1 means
28  * float (single precision); 2 (the default) means double; 3 means long double;
29  * 4 is reserved for quadruple precision. Nearly all the testing has been
30  * carried out with doubles and that's the recommended configuration. In order
31  * for long double to be used, GEOGRAPHICLIB_HAVE_LONG_DOUBLE needs to be
32  * defined. Note that with Microsoft Visual Studio, long double is the same as
33  * double.
34  **********************************************************************/
35 # define GEOGRAPHICLIB_PRECISION 2
36 #endif
37 
38 #include <cmath>
39 #include <algorithm>
40 #include <limits>
41 
42 #if GEOGRAPHICLIB_PRECISION == 4
43 #include <boost/version.hpp>
44 #include <boost/multiprecision/float128.hpp>
45 #include <boost/math/special_functions.hpp>
46 #elif GEOGRAPHICLIB_PRECISION == 5
47 #include <mpreal.h>
48 #endif
49 
50 #if GEOGRAPHICLIB_PRECISION > 3
51 // volatile keyword makes no sense for multiprec types
52 #define GEOGRAPHICLIB_VOLATILE
53 // Signal a convergence failure with multiprec types by throwing an exception
54 // at loop exit.
55 #define GEOGRAPHICLIB_PANIC \
56  (throw GeographicLib::GeographicErr("Convergence failure"), false)
57 #else
58 #define GEOGRAPHICLIB_VOLATILE volatile
59 // Ignore convergence failures with standard floating points types by allowing
60 // loop to exit cleanly.
61 #define GEOGRAPHICLIB_PANIC false
62 #endif
63 
64 namespace GeographicLib {
65 
66  /**
67  * \brief Mathematical functions needed by %GeographicLib
68  *
69  * Define mathematical functions in order to localize system dependencies and
70  * to provide generic versions of the functions. In addition define a real
71  * type to be used by %GeographicLib.
72  *
73  * Example of use:
74  * \include example-Math.cpp
75  **********************************************************************/
77  private:
78  void dummy(); // Static check for GEOGRAPHICLIB_PRECISION
79  Math(); // Disable constructor
80  public:
81 
82 #if GEOGRAPHICLIB_HAVE_LONG_DOUBLE
83  /**
84  * The extended precision type for real numbers, used for some testing.
85  * This is long double on computers with this type; otherwise it is double.
86  **********************************************************************/
87  typedef long double extended;
88 #else
89  typedef double extended;
90 #endif
91 
92 #if GEOGRAPHICLIB_PRECISION == 2
93  /**
94  * The real type for %GeographicLib. Nearly all the testing has been done
95  * with \e real = double. However, the algorithms should also work with
96  * float and long double (where available). (<b>CAUTION</b>: reasonable
97  * accuracy typically cannot be obtained using floats.)
98  **********************************************************************/
99  typedef double real;
100 #elif GEOGRAPHICLIB_PRECISION == 1
101  typedef float real;
102 #elif GEOGRAPHICLIB_PRECISION == 3
103  typedef extended real;
104 #elif GEOGRAPHICLIB_PRECISION == 4
105  typedef boost::multiprecision::float128 real;
106 #elif GEOGRAPHICLIB_PRECISION == 5
107  typedef mpfr::mpreal real;
108 #else
109  typedef double real;
110 #endif
111 
112  /**
113  * @return the number of bits of precision in a real number.
114  **********************************************************************/
115  static int digits();
116 
117  /**
118  * Set the binary precision of a real number.
119  *
120  * @param[in] ndigits the number of bits of precision.
121  * @return the resulting number of bits of precision.
122  *
123  * This only has an effect when GEOGRAPHICLIB_PRECISION = 5. See also
124  * Utility::set_digits for caveats about when this routine should be
125  * called.
126  **********************************************************************/
127  static int set_digits(int ndigits);
128 
129  /**
130  * @return the number of decimal digits of precision in a real number.
131  **********************************************************************/
132  static int digits10();
133 
134  /**
135  * Number of additional decimal digits of precision for real relative to
136  * double (0 for float).
137  **********************************************************************/
138  static int extra_digits();
139 
140  /**
141  * true if the machine is big-endian.
142  **********************************************************************/
143  static const bool bigendian = GEOGRAPHICLIB_WORDS_BIGENDIAN;
144 
145  /**
146  * @tparam T the type of the returned value.
147  * @return &pi;.
148  **********************************************************************/
149  template<typename T = real> static T pi() {
150  using std::atan2;
151  static const T pi = atan2(T(0), T(-1));
152  return pi;
153  }
154 
155  /**
156  * @tparam T the type of the returned value.
157  * @return the number of radians in a degree.
158  **********************************************************************/
159  template<typename T = real> static T degree() {
160  static const T degree = pi<T>() / 180;
161  return degree;
162  }
163 
164  /**
165  * Square a number.
166  *
167  * @tparam T the type of the argument and the returned value.
168  * @param[in] x
169  * @return <i>x</i><sup>2</sup>.
170  **********************************************************************/
171  template<typename T> static T sq(T x)
172  { return x * x; }
173 
174  /**
175  * The hypotenuse function avoiding underflow and overflow.
176  *
177  * @tparam T the type of the arguments and the returned value.
178  * @param[in] x
179  * @param[in] y
180  * @return sqrt(<i>x</i><sup>2</sup> + <i>y</i><sup>2</sup>).
181  *
182  * \deprecated Use std::hypot(x, y).
183  **********************************************************************/
184  template<typename T>
185  GEOGRAPHICLIB_DEPRECATED("Use std::hypot(x, y)")
186  static T hypot(T x, T y);
187 
188  /**
189  * exp(\e x) &minus; 1 accurate near \e x = 0.
190  *
191  * @tparam T the type of the argument and the returned value.
192  * @param[in] x
193  * @return exp(\e x) &minus; 1.
194  *
195  * \deprecated Use std::expm1(x).
196  **********************************************************************/
197  template<typename T>
198  GEOGRAPHICLIB_DEPRECATED("Use std::expm1(x)")
199  static T expm1(T x);
200 
201  /**
202  * log(1 + \e x) accurate near \e x = 0.
203  *
204  * @tparam T the type of the argument and the returned value.
205  * @param[in] x
206  * @return log(1 + \e x).
207  *
208  * \deprecated Use std::log1p(x).
209  **********************************************************************/
210  template<typename T>
211  GEOGRAPHICLIB_DEPRECATED("Use std::log1p(x)")
212  static T log1p(T x);
213 
214  /**
215  * The inverse hyperbolic sine function.
216  *
217  * @tparam T the type of the argument and the returned value.
218  * @param[in] x
219  * @return asinh(\e x).
220  *
221  * \deprecated Use std::asinh(x).
222  **********************************************************************/
223  template<typename T>
224  GEOGRAPHICLIB_DEPRECATED("Use std::asinh(x)")
225  static T asinh(T x);
226 
227  /**
228  * The inverse hyperbolic tangent function.
229  *
230  * @tparam T the type of the argument and the returned value.
231  * @param[in] x
232  * @return atanh(\e x).
233  *
234  * \deprecated Use std::atanh(x).
235  **********************************************************************/
236  template<typename T>
237  GEOGRAPHICLIB_DEPRECATED("Use std::atanh(x)")
238  static T atanh(T x);
239 
240  /**
241  * Copy the sign.
242  *
243  * @tparam T the type of the argument.
244  * @param[in] x gives the magitude of the result.
245  * @param[in] y gives the sign of the result.
246  * @return value with the magnitude of \e x and with the sign of \e y.
247  *
248  * This routine correctly handles the case \e y = &minus;0, returning
249  * &minus|<i>x</i>|.
250  *
251  * \deprecated Use std::copysign(x, y).
252  **********************************************************************/
253  template<typename T>
254  GEOGRAPHICLIB_DEPRECATED("Use std::copysign(x, y)")
255  static T copysign(T x, T y);
256 
257  /**
258  * The cube root function.
259  *
260  * @tparam T the type of the argument and the returned value.
261  * @param[in] x
262  * @return the real cube root of \e x.
263  *
264  * \deprecated Use std::cbrt(x).
265  **********************************************************************/
266  template<typename T>
267  GEOGRAPHICLIB_DEPRECATED("Use std::cbrt(x)")
268  static T cbrt(T x);
269 
270  /**
271  * The remainder function.
272  *
273  * @tparam T the type of the arguments and the returned value.
274  * @param[in] x
275  * @param[in] y
276  * @return the remainder of \e x/\e y in the range [&minus;\e y/2, \e y/2].
277  *
278  * \deprecated Use std::remainder(x).
279  **********************************************************************/
280  template<typename T>
281  GEOGRAPHICLIB_DEPRECATED("Use std::remainder(x)")
282  static T remainder(T x, T y);
283 
284  /**
285  * The remquo function.
286  *
287  * @tparam T the type of the arguments and the returned value.
288  * @param[in] x
289  * @param[in] y
290  * @param[out] n the low 3 bits of the quotient
291  * @return the remainder of \e x/\e y in the range [&minus;\e y/2, \e y/2].
292  *
293  * \deprecated Use std::remquo(x, y, n).
294  **********************************************************************/
295  template<typename T>
296  GEOGRAPHICLIB_DEPRECATED("Use std::remquo(x, y, n)")
297  static T remquo(T x, T y, int* n);
298 
299  /**
300  * The round function.
301  *
302  * @tparam T the type of the argument and the returned value.
303  * @param[in] x
304  * @return \e x round to the nearest integer (ties round away from 0).
305  *
306  * \deprecated Use std::round(x).
307  **********************************************************************/
308  template<typename T>
309  GEOGRAPHICLIB_DEPRECATED("Use std::round(x)")
310  static T round(T x);
311 
312  /**
313  * The lround function.
314  *
315  * @tparam T the type of the argument.
316  * @param[in] x
317  * @return \e x round to the nearest integer as a long int (ties round away
318  * from 0).
319  *
320  * If the result does not fit in a long int, the return value is undefined.
321  *
322  * \deprecated Use std::lround(x).
323  **********************************************************************/
324  template<typename T>
325  GEOGRAPHICLIB_DEPRECATED("Use std::lround(x)")
326  static long lround(T x);
327 
328  /**
329  * Fused multiply and add.
330  *
331  * @tparam T the type of the arguments and the returned value.
332  * @param[in] x
333  * @param[in] y
334  * @param[in] z
335  * @return <i>xy</i> + <i>z</i>, correctly rounded (on those platforms with
336  * support for the <code>fma</code> instruction).
337  *
338  * On platforms without the <code>fma</code> instruction, no attempt is
339  * made to improve on the result of a rounded multiplication followed by a
340  * rounded addition.
341  *
342  * \deprecated Use std::fma(x, y, z).
343  **********************************************************************/
344  template<typename T>
345  GEOGRAPHICLIB_DEPRECATED("Use std::fma(x, y, z)")
346  static T fma(T x, T y, T z);
347 
348  /**
349  * Normalize a two-vector.
350  *
351  * @tparam T the type of the argument and the returned value.
352  * @param[in,out] x on output set to <i>x</i>/hypot(<i>x</i>, <i>y</i>).
353  * @param[in,out] y on output set to <i>y</i>/hypot(<i>x</i>, <i>y</i>).
354  **********************************************************************/
355  template<typename T> static void norm(T& x, T& y) {
356 #if defined(_MSC_VER) && defined(_M_IX86)
357  // hypot for Visual Studio (A=win32) fails monotonicity, e.g., with
358  // x = 0.6102683302836215
359  // y1 = 0.7906090004346522
360  // y2 = y1 + 1e-16
361  // the test
362  // hypot(x, y2) >= hypot(x, y1)
363  // fails. Reported 2021-03-14:
364  // https://developercommunity.visualstudio.com/t/1369259
365  // See also:
366  // https://bugs.python.org/issue43088
367  using std::sqrt; T h = sqrt(x * x + y * y);
368 #else
369  using std::hypot; T h = hypot(x, y);
370 #endif
371  x /= h; y /= h;
372  }
373 
374  /**
375  * The error-free sum of two numbers.
376  *
377  * @tparam T the type of the argument and the returned value.
378  * @param[in] u
379  * @param[in] v
380  * @param[out] t the exact error given by (\e u + \e v) - \e s.
381  * @return \e s = round(\e u + \e v).
382  *
383  * See D. E. Knuth, TAOCP, Vol 2, 4.2.2, Theorem B. (Note that \e t can be
384  * the same as one of the first two arguments.)
385  **********************************************************************/
386  template<typename T> static T sum(T u, T v, T& t);
387 
388  /**
389  * Evaluate a polynomial.
390  *
391  * @tparam T the type of the arguments and returned value.
392  * @param[in] N the order of the polynomial.
393  * @param[in] p the coefficient array (of size \e N + 1).
394  * @param[in] x the variable.
395  * @return the value of the polynomial.
396  *
397  * Evaluate <i>y</i> = &sum;<sub><i>n</i>=0..<i>N</i></sub>
398  * <i>p</i><sub><i>n</i></sub> <i>x</i><sup><i>N</i>&minus;<i>n</i></sup>.
399  * Return 0 if \e N &lt; 0. Return <i>p</i><sub>0</sub>, if \e N = 0 (even
400  * if \e x is infinite or a nan). The evaluation uses Horner's method.
401  **********************************************************************/
402  template<typename T> static T polyval(int N, const T p[], T x) {
403  // This used to employ Math::fma; but that's too slow and it seemed not to
404  // improve the accuracy noticeably. This might change when there's direct
405  // hardware support for fma.
406  T y = N < 0 ? 0 : *p++;
407  while (--N >= 0) y = y * x + *p++;
408  return y;
409  }
410 
411  /**
412  * Normalize an angle.
413  *
414  * @tparam T the type of the argument and returned value.
415  * @param[in] x the angle in degrees.
416  * @return the angle reduced to the range (&minus;180&deg;, 180&deg;].
417  *
418  * The range of \e x is unrestricted.
419  **********************************************************************/
420  template<typename T> static T AngNormalize(T x) {
421  using std::remainder;
422  x = remainder(x, T(360)); return x != -180 ? x : 180;
423  }
424 
425  /**
426  * Normalize a latitude.
427  *
428  * @tparam T the type of the argument and returned value.
429  * @param[in] x the angle in degrees.
430  * @return x if it is in the range [&minus;90&deg;, 90&deg;], otherwise
431  * return NaN.
432  **********************************************************************/
433  template<typename T> static T LatFix(T x)
434  { using std::abs; return abs(x) > 90 ? NaN<T>() : x; }
435 
436  /**
437  * The exact difference of two angles reduced to
438  * (&minus;180&deg;, 180&deg;].
439  *
440  * @tparam T the type of the arguments and returned value.
441  * @param[in] x the first angle in degrees.
442  * @param[in] y the second angle in degrees.
443  * @param[out] e the error term in degrees.
444  * @return \e d, the truncated value of \e y &minus; \e x.
445  *
446  * This computes \e z = \e y &minus; \e x exactly, reduced to
447  * (&minus;180&deg;, 180&deg;]; and then sets \e z = \e d + \e e where \e d
448  * is the nearest representable number to \e z and \e e is the truncation
449  * error. If \e d = &minus;180, then \e e &gt; 0; If \e d = 180, then \e e
450  * &le; 0.
451  **********************************************************************/
452  template<typename T> static T AngDiff(T x, T y, T& e) {
453  using std::remainder;
454  T t, d = AngNormalize(sum(remainder(-x, T(360)),
455  remainder( y, T(360)), t));
456  // Here y - x = d + t (mod 360), exactly, where d is in (-180,180] and
457  // abs(t) <= eps (eps = 2^-45 for doubles). The only case where the
458  // addition of t takes the result outside the range (-180,180] is d = 180
459  // and t > 0. The case, d = -180 + eps, t = -eps, can't happen, since
460  // sum would have returned the exact result in such a case (i.e., given t
461  // = 0).
462  return sum(d == 180 && t > 0 ? -180 : d, t, e);
463  }
464 
465  /**
466  * Difference of two angles reduced to [&minus;180&deg;, 180&deg;]
467  *
468  * @tparam T the type of the arguments and returned value.
469  * @param[in] x the first angle in degrees.
470  * @param[in] y the second angle in degrees.
471  * @return \e y &minus; \e x, reduced to the range [&minus;180&deg;,
472  * 180&deg;].
473  *
474  * The result is equivalent to computing the difference exactly, reducing
475  * it to (&minus;180&deg;, 180&deg;] and rounding the result. Note that
476  * this prescription allows &minus;180&deg; to be returned (e.g., if \e x
477  * is tiny and negative and \e y = 180&deg;).
478  **********************************************************************/
479  template<typename T> static T AngDiff(T x, T y)
480  { T e; return AngDiff(x, y, e); }
481 
482  /**
483  * Coarsen a value close to zero.
484  *
485  * @tparam T the type of the argument and returned value.
486  * @param[in] x
487  * @return the coarsened value.
488  *
489  * The makes the smallest gap in \e x = 1/16 &minus; nextafter(1/16, 0) =
490  * 1/2<sup>57</sup> for reals = 0.7 pm on the earth if \e x is an angle in
491  * degrees. (This is about 1000 times more resolution than we get with
492  * angles around 90&deg;.) We use this to avoid having to deal with near
493  * singular cases when \e x is non-zero but tiny (e.g.,
494  * 10<sup>&minus;200</sup>). This converts &minus;0 to +0; however tiny
495  * negative numbers get converted to &minus;0.
496  **********************************************************************/
497  template<typename T> static T AngRound(T x);
498 
499  /**
500  * Evaluate the sine and cosine function with the argument in degrees
501  *
502  * @tparam T the type of the arguments.
503  * @param[in] x in degrees.
504  * @param[out] sinx sin(<i>x</i>).
505  * @param[out] cosx cos(<i>x</i>).
506  *
507  * The results obey exactly the elementary properties of the trigonometric
508  * functions, e.g., sin 9&deg; = cos 81&deg; = &minus; sin 123456789&deg;.
509  * If x = &minus;0, then \e sinx = &minus;0; this is the only case where
510  * &minus;0 is returned.
511  **********************************************************************/
512  template<typename T> static void sincosd(T x, T& sinx, T& cosx);
513 
514  /**
515  * Evaluate the sine function with the argument in degrees
516  *
517  * @tparam T the type of the argument and the returned value.
518  * @param[in] x in degrees.
519  * @return sin(<i>x</i>).
520  **********************************************************************/
521  template<typename T> static T sind(T x);
522 
523  /**
524  * Evaluate the cosine function with the argument in degrees
525  *
526  * @tparam T the type of the argument and the returned value.
527  * @param[in] x in degrees.
528  * @return cos(<i>x</i>).
529  **********************************************************************/
530  template<typename T> static T cosd(T x);
531 
532  /**
533  * Evaluate the tangent function with the argument in degrees
534  *
535  * @tparam T the type of the argument and the returned value.
536  * @param[in] x in degrees.
537  * @return tan(<i>x</i>).
538  *
539  * If \e x = &plusmn;90&deg;, then a suitably large (but finite) value is
540  * returned.
541  **********************************************************************/
542  template<typename T> static T tand(T x);
543 
544  /**
545  * Evaluate the atan2 function with the result in degrees
546  *
547  * @tparam T the type of the arguments and the returned value.
548  * @param[in] y
549  * @param[in] x
550  * @return atan2(<i>y</i>, <i>x</i>) in degrees.
551  *
552  * The result is in the range (&minus;180&deg; 180&deg;]. N.B.,
553  * atan2d(&plusmn;0, &minus;1) = +180&deg;; atan2d(&minus;&epsilon;,
554  * &minus;1) = &minus;180&deg;, for &epsilon; positive and tiny;
555  * atan2d(&plusmn;0, +1) = &plusmn;0&deg;.
556  **********************************************************************/
557  template<typename T> static T atan2d(T y, T x);
558 
559  /**
560  * Evaluate the atan function with the result in degrees
561  *
562  * @tparam T the type of the argument and the returned value.
563  * @param[in] x
564  * @return atan(<i>x</i>) in degrees.
565  **********************************************************************/
566  template<typename T> static T atand(T x);
567 
568  /**
569  * Evaluate <i>e</i> atanh(<i>e x</i>)
570  *
571  * @tparam T the type of the argument and the returned value.
572  * @param[in] x
573  * @param[in] es the signed eccentricity = sign(<i>e</i><sup>2</sup>)
574  * sqrt(|<i>e</i><sup>2</sup>|)
575  * @return <i>e</i> atanh(<i>e x</i>)
576  *
577  * If <i>e</i><sup>2</sup> is negative (<i>e</i> is imaginary), the
578  * expression is evaluated in terms of atan.
579  **********************************************************************/
580  template<typename T> static T eatanhe(T x, T es);
581 
582  /**
583  * tan&chi; in terms of tan&phi;
584  *
585  * @tparam T the type of the argument and the returned value.
586  * @param[in] tau &tau; = tan&phi;
587  * @param[in] es the signed eccentricity = sign(<i>e</i><sup>2</sup>)
588  * sqrt(|<i>e</i><sup>2</sup>|)
589  * @return &tau;&prime; = tan&chi;
590  *
591  * See Eqs. (7--9) of
592  * C. F. F. Karney,
593  * <a href="https://doi.org/10.1007/s00190-011-0445-3">
594  * Transverse Mercator with an accuracy of a few nanometers,</a>
595  * J. Geodesy 85(8), 475--485 (Aug. 2011)
596  * (preprint
597  * <a href="https://arxiv.org/abs/1002.1417">arXiv:1002.1417</a>).
598  **********************************************************************/
599  template<typename T> static T taupf(T tau, T es);
600 
601  /**
602  * tan&phi; in terms of tan&chi;
603  *
604  * @tparam T the type of the argument and the returned value.
605  * @param[in] taup &tau;&prime; = tan&chi;
606  * @param[in] es the signed eccentricity = sign(<i>e</i><sup>2</sup>)
607  * sqrt(|<i>e</i><sup>2</sup>|)
608  * @return &tau; = tan&phi;
609  *
610  * See Eqs. (19--21) of
611  * C. F. F. Karney,
612  * <a href="https://doi.org/10.1007/s00190-011-0445-3">
613  * Transverse Mercator with an accuracy of a few nanometers,</a>
614  * J. Geodesy 85(8), 475--485 (Aug. 2011)
615  * (preprint
616  * <a href="https://arxiv.org/abs/1002.1417">arXiv:1002.1417</a>).
617  **********************************************************************/
618  template<typename T> static T tauf(T taup, T es);
619 
620  /**
621  * Test for finiteness.
622  *
623  * @tparam T the type of the argument.
624  * @param[in] x
625  * @return true if number is finite, false if NaN or infinite.
626  *
627  * \deprecated Use std::isfinite(x).
628  **********************************************************************/
629  template<typename T>
630  GEOGRAPHICLIB_DEPRECATED("Use std::isfinite(x)")
631  static bool isfinite(T x);
632 
633  /**
634  * The NaN (not a number)
635  *
636  * @tparam T the type of the returned value.
637  * @return NaN if available, otherwise return the max real of type T.
638  **********************************************************************/
639  template<typename T = real> static T NaN();
640 
641  /**
642  * Test for NaN.
643  *
644  * @tparam T the type of the argument.
645  * @param[in] x
646  * @return true if argument is a NaN.
647  *
648  * \deprecated Use std::isnan(x).
649  **********************************************************************/
650  template<typename T>
651  GEOGRAPHICLIB_DEPRECATED("Use std::isnan(x)")
652  static bool isnan(T x);
653 
654  /**
655  * Infinity
656  *
657  * @tparam T the type of the returned value.
658  * @return infinity if available, otherwise return the max real.
659  **********************************************************************/
660  template<typename T = real> static T infinity();
661 
662  /**
663  * Swap the bytes of a quantity
664  *
665  * @tparam T the type of the argument and the returned value.
666  * @param[in] x
667  * @return x with its bytes swapped.
668  **********************************************************************/
669  template<typename T> static T swab(T x) {
670  union {
671  T r;
672  unsigned char c[sizeof(T)];
673  } b;
674  b.r = x;
675  for (int i = sizeof(T)/2; i--; )
676  std::swap(b.c[i], b.c[sizeof(T) - 1 - i]);
677  return b.r;
678  }
679 
680  };
681 
682 } // namespace GeographicLib
683 
684 #endif // GEOGRAPHICLIB_MATH_HPP
Header for GeographicLib::Constants class.
#define GEOGRAPHICLIB_EXPORT
Definition: Constants.hpp:66
#define GEOGRAPHICLIB_DEPRECATED(msg)
Definition: Constants.hpp:81
GeographicLib::Math::real real
Definition: GeodSolve.cpp:31
#define GEOGRAPHICLIB_WORDS_BIGENDIAN
Definition: Math.hpp:18
Mathematical functions needed by GeographicLib.
Definition: Math.hpp:76
static T AngNormalize(T x)
Definition: Math.hpp:420
static T degree()
Definition: Math.hpp:159
static T LatFix(T x)
Definition: Math.hpp:433
double extended
Definition: Math.hpp:89
static T sq(T x)
Definition: Math.hpp:171
static T pi()
Definition: Math.hpp:149
static T polyval(int N, const T p[], T x)
Definition: Math.hpp:402
static T AngDiff(T x, T y)
Definition: Math.hpp:479
static T AngDiff(T x, T y, T &e)
Definition: Math.hpp:452
Namespace for GeographicLib.
Definition: Accumulator.cpp:12
void swap(GeographicLib::NearestNeighbor< dist_t, pos_t, distfun_t > &a, GeographicLib::NearestNeighbor< dist_t, pos_t, distfun_t > &b)