14 #if !defined(GEOGRAPHICLIB_MATH_HPP)
15 #define GEOGRAPHICLIB_MATH_HPP 1
20 #if !defined(GEOGRAPHICLIB_CPLUSPLUS11_MATH)
21 # if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 7 \
22 && __cplusplus >= 201103 && !(defined(__ANDROID__) || defined(ANDROID))
26 # define GEOGRAPHICLIB_CPLUSPLUS11_MATH 1
27 # elif defined(_MSC_VER) && _MSC_VER >= 1800
28 # define GEOGRAPHICLIB_CPLUSPLUS11_MATH 1
30 # define GEOGRAPHICLIB_CPLUSPLUS11_MATH 0
34 #if !defined(WORDS_BIGENDIAN)
35 # define WORDS_BIGENDIAN 0
38 #if !defined(HAVE_LONG_DOUBLE)
39 # define HAVE_LONG_DOUBLE 0
42 #if !defined(GEOGRAPHICLIB_PRECISION)
51 # define GEOGRAPHICLIB_PRECISION 2
57 #if defined(_LIBCPP_VERSION)
58 #include <type_traits>
61 namespace GeographicLib {
78 "Bad value of precision");
93 #if GEOGRAPHICLIB_PRECISION == 2
101 #elif GEOGRAPHICLIB_PRECISION == 1
103 #elif GEOGRAPHICLIB_PRECISION == 3
113 static const int extradigits =
114 std::numeric_limits<real>::digits10 >
115 std::numeric_limits<double>::digits10 ?
116 std::numeric_limits<real>::digits10 -
117 std::numeric_limits<double>::digits10 : 0;
128 template<
typename T>
static inline T
pi() throw()
129 {
return std::atan2(T(0), -T(1)); }
133 static inline real pi() throw() {
return pi<real>(); }
139 template<
typename T>
static inline T
degree() throw()
140 {
return pi<T>() / T(180); }
144 static inline real degree() throw() {
return degree<real>(); }
153 template<
typename T>
static inline T
sq(T x)
throw()
165 template<
typename T>
static inline T
hypot(T x, T y)
throw() {
166 x = std::abs(x); y = std::abs(y);
167 T a = (std::max)(x, y), b = (std::min)(x, y) / (a ? a : 1);
168 return a * std::sqrt(1 + b * b);
173 #elif GEOGRAPHICLIB_CPLUSPLUS11_MATH || (defined(_MSC_VER) && _MSC_VER >= 1700)
174 template<
typename T>
static inline T hypot(T x, T y)
throw()
175 {
return std::hypot(x, y); }
176 # if HAVE_LONG_DOUBLE && defined(_MSC_VER) && _MSC_VER == 1700
181 static inline long double hypot(
long double x,
long double y)
throw()
182 {
return std::hypot(
double(x),
double(y)); }
184 #elif defined(_MSC_VER)
185 static inline double hypot(
double x,
double y)
throw()
186 {
return _hypot(x, y); }
189 static inline float hypot(
float x,
float y)
throw()
190 {
return float(_hypot(x, y)); }
192 static inline float hypot(
float x,
float y)
throw()
193 {
return _hypotf(x, y); }
195 # if HAVE_LONG_DOUBLE
196 static inline long double hypot(
long double x,
long double y)
throw()
197 {
return _hypot(
double(x),
double(y)); }
201 static inline double hypot(
double x,
double y)
throw()
202 { return ::hypot(x, y); }
203 static inline float hypot(
float x,
float y)
throw()
204 { return ::hypotf(x, y); }
205 # if HAVE_LONG_DOUBLE
206 static inline long double hypot(
long double x,
long double y)
throw()
207 { return ::hypotl(x, y); }
211 #if defined(DOXYGEN) || (defined(_MSC_VER) && !GEOGRAPHICLIB_CPLUSPLUS11_MATH)
221 template<
typename T>
static inline T
expm1(T x)
throw() {
229 return std::abs(x) > 1 ? z : (z == 0 ? x : x * z / std::log(y));
231 #elif GEOGRAPHICLIB_CPLUSPLUS11_MATH
232 template<
typename T>
static inline T expm1(T x)
throw()
233 {
return std::expm1(x); }
235 static inline double expm1(
double x)
throw() { return ::expm1(x); }
236 static inline float expm1(
float x)
throw() { return ::expm1f(x); }
237 # if HAVE_LONG_DOUBLE
238 static inline long double expm1(
long double x)
throw()
239 { return ::expm1l(x); }
243 #if defined(DOXYGEN) || (defined(_MSC_VER) && !GEOGRAPHICLIB_CPLUSPLUS11_MATH)
256 template<
typename T>
static inline T
log1p(T x)
throw() {
264 return z == 0 ? x : x * std::log(y) / z;
266 #elif GEOGRAPHICLIB_CPLUSPLUS11_MATH
267 template<
typename T>
static inline T log1p(T x)
throw()
268 {
return std::log1p(x); }
270 static inline double log1p(
double x)
throw() { return ::log1p(x); }
271 static inline float log1p(
float x)
throw() { return ::log1pf(x); }
272 # if HAVE_LONG_DOUBLE
273 static inline long double log1p(
long double x)
throw()
274 { return ::log1pl(x); }
278 #if defined(DOXYGEN) || (defined(_MSC_VER) && !GEOGRAPHICLIB_CPLUSPLUS11_MATH)
288 template<
typename T>
static inline T
asinh(T x)
throw() {
290 y = log1p(y * (1 + y/(hypot(T(1), y) + 1)));
291 return x < 0 ? -y : y;
293 #elif GEOGRAPHICLIB_CPLUSPLUS11_MATH
294 template<
typename T>
static inline T asinh(T x)
throw()
295 {
return std::asinh(x); }
297 static inline double asinh(
double x)
throw() { return ::asinh(x); }
298 static inline float asinh(
float x)
throw() { return ::asinhf(x); }
299 # if HAVE_LONG_DOUBLE
300 static inline long double asinh(
long double x)
throw()
301 { return ::asinhl(x); }
305 #if defined(DOXYGEN) || (defined(_MSC_VER) && !GEOGRAPHICLIB_CPLUSPLUS11_MATH)
315 template<
typename T>
static inline T
atanh(T x)
throw() {
317 y = log1p(2 * y/(1 - y))/2;
318 return x < 0 ? -y : y;
320 #elif GEOGRAPHICLIB_CPLUSPLUS11_MATH
321 template<
typename T>
static inline T atanh(T x)
throw()
322 {
return std::atanh(x); }
324 static inline double atanh(
double x)
throw() { return ::atanh(x); }
325 static inline float atanh(
float x)
throw() { return ::atanhf(x); }
326 # if HAVE_LONG_DOUBLE
327 static inline long double atanh(
long double x)
throw()
328 { return ::atanhl(x); }
332 #if defined(DOXYGEN) || (defined(_MSC_VER) && !GEOGRAPHICLIB_CPLUSPLUS11_MATH)
340 template<
typename T>
static inline T
cbrt(T x)
throw() {
341 T y = std::pow(std::abs(x), 1/T(3));
342 return x < 0 ? -y : y;
344 #elif GEOGRAPHICLIB_CPLUSPLUS11_MATH
345 template<
typename T>
static inline T cbrt(T x)
throw()
346 {
return std::cbrt(x); }
348 static inline double cbrt(
double x)
throw() { return ::cbrt(x); }
349 static inline float cbrt(
float x)
throw() { return ::cbrtf(x); }
350 # if HAVE_LONG_DOUBLE
351 static inline long double cbrt(
long double x)
throw() { return ::cbrtl(x); }
367 template<
typename T>
static inline T
sum(T u, T v, T& t)
throw() {
368 volatile T s = u + v;
369 volatile T up = s - v;
370 volatile T vpp = s - up;
389 {
return x >= 180 ? x - 360 : (x < -180 ? x + 360 : x); }
401 {
return AngNormalize<T>(std::fmod(x, T(360))); }
418 template<
typename T>
static inline T
AngDiff(T x, T y)
throw() {
419 T t, d = sum(-x, y, t);
420 if ((d - T(180)) + t > T(0))
422 else if ((d + T(180)) + t <= T(0))
435 template<
typename T>
static inline bool isfinite(T x)
throw() {
436 return std::abs(x) <= (std::numeric_limits<T>::max)();
438 #elif (defined(_MSC_VER) && !GEOGRAPHICLIB_CPLUSPLUS11_MATH)
439 template<
typename T>
static inline bool isfinite(T x)
throw() {
440 return _finite(
double(x)) != 0;
442 #elif defined(_LIBCPP_VERSION)
447 template<
typename T>
static inline
448 typename std::enable_if<std::is_floating_point<T>::value,
bool>::type
449 isfinite(T x)
throw() {
450 return std::isfinite(x);
452 template<
typename T>
static inline
453 typename std::enable_if<!std::is_floating_point<T>::value,
bool>::type
454 isfinite(T ) throw() {
458 template<
typename T>
static inline bool isfinite(T x)
throw() {
459 return std::isfinite(x);
469 template<
typename T>
static inline T
NaN() throw() {
470 return std::numeric_limits<T>::has_quiet_NaN ?
471 std::numeric_limits<T>::quiet_NaN() :
472 (std::numeric_limits<T>::max)();
477 static inline real NaN() throw() {
return NaN<real>(); }
486 template<
typename T>
static inline bool isnan(T x)
throw() {
487 #if defined(DOXYGEN) || (defined(_MSC_VER) && !GEOGRAPHICLIB_CPLUSPLUS11_MATH)
490 return std::isnan(x);
500 template<
typename T>
static inline T
infinity() throw() {
501 return std::numeric_limits<T>::has_infinity ?
502 std::numeric_limits<T>::infinity() :
503 (std::numeric_limits<T>::max)();
517 template<
typename T>
static inline T
swab(T x) {
520 unsigned char c[
sizeof(T)];
523 for (
int i =
sizeof(T)/2; i--; )
524 std::swap(b.c[i], b.c[
sizeof(T) - 1 - i]);
531 #endif // GEOGRAPHICLIB_MATH_HPP
static T AngNormalize(T x)
static T sum(T u, T v, T &t)
#define GEOGRAPHICLIB_EXPORT
GeographicLib::Math::real real
static bool isfinite(T x)
Mathematical functions needed by GeographicLib.
#define GEOGRAPHICLIB_PRECISION
static T AngDiff(T x, T y)
#define STATIC_ASSERT(cond, reason)
Header for GeographicLib::Constants class.
static T AngNormalize2(T x)