diff DEPENDENCIES/generic/include/boost/geometry/util/math.hpp @ 101:c530137014c0

Update Boost headers (1.58.0)
author Chris Cannam
date Mon, 07 Sep 2015 11:12:49 +0100
parents 2665513ce2d3
children
line wrap: on
line diff
--- a/DEPENDENCIES/generic/include/boost/geometry/util/math.hpp	Fri Sep 04 12:01:02 2015 +0100
+++ b/DEPENDENCIES/generic/include/boost/geometry/util/math.hpp	Mon Sep 07 11:12:49 2015 +0100
@@ -1,8 +1,14 @@
 // Boost.Geometry (aka GGL, Generic Geometry Library)
 
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
-// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
+
+// This file was modified by Oracle on 2014, 2015.
+// Modifications copyright (c) 2014-2015, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
 
 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -17,7 +23,15 @@
 #include <cmath>
 #include <limits>
 
+#include <boost/core/ignore_unused.hpp>
+
 #include <boost/math/constants/constants.hpp>
+#ifdef BOOST_GEOMETRY_SQRT_CHECK_FINITENESS
+#include <boost/math/special_functions/fpclassify.hpp>
+#endif // BOOST_GEOMETRY_SQRT_CHECK_FINITENESS
+#include <boost/math/special_functions/round.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+#include <boost/type_traits/is_fundamental.hpp>
 
 #include <boost/geometry/util/select_most_precise.hpp>
 
@@ -31,11 +45,104 @@
 namespace detail
 {
 
+template <typename T>
+inline T const& greatest(T const& v1, T const& v2)
+{
+    return (std::max)(v1, v2);
+}
 
-template <typename Type, bool IsFloatingPoint>
+template <typename T>
+inline T const& greatest(T const& v1, T const& v2, T const& v3)
+{
+    return (std::max)(greatest(v1, v2), v3);
+}
+
+template <typename T>
+inline T const& greatest(T const& v1, T const& v2, T const& v3, T const& v4)
+{
+    return (std::max)(greatest(v1, v2, v3), v4);
+}
+
+template <typename T>
+inline T const& greatest(T const& v1, T const& v2, T const& v3, T const& v4, T const& v5)
+{
+    return (std::max)(greatest(v1, v2, v3, v4), v5);
+}
+
+
+template <typename T,
+          bool IsFloatingPoint = boost::is_floating_point<T>::value>
+struct abs
+{
+    static inline T apply(T const& value)
+    {
+        T const zero = T();
+        return value < zero ? -value : value;
+    }
+};
+
+template <typename T>
+struct abs<T, true>
+{
+    static inline T apply(T const& value)
+    {
+        return fabs(value);
+    }
+};
+
+
+struct equals_default_policy
+{
+    template <typename T>
+    static inline T apply(T const& a, T const& b)
+    {
+        // See http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.17
+        return greatest(abs<T>::apply(a), abs<T>::apply(b), T(1));
+    }
+};
+
+template <typename T,
+          bool IsFloatingPoint = boost::is_floating_point<T>::value>
+struct equals_factor_policy
+{
+    equals_factor_policy()
+        : factor(1) {}
+    explicit equals_factor_policy(T const& v)
+        : factor(greatest(abs<T>::apply(v), T(1)))
+    {}
+    equals_factor_policy(T const& v0, T const& v1, T const& v2, T const& v3)
+        : factor(greatest(abs<T>::apply(v0), abs<T>::apply(v1),
+                          abs<T>::apply(v2), abs<T>::apply(v3),
+                          T(1)))
+    {}
+
+    T const& apply(T const&, T const&) const
+    {
+        return factor;
+    }
+
+    T factor;
+};
+
+template <typename T>
+struct equals_factor_policy<T, false>
+{
+    equals_factor_policy() {}
+    explicit equals_factor_policy(T const&) {}
+    equals_factor_policy(T const& , T const& , T const& , T const& ) {}
+
+    static inline T apply(T const&, T const&)
+    {
+        return T(1);
+    }
+};
+
+template <typename Type,
+          bool IsFloatingPoint = boost::is_floating_point<Type>::value>
 struct equals
 {
-    static inline bool apply(Type const& a, Type const& b)
+    template <typename Policy>
+    static inline bool apply(Type const& a, Type const& b, Policy const&)
     {
         return a == b;
     }
@@ -44,25 +151,31 @@
 template <typename Type>
 struct equals<Type, true>
 {
-    static inline Type get_max(Type const& a, Type const& b, Type const& c)
+    template <typename Policy>
+    static inline bool apply(Type const& a, Type const& b, Policy const& policy)
     {
-        return (std::max)((std::max)(a, b), c);
-    }
+        boost::ignore_unused(policy);
 
-    static inline bool apply(Type const& a, Type const& b)
-    {
         if (a == b)
         {
             return true;
         }
 
-        // See http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.17,
-        // FUTURE: replace by some boost tool or boost::test::close_at_tolerance
-        return std::abs(a - b) <= std::numeric_limits<Type>::epsilon() * get_max(std::abs(a), std::abs(b), 1.0);
+        return abs<Type>::apply(a - b) <= std::numeric_limits<Type>::epsilon() * policy.apply(a, b);
     }
 };
 
-template <typename Type, bool IsFloatingPoint>
+template <typename T1, typename T2, typename Policy>
+inline bool equals_by_policy(T1 const& a, T2 const& b, Policy const& policy)
+{
+    return detail::equals
+        <
+            typename select_most_precise<T1, T2>::type
+        >::apply(a, b, policy);
+}
+
+template <typename Type,
+          bool IsFloatingPoint = boost::is_floating_point<Type>::value>
 struct smaller
 {
     static inline bool apply(Type const& a, Type const& b)
@@ -76,7 +189,7 @@
 {
     static inline bool apply(Type const& a, Type const& b)
     {
-        if (equals<Type, true>::apply(a, b))
+        if (equals<Type, true>::apply(a, b, equals_default_policy()))
         {
             return false;
         }
@@ -85,8 +198,101 @@
 };
 
 
-template <typename Type, bool IsFloatingPoint> 
-struct equals_with_epsilon : public equals<Type, IsFloatingPoint> {};
+template <typename Type,
+          bool IsFloatingPoint = boost::is_floating_point<Type>::value>
+struct equals_with_epsilon
+    : public equals<Type, IsFloatingPoint>
+{};
+
+template
+<
+    typename T,
+    bool IsFundemantal = boost::is_fundamental<T>::value /* false */
+>
+struct square_root
+{
+    typedef T return_type;
+
+    static inline T apply(T const& value)
+    {
+        // for non-fundamental number types assume that sqrt is
+        // defined either:
+        // 1) at T's scope, or
+        // 2) at global scope, or
+        // 3) in namespace std
+        using ::sqrt;
+        using std::sqrt;
+
+        return sqrt(value);
+    }
+};
+
+template <typename FundamentalFP>
+struct square_root_for_fundamental_fp
+{
+    typedef FundamentalFP return_type;
+
+    static inline FundamentalFP apply(FundamentalFP const& value)
+    {
+#ifdef BOOST_GEOMETRY_SQRT_CHECK_FINITENESS
+        // This is a workaround for some 32-bit platforms.
+        // For some of those platforms it has been reported that
+        // std::sqrt(nan) and/or std::sqrt(-nan) returns a finite value.
+        // For those platforms we need to define the macro
+        // BOOST_GEOMETRY_SQRT_CHECK_FINITENESS so that the argument
+        // to std::sqrt is checked appropriately before passed to std::sqrt
+        if (boost::math::isfinite(value))
+        {
+            return std::sqrt(value);
+        }
+        else if (boost::math::isinf(value) && value < 0)
+        {
+            return -std::numeric_limits<FundamentalFP>::quiet_NaN();
+        }
+        return value;
+#else
+        // for fundamental floating point numbers use std::sqrt
+        return std::sqrt(value);
+#endif // BOOST_GEOMETRY_SQRT_CHECK_FINITENESS
+    }
+};
+
+template <>
+struct square_root<float, true>
+    : square_root_for_fundamental_fp<float>
+{
+};
+
+template <>
+struct square_root<double, true>
+    : square_root_for_fundamental_fp<double>
+{
+};
+
+template <>
+struct square_root<long double, true>
+    : square_root_for_fundamental_fp<long double>
+{
+};
+
+template <typename T>
+struct square_root<T, true>
+{
+    typedef double return_type;
+
+    static inline double apply(T const& value)
+    {
+        // for all other fundamental number types use also std::sqrt
+        //
+        // Note: in C++98 the only other possibility is double;
+        //       in C++11 there are also overloads for integral types;
+        //       this specialization works for those as well.
+        return square_root_for_fundamental_fp
+            <
+                double
+            >::apply(boost::numeric_cast<double>(value));
+    }
+};
 
 
 /*!
@@ -111,6 +317,30 @@
     }
 };
 
+// ItoF ItoI FtoF
+template <typename Result, typename Source,
+          bool ResultIsInteger = std::numeric_limits<Result>::is_integer,
+          bool SourceIsInteger = std::numeric_limits<Source>::is_integer>
+struct round
+{
+    static inline Result apply(Source const& v)
+    {
+        return boost::numeric_cast<Result>(v);
+    }
+};
+
+// FtoI
+template <typename Result, typename Source>
+struct round<Result, Source, true, false>
+{
+    static inline Result apply(Source const& v)
+    {
+        namespace bmp = boost::math::policies;
+        // ignore rounding errors for backward compatibility
+        typedef bmp::policy< bmp::rounding_error<bmp::ignore_error> > policy;
+        return boost::numeric_cast<Result>(boost::math::round(v, policy()));
+    }
+};
 
 } // namespace detail
 #endif
@@ -144,44 +374,36 @@
 template <typename T1, typename T2>
 inline bool equals(T1 const& a, T2 const& b)
 {
-    typedef typename select_most_precise<T1, T2>::type select_type;
     return detail::equals
         <
-            select_type,
-            boost::is_floating_point<select_type>::type::value
-        >::apply(a, b);
+            typename select_most_precise<T1, T2>::type
+        >::apply(a, b, detail::equals_default_policy());
 }
 
 template <typename T1, typename T2>
 inline bool equals_with_epsilon(T1 const& a, T2 const& b)
 {
-    typedef typename select_most_precise<T1, T2>::type select_type;
     return detail::equals_with_epsilon
         <
-            select_type, 
-            boost::is_floating_point<select_type>::type::value
-        >::apply(a, b);
+            typename select_most_precise<T1, T2>::type
+        >::apply(a, b, detail::equals_default_policy());
 }
 
 template <typename T1, typename T2>
 inline bool smaller(T1 const& a, T2 const& b)
 {
-    typedef typename select_most_precise<T1, T2>::type select_type;
     return detail::smaller
         <
-            select_type,
-            boost::is_floating_point<select_type>::type::value
+            typename select_most_precise<T1, T2>::type
         >::apply(a, b);
 }
 
 template <typename T1, typename T2>
 inline bool larger(T1 const& a, T2 const& b)
 {
-    typedef typename select_most_precise<T1, T2>::type select_type;
     return detail::smaller
         <
-            select_type,
-            boost::is_floating_point<select_type>::type::value
+            typename select_most_precise<T1, T2>::type
         >::apply(b, a);
 }
 
@@ -217,6 +439,22 @@
 }
 
 /*!
+\brief Short utility to return the square root
+\ingroup utility
+\param value Value to calculate the square root from
+\return The square root value
+*/
+template <typename T>
+inline typename detail::square_root<T>::return_type
+sqrt(T const& value)
+{
+    return detail::square_root
+        <
+            T, boost::is_fundamental<T>::value
+        >::apply(value);
+}
+
+/*!
 \brief Short utility to workaround gcc/clang problem that abs is converting to integer
        and that older versions of MSVC does not support abs of long long...
 \ingroup utility
@@ -224,8 +462,7 @@
 template<typename T>
 inline T abs(T const& value)
 {
-    T const zero = T();
-    return value < zero ? -value : value;
+    return detail::abs<T>::apply(value);
 }
 
 /*!
@@ -233,12 +470,24 @@
 \ingroup utility
 */
 template <typename T>
-static inline int sign(T const& value) 
+static inline int sign(T const& value)
 {
     T const zero = T();
     return value > zero ? 1 : value < zero ? -1 : 0;
 }
 
+/*!
+\brief Short utility to calculate the rounded value of a number.
+\ingroup utility
+\note If the source T is NOT an integral type and Result is an integral type
+      the value is rounded towards the closest integral value. Otherwise it's
+      casted.
+*/
+template <typename Result, typename T>
+inline Result round(T const& v)
+{
+    return detail::round<Result, T>::apply(v);
+}
 
 } // namespace math