]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/geometry/util/math.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / 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
92f5a8d4
TL
7// This file was modified by Oracle on 2014, 2015, 2018, 2019.
8// Modifications copyright (c) 2014-2019, Oracle and/or its affiliates.
7c673cae
FG
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
92f5a8d4 12// Contributed and/or modified by Adeel Ahmad, as part of Google Summer of Code 2018 program
7c673cae
FG
13
14// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
15// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
16
17// Use, modification and distribution is subject to the Boost Software License,
18// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
19// http://www.boost.org/LICENSE_1_0.txt)
20
21#ifndef BOOST_GEOMETRY_UTIL_MATH_HPP
22#define BOOST_GEOMETRY_UTIL_MATH_HPP
23
24#include <cmath>
25#include <limits>
26
27#include <boost/core/ignore_unused.hpp>
28
29#include <boost/math/constants/constants.hpp>
30#include <boost/math/special_functions/fpclassify.hpp>
31//#include <boost/math/special_functions/round.hpp>
32#include <boost/numeric/conversion/cast.hpp>
33#include <boost/type_traits/is_fundamental.hpp>
34#include <boost/type_traits/is_integral.hpp>
35
36#include <boost/geometry/core/cs.hpp>
37
38#include <boost/geometry/util/select_most_precise.hpp>
39
40namespace boost { namespace geometry
41{
42
43namespace math
44{
45
46#ifndef DOXYGEN_NO_DETAIL
47namespace detail
48{
49
50template <typename T>
51inline T const& greatest(T const& v1, T const& v2)
52{
53 return (std::max)(v1, v2);
54}
55
56template <typename T>
57inline T const& greatest(T const& v1, T const& v2, T const& v3)
58{
59 return (std::max)(greatest(v1, v2), v3);
60}
61
62template <typename T>
63inline T const& greatest(T const& v1, T const& v2, T const& v3, T const& v4)
64{
65 return (std::max)(greatest(v1, v2, v3), v4);
66}
67
68template <typename T>
69inline T const& greatest(T const& v1, T const& v2, T const& v3, T const& v4, T const& v5)
70{
71 return (std::max)(greatest(v1, v2, v3, v4), v5);
72}
73
74
b32b8144
FG
75template <typename T>
76inline T bounded(T const& v, T const& lower, T const& upper)
77{
78 return (std::min)((std::max)(v, lower), upper);
79}
80
81template <typename T>
82inline T bounded(T const& v, T const& lower)
83{
84 return (std::max)(v, lower);
85}
86
87
7c673cae
FG
88template <typename T,
89 bool IsFloatingPoint = boost::is_floating_point<T>::value>
90struct abs
91{
92 static inline T apply(T const& value)
93 {
94 T const zero = T();
95 return value < zero ? -value : value;
96 }
97};
98
99template <typename T>
100struct abs<T, true>
101{
102 static inline T apply(T const& value)
103 {
104 using ::fabs;
105 using std::fabs; // for long double
106
107 return fabs(value);
108 }
109};
110
111
112struct equals_default_policy
113{
114 template <typename T>
115 static inline T apply(T const& a, T const& b)
116 {
117 // See http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.17
118 return greatest(abs<T>::apply(a), abs<T>::apply(b), T(1));
119 }
120};
121
122template <typename T,
123 bool IsFloatingPoint = boost::is_floating_point<T>::value>
124struct equals_factor_policy
125{
126 equals_factor_policy()
127 : factor(1) {}
128 explicit equals_factor_policy(T const& v)
129 : factor(greatest(abs<T>::apply(v), T(1)))
130 {}
131 equals_factor_policy(T const& v0, T const& v1, T const& v2, T const& v3)
132 : factor(greatest(abs<T>::apply(v0), abs<T>::apply(v1),
133 abs<T>::apply(v2), abs<T>::apply(v3),
134 T(1)))
135 {}
136
137 T const& apply(T const&, T const&) const
138 {
139 return factor;
140 }
141
142 T factor;
143};
144
145template <typename T>
146struct equals_factor_policy<T, false>
147{
148 equals_factor_policy() {}
149 explicit equals_factor_policy(T const&) {}
150 equals_factor_policy(T const& , T const& , T const& , T const& ) {}
151
152 static inline T apply(T const&, T const&)
153 {
154 return T(1);
155 }
156};
157
158template <typename Type,
159 bool IsFloatingPoint = boost::is_floating_point<Type>::value>
160struct equals
161{
162 template <typename Policy>
163 static inline bool apply(Type const& a, Type const& b, Policy const&)
164 {
165 return a == b;
166 }
167};
168
169template <typename Type>
170struct equals<Type, true>
171{
172 template <typename Policy>
173 static inline bool apply(Type const& a, Type const& b, Policy const& policy)
174 {
175 boost::ignore_unused(policy);
176
177 if (a == b)
178 {
179 return true;
180 }
181
182 if (boost::math::isfinite(a) && boost::math::isfinite(b))
183 {
184 // If a is INF and b is e.g. 0, the expression below returns true
185 // but the values are obviously not equal, hence the condition
186 return abs<Type>::apply(a - b)
187 <= std::numeric_limits<Type>::epsilon() * policy.apply(a, b);
188 }
189 else
190 {
191 return a == b;
192 }
193 }
194};
195
196template <typename T1, typename T2, typename Policy>
197inline bool equals_by_policy(T1 const& a, T2 const& b, Policy const& policy)
198{
199 return detail::equals
200 <
201 typename select_most_precise<T1, T2>::type
202 >::apply(a, b, policy);
203}
204
205template <typename Type,
206 bool IsFloatingPoint = boost::is_floating_point<Type>::value>
207struct smaller
208{
209 static inline bool apply(Type const& a, Type const& b)
210 {
211 return a < b;
212 }
213};
214
215template <typename Type>
216struct smaller<Type, true>
217{
218 static inline bool apply(Type const& a, Type const& b)
219 {
220 if (!(a < b)) // a >= b
221 {
222 return false;
223 }
224
225 return ! equals<Type, true>::apply(b, a, equals_default_policy());
226 }
227};
228
229template <typename Type,
230 bool IsFloatingPoint = boost::is_floating_point<Type>::value>
231struct smaller_or_equals
232{
233 static inline bool apply(Type const& a, Type const& b)
234 {
235 return a <= b;
236 }
237};
238
239template <typename Type>
240struct smaller_or_equals<Type, true>
241{
242 static inline bool apply(Type const& a, Type const& b)
243 {
244 if (a <= b)
245 {
246 return true;
247 }
248
249 return equals<Type, true>::apply(a, b, equals_default_policy());
250 }
251};
252
253
254template <typename Type,
255 bool IsFloatingPoint = boost::is_floating_point<Type>::value>
256struct equals_with_epsilon
257 : public equals<Type, IsFloatingPoint>
258{};
259
260template
261<
262 typename T,
263 bool IsFundemantal = boost::is_fundamental<T>::value /* false */
264>
265struct square_root
266{
267 typedef T return_type;
268
269 static inline T apply(T const& value)
270 {
271 // for non-fundamental number types assume that sqrt is
272 // defined either:
273 // 1) at T's scope, or
274 // 2) at global scope, or
275 // 3) in namespace std
276 using ::sqrt;
277 using std::sqrt;
278
279 return sqrt(value);
280 }
281};
282
283template <typename FundamentalFP>
284struct square_root_for_fundamental_fp
285{
286 typedef FundamentalFP return_type;
287
288 static inline FundamentalFP apply(FundamentalFP const& value)
289 {
290#ifdef BOOST_GEOMETRY_SQRT_CHECK_FINITENESS
291 // This is a workaround for some 32-bit platforms.
292 // For some of those platforms it has been reported that
293 // std::sqrt(nan) and/or std::sqrt(-nan) returns a finite value.
294 // For those platforms we need to define the macro
295 // BOOST_GEOMETRY_SQRT_CHECK_FINITENESS so that the argument
296 // to std::sqrt is checked appropriately before passed to std::sqrt
297 if (boost::math::isfinite(value))
298 {
299 return std::sqrt(value);
300 }
301 else if (boost::math::isinf(value) && value < 0)
302 {
303 return -std::numeric_limits<FundamentalFP>::quiet_NaN();
304 }
305 return value;
306#else
307 // for fundamental floating point numbers use std::sqrt
308 return std::sqrt(value);
309#endif // BOOST_GEOMETRY_SQRT_CHECK_FINITENESS
310 }
311};
312
313template <>
314struct square_root<float, true>
315 : square_root_for_fundamental_fp<float>
316{
317};
318
319template <>
320struct square_root<double, true>
321 : square_root_for_fundamental_fp<double>
322{
323};
324
325template <>
326struct square_root<long double, true>
327 : square_root_for_fundamental_fp<long double>
328{
329};
330
331template <typename T>
332struct square_root<T, true>
333{
334 typedef double return_type;
335
336 static inline double apply(T const& value)
337 {
338 // for all other fundamental number types use also std::sqrt
339 //
340 // Note: in C++98 the only other possibility is double;
341 // in C++11 there are also overloads for integral types;
342 // this specialization works for those as well.
343 return square_root_for_fundamental_fp
344 <
345 double
346 >::apply(boost::numeric_cast<double>(value));
347 }
348};
349
350
351
352template
353<
354 typename T,
355 bool IsFundemantal = boost::is_fundamental<T>::value /* false */
356>
357struct modulo
358{
359 typedef T return_type;
360
361 static inline T apply(T const& value1, T const& value2)
362 {
363 // for non-fundamental number types assume that a free
364 // function mod() is defined either:
365 // 1) at T's scope, or
366 // 2) at global scope
367 return mod(value1, value2);
368 }
369};
370
371template
372<
373 typename Fundamental,
374 bool IsIntegral = boost::is_integral<Fundamental>::value
375>
376struct modulo_for_fundamental
377{
378 typedef Fundamental return_type;
379
380 static inline Fundamental apply(Fundamental const& value1,
381 Fundamental const& value2)
382 {
383 return value1 % value2;
384 }
385};
386
387// specialization for floating-point numbers
388template <typename Fundamental>
389struct modulo_for_fundamental<Fundamental, false>
390{
391 typedef Fundamental return_type;
392
393 static inline Fundamental apply(Fundamental const& value1,
394 Fundamental const& value2)
395 {
396 return std::fmod(value1, value2);
397 }
398};
399
400// specialization for fundamental number type
401template <typename Fundamental>
402struct modulo<Fundamental, true>
403 : modulo_for_fundamental<Fundamental>
404{};
405
406
407
408/*!
409\brief Short constructs to enable partial specialization for PI, 2*PI
410 and PI/2, currently not possible in Math.
411*/
412template <typename T>
413struct define_pi
414{
415 static inline T apply()
416 {
417 // Default calls Boost.Math
418 return boost::math::constants::pi<T>();
419 }
420};
421
422template <typename T>
423struct define_two_pi
424{
425 static inline T apply()
426 {
427 // Default calls Boost.Math
428 return boost::math::constants::two_pi<T>();
429 }
430};
431
432template <typename T>
433struct define_half_pi
434{
435 static inline T apply()
436 {
437 // Default calls Boost.Math
438 return boost::math::constants::half_pi<T>();
439 }
440};
441
442template <typename T>
443struct relaxed_epsilon
444{
445 static inline T apply(const T& factor)
446 {
447 return factor * std::numeric_limits<T>::epsilon();
448 }
449};
450
451// This must be consistent with math::equals.
452// By default math::equals() scales the error by epsilon using the greater of
453// compared values but here is only one value, though it should work the same way.
454// (a-a) <= max(a, a) * EPS -> 0 <= a*EPS
455// (a+da-a) <= max(a+da, a) * EPS -> da <= (a+da)*EPS
92f5a8d4 456template <typename T, bool IsIntegral = boost::is_integral<T>::value>
7c673cae
FG
457struct scaled_epsilon
458{
459 static inline T apply(T const& val)
460 {
461 return (std::max)(abs<T>::apply(val), T(1))
462 * std::numeric_limits<T>::epsilon();
463 }
92f5a8d4
TL
464
465 static inline T apply(T const& val, T const& eps)
466 {
467 return (std::max)(abs<T>::apply(val), T(1))
468 * eps;
469 }
7c673cae
FG
470};
471
472template <typename T>
92f5a8d4 473struct scaled_epsilon<T, true>
7c673cae
FG
474{
475 static inline T apply(T const&)
476 {
477 return T(0);
478 }
92f5a8d4
TL
479
480 static inline T apply(T const&, T const&)
481 {
482 return T(0);
483 }
7c673cae
FG
484};
485
486// ItoF ItoI FtoF
487template <typename Result, typename Source,
488 bool ResultIsInteger = std::numeric_limits<Result>::is_integer,
489 bool SourceIsInteger = std::numeric_limits<Source>::is_integer>
490struct rounding_cast
491{
492 static inline Result apply(Source const& v)
493 {
494 return boost::numeric_cast<Result>(v);
495 }
496};
497
498// TtoT
499template <typename Source, bool ResultIsInteger, bool SourceIsInteger>
500struct rounding_cast<Source, Source, ResultIsInteger, SourceIsInteger>
501{
502 static inline Source apply(Source const& v)
503 {
504 return v;
505 }
506};
507
508// FtoI
509template <typename Result, typename Source>
510struct rounding_cast<Result, Source, true, false>
511{
512 static inline Result apply(Source const& v)
513 {
514 return boost::numeric_cast<Result>(v < Source(0) ?
515 v - Source(0.5) :
516 v + Source(0.5));
517 }
518};
519
520} // namespace detail
521#endif
522
523
524template <typename T>
525inline T pi() { return detail::define_pi<T>::apply(); }
526
527template <typename T>
528inline T two_pi() { return detail::define_two_pi<T>::apply(); }
529
530template <typename T>
531inline T half_pi() { return detail::define_half_pi<T>::apply(); }
532
533template <typename T>
534inline T relaxed_epsilon(T const& factor)
535{
536 return detail::relaxed_epsilon<T>::apply(factor);
537}
538
539template <typename T>
540inline T scaled_epsilon(T const& value)
541{
542 return detail::scaled_epsilon<T>::apply(value);
543}
544
92f5a8d4
TL
545template <typename T>
546inline T scaled_epsilon(T const& value, T const& eps)
547{
548 return detail::scaled_epsilon<T>::apply(value, eps);
549}
7c673cae 550
b32b8144 551// Maybe replace this by boost equals or so
7c673cae
FG
552
553/*!
554 \brief returns true if both arguments are equal.
555 \ingroup utility
556 \param a first argument
557 \param b second argument
558 \return true if a == b
559 \note If both a and b are of an integral type, comparison is done by ==.
560 If one of the types is floating point, comparison is done by abs and
561 comparing with epsilon. If one of the types is non-fundamental, it might
562 be a high-precision number and comparison is done using the == operator
563 of that class.
564*/
565
566template <typename T1, typename T2>
567inline bool equals(T1 const& a, T2 const& b)
568{
569 return detail::equals
570 <
571 typename select_most_precise<T1, T2>::type
572 >::apply(a, b, detail::equals_default_policy());
573}
574
575template <typename T1, typename T2>
576inline bool equals_with_epsilon(T1 const& a, T2 const& b)
577{
578 return detail::equals_with_epsilon
579 <
580 typename select_most_precise<T1, T2>::type
581 >::apply(a, b, detail::equals_default_policy());
582}
583
584template <typename T1, typename T2>
585inline bool smaller(T1 const& a, T2 const& b)
586{
587 return detail::smaller
588 <
589 typename select_most_precise<T1, T2>::type
590 >::apply(a, b);
591}
592
593template <typename T1, typename T2>
594inline bool larger(T1 const& a, T2 const& b)
595{
596 return detail::smaller
597 <
598 typename select_most_precise<T1, T2>::type
599 >::apply(b, a);
600}
601
602template <typename T1, typename T2>
603inline bool smaller_or_equals(T1 const& a, T2 const& b)
604{
605 return detail::smaller_or_equals
606 <
607 typename select_most_precise<T1, T2>::type
608 >::apply(a, b);
609}
610
611template <typename T1, typename T2>
612inline bool larger_or_equals(T1 const& a, T2 const& b)
613{
614 return detail::smaller_or_equals
615 <
616 typename select_most_precise<T1, T2>::type
617 >::apply(b, a);
618}
619
620
621template <typename T>
622inline T d2r()
623{
624 static T const conversion_coefficient = geometry::math::pi<T>() / T(180.0);
625 return conversion_coefficient;
626}
627
628template <typename T>
629inline T r2d()
630{
631 static T const conversion_coefficient = T(180.0) / geometry::math::pi<T>();
632 return conversion_coefficient;
633}
634
635
636#ifndef DOXYGEN_NO_DETAIL
637namespace detail {
638
639template <typename DegreeOrRadian>
640struct as_radian
641{
642 template <typename T>
643 static inline T apply(T const& value)
644 {
645 return value;
646 }
647};
648
649template <>
650struct as_radian<degree>
651{
652 template <typename T>
653 static inline T apply(T const& value)
654 {
655 return value * d2r<T>();
656 }
657};
658
659template <typename DegreeOrRadian>
660struct from_radian
661{
662 template <typename T>
663 static inline T apply(T const& value)
664 {
665 return value;
666 }
667};
668
669template <>
670struct from_radian<degree>
671{
672 template <typename T>
673 static inline T apply(T const& value)
674 {
675 return value * r2d<T>();
676 }
677};
678
679} // namespace detail
680#endif
681
682template <typename DegreeOrRadian, typename T>
683inline T as_radian(T const& value)
684{
685 return detail::as_radian<DegreeOrRadian>::apply(value);
686}
687
688template <typename DegreeOrRadian, typename T>
689inline T from_radian(T const& value)
690{
691 return detail::from_radian<DegreeOrRadian>::apply(value);
692}
693
694
695/*!
696 \brief Calculates the haversine of an angle
697 \ingroup utility
698 \note See http://en.wikipedia.org/wiki/Haversine_formula
699 haversin(alpha) = sin2(alpha/2)
700*/
701template <typename T>
702inline T hav(T const& theta)
703{
704 T const half = T(0.5);
705 T const sn = sin(half * theta);
706 return sn * sn;
707}
708
709/*!
710\brief Short utility to return the square
711\ingroup utility
712\param value Value to calculate the square from
713\return The squared value
714*/
715template <typename T>
716inline T sqr(T const& value)
717{
718 return value * value;
719}
720
721/*!
722\brief Short utility to return the square root
723\ingroup utility
724\param value Value to calculate the square root from
725\return The square root value
726*/
727template <typename T>
728inline typename detail::square_root<T>::return_type
729sqrt(T const& value)
730{
731 return detail::square_root
732 <
733 T, boost::is_fundamental<T>::value
734 >::apply(value);
735}
736
737/*!
738\brief Short utility to return the modulo of two values
739\ingroup utility
740\param value1 First value
741\param value2 Second value
742\return The result of the modulo operation on the (ordered) pair
743(value1, value2)
744*/
745template <typename T>
746inline typename detail::modulo<T>::return_type
747mod(T const& value1, T const& value2)
748{
749 return detail::modulo
750 <
751 T, boost::is_fundamental<T>::value
752 >::apply(value1, value2);
753}
754
755/*!
756\brief Short utility to workaround gcc/clang problem that abs is converting to integer
757 and that older versions of MSVC does not support abs of long long...
758\ingroup utility
759*/
760template<typename T>
761inline T abs(T const& value)
762{
763 return detail::abs<T>::apply(value);
764}
765
766/*!
767\brief Short utility to calculate the sign of a number: -1 (negative), 0 (zero), 1 (positive)
768\ingroup utility
769*/
770template <typename T>
771inline int sign(T const& value)
772{
773 T const zero = T();
774 return value > zero ? 1 : value < zero ? -1 : 0;
775}
776
777/*!
778\brief Short utility to cast a value possibly rounding it to the nearest
779 integral value.
780\ingroup utility
781\note If the source T is NOT an integral type and Result is an integral type
782 the value is rounded towards the closest integral value. Otherwise it's
783 casted without rounding.
784*/
785template <typename Result, typename T>
786inline Result rounding_cast(T const& v)
787{
788 return detail::rounding_cast<Result, T>::apply(v);
789}
790
92f5a8d4
TL
791/*!
792\brief Evaluate the sine and cosine function with the argument in degrees
793\note The results obey exactly the elementary properties of the trigonometric
794 functions, e.g., sin 9&deg; = cos 81&deg; = &minus; sin 123456789&deg;.
795 If x = &minus;0, then \e sinx = &minus;0; this is the only case where
796 &minus;0 is returned.
797*/
798template<typename T>
799inline void sin_cos_degrees(T const& x,
800 T & sinx,
801 T & cosx)
802{
803 // In order to minimize round-off errors, this function exactly reduces
804 // the argument to the range [-45, 45] before converting it to radians.
805 T remainder; int quotient;
806
807 remainder = math::mod(x, T(360));
808 quotient = floor(remainder / 90 + T(0.5));
809 remainder -= 90 * quotient;
810
811 // Convert to radians.
812 remainder *= d2r<T>();
813
814 T s = sin(remainder), c = cos(remainder);
815
816 switch (unsigned(quotient) & 3U)
817 {
818 case 0U: sinx = s; cosx = c; break;
819 case 1U: sinx = c; cosx = -s; break;
820 case 2U: sinx = -s; cosx = -c; break;
821 default: sinx = -c; cosx = s; break; // case 3U
822 }
823
824 // Set sign of 0 results. -0 only produced for sin(-0).
825 if (x != 0)
826 {
827 sinx += T(0); cosx += T(0);
828 }
829}
830
831/*!
832\brief Round off a given angle
833*/
834template<typename T>
835inline T round_angle(T const& x) {
836 static const T z = 1/T(16);
837
838 if (x == 0)
839 {
840 return 0;
841 }
842
843 T y = math::abs(x);
844
845 // z - (z - y) must not be simplified to y.
846 y = y < z ? z - (z - y) : y;
847
848 return x < 0 ? -y : y;
849}
850
851
852/*!
853\brief The error-free sum of two numbers.
854*/
855template<typename T>
856inline T sum_error(T const& u, T const& v, T& t)
857{
858 volatile T s = u + v;
859 volatile T up = s - v;
860 volatile T vpp = s - up;
861
862 up -= u;
863 vpp -= v;
864 t = -(up + vpp);
865
866 return s;
867}
868
869/*!
870\brief Evaluate the polynomial in x using Horner's method.
871*/
872// TODO: adl1995 - Merge these functions with formulas/area_formulas.hpp
873// i.e. place them in one file.
874template <typename NT, typename IteratorType>
875inline NT horner_evaluate(NT const& x,
876 IteratorType begin,
877 IteratorType end)
878{
879 NT result(0);
880 IteratorType it = end;
881 do
882 {
883 result = result * x + *--it;
884 }
885 while (it != begin);
886 return result;
887}
888
889/*!
890\brief Evaluate the polynomial.
891*/
892template<typename IteratorType, typename CT>
893inline CT polyval(IteratorType first,
894 IteratorType last,
895 CT const& eps)
896{
897 int N = std::distance(first, last) - 1;
898 int index = 0;
899
900 CT y = N < 0 ? 0 : *(first + (index++));
901
902 while (--N >= 0)
903 {
904 y = y * eps + *(first + (index++));
905 }
906
907 return y;
908}
909
910/*
911\brief Short utility to calculate the power
912\ingroup utility
913*/
914template <typename T1, typename T2>
915inline T1 pow(T1 const& a, T2 const& b)
916{
917 using std::pow;
918 return pow(a, b);
919}
920
7c673cae
FG
921} // namespace math
922
923
924}} // namespace boost::geometry
925
926#endif // BOOST_GEOMETRY_UTIL_MATH_HPP