// 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. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_GEOMETRY_UTIL_MATH_HPP #define BOOST_GEOMETRY_UTIL_MATH_HPP #include #include #include #include namespace boost { namespace geometry { namespace math { #ifndef DOXYGEN_NO_DETAIL namespace detail { template struct equals { static inline bool apply(Type const& a, Type const& b) { return a == b; } }; template struct equals { 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; } // 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::epsilon() * get_max(std::abs(a), std::abs(b), 1.0); } }; template struct smaller { static inline bool apply(Type const& a, Type const& b) { return a < b; } }; template struct smaller { static inline bool apply(Type const& a, Type const& b) { if (equals::apply(a, b)) { return false; } return a < b; } }; template struct equals_with_epsilon : public equals {}; /*! \brief Short construct to enable partial specialization for PI, currently not possible in Math. */ template struct define_pi { static inline T apply() { // Default calls Boost.Math return boost::math::constants::pi(); } }; template struct relaxed_epsilon { static inline T apply(const T& factor) { return factor * std::numeric_limits::epsilon(); } }; } // namespace detail #endif template inline T pi() { return detail::define_pi::apply(); } template inline T relaxed_epsilon(T const& factor) { return detail::relaxed_epsilon::apply(factor); } // Maybe replace this by boost equals or boost ublas numeric equals or so /*! \brief returns true if both arguments are equal. \ingroup utility \param a first argument \param b second argument \return true if a == b \note If both a and b are of an integral type, comparison is done by ==. If one of the types is floating point, comparison is done by abs and comparing with epsilon. If one of the types is non-fundamental, it might be a high-precision number and comparison is done using the == operator of that class. */ template inline bool equals(T1 const& a, T2 const& b) { typedef typename select_most_precise::type select_type; return detail::equals < select_type, boost::is_floating_point::type::value >::apply(a, b); } template inline bool equals_with_epsilon(T1 const& a, T2 const& b) { typedef typename select_most_precise::type select_type; return detail::equals_with_epsilon < select_type, boost::is_floating_point::type::value >::apply(a, b); } template inline bool smaller(T1 const& a, T2 const& b) { typedef typename select_most_precise::type select_type; return detail::smaller < select_type, boost::is_floating_point::type::value >::apply(a, b); } template inline bool larger(T1 const& a, T2 const& b) { typedef typename select_most_precise::type select_type; return detail::smaller < select_type, boost::is_floating_point::type::value >::apply(b, a); } double const d2r = geometry::math::pi() / 180.0; double const r2d = 1.0 / d2r; /*! \brief Calculates the haversine of an angle \ingroup utility \note See http://en.wikipedia.org/wiki/Haversine_formula haversin(alpha) = sin2(alpha/2) */ template inline T hav(T const& theta) { T const half = T(0.5); T const sn = sin(half * theta); return sn * sn; } /*! \brief Short utility to return the square \ingroup utility \param value Value to calculate the square from \return The squared value */ template inline T sqr(T const& value) { return value * 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 inline T abs(T const& value) { 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 static inline int sign(T const& value) { T const zero = T(); return value > zero ? 1 : value < zero ? -1 : 0; } } // namespace math }} // namespace boost::geometry #endif // BOOST_GEOMETRY_UTIL_MATH_HPP