14 #if !defined(GEOGRAPHICLIB_MATH_HPP)
15 #define GEOGRAPHICLIB_MATH_HPP 1
20 #if !defined(GEOGRAPHICLIB_CXX11_MATH)
28 # if defined(__GNUC__) && __cplusplus >= 201103 && \
29 !(defined(__ANDROID__) || defined(ANDROID) || defined(__CYGWIN__))
30 # define GEOGRAPHICLIB_CXX11_MATH 1
32 # elif defined(_MSC_VER) && _MSC_VER >= 1800
33 # define GEOGRAPHICLIB_CXX11_MATH 1
35 # define GEOGRAPHICLIB_CXX11_MATH 0
39 #if !defined(GEOGRAPHICLIB_WORDS_BIGENDIAN)
40 # define GEOGRAPHICLIB_WORDS_BIGENDIAN 0
43 #if !defined(GEOGRAPHICLIB_HAVE_LONG_DOUBLE)
44 # define GEOGRAPHICLIB_HAVE_LONG_DOUBLE 0
47 #if !defined(GEOGRAPHICLIB_PRECISION)
57 # define GEOGRAPHICLIB_PRECISION 2
64 #if GEOGRAPHICLIB_PRECISION == 4
65 #include <boost/version.hpp>
66 #if BOOST_VERSION >= 105600
67 #include <boost/cstdfloat.hpp>
69 #include <boost/multiprecision/float128.hpp>
70 #include <boost/math/special_functions.hpp>
71 __float128 fmaq(__float128, __float128, __float128);
72 #elif GEOGRAPHICLIB_PRECISION == 5
76 #if GEOGRAPHICLIB_PRECISION > 3
78 #define GEOGRAPHICLIB_VOLATILE
81 #define GEOGRAPHICLIB_PANIC \
82 (throw GeographicLib::GeographicErr("Convergence failure"), false)
84 #define GEOGRAPHICLIB_VOLATILE volatile
87 #define GEOGRAPHICLIB_PANIC false
107 "Bad value of precision");
112 #if GEOGRAPHICLIB_HAVE_LONG_DOUBLE
122 #if GEOGRAPHICLIB_PRECISION == 2
130 #elif GEOGRAPHICLIB_PRECISION == 1
132 #elif GEOGRAPHICLIB_PRECISION == 3
133 typedef extended
real;
134 #elif GEOGRAPHICLIB_PRECISION == 4
135 typedef boost::multiprecision::float128
real;
136 #elif GEOGRAPHICLIB_PRECISION == 5
137 typedef mpfr::mpreal
real;
146 #if GEOGRAPHICLIB_PRECISION != 5
147 return std::numeric_limits<real>::digits;
149 return std::numeric_limits<real>::digits();
164 #if GEOGRAPHICLIB_PRECISION != 5
167 mpfr::mpreal::set_default_prec(ndigits >= 2 ? ndigits : 2);
176 #if GEOGRAPHICLIB_PRECISION != 5
177 return std::numeric_limits<real>::digits10;
179 return std::numeric_limits<real>::digits10();
189 digits10() > std::numeric_limits<double>::digits10 ?
190 digits10() - std::numeric_limits<double>::digits10 : 0;
193 #if GEOGRAPHICLIB_PRECISION <= 3
200 static const int extradigits =
201 std::numeric_limits<real>::digits10 >
202 std::numeric_limits<double>::digits10 ?
203 std::numeric_limits<real>::digits10 -
204 std::numeric_limits<double>::digits10 : 0;
216 template<
typename T>
static inline T
pi() {
218 static const T pi = atan2(T(0), T(-1));
224 static inline real
pi() {
return pi<real>(); }
230 template<
typename T>
static inline T
degree() {
231 static const T degree = pi<T>() / 180;
237 static inline real
degree() {
return degree<real>(); }
246 template<
typename T>
static inline T
sq(T x)
257 template<
typename T>
static inline T
hypot(T x, T y) {
258 #if GEOGRAPHICLIB_CXX11_MATH
259 using std::hypot;
return hypot(x, y);
261 using std::abs;
using std::sqrt;
262 x = abs(x); y = abs(y);
263 if (x < y) std::swap(x, y);
265 return x * sqrt(1 + y * y);
279 template<
typename T>
static inline T
expm1(T x) {
280 #if GEOGRAPHICLIB_CXX11_MATH
281 using std::expm1;
return expm1(x);
283 using std::exp;
using std::abs;
using std::log;
291 return abs(x) > 1 ? z : (z == 0 ? x : x * z / log(y));
302 template<
typename T>
static inline T
log1p(T x) {
303 #if GEOGRAPHICLIB_CXX11_MATH
304 using std::log1p;
return log1p(x);
314 return z == 0 ? x : x * log(y) / z;
325 template<
typename T>
static inline T
asinh(T x) {
326 #if GEOGRAPHICLIB_CXX11_MATH
327 using std::asinh;
return asinh(x);
329 using std::abs; T y = abs(x);
330 y = log1p(y * (1 + y/(hypot(T(1), y) + 1)));
331 return x < 0 ? -y : y;
342 template<
typename T>
static inline T
atanh(T x) {
343 #if GEOGRAPHICLIB_CXX11_MATH
344 using std::atanh;
return atanh(x);
346 using std::abs; T y = abs(x);
347 y = log1p(2 * y/(1 - y))/2;
348 return x < 0 ? -y : y;
359 template<
typename T>
static inline T
cbrt(T x) {
360 #if GEOGRAPHICLIB_CXX11_MATH
361 using std::cbrt;
return cbrt(x);
363 using std::abs;
using std::pow;
364 T y = pow(abs(x), 1/T(3));
365 return x < 0 ? -y : y;
383 template<
typename T>
static inline T
fma(T x, T y, T z) {
384 #if GEOGRAPHICLIB_CXX11_MATH
385 using std::fma;
return fma(x, y, z);
398 template<
typename T>
static inline void norm(T& x, T& y)
399 { T h = hypot(x, y); x /= h; y /= h; }
413 template<
typename T>
static inline T
sum(T u, T v, T& t) {
439 template<
typename T>
static inline T
polyval(
int N,
const T p[], T x)
440 { T y = N < 0 ? 0 : *p++;
while (--N >= 0) y = y * x + *p++;
return y; }
452 #if GEOGRAPHICLIB_CXX11_MATH && GEOGRAPHICLIB_PRECISION != 4
453 using std::remainder;
454 x = remainder(x, T(360));
return x != 180 ? x : -180;
458 return x < -180 ? x + 360 : (x < 180 ? x : x - 360);
472 {
return AngNormalize<T>(x); }
482 template<
typename T>
static inline T
LatFix(T x)
483 {
using std::abs;
return abs(x) > 90 ? NaN<T>() : x; }
499 template<
typename T>
static inline T
AngDiff(T x, T y) {
500 #if GEOGRAPHICLIB_CXX11_MATH && GEOGRAPHICLIB_PRECISION != 4
501 using std::remainder;
502 T t, d = - AngNormalize(sum(remainder( x, T(360)),
503 remainder(-y, T(360)), t));
505 T t, d = - AngNormalize(sum(AngNormalize(x), AngNormalize(-y), t));
513 return (d == 180 && t < 0 ? -180 : d) - t;
530 template<
typename T>
static inline T
AngRound(T x) {
535 y = y < z ? z - (z - y) : y;
536 #if GEOGRAPHICLIB_PRECISION == 4
539 return x <= 0 ? 0 - y : y;
540 #elif GEOGRAPHICLIB_PRECISION == 5
542 return x < 0 ? T(0) - y : y;
544 return x < 0 ? 0 - y : y;
559 template<
typename T>
static inline void sincosd(T x, T& sinx, T& cosx) {
562 using std::sin;
using std::cos;
564 #if GEOGRAPHICLIB_CXX11_MATH && GEOGRAPHICLIB_PRECISION <= 3 && \
571 r = remquo(x, T(90), &q);
573 using std::fmod;
using std::floor;
575 q = int(floor(r / 90 + T(0.5)));
581 T s = sin(r), c = cos(r);
582 switch (
unsigned(q) & 3U) {
583 case 0U: sinx = s; cosx = c;
break;
584 case 1U: sinx = c; cosx = 0 - s;
break;
585 case 2U: sinx = 0 - s; cosx = 0 - c;
break;
586 default: sinx = 0 - c; cosx = s;
break;
597 template<
typename T>
static inline T
sind(T x) {
599 using std::sin;
using std::cos;
601 #if GEOGRAPHICLIB_CXX11_MATH && GEOGRAPHICLIB_PRECISION <= 3 && \
604 r = remquo(x, T(90), &q);
606 using std::fmod;
using std::floor;
608 q = int(floor(r / 90 + T(0.5)));
613 unsigned p = unsigned(q);
614 r = p & 1U ? cos(r) : sin(r);
615 return p & 2U ? 0 - r : r;
625 template<
typename T>
static inline T
cosd(T x) {
627 using std::sin;
using std::cos;
629 #if GEOGRAPHICLIB_CXX11_MATH && GEOGRAPHICLIB_PRECISION <= 3 && \
632 r = remquo(x, T(90), &q);
634 using std::fmod;
using std::floor;
636 q = int(floor(r / 90 + T(0.5)));
641 unsigned p = unsigned(q + 1);
642 r = p & 1U ? cos(r) : sin(r);
643 return p & 2U ? 0 - r : r;
656 template<
typename T>
static inline T
tand(T x) {
657 static const T overflow = 1 / sq(std::numeric_limits<T>::epsilon());
660 return c ? s / c : (s < 0 ? -overflow : overflow);
676 template<
typename T>
static inline T
atan2d(T y, T x) {
681 using std::atan2;
using std::abs;
683 if (abs(y) > abs(x)) { std::swap(x, y); q = 2; }
684 if (x < 0) { x = -x; ++q; }
686 T ang = atan2(y, x) / degree();
694 case 1: ang = (y > 0 ? 180 : -180) - ang;
break;
695 case 2: ang = 90 - ang;
break;
696 case 3: ang = -90 + ang;
break;
708 template<
typename T>
static inline T
atand(T x)
709 {
return atan2d(x, T(1)); }
723 template<
typename T>
static T eatanhe(T x, T es);
741 template<
typename T>
static T taupf(T tau, T es);
759 template<
typename T>
static T tauf(T taup, T es);
768 template<
typename T>
static inline bool isfinite(T x) {
769 #if GEOGRAPHICLIB_CXX11_MATH
770 using std::isfinite;
return isfinite(x);
773 return abs(x) <= (std::numeric_limits<T>::max)();
783 template<
typename T>
static inline T
NaN() {
784 return std::numeric_limits<T>::has_quiet_NaN ?
785 std::numeric_limits<T>::quiet_NaN() :
786 (std::numeric_limits<T>::max)();
791 static inline real
NaN() {
return NaN<real>(); }
800 template<
typename T>
static inline bool isnan(T x) {
801 #if GEOGRAPHICLIB_CXX11_MATH
802 using std::isnan;
return isnan(x);
815 return std::numeric_limits<T>::has_infinity ?
816 std::numeric_limits<T>::infinity() :
817 (std::numeric_limits<T>::max)();
822 static inline real
infinity() {
return infinity<real>(); }
831 template<
typename T>
static inline T
swab(T x) {
834 unsigned char c[
sizeof(T)];
837 for (
int i =
sizeof(T)/2; i--; )
838 std::swap(b.c[i], b.c[
sizeof(T) - 1 - i]);
842 #if GEOGRAPHICLIB_PRECISION == 4
843 typedef boost::math::policies::policy
844 < boost::math::policies::domain_error
845 <boost::math::policies::errno_on_error>,
846 boost::math::policies::pole_error
847 <boost::math::policies::errno_on_error>,
848 boost::math::policies::overflow_error
849 <boost::math::policies::errno_on_error>,
850 boost::math::policies::evaluation_error
851 <boost::math::policies::errno_on_error> >
852 boost_special_functions_policy;
854 static inline real hypot(real x, real y)
855 {
return boost::math::hypot(x, y, boost_special_functions_policy()); }
857 static inline real expm1(real x)
858 {
return boost::math::expm1(x, boost_special_functions_policy()); }
860 static inline real log1p(real x)
861 {
return boost::math::log1p(x, boost_special_functions_policy()); }
863 static inline real asinh(real x)
864 {
return boost::math::asinh(x, boost_special_functions_policy()); }
866 static inline real atanh(real x)
867 {
return boost::math::atanh(x, boost_special_functions_policy()); }
869 static inline real cbrt(real x)
870 {
return boost::math::cbrt(x, boost_special_functions_policy()); }
872 static inline real fma(real x, real y, real z)
873 {
return fmaq(__float128(x), __float128(y), __float128(z)); }
875 static inline bool isnan(real x) {
return boost::math::isnan(x); }
877 static inline bool isfinite(real x) {
return boost::math::isfinite(x); }
883 #endif // GEOGRAPHICLIB_MATH_HPP
static T AngNormalize(T x)
static T sum(T u, T v, T &t)
static int set_digits(int ndigits)
#define GEOGRAPHICLIB_EXPORT
#define GEOGRAPHICLIB_WORDS_BIGENDIAN
GeographicLib::Math::real real
static bool isfinite(T x)
Mathematical functions needed by GeographicLib.
static void sincosd(T x, T &sinx, T &cosx)
static void norm(T &x, T &y)
#define GEOGRAPHICLIB_PRECISION
#define GEOGRAPHICLIB_VOLATILE
static int extra_digits()
static T atan2d(T y, T x)
static T polyval(int N, const T p[], T x)
Namespace for GeographicLib.
static T AngDiff(T x, T y)
Header for GeographicLib::Constants class.
static T fma(T x, T y, T z)
static T AngNormalize2(T x)