Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 #if !defined(GEOGRAPHICLIB_CONSTANTS_HPP)
00011 #define GEOGRAPHICLIB_CONSTANTS_HPP "$Id: Constants.hpp 6967 2011-02-19 15:53:41Z karney $"
00012 
00013 
00014 
00015 
00016 #if !defined(GEOGRAPHICLIB_CPLUSPLUS0X_MATH)
00017 #if defined(__GXX_EXPERIMENTAL_CXX0X__)
00018 #define GEOGRAPHICLIB_CPLUSPLUS0X_MATH 1
00019 #else
00020 #define GEOGRAPHICLIB_CPLUSPLUS0X_MATH 0
00021 #endif
00022 #endif
00023 
00024 
00025 
00026 
00027 #if !defined(STATIC_ASSERT)
00028 #if defined(__GXX_EXPERIMENTAL_CXX0X__)
00029 #define STATIC_ASSERT static_assert
00030 #elif defined(_MSC_VER) && _MSC_VER >= 1600
00031 #define STATIC_ASSERT static_assert
00032 #else
00033 #define STATIC_ASSERT(cond,reason) { enum{ STATIC_ASSERT_ENUM=1/int(cond) }; }
00034 #endif
00035 #endif
00036 
00037 #if defined(__GNUC__)
00038 
00039 #define RCSID_DECL(x) namespace \
00040 { char VAR_ ## x [] __attribute__((used)) = x; }
00041 #else
00042 
00043 
00044 
00045 #define RCSID_DECL(x) namespace { char VAR_ ## x [] = x; }
00046 #endif
00047 
00048 RCSID_DECL(GEOGRAPHICLIB_CONSTANTS_HPP)
00049 
00050 #if !defined(GEOGRAPHICLIB_PREC)
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 #define GEOGRAPHICLIB_PREC 1
00059 #endif
00060 
00061 #if defined(__CYGWIN__) && defined(__GNUC__) && __GNUC__ < 4
00062 
00063 #define __NO_LONG_DOUBLE_MATH 1
00064 #endif
00065 
00066 #include <cmath>
00067 #include <limits>
00068 #include <algorithm>
00069 #include <stdexcept>
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 namespace GeographicLib {
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087   class Math {
00088   private:
00089     void dummy() {
00090       STATIC_ASSERT((GEOGRAPHICLIB_PREC) >= 0 && (GEOGRAPHICLIB_PREC) <= 2,
00091                     "Bad value of precision");
00092     }
00093     Math();                     
00094   public:
00095 
00096 #if !defined(__NO_LONG_DOUBLE_MATH)
00097 
00098 
00099 
00100 
00101     typedef long double extended;
00102 #else
00103     typedef double extended;
00104 #endif
00105 
00106 #if GEOGRAPHICLIB_PREC == 1
00107 
00108 
00109 
00110 
00111 
00112     typedef double real;
00113 #elif GEOGRAPHICLIB_PREC == 0
00114     typedef float real;
00115 #elif GEOGRAPHICLIB_PREC == 2
00116     typedef extended real;
00117 #else
00118     typedef double real;
00119 #endif
00120 
00121 
00122 
00123 
00124     template<typename T>
00125     static inline T pi() throw()
00126     
00127     { return T(3.1415926535897932384626433832795028841971693993751L); }
00128 
00129 
00130 
00131     static inline real pi() throw() { return pi<real>(); }
00132 
00133 
00134 
00135     static inline extended epi() throw() { return pi<extended>(); }
00136 
00137 
00138 
00139 
00140     template<typename T>
00141     static inline T degree() throw() { return pi<T>() / T(180); }
00142 
00143 
00144 
00145     static inline real degree() throw() { return degree<real>(); }
00146 
00147 
00148 
00149     static inline extended edegree() throw() { return degree<extended>(); }
00150 
00151 #if defined(DOXYGEN)
00152 
00153 
00154 
00155 
00156 
00157 
00158 
00159     template<typename T>
00160     static inline T hypot(T x, T y) throw() {
00161       x = std::abs(x);
00162       y = std::abs(y);
00163       T a = std::max(x, y),
00164         b = std::min(x, y) / a;
00165       return a * std::sqrt(1 + b * b);
00166     }
00167 #elif GEOGRAPHICLIB_CPLUSPLUS0X_MATH
00168     template<typename T>
00169     static inline T hypot(T x, T y) throw() { return std::hypot(x, y); }
00170 #elif defined(_MSC_VER)
00171     static inline double hypot(double x, double y) throw()
00172     { return _hypot(x, y); }
00173     static inline float hypot(float x, float y) throw()
00174     { return _hypotf(x, y); }
00175 #if !defined(__NO_LONG_DOUBLE_MATH)
00176     static inline long double hypot(long double x, long double y) throw()
00177     { return _hypot(x, y); }
00178 #endif
00179 #else
00180     
00181     static inline double hypot(double x, double y) throw()
00182     { return ::hypot(x, y); }
00183     static inline float hypot(float x, float y) throw()
00184     { return ::hypotf(x, y); }
00185 #if !defined(__NO_LONG_DOUBLE_MATH)
00186     static inline long double hypot(long double x, long double y) throw()
00187     { return ::hypotl(x, y); }
00188 #endif
00189 #endif
00190 
00191 #if defined(DOXYGEN) || (defined(_MSC_VER) && !GEOGRAPHICLIB_CPLUSPLUS0X_MATH)
00192 
00193 
00194 
00195 
00196 
00197 
00198 
00199 
00200     template<typename T>
00201     static inline T expm1(T x) throw() {
00202       volatile T
00203         y = std::exp(x),
00204         z = y - 1;
00205       
00206       
00207       
00208       
00209       return std::abs(x) > 1 ? z : z == 0 ?  x : x * z / std::log(y);
00210     }
00211 #elif GEOGRAPHICLIB_CPLUSPLUS0X_MATH
00212     template<typename T>
00213     static inline T expm1(T x) throw() { return std::expm1(x); }
00214 #else
00215     static inline double expm1(double x) throw() { return ::expm1(x); }
00216     static inline float expm1(float x) throw() { return ::expm1f(x); }
00217 #if !defined(__NO_LONG_DOUBLE_MATH)
00218     static inline long double expm1(long double x) throw()
00219     { return ::expm1l(x); }
00220 #endif
00221 #endif
00222 
00223 #if defined(DOXYGEN) || (defined(_MSC_VER) && !GEOGRAPHICLIB_CPLUSPLUS0X_MATH)
00224 
00225 
00226 
00227 
00228 
00229 
00230 
00231 
00232 
00233 
00234 
00235     template<typename T>
00236     static inline T log1p(T x) throw() {
00237       volatile T
00238         y = 1 + x,
00239         z = y - 1;
00240       
00241       
00242       
00243       
00244       return z == 0 ? x : x * std::log(y) / z;
00245     }
00246 #elif GEOGRAPHICLIB_CPLUSPLUS0X_MATH
00247     template<typename T>
00248     static inline T log1p(T x) throw() { return std::log1p(x); }
00249 #else
00250     static inline double log1p(double x) throw() { return ::log1p(x); }
00251     static inline float log1p(float x) throw() { return ::log1pf(x); }
00252 #if !defined(__NO_LONG_DOUBLE_MATH)
00253     static inline long double log1p(long double x) throw()
00254     { return ::log1pl(x); }
00255 #endif
00256 #endif
00257 
00258 #if defined(DOXYGEN) || (defined(_MSC_VER) && !GEOGRAPHICLIB_CPLUSPLUS0X_MATH)
00259 
00260 
00261 
00262 
00263 
00264 
00265 
00266 
00267     template<typename T>
00268     static inline T asinh(T x) throw() {
00269       T y = std::abs(x);     
00270       y = log1p(y * (1 + y/(hypot(T(1), y) + 1)));
00271       return x < 0 ? -y : y;
00272     }
00273 #elif GEOGRAPHICLIB_CPLUSPLUS0X_MATH
00274     template<typename T>
00275     static inline T asinh(T x) throw() { return std::asinh(x); }
00276 #else
00277     static inline double asinh(double x) throw() { return ::asinh(x); }
00278     static inline float asinh(float x) throw() { return ::asinhf(x); }
00279 #if !defined(__NO_LONG_DOUBLE_MATH)
00280     static inline long double asinh(long double x) throw()
00281     { return ::asinhl(x); }
00282 #endif
00283 #endif
00284 
00285 #if defined(DOXYGEN) || (defined(_MSC_VER) && !GEOGRAPHICLIB_CPLUSPLUS0X_MATH)
00286 
00287 
00288 
00289 
00290 
00291 
00292 
00293 
00294     template<typename T>
00295     static inline T atanh(T x) throw() {
00296       T y = std::abs(x);     
00297       y = log1p(2 * y/(1 - y))/2;
00298       return x < 0 ? -y : y;
00299     }
00300 #elif GEOGRAPHICLIB_CPLUSPLUS0X_MATH
00301     template<typename T>
00302     static inline T atanh(T x) throw() { return std::atanh(x); }
00303 #else
00304     static inline double atanh(double x) throw() { return ::atanh(x); }
00305     static inline float atanh(float x) throw() { return ::atanhf(x); }
00306 #if !defined(__NO_LONG_DOUBLE_MATH)
00307     static inline long double atanh(long double x) throw()
00308     { return ::atanhl(x); }
00309 #endif
00310 #endif
00311 
00312 #if defined(DOXYGEN) || (defined(_MSC_VER) && !GEOGRAPHICLIB_CPLUSPLUS0X_MATH)
00313 
00314 
00315 
00316 
00317 
00318 
00319     template<typename T>
00320     static inline T cbrt(T x) throw() {
00321       T y = std::pow(std::abs(x), 1/T(3)); 
00322       return x < 0 ? -y : y;
00323     }
00324 #elif GEOGRAPHICLIB_CPLUSPLUS0X_MATH
00325     template<typename T>
00326     static inline T cbrt(T x) throw() { return std::cbrt(x); }
00327 #else
00328     static inline double cbrt(double x) throw() { return ::cbrt(x); }
00329     static inline float cbrt(float x) throw() { return ::cbrtf(x); }
00330 #if !defined(__NO_LONG_DOUBLE_MATH)
00331     static inline long double cbrt(long double x) throw() { return ::cbrtl(x); }
00332 #endif
00333 #endif
00334 
00335 
00336 
00337 
00338 
00339 
00340 
00341     template<typename T>
00342     static inline bool isfinite(T x) throw() {
00343 #if defined(DOXYGEN)
00344       return std::abs(x) <= std::numeric_limits<T>::max();
00345 #elif (defined(_MSC_VER) && !GEOGRAPHICLIB_CPLUSPLUS0X_MATH)
00346       return _finite(x) != 0;
00347 #else
00348       return std::isfinite(x);
00349 #endif
00350     }
00351 
00352 
00353 
00354 
00355 
00356 
00357     template<typename T>
00358     static inline T NaN() throw() {
00359       return std::numeric_limits<T>::has_quiet_NaN ?
00360         std::numeric_limits<T>::quiet_NaN() :
00361         std::numeric_limits<T>::max();
00362     }
00363 
00364 
00365 
00366     static inline real NaN() throw() { return NaN<real>(); }
00367 
00368 
00369 
00370 
00371 
00372 
00373 
00374     template<typename T>
00375     static inline bool isnan(T x) throw() {
00376 #if defined(DOXYGEN) || (defined(_MSC_VER) && !GEOGRAPHICLIB_CPLUSPLUS0X_MATH)
00377       return x != x;
00378 #else
00379       return std::isnan(x);
00380 #endif
00381     }
00382 
00383 
00384 
00385 
00386 
00387 
00388     template<typename T>
00389     static inline T infinity() throw() {
00390       return std::numeric_limits<T>::has_infinity ?
00391         std::numeric_limits<T>::infinity() :
00392         std::numeric_limits<T>::max();
00393     }
00394 
00395 
00396 
00397     static inline real infinity() throw() { return infinity<real>(); }
00398   };
00399 
00400 
00401 
00402 
00403 
00404 
00405 
00406   class Constants {
00407   private:
00408     typedef Math::real real;
00409     Constants();                
00410 
00411   public:
00412 
00413 
00414 
00415     static inline Math::real pi() throw() { return Math::pi<real>(); }
00416 
00417 
00418 
00419     static inline Math::real degree() throw() { return Math::degree<real>(); }
00420 
00421 
00422 
00423     static inline Math::real arcminute() throw()
00424     { return Math::degree<real>() / 60; }
00425 
00426 
00427 
00428     static inline Math::real arcsecond() throw()
00429     { return Math::degree<real>() / 3600; }
00430 
00431 
00432 
00433 
00434 
00435 
00436 
00437     template<typename T>
00438     static inline T WGS84_a() throw() { return T(6378137) * meter<T>(); }
00439 
00440 
00441 
00442     static inline Math::real WGS84_a() throw() { return WGS84_a<real>(); }
00443 
00444 
00445 
00446     template<typename T>
00447     static inline T WGS84_r() throw() {
00448       
00449       return (T(3393) * T(87903691)) / T(1000000000);
00450     }
00451 
00452 
00453 
00454     static inline Math::real WGS84_r() throw() { return WGS84_r<real>(); }
00455 
00456 
00457 
00458     template<typename T>
00459     static inline T UTM_k0() throw() {return T(9996) / T(10000); } 
00460 
00461 
00462 
00463     static inline Math::real UTM_k0() throw() { return UTM_k0<real>(); }
00464 
00465 
00466 
00467     template<typename T>
00468     static inline T UPS_k0() throw() { return T(994) / T(1000); } 
00469 
00470 
00471 
00472     static inline Math::real UPS_k0() throw() { return UPS_k0<real>(); }
00473 
00474 
00475 
00476 
00477 
00478 
00479 
00480 
00481 
00482 
00483 
00484     template<typename T>
00485     static inline T meter() throw() { return T(1); }
00486 
00487 
00488 
00489     static inline Math::real meter() throw() { return meter<real>(); }
00490 
00491 
00492 
00493     static inline Math::real kilometer() throw()
00494     { return 1000 * meter<real>(); }
00495 
00496 
00497 
00498 
00499     static inline Math::real nauticalmile() throw()
00500     { return 1852 * meter<real>(); }
00501 
00502 
00503 
00504 
00505 
00506 
00507 
00508 
00509     static inline Math::real foot() throw()
00510     { return real(0.0254L) * 12 * meter<real>(); }
00511 
00512 
00513 
00514     static inline Math::real yard() throw() { return 3 * foot(); }
00515 
00516 
00517 
00518     static inline Math::real fathom() throw() { return 2 * yard(); }
00519 
00520 
00521 
00522     static inline Math::real chain() throw() { return 22 * yard(); }
00523 
00524 
00525 
00526     static inline Math::real furlong() throw() { return 10 * chain(); }
00527 
00528 
00529 
00530     static inline Math::real mile() throw() { return 8 * furlong(); }
00531 
00532 
00533 
00534 
00535 
00536 
00537 
00538 
00539     static inline Math::real surveyfoot() throw()
00540     { return real(1200) / real(3937) * meter<real>(); }
00541 
00542   };
00543 
00544 
00545 
00546 
00547 
00548 
00549 
00550   class GeographicErr : public std::runtime_error {
00551   public:
00552 
00553 
00554 
00555 
00556 
00557 
00558 
00559     GeographicErr(const std::string& msg) : std::runtime_error(msg) {}
00560   };
00561 
00562 } 
00563 
00564 #endif