// Boost.Geometry (aka GGL, Generic Geometry Library) // Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2011-2012 Bruno Lalande, Paris, France. // Copyright (c) 2011-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_RATIONAL_HPP #define BOOST_GEOMETRY_UTIL_RATIONAL_HPP // Contains specializations for Boost.Rational #include #include #include #include #include namespace boost{ namespace geometry { // Specialize for Boost.Geometry's coordinate cast // (from string to coordinate type) namespace detail { template struct coordinate_cast > { static inline void split_parts(std::string const& source, std::string::size_type p, T& before, T& after, bool& negate, std::string::size_type& len) { std::string before_part = source.substr(0, p); std::string const after_part = source.substr(p + 1); negate = false; if (before_part.size() > 0 && before_part[0] == '-') { negate = true; before_part.erase(0, 1); } before = atol(before_part.c_str()); after = atol(after_part.c_str()); len = after_part.length(); } static inline rational apply(std::string const& source) { T before, after; bool negate; std::string::size_type len; // Note: decimal comma is not (yet) supported, it does (and should) not // occur in a WKT, where points are comma separated. std::string::size_type p = source.find('.'); if (p == std::string::npos) { p = source.find('/'); if (p == std::string::npos) { return rational(atol(source.c_str())); } split_parts(source, p, before, after, negate, len); return negate ? -rational(before, after) : rational(before, after) ; } split_parts(source, p, before, after, negate, len); T den = 1; for (std::string::size_type i = 0; i < len; i++) { den *= 10; } return negate ? -rational(before) - rational(after, den) : rational(before) + rational(after, den) ; } }; } // namespace detail // Specialize for Boost.Geometry's select_most_precise template struct select_most_precise, boost::rational > { typedef typename boost::rational < typename select_most_precise::type > type; }; template struct select_most_precise, double> { typedef typename boost::rational type; }; namespace util { #ifndef DOXYGEN_NO_DETAIL namespace detail { // Specialize numeric_caster, needed for geomery::util::numeric_cast, for Boost.Rational // Without it, code using Boost.Rational does not compile template struct numeric_caster> { static inline Target apply(rational const& source) { return boost::rational_cast(source); } }; } // namespace detail #endif // Specializes geometry::util::bounds for Boost.Rational // Without it, bounds contains (0,1) by default for Boost.Rational template struct bounds > { static inline rational lowest() { return rational(bounds::lowest(), 1); } static inline rational highest() { return rational(bounds::highest(), 1); } }; } // namespace util }} // namespace boost::geometry #endif // BOOST_GEOMETRY_UTIL_RATIONAL_HPP