summaryrefslogtreecommitdiff
path: root/boost/geometry/util/math.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/geometry/util/math.hpp')
-rw-r--r--boost/geometry/util/math.hpp193
1 files changed, 172 insertions, 21 deletions
diff --git a/boost/geometry/util/math.hpp b/boost/geometry/util/math.hpp
index 95cbdf2ce4..22c02168ad 100644
--- a/boost/geometry/util/math.hpp
+++ b/boost/geometry/util/math.hpp
@@ -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-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
+
+// This file was modified by Oracle on 2014.
+// Modifications copyright (c) 2014, 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.
@@ -18,6 +24,9 @@
#include <limits>
#include <boost/math/constants/constants.hpp>
+#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>
@@ -44,17 +53,17 @@ struct equals
template <typename Type>
struct equals<Type, true>
{
- static inline Type get_max(Type const& a, Type const& b, Type const& c)
- {
- return (std::max)((std::max)(a, b), c);
- }
+ static inline Type get_max(Type const& a, Type const& b, Type const& c)
+ {
+ return (std::max)((std::max)(a, b), c);
+ }
static inline bool apply(Type const& a, Type const& b)
{
- if (a == b)
- {
- return true;
- }
+ 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
@@ -76,18 +85,81 @@ struct smaller<Type, true>
{
static inline bool apply(Type const& a, Type const& b)
{
- if (equals<Type, true>::apply(a, b))
- {
- return false;
- }
- return a < b;
+ if (equals<Type, true>::apply(a, b))
+ {
+ return false;
+ }
+ return a < b;
}
};
-template <typename Type, bool IsFloatingPoint>
+template <typename Type, bool IsFloatingPoint>
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 <>
+struct square_root<float, true>
+{
+ typedef float return_type;
+
+ static inline float apply(float const& value)
+ {
+ // for float use std::sqrt
+ return std::sqrt(value);
+ }
+};
+
+template <>
+struct square_root<long double, true>
+{
+ typedef long double return_type;
+
+ static inline long double apply(long double const& value)
+ {
+ // for long double use std::sqrt
+ return std::sqrt(value);
+ }
+};
+
+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 std::sqrt(boost::numeric_cast<double>(value));
+ }
+};
+
/*!
\brief Short construct to enable partial specialization for PI, currently not possible in Math.
@@ -102,6 +174,39 @@ struct define_pi
}
};
+template <typename T>
+struct relaxed_epsilon
+{
+ static inline T apply(const T& factor)
+ {
+ return factor * std::numeric_limits<T>::epsilon();
+ }
+};
+
+// 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
@@ -110,6 +215,12 @@ struct define_pi
template <typename T>
inline T pi() { return detail::define_pi<T>::apply(); }
+template <typename T>
+inline T relaxed_epsilon(T const& factor)
+{
+ return detail::relaxed_epsilon<T>::apply(factor);
+}
+
// Maybe replace this by boost equals or boost ublas numeric equals or so
@@ -143,7 +254,7 @@ 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,
+ select_type,
boost::is_floating_point<select_type>::type::value
>::apply(a, b);
}
@@ -201,18 +312,58 @@ inline T sqr(T const& value)
return value * value;
}
+/*!
+\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
*/
template<typename T>
-inline T abs(const T& t)
+inline T abs(T const& value)
{
- using std::abs;
- return abs(t);
+ T const zero = T();
+ return value < zero ? -value : value;
}
+/*!
+\brief Short utility to calculate the sign of a number: -1 (negative), 0 (zero), 1 (positive)
+\ingroup utility
+*/
+template <typename T>
+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
+ just casted.
+*/
+template <typename Result, typename T>
+inline Result round(T const& v)
+{
+ // NOTE: boost::round() could be used instead but it throws in some situations
+ return detail::round<Result, T>::apply(v);
+}
} // namespace math