annotate DEPENDENCIES/generic/include/boost/geometry/util/math.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 // Boost.Geometry (aka GGL, Generic Geometry Library)
Chris@16 2
Chris@101 3 // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
Chris@101 4 // Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
Chris@101 5 // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
Chris@101 6
Chris@101 7 // This file was modified by Oracle on 2014, 2015.
Chris@101 8 // Modifications copyright (c) 2014-2015, Oracle and/or its affiliates.
Chris@101 9
Chris@101 10 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
Chris@101 11 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
Chris@16 12
Chris@16 13 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
Chris@16 14 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
Chris@16 15
Chris@16 16 // Use, modification and distribution is subject to the Boost Software License,
Chris@16 17 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 18 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 19
Chris@16 20 #ifndef BOOST_GEOMETRY_UTIL_MATH_HPP
Chris@16 21 #define BOOST_GEOMETRY_UTIL_MATH_HPP
Chris@16 22
Chris@16 23 #include <cmath>
Chris@16 24 #include <limits>
Chris@16 25
Chris@101 26 #include <boost/core/ignore_unused.hpp>
Chris@101 27
Chris@16 28 #include <boost/math/constants/constants.hpp>
Chris@101 29 #ifdef BOOST_GEOMETRY_SQRT_CHECK_FINITENESS
Chris@101 30 #include <boost/math/special_functions/fpclassify.hpp>
Chris@101 31 #endif // BOOST_GEOMETRY_SQRT_CHECK_FINITENESS
Chris@101 32 #include <boost/math/special_functions/round.hpp>
Chris@101 33 #include <boost/numeric/conversion/cast.hpp>
Chris@101 34 #include <boost/type_traits/is_fundamental.hpp>
Chris@16 35
Chris@16 36 #include <boost/geometry/util/select_most_precise.hpp>
Chris@16 37
Chris@16 38 namespace boost { namespace geometry
Chris@16 39 {
Chris@16 40
Chris@16 41 namespace math
Chris@16 42 {
Chris@16 43
Chris@16 44 #ifndef DOXYGEN_NO_DETAIL
Chris@16 45 namespace detail
Chris@16 46 {
Chris@16 47
Chris@101 48 template <typename T>
Chris@101 49 inline T const& greatest(T const& v1, T const& v2)
Chris@101 50 {
Chris@101 51 return (std::max)(v1, v2);
Chris@101 52 }
Chris@16 53
Chris@101 54 template <typename T>
Chris@101 55 inline T const& greatest(T const& v1, T const& v2, T const& v3)
Chris@101 56 {
Chris@101 57 return (std::max)(greatest(v1, v2), v3);
Chris@101 58 }
Chris@101 59
Chris@101 60 template <typename T>
Chris@101 61 inline T const& greatest(T const& v1, T const& v2, T const& v3, T const& v4)
Chris@101 62 {
Chris@101 63 return (std::max)(greatest(v1, v2, v3), v4);
Chris@101 64 }
Chris@101 65
Chris@101 66 template <typename T>
Chris@101 67 inline T const& greatest(T const& v1, T const& v2, T const& v3, T const& v4, T const& v5)
Chris@101 68 {
Chris@101 69 return (std::max)(greatest(v1, v2, v3, v4), v5);
Chris@101 70 }
Chris@101 71
Chris@101 72
Chris@101 73 template <typename T,
Chris@101 74 bool IsFloatingPoint = boost::is_floating_point<T>::value>
Chris@101 75 struct abs
Chris@101 76 {
Chris@101 77 static inline T apply(T const& value)
Chris@101 78 {
Chris@101 79 T const zero = T();
Chris@101 80 return value < zero ? -value : value;
Chris@101 81 }
Chris@101 82 };
Chris@101 83
Chris@101 84 template <typename T>
Chris@101 85 struct abs<T, true>
Chris@101 86 {
Chris@101 87 static inline T apply(T const& value)
Chris@101 88 {
Chris@101 89 return fabs(value);
Chris@101 90 }
Chris@101 91 };
Chris@101 92
Chris@101 93
Chris@101 94 struct equals_default_policy
Chris@101 95 {
Chris@101 96 template <typename T>
Chris@101 97 static inline T apply(T const& a, T const& b)
Chris@101 98 {
Chris@101 99 // See http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.17
Chris@101 100 return greatest(abs<T>::apply(a), abs<T>::apply(b), T(1));
Chris@101 101 }
Chris@101 102 };
Chris@101 103
Chris@101 104 template <typename T,
Chris@101 105 bool IsFloatingPoint = boost::is_floating_point<T>::value>
Chris@101 106 struct equals_factor_policy
Chris@101 107 {
Chris@101 108 equals_factor_policy()
Chris@101 109 : factor(1) {}
Chris@101 110 explicit equals_factor_policy(T const& v)
Chris@101 111 : factor(greatest(abs<T>::apply(v), T(1)))
Chris@101 112 {}
Chris@101 113 equals_factor_policy(T const& v0, T const& v1, T const& v2, T const& v3)
Chris@101 114 : factor(greatest(abs<T>::apply(v0), abs<T>::apply(v1),
Chris@101 115 abs<T>::apply(v2), abs<T>::apply(v3),
Chris@101 116 T(1)))
Chris@101 117 {}
Chris@101 118
Chris@101 119 T const& apply(T const&, T const&) const
Chris@101 120 {
Chris@101 121 return factor;
Chris@101 122 }
Chris@101 123
Chris@101 124 T factor;
Chris@101 125 };
Chris@101 126
Chris@101 127 template <typename T>
Chris@101 128 struct equals_factor_policy<T, false>
Chris@101 129 {
Chris@101 130 equals_factor_policy() {}
Chris@101 131 explicit equals_factor_policy(T const&) {}
Chris@101 132 equals_factor_policy(T const& , T const& , T const& , T const& ) {}
Chris@101 133
Chris@101 134 static inline T apply(T const&, T const&)
Chris@101 135 {
Chris@101 136 return T(1);
Chris@101 137 }
Chris@101 138 };
Chris@101 139
Chris@101 140 template <typename Type,
Chris@101 141 bool IsFloatingPoint = boost::is_floating_point<Type>::value>
Chris@16 142 struct equals
Chris@16 143 {
Chris@101 144 template <typename Policy>
Chris@101 145 static inline bool apply(Type const& a, Type const& b, Policy const&)
Chris@16 146 {
Chris@16 147 return a == b;
Chris@16 148 }
Chris@16 149 };
Chris@16 150
Chris@16 151 template <typename Type>
Chris@16 152 struct equals<Type, true>
Chris@16 153 {
Chris@101 154 template <typename Policy>
Chris@101 155 static inline bool apply(Type const& a, Type const& b, Policy const& policy)
Chris@16 156 {
Chris@101 157 boost::ignore_unused(policy);
Chris@16 158
Chris@16 159 if (a == b)
Chris@16 160 {
Chris@16 161 return true;
Chris@16 162 }
Chris@16 163
Chris@101 164 return abs<Type>::apply(a - b) <= std::numeric_limits<Type>::epsilon() * policy.apply(a, b);
Chris@16 165 }
Chris@16 166 };
Chris@16 167
Chris@101 168 template <typename T1, typename T2, typename Policy>
Chris@101 169 inline bool equals_by_policy(T1 const& a, T2 const& b, Policy const& policy)
Chris@101 170 {
Chris@101 171 return detail::equals
Chris@101 172 <
Chris@101 173 typename select_most_precise<T1, T2>::type
Chris@101 174 >::apply(a, b, policy);
Chris@101 175 }
Chris@101 176
Chris@101 177 template <typename Type,
Chris@101 178 bool IsFloatingPoint = boost::is_floating_point<Type>::value>
Chris@16 179 struct smaller
Chris@16 180 {
Chris@16 181 static inline bool apply(Type const& a, Type const& b)
Chris@16 182 {
Chris@16 183 return a < b;
Chris@16 184 }
Chris@16 185 };
Chris@16 186
Chris@16 187 template <typename Type>
Chris@16 188 struct smaller<Type, true>
Chris@16 189 {
Chris@16 190 static inline bool apply(Type const& a, Type const& b)
Chris@16 191 {
Chris@101 192 if (equals<Type, true>::apply(a, b, equals_default_policy()))
Chris@16 193 {
Chris@16 194 return false;
Chris@16 195 }
Chris@16 196 return a < b;
Chris@16 197 }
Chris@16 198 };
Chris@16 199
Chris@16 200
Chris@101 201 template <typename Type,
Chris@101 202 bool IsFloatingPoint = boost::is_floating_point<Type>::value>
Chris@101 203 struct equals_with_epsilon
Chris@101 204 : public equals<Type, IsFloatingPoint>
Chris@101 205 {};
Chris@101 206
Chris@101 207 template
Chris@101 208 <
Chris@101 209 typename T,
Chris@101 210 bool IsFundemantal = boost::is_fundamental<T>::value /* false */
Chris@101 211 >
Chris@101 212 struct square_root
Chris@101 213 {
Chris@101 214 typedef T return_type;
Chris@101 215
Chris@101 216 static inline T apply(T const& value)
Chris@101 217 {
Chris@101 218 // for non-fundamental number types assume that sqrt is
Chris@101 219 // defined either:
Chris@101 220 // 1) at T's scope, or
Chris@101 221 // 2) at global scope, or
Chris@101 222 // 3) in namespace std
Chris@101 223 using ::sqrt;
Chris@101 224 using std::sqrt;
Chris@101 225
Chris@101 226 return sqrt(value);
Chris@101 227 }
Chris@101 228 };
Chris@101 229
Chris@101 230 template <typename FundamentalFP>
Chris@101 231 struct square_root_for_fundamental_fp
Chris@101 232 {
Chris@101 233 typedef FundamentalFP return_type;
Chris@101 234
Chris@101 235 static inline FundamentalFP apply(FundamentalFP const& value)
Chris@101 236 {
Chris@101 237 #ifdef BOOST_GEOMETRY_SQRT_CHECK_FINITENESS
Chris@101 238 // This is a workaround for some 32-bit platforms.
Chris@101 239 // For some of those platforms it has been reported that
Chris@101 240 // std::sqrt(nan) and/or std::sqrt(-nan) returns a finite value.
Chris@101 241 // For those platforms we need to define the macro
Chris@101 242 // BOOST_GEOMETRY_SQRT_CHECK_FINITENESS so that the argument
Chris@101 243 // to std::sqrt is checked appropriately before passed to std::sqrt
Chris@101 244 if (boost::math::isfinite(value))
Chris@101 245 {
Chris@101 246 return std::sqrt(value);
Chris@101 247 }
Chris@101 248 else if (boost::math::isinf(value) && value < 0)
Chris@101 249 {
Chris@101 250 return -std::numeric_limits<FundamentalFP>::quiet_NaN();
Chris@101 251 }
Chris@101 252 return value;
Chris@101 253 #else
Chris@101 254 // for fundamental floating point numbers use std::sqrt
Chris@101 255 return std::sqrt(value);
Chris@101 256 #endif // BOOST_GEOMETRY_SQRT_CHECK_FINITENESS
Chris@101 257 }
Chris@101 258 };
Chris@101 259
Chris@101 260 template <>
Chris@101 261 struct square_root<float, true>
Chris@101 262 : square_root_for_fundamental_fp<float>
Chris@101 263 {
Chris@101 264 };
Chris@101 265
Chris@101 266 template <>
Chris@101 267 struct square_root<double, true>
Chris@101 268 : square_root_for_fundamental_fp<double>
Chris@101 269 {
Chris@101 270 };
Chris@101 271
Chris@101 272 template <>
Chris@101 273 struct square_root<long double, true>
Chris@101 274 : square_root_for_fundamental_fp<long double>
Chris@101 275 {
Chris@101 276 };
Chris@101 277
Chris@101 278 template <typename T>
Chris@101 279 struct square_root<T, true>
Chris@101 280 {
Chris@101 281 typedef double return_type;
Chris@101 282
Chris@101 283 static inline double apply(T const& value)
Chris@101 284 {
Chris@101 285 // for all other fundamental number types use also std::sqrt
Chris@101 286 //
Chris@101 287 // Note: in C++98 the only other possibility is double;
Chris@101 288 // in C++11 there are also overloads for integral types;
Chris@101 289 // this specialization works for those as well.
Chris@101 290 return square_root_for_fundamental_fp
Chris@101 291 <
Chris@101 292 double
Chris@101 293 >::apply(boost::numeric_cast<double>(value));
Chris@101 294 }
Chris@101 295 };
Chris@16 296
Chris@16 297
Chris@16 298 /*!
Chris@16 299 \brief Short construct to enable partial specialization for PI, currently not possible in Math.
Chris@16 300 */
Chris@16 301 template <typename T>
Chris@16 302 struct define_pi
Chris@16 303 {
Chris@16 304 static inline T apply()
Chris@16 305 {
Chris@16 306 // Default calls Boost.Math
Chris@16 307 return boost::math::constants::pi<T>();
Chris@16 308 }
Chris@16 309 };
Chris@16 310
Chris@16 311 template <typename T>
Chris@16 312 struct relaxed_epsilon
Chris@16 313 {
Chris@16 314 static inline T apply(const T& factor)
Chris@16 315 {
Chris@16 316 return factor * std::numeric_limits<T>::epsilon();
Chris@16 317 }
Chris@16 318 };
Chris@16 319
Chris@101 320 // ItoF ItoI FtoF
Chris@101 321 template <typename Result, typename Source,
Chris@101 322 bool ResultIsInteger = std::numeric_limits<Result>::is_integer,
Chris@101 323 bool SourceIsInteger = std::numeric_limits<Source>::is_integer>
Chris@101 324 struct round
Chris@101 325 {
Chris@101 326 static inline Result apply(Source const& v)
Chris@101 327 {
Chris@101 328 return boost::numeric_cast<Result>(v);
Chris@101 329 }
Chris@101 330 };
Chris@101 331
Chris@101 332 // FtoI
Chris@101 333 template <typename Result, typename Source>
Chris@101 334 struct round<Result, Source, true, false>
Chris@101 335 {
Chris@101 336 static inline Result apply(Source const& v)
Chris@101 337 {
Chris@101 338 namespace bmp = boost::math::policies;
Chris@101 339 // ignore rounding errors for backward compatibility
Chris@101 340 typedef bmp::policy< bmp::rounding_error<bmp::ignore_error> > policy;
Chris@101 341 return boost::numeric_cast<Result>(boost::math::round(v, policy()));
Chris@101 342 }
Chris@101 343 };
Chris@16 344
Chris@16 345 } // namespace detail
Chris@16 346 #endif
Chris@16 347
Chris@16 348
Chris@16 349 template <typename T>
Chris@16 350 inline T pi() { return detail::define_pi<T>::apply(); }
Chris@16 351
Chris@16 352 template <typename T>
Chris@16 353 inline T relaxed_epsilon(T const& factor)
Chris@16 354 {
Chris@16 355 return detail::relaxed_epsilon<T>::apply(factor);
Chris@16 356 }
Chris@16 357
Chris@16 358
Chris@16 359 // Maybe replace this by boost equals or boost ublas numeric equals or so
Chris@16 360
Chris@16 361 /*!
Chris@16 362 \brief returns true if both arguments are equal.
Chris@16 363 \ingroup utility
Chris@16 364 \param a first argument
Chris@16 365 \param b second argument
Chris@16 366 \return true if a == b
Chris@16 367 \note If both a and b are of an integral type, comparison is done by ==.
Chris@16 368 If one of the types is floating point, comparison is done by abs and
Chris@16 369 comparing with epsilon. If one of the types is non-fundamental, it might
Chris@16 370 be a high-precision number and comparison is done using the == operator
Chris@16 371 of that class.
Chris@16 372 */
Chris@16 373
Chris@16 374 template <typename T1, typename T2>
Chris@16 375 inline bool equals(T1 const& a, T2 const& b)
Chris@16 376 {
Chris@16 377 return detail::equals
Chris@16 378 <
Chris@101 379 typename select_most_precise<T1, T2>::type
Chris@101 380 >::apply(a, b, detail::equals_default_policy());
Chris@16 381 }
Chris@16 382
Chris@16 383 template <typename T1, typename T2>
Chris@16 384 inline bool equals_with_epsilon(T1 const& a, T2 const& b)
Chris@16 385 {
Chris@16 386 return detail::equals_with_epsilon
Chris@16 387 <
Chris@101 388 typename select_most_precise<T1, T2>::type
Chris@101 389 >::apply(a, b, detail::equals_default_policy());
Chris@16 390 }
Chris@16 391
Chris@16 392 template <typename T1, typename T2>
Chris@16 393 inline bool smaller(T1 const& a, T2 const& b)
Chris@16 394 {
Chris@16 395 return detail::smaller
Chris@16 396 <
Chris@101 397 typename select_most_precise<T1, T2>::type
Chris@16 398 >::apply(a, b);
Chris@16 399 }
Chris@16 400
Chris@16 401 template <typename T1, typename T2>
Chris@16 402 inline bool larger(T1 const& a, T2 const& b)
Chris@16 403 {
Chris@16 404 return detail::smaller
Chris@16 405 <
Chris@101 406 typename select_most_precise<T1, T2>::type
Chris@16 407 >::apply(b, a);
Chris@16 408 }
Chris@16 409
Chris@16 410
Chris@16 411
Chris@16 412 double const d2r = geometry::math::pi<double>() / 180.0;
Chris@16 413 double const r2d = 1.0 / d2r;
Chris@16 414
Chris@16 415 /*!
Chris@16 416 \brief Calculates the haversine of an angle
Chris@16 417 \ingroup utility
Chris@16 418 \note See http://en.wikipedia.org/wiki/Haversine_formula
Chris@16 419 haversin(alpha) = sin2(alpha/2)
Chris@16 420 */
Chris@16 421 template <typename T>
Chris@16 422 inline T hav(T const& theta)
Chris@16 423 {
Chris@16 424 T const half = T(0.5);
Chris@16 425 T const sn = sin(half * theta);
Chris@16 426 return sn * sn;
Chris@16 427 }
Chris@16 428
Chris@16 429 /*!
Chris@16 430 \brief Short utility to return the square
Chris@16 431 \ingroup utility
Chris@16 432 \param value Value to calculate the square from
Chris@16 433 \return The squared value
Chris@16 434 */
Chris@16 435 template <typename T>
Chris@16 436 inline T sqr(T const& value)
Chris@16 437 {
Chris@16 438 return value * value;
Chris@16 439 }
Chris@16 440
Chris@16 441 /*!
Chris@101 442 \brief Short utility to return the square root
Chris@101 443 \ingroup utility
Chris@101 444 \param value Value to calculate the square root from
Chris@101 445 \return The square root value
Chris@101 446 */
Chris@101 447 template <typename T>
Chris@101 448 inline typename detail::square_root<T>::return_type
Chris@101 449 sqrt(T const& value)
Chris@101 450 {
Chris@101 451 return detail::square_root
Chris@101 452 <
Chris@101 453 T, boost::is_fundamental<T>::value
Chris@101 454 >::apply(value);
Chris@101 455 }
Chris@101 456
Chris@101 457 /*!
Chris@16 458 \brief Short utility to workaround gcc/clang problem that abs is converting to integer
Chris@16 459 and that older versions of MSVC does not support abs of long long...
Chris@16 460 \ingroup utility
Chris@16 461 */
Chris@16 462 template<typename T>
Chris@16 463 inline T abs(T const& value)
Chris@16 464 {
Chris@101 465 return detail::abs<T>::apply(value);
Chris@16 466 }
Chris@16 467
Chris@16 468 /*!
Chris@16 469 \brief Short utility to calculate the sign of a number: -1 (negative), 0 (zero), 1 (positive)
Chris@16 470 \ingroup utility
Chris@16 471 */
Chris@16 472 template <typename T>
Chris@101 473 static inline int sign(T const& value)
Chris@16 474 {
Chris@16 475 T const zero = T();
Chris@16 476 return value > zero ? 1 : value < zero ? -1 : 0;
Chris@16 477 }
Chris@16 478
Chris@101 479 /*!
Chris@101 480 \brief Short utility to calculate the rounded value of a number.
Chris@101 481 \ingroup utility
Chris@101 482 \note If the source T is NOT an integral type and Result is an integral type
Chris@101 483 the value is rounded towards the closest integral value. Otherwise it's
Chris@101 484 casted.
Chris@101 485 */
Chris@101 486 template <typename Result, typename T>
Chris@101 487 inline Result round(T const& v)
Chris@101 488 {
Chris@101 489 return detail::round<Result, T>::apply(v);
Chris@101 490 }
Chris@16 491
Chris@16 492 } // namespace math
Chris@16 493
Chris@16 494
Chris@16 495 }} // namespace boost::geometry
Chris@16 496
Chris@16 497 #endif // BOOST_GEOMETRY_UTIL_MATH_HPP