]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/geometry/include/boost/geometry/util/math.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / geometry / include / boost / geometry / util / math.hpp
CommitLineData
7c673cae
FG
1// Boost.Geometry (aka GGL, Generic Geometry Library)
2
3// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
4// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
5// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
6
7// This file was modified by Oracle on 2014, 2015.
8// Modifications copyright (c) 2014-2015, Oracle and/or its affiliates.
9
10// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
11// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
12
13// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
14// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
15
16// Use, modification and distribution is subject to the Boost Software License,
17// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
18// http://www.boost.org/LICENSE_1_0.txt)
19
20#ifndef BOOST_GEOMETRY_UTIL_MATH_HPP
21#define BOOST_GEOMETRY_UTIL_MATH_HPP
22
23#include <cmath>
24#include <limits>
25
26#include <boost/core/ignore_unused.hpp>
27
28#include <boost/math/constants/constants.hpp>
29#include <boost/math/special_functions/fpclassify.hpp>
30//#include <boost/math/special_functions/round.hpp>
31#include <boost/numeric/conversion/cast.hpp>
32#include <boost/type_traits/is_fundamental.hpp>
33#include <boost/type_traits/is_integral.hpp>
34
35#include <boost/geometry/core/cs.hpp>
36
37#include <boost/geometry/util/select_most_precise.hpp>
38
39namespace boost { namespace geometry
40{
41
42namespace math
43{
44
45#ifndef DOXYGEN_NO_DETAIL
46namespace detail
47{
48
49template <typename T>
50inline T const& greatest(T const& v1, T const& v2)
51{
52 return (std::max)(v1, v2);
53}
54
55template <typename T>
56inline T const& greatest(T const& v1, T const& v2, T const& v3)
57{
58 return (std::max)(greatest(v1, v2), v3);
59}
60
61template <typename T>
62inline T const& greatest(T const& v1, T const& v2, T const& v3, T const& v4)
63{
64 return (std::max)(greatest(v1, v2, v3), v4);
65}
66
67template <typename T>
68inline T const& greatest(T const& v1, T const& v2, T const& v3, T const& v4, T const& v5)
69{
70 return (std::max)(greatest(v1, v2, v3, v4), v5);
71}
72
73
74template <typename T,
75 bool IsFloatingPoint = boost::is_floating_point<T>::value>
76struct abs
77{
78 static inline T apply(T const& value)
79 {
80 T const zero = T();
81 return value < zero ? -value : value;
82 }
83};
84
85template <typename T>
86struct abs<T, true>
87{
88 static inline T apply(T const& value)
89 {
90 using ::fabs;
91 using std::fabs; // for long double
92
93 return fabs(value);
94 }
95};
96
97
98struct equals_default_policy
99{
100 template <typename T>
101 static inline T apply(T const& a, T const& b)
102 {
103 // See http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.17
104 return greatest(abs<T>::apply(a), abs<T>::apply(b), T(1));
105 }
106};
107
108template <typename T,
109 bool IsFloatingPoint = boost::is_floating_point<T>::value>
110struct equals_factor_policy
111{
112 equals_factor_policy()
113 : factor(1) {}
114 explicit equals_factor_policy(T const& v)
115 : factor(greatest(abs<T>::apply(v), T(1)))
116 {}
117 equals_factor_policy(T const& v0, T const& v1, T const& v2, T const& v3)
118 : factor(greatest(abs<T>::apply(v0), abs<T>::apply(v1),
119 abs<T>::apply(v2), abs<T>::apply(v3),
120 T(1)))
121 {}
122
123 T const& apply(T const&, T const&) const
124 {
125 return factor;
126 }
127
128 T factor;
129};
130
131template <typename T>
132struct equals_factor_policy<T, false>
133{
134 equals_factor_policy() {}
135 explicit equals_factor_policy(T const&) {}
136 equals_factor_policy(T const& , T const& , T const& , T const& ) {}
137
138 static inline T apply(T const&, T const&)
139 {
140 return T(1);
141 }
142};
143
144template <typename Type,
145 bool IsFloatingPoint = boost::is_floating_point<Type>::value>
146struct equals
147{
148 template <typename Policy>
149 static inline bool apply(Type const& a, Type const& b, Policy const&)
150 {
151 return a == b;
152 }
153};
154
155template <typename Type>
156struct equals<Type, true>
157{
158 template <typename Policy>
159 static inline bool apply(Type const& a, Type const& b, Policy const& policy)
160 {
161 boost::ignore_unused(policy);
162
163 if (a == b)
164 {
165 return true;
166 }
167
168 if (boost::math::isfinite(a) && boost::math::isfinite(b))
169 {
170 // If a is INF and b is e.g. 0, the expression below returns true
171 // but the values are obviously not equal, hence the condition
172 return abs<Type>::apply(a - b)
173 <= std::numeric_limits<Type>::epsilon() * policy.apply(a, b);
174 }
175 else
176 {
177 return a == b;
178 }
179 }
180};
181
182template <typename T1, typename T2, typename Policy>
183inline bool equals_by_policy(T1 const& a, T2 const& b, Policy const& policy)
184{
185 return detail::equals
186 <
187 typename select_most_precise<T1, T2>::type
188 >::apply(a, b, policy);
189}
190
191template <typename Type,
192 bool IsFloatingPoint = boost::is_floating_point<Type>::value>
193struct smaller
194{
195 static inline bool apply(Type const& a, Type const& b)
196 {
197 return a < b;
198 }
199};
200
201template <typename Type>
202struct smaller<Type, true>
203{
204 static inline bool apply(Type const& a, Type const& b)
205 {
206 if (!(a < b)) // a >= b
207 {
208 return false;
209 }
210
211 return ! equals<Type, true>::apply(b, a, equals_default_policy());
212 }
213};
214
215template <typename Type,
216 bool IsFloatingPoint = boost::is_floating_point<Type>::value>
217struct smaller_or_equals
218{
219 static inline bool apply(Type const& a, Type const& b)
220 {
221 return a <= b;
222 }
223};
224
225template <typename Type>
226struct smaller_or_equals<Type, true>
227{
228 static inline bool apply(Type const& a, Type const& b)
229 {
230 if (a <= b)
231 {
232 return true;
233 }
234
235 return equals<Type, true>::apply(a, b, equals_default_policy());
236 }
237};
238
239
240template <typename Type,
241 bool IsFloatingPoint = boost::is_floating_point<Type>::value>
242struct equals_with_epsilon
243 : public equals<Type, IsFloatingPoint>
244{};
245
246template
247<
248 typename T,
249 bool IsFundemantal = boost::is_fundamental<T>::value /* false */
250>
251struct square_root
252{
253 typedef T return_type;
254
255 static inline T apply(T const& value)
256 {
257 // for non-fundamental number types assume that sqrt is
258 // defined either:
259 // 1) at T's scope, or
260 // 2) at global scope, or
261 // 3) in namespace std
262 using ::sqrt;
263 using std::sqrt;
264
265 return sqrt(value);
266 }
267};
268
269template <typename FundamentalFP>
270struct square_root_for_fundamental_fp
271{
272 typedef FundamentalFP return_type;
273
274 static inline FundamentalFP apply(FundamentalFP const& value)
275 {
276#ifdef BOOST_GEOMETRY_SQRT_CHECK_FINITENESS
277 // This is a workaround for some 32-bit platforms.
278 // For some of those platforms it has been reported that
279 // std::sqrt(nan) and/or std::sqrt(-nan) returns a finite value.
280 // For those platforms we need to define the macro
281 // BOOST_GEOMETRY_SQRT_CHECK_FINITENESS so that the argument
282 // to std::sqrt is checked appropriately before passed to std::sqrt
283 if (boost::math::isfinite(value))
284 {
285 return std::sqrt(value);
286 }
287 else if (boost::math::isinf(value) && value < 0)
288 {
289 return -std::numeric_limits<FundamentalFP>::quiet_NaN();
290 }
291 return value;
292#else
293 // for fundamental floating point numbers use std::sqrt
294 return std::sqrt(value);
295#endif // BOOST_GEOMETRY_SQRT_CHECK_FINITENESS
296 }
297};
298
299template <>
300struct square_root<float, true>
301 : square_root_for_fundamental_fp<float>
302{
303};
304
305template <>
306struct square_root<double, true>
307 : square_root_for_fundamental_fp<double>
308{
309};
310
311template <>
312struct square_root<long double, true>
313 : square_root_for_fundamental_fp<long double>
314{
315};
316
317template <typename T>
318struct square_root<T, true>
319{
320 typedef double return_type;
321
322 static inline double apply(T const& value)
323 {
324 // for all other fundamental number types use also std::sqrt
325 //
326 // Note: in C++98 the only other possibility is double;
327 // in C++11 there are also overloads for integral types;
328 // this specialization works for those as well.
329 return square_root_for_fundamental_fp
330 <
331 double
332 >::apply(boost::numeric_cast<double>(value));
333 }
334};
335
336
337
338template
339<
340 typename T,
341 bool IsFundemantal = boost::is_fundamental<T>::value /* false */
342>
343struct modulo
344{
345 typedef T return_type;
346
347 static inline T apply(T const& value1, T const& value2)
348 {
349 // for non-fundamental number types assume that a free
350 // function mod() is defined either:
351 // 1) at T's scope, or
352 // 2) at global scope
353 return mod(value1, value2);
354 }
355};
356
357template
358<
359 typename Fundamental,
360 bool IsIntegral = boost::is_integral<Fundamental>::value
361>
362struct modulo_for_fundamental
363{
364 typedef Fundamental return_type;
365
366 static inline Fundamental apply(Fundamental const& value1,
367 Fundamental const& value2)
368 {
369 return value1 % value2;
370 }
371};
372
373// specialization for floating-point numbers
374template <typename Fundamental>
375struct modulo_for_fundamental<Fundamental, false>
376{
377 typedef Fundamental return_type;
378
379 static inline Fundamental apply(Fundamental const& value1,
380 Fundamental const& value2)
381 {
382 return std::fmod(value1, value2);
383 }
384};
385
386// specialization for fundamental number type
387template <typename Fundamental>
388struct modulo<Fundamental, true>
389 : modulo_for_fundamental<Fundamental>
390{};
391
392
393
394/*!
395\brief Short constructs to enable partial specialization for PI, 2*PI
396 and PI/2, currently not possible in Math.
397*/
398template <typename T>
399struct define_pi
400{
401 static inline T apply()
402 {
403 // Default calls Boost.Math
404 return boost::math::constants::pi<T>();
405 }
406};
407
408template <typename T>
409struct define_two_pi
410{
411 static inline T apply()
412 {
413 // Default calls Boost.Math
414 return boost::math::constants::two_pi<T>();
415 }
416};
417
418template <typename T>
419struct define_half_pi
420{
421 static inline T apply()
422 {
423 // Default calls Boost.Math
424 return boost::math::constants::half_pi<T>();
425 }
426};
427
428template <typename T>
429struct relaxed_epsilon
430{
431 static inline T apply(const T& factor)
432 {
433 return factor * std::numeric_limits<T>::epsilon();
434 }
435};
436
437// This must be consistent with math::equals.
438// By default math::equals() scales the error by epsilon using the greater of
439// compared values but here is only one value, though it should work the same way.
440// (a-a) <= max(a, a) * EPS -> 0 <= a*EPS
441// (a+da-a) <= max(a+da, a) * EPS -> da <= (a+da)*EPS
442template <typename T, bool IsFloat = boost::is_floating_point<T>::value>
443struct scaled_epsilon
444{
445 static inline T apply(T const& val)
446 {
447 return (std::max)(abs<T>::apply(val), T(1))
448 * std::numeric_limits<T>::epsilon();
449 }
450};
451
452template <typename T>
453struct scaled_epsilon<T, false>
454{
455 static inline T apply(T const&)
456 {
457 return T(0);
458 }
459};
460
461// ItoF ItoI FtoF
462template <typename Result, typename Source,
463 bool ResultIsInteger = std::numeric_limits<Result>::is_integer,
464 bool SourceIsInteger = std::numeric_limits<Source>::is_integer>
465struct rounding_cast
466{
467 static inline Result apply(Source const& v)
468 {
469 return boost::numeric_cast<Result>(v);
470 }
471};
472
473// TtoT
474template <typename Source, bool ResultIsInteger, bool SourceIsInteger>
475struct rounding_cast<Source, Source, ResultIsInteger, SourceIsInteger>
476{
477 static inline Source apply(Source const& v)
478 {
479 return v;
480 }
481};
482
483// FtoI
484template <typename Result, typename Source>
485struct rounding_cast<Result, Source, true, false>
486{
487 static inline Result apply(Source const& v)
488 {
489 return boost::numeric_cast<Result>(v < Source(0) ?
490 v - Source(0.5) :
491 v + Source(0.5));
492 }
493};
494
495} // namespace detail
496#endif
497
498
499template <typename T>
500inline T pi() { return detail::define_pi<T>::apply(); }
501
502template <typename T>
503inline T two_pi() { return detail::define_two_pi<T>::apply(); }
504
505template <typename T>
506inline T half_pi() { return detail::define_half_pi<T>::apply(); }
507
508template <typename T>
509inline T relaxed_epsilon(T const& factor)
510{
511 return detail::relaxed_epsilon<T>::apply(factor);
512}
513
514template <typename T>
515inline T scaled_epsilon(T const& value)
516{
517 return detail::scaled_epsilon<T>::apply(value);
518}
519
520
521// Maybe replace this by boost equals or boost ublas numeric equals or so
522
523/*!
524 \brief returns true if both arguments are equal.
525 \ingroup utility
526 \param a first argument
527 \param b second argument
528 \return true if a == b
529 \note If both a and b are of an integral type, comparison is done by ==.
530 If one of the types is floating point, comparison is done by abs and
531 comparing with epsilon. If one of the types is non-fundamental, it might
532 be a high-precision number and comparison is done using the == operator
533 of that class.
534*/
535
536template <typename T1, typename T2>
537inline bool equals(T1 const& a, T2 const& b)
538{
539 return detail::equals
540 <
541 typename select_most_precise<T1, T2>::type
542 >::apply(a, b, detail::equals_default_policy());
543}
544
545template <typename T1, typename T2>
546inline bool equals_with_epsilon(T1 const& a, T2 const& b)
547{
548 return detail::equals_with_epsilon
549 <
550 typename select_most_precise<T1, T2>::type
551 >::apply(a, b, detail::equals_default_policy());
552}
553
554template <typename T1, typename T2>
555inline bool smaller(T1 const& a, T2 const& b)
556{
557 return detail::smaller
558 <
559 typename select_most_precise<T1, T2>::type
560 >::apply(a, b);
561}
562
563template <typename T1, typename T2>
564inline bool larger(T1 const& a, T2 const& b)
565{
566 return detail::smaller
567 <
568 typename select_most_precise<T1, T2>::type
569 >::apply(b, a);
570}
571
572template <typename T1, typename T2>
573inline bool smaller_or_equals(T1 const& a, T2 const& b)
574{
575 return detail::smaller_or_equals
576 <
577 typename select_most_precise<T1, T2>::type
578 >::apply(a, b);
579}
580
581template <typename T1, typename T2>
582inline bool larger_or_equals(T1 const& a, T2 const& b)
583{
584 return detail::smaller_or_equals
585 <
586 typename select_most_precise<T1, T2>::type
587 >::apply(b, a);
588}
589
590
591template <typename T>
592inline T d2r()
593{
594 static T const conversion_coefficient = geometry::math::pi<T>() / T(180.0);
595 return conversion_coefficient;
596}
597
598template <typename T>
599inline T r2d()
600{
601 static T const conversion_coefficient = T(180.0) / geometry::math::pi<T>();
602 return conversion_coefficient;
603}
604
605
606#ifndef DOXYGEN_NO_DETAIL
607namespace detail {
608
609template <typename DegreeOrRadian>
610struct as_radian
611{
612 template <typename T>
613 static inline T apply(T const& value)
614 {
615 return value;
616 }
617};
618
619template <>
620struct as_radian<degree>
621{
622 template <typename T>
623 static inline T apply(T const& value)
624 {
625 return value * d2r<T>();
626 }
627};
628
629template <typename DegreeOrRadian>
630struct from_radian
631{
632 template <typename T>
633 static inline T apply(T const& value)
634 {
635 return value;
636 }
637};
638
639template <>
640struct from_radian<degree>
641{
642 template <typename T>
643 static inline T apply(T const& value)
644 {
645 return value * r2d<T>();
646 }
647};
648
649} // namespace detail
650#endif
651
652template <typename DegreeOrRadian, typename T>
653inline T as_radian(T const& value)
654{
655 return detail::as_radian<DegreeOrRadian>::apply(value);
656}
657
658template <typename DegreeOrRadian, typename T>
659inline T from_radian(T const& value)
660{
661 return detail::from_radian<DegreeOrRadian>::apply(value);
662}
663
664
665/*!
666 \brief Calculates the haversine of an angle
667 \ingroup utility
668 \note See http://en.wikipedia.org/wiki/Haversine_formula
669 haversin(alpha) = sin2(alpha/2)
670*/
671template <typename T>
672inline T hav(T const& theta)
673{
674 T const half = T(0.5);
675 T const sn = sin(half * theta);
676 return sn * sn;
677}
678
679/*!
680\brief Short utility to return the square
681\ingroup utility
682\param value Value to calculate the square from
683\return The squared value
684*/
685template <typename T>
686inline T sqr(T const& value)
687{
688 return value * value;
689}
690
691/*!
692\brief Short utility to return the square root
693\ingroup utility
694\param value Value to calculate the square root from
695\return The square root value
696*/
697template <typename T>
698inline typename detail::square_root<T>::return_type
699sqrt(T const& value)
700{
701 return detail::square_root
702 <
703 T, boost::is_fundamental<T>::value
704 >::apply(value);
705}
706
707/*!
708\brief Short utility to return the modulo of two values
709\ingroup utility
710\param value1 First value
711\param value2 Second value
712\return The result of the modulo operation on the (ordered) pair
713(value1, value2)
714*/
715template <typename T>
716inline typename detail::modulo<T>::return_type
717mod(T const& value1, T const& value2)
718{
719 return detail::modulo
720 <
721 T, boost::is_fundamental<T>::value
722 >::apply(value1, value2);
723}
724
725/*!
726\brief Short utility to workaround gcc/clang problem that abs is converting to integer
727 and that older versions of MSVC does not support abs of long long...
728\ingroup utility
729*/
730template<typename T>
731inline T abs(T const& value)
732{
733 return detail::abs<T>::apply(value);
734}
735
736/*!
737\brief Short utility to calculate the sign of a number: -1 (negative), 0 (zero), 1 (positive)
738\ingroup utility
739*/
740template <typename T>
741inline int sign(T const& value)
742{
743 T const zero = T();
744 return value > zero ? 1 : value < zero ? -1 : 0;
745}
746
747/*!
748\brief Short utility to cast a value possibly rounding it to the nearest
749 integral value.
750\ingroup utility
751\note If the source T is NOT an integral type and Result is an integral type
752 the value is rounded towards the closest integral value. Otherwise it's
753 casted without rounding.
754*/
755template <typename Result, typename T>
756inline Result rounding_cast(T const& v)
757{
758 return detail::rounding_cast<Result, T>::apply(v);
759}
760
761} // namespace math
762
763
764}} // namespace boost::geometry
765
766#endif // BOOST_GEOMETRY_UTIL_MATH_HPP