Math.hpp 25 KB

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