Constants.hpp
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 6827 2010-05-20 19:56:18Z karney $"
00012
00013
00014
00015
00016
00017 #if !defined(STATIC_ASSERT)
00018 #define STATIC_ASSERT(cond,reason) { enum{ STATIC_ASSERT_ENUM=1/int(cond) }; }
00019 #endif
00020
00021 #if defined(__GNUC__)
00022
00023 #define RCSID_DECL(x) namespace \
00024 { char VAR_ ## x [] __attribute__((unused)) = x; }
00025 #else
00026
00027
00028
00029 #define RCSID_DECL(x) namespace { char VAR_ ## x [] = x; }
00030 #endif
00031
00032 RCSID_DECL(GEOGRAPHICLIB_CONSTANTS_HPP)
00033
00034 #if !defined(GEOGRAPHICLIB_PREC)
00035
00036
00037
00038
00039
00040
00041
00042 #define GEOGRAPHICLIB_PREC 1
00043 #endif
00044
00045 #include <cmath>
00046 #include <limits>
00047 #include <algorithm>
00048 #include <stdexcept>
00049
00050
00051
00052
00053
00054
00055
00056
00057 namespace GeographicLib {
00058
00059
00060
00061
00062
00063
00064
00065
00066 class Math {
00067 private:
00068 void dummy() {
00069 STATIC_ASSERT((GEOGRAPHICLIB_PREC) >= 0 && (GEOGRAPHICLIB_PREC) <= 2,
00070 "Bad value of precision");
00071 }
00072 Math();
00073 public:
00074
00075 #if GEOGRAPHICLIB_PREC == 1
00076
00077
00078
00079
00080
00081 typedef double real;
00082 #elif GEOGRAPHICLIB_PREC == 0
00083 typedef float real;
00084 #elif GEOGRAPHICLIB_PREC == 2
00085 typedef long double real;
00086 #else
00087 typedef double real;
00088 #endif
00089
00090 #if defined(DOXYGEN)
00091
00092
00093
00094
00095 static inline real hypot(real x, real y) throw() {
00096 x = std::abs(x);
00097 y = std::abs(y);
00098 real
00099 a = std::max(x, y),
00100 b = std::min(x, y) / a;
00101 return a * std::sqrt(1 + b * b);
00102 }
00103 #elif defined(_MSC_VER)
00104 static inline double hypot(double x, double y) throw()
00105 { return _hypot(x, y); }
00106 static inline float hypot(float x, float y) throw()
00107 { return _hypotf(x, y); }
00108 #else
00109
00110 static inline double hypot(double x, double y) throw()
00111 { return ::hypot(x, y); }
00112 static inline float hypot(float x, float y) throw()
00113 { return ::hypotf(x, y); }
00114 #if !defined(__NO_LONG_DOUBLE_MATH)
00115 static inline long double hypot(long double x, long double y) throw()
00116 { return ::hypotl(x, y); }
00117 #endif
00118 #endif
00119
00120 #if defined(DOXYGEN) || defined(_MSC_VER)
00121
00122
00123
00124
00125
00126 static inline real expm1(real x) throw() {
00127 volatile real
00128 y = std::exp(x),
00129 z = y - 1;
00130
00131
00132
00133
00134 return std::abs(x) > 1 ? z : z == 0 ? x : x * z / std::log(y);
00135 }
00136 #else
00137 static inline double expm1(double x) throw() { return ::expm1(x); }
00138 static inline float expm1(float x) throw() { return ::expm1f(x); }
00139 #if !defined(__NO_LONG_DOUBLE_MATH)
00140 static inline long double expm1(long double x) throw()
00141 { return ::expm1l(x); }
00142 #endif
00143 #endif
00144
00145 #if defined(DOXYGEN) || defined(_MSC_VER)
00146
00147
00148
00149
00150
00151
00152
00153
00154 static inline real log1p(real x) throw() {
00155 volatile real
00156 y = 1 + x,
00157 z = y - 1;
00158
00159
00160
00161
00162 return z == 0 ? x : x * std::log(y) / z;
00163 }
00164 #else
00165 static inline double log1p(double x) throw() { return ::log1p(x); }
00166 static inline float log1p(float x) throw() { return ::log1pf(x); }
00167 #if !defined(__NO_LONG_DOUBLE_MATH)
00168 static inline long double log1p(long double x) throw()
00169 { return ::log1pl(x); }
00170 #endif
00171 #endif
00172
00173 #if defined(DOXYGEN) || defined(_MSC_VER)
00174
00175
00176
00177
00178
00179 static inline real asinh(real x) throw() {
00180 real y = std::abs(x);
00181 y = log1p(y * (1 + y/(hypot(real(1), y) + 1)));
00182 return x < 0 ? -y : y;
00183 }
00184 #else
00185 static inline double asinh(double x) throw() { return ::asinh(x); }
00186 static inline float asinh(float x) throw() { return ::asinhf(x); }
00187 #if !defined(__NO_LONG_DOUBLE_MATH)
00188 static inline long double asinh(long double x) throw()
00189 { return ::asinhl(x); }
00190 #endif
00191 #endif
00192
00193 #if defined(DOXYGEN) || defined(_MSC_VER)
00194
00195
00196
00197
00198
00199 static inline real atanh(real x) throw() {
00200 real y = std::abs(x);
00201 y = log1p(2 * y/(1 - y))/2;
00202 return x < 0 ? -y : y;
00203 }
00204 #else
00205 static inline double atanh(double x) throw() { return ::atanh(x); }
00206 static inline float atanh(float x) throw() { return ::atanhf(x); }
00207 #if !defined(__NO_LONG_DOUBLE_MATH)
00208 static inline long double atanh(long double x) throw()
00209 { return ::atanhl(x); }
00210 #endif
00211 #endif
00212
00213 #if defined(DOXYGEN) || defined(_MSC_VER)
00214
00215
00216
00217 static inline real cbrt(real x) throw() {
00218 real y = std::pow(std::abs(x), 1/real(3));
00219 return x < 0 ? -y : y;
00220 }
00221 #else
00222 static inline double cbrt(double x) throw() { return ::cbrt(x); }
00223 static inline float cbrt(float x) throw() { return ::cbrtf(x); }
00224 #if !defined(__NO_LONG_DOUBLE_MATH)
00225 static inline long double cbrt(long double x) throw() { return ::cbrtl(x); }
00226 #endif
00227 #endif
00228
00229
00230
00231
00232 static inline bool isfinite(real x) throw() {
00233 #if defined(DOXYGEN)
00234 return std::abs(x) <= std::numeric_limits<real>::max();
00235 #elif defined(_MSC_VER)
00236 return _finite(x) != 0;
00237 #else
00238 return std::isfinite(x) != 0;
00239 #endif
00240 }
00241 };
00242
00243
00244
00245
00246
00247
00248
00249 class Constants {
00250 private:
00251 typedef Math::real real;
00252 Constants();
00253
00254 public:
00255
00256
00257
00258 static inline Math::real pi() throw()
00259
00260 { return real(3.141592653589793238462643383279502884L); }
00261
00262
00263
00264 static inline Math::real degree() throw() { return pi() / 180; }
00265
00266
00267
00268 static inline Math::real arcminute() throw() { return degree() / 60; }
00269
00270
00271
00272 static inline Math::real arcsecond() throw() { return arcminute() / 60; }
00273
00274
00275
00276
00277
00278
00279
00280 static inline Math::real WGS84_a() throw() { return 6378137 * meter(); }
00281
00282
00283
00284 static inline Math::real WGS84_r() throw() { return real(298.257223563L); }
00285
00286
00287
00288 static inline Math::real UTM_k0() throw() {return real(0.9996L); }
00289
00290
00291
00292 static inline Math::real UPS_k0() throw() { return real(0.994L); }
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 static inline Math::real meter() throw() { return real(1); }
00303
00304
00305
00306 static inline Math::real kilometer() throw() { return 1000 * meter(); }
00307
00308
00309
00310
00311
00312
00313 static inline Math::real nauticalmile() throw() { return 1852 * meter(); }
00314
00315
00316
00317
00318
00319
00320
00321 static inline Math::real foot() throw()
00322 { return real(0.0254L) * 12 * meter(); }
00323
00324
00325
00326 static inline Math::real yard() throw() { return 3 * foot(); }
00327
00328
00329
00330 static inline Math::real fathom() throw() { return 2 * yard(); }
00331
00332
00333
00334 static inline Math::real chain() throw() { return 22 * yard(); }
00335
00336
00337
00338 static inline Math::real furlong() throw() { return 10 * chain(); }
00339
00340
00341
00342 static inline Math::real mile() throw() { return 8 * furlong(); }
00343
00344
00345
00346
00347
00348
00349
00350
00351 static inline Math::real surveyfoot() throw()
00352 { return real(1200) / real(3937) * meter(); }
00353
00354 };
00355
00356
00357
00358
00359
00360
00361
00362 class GeographicErr : public std::runtime_error {
00363 public:
00364
00365
00366
00367
00368
00369 GeographicErr(const std::string& msg) : std::runtime_error(msg) {}
00370 };
00371
00372 }
00373
00374 #endif