rational.hpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Copyright (c) 2011-2012 Bruno Lalande, Paris, France.
  4. // Copyright (c) 2011-2012 Mateusz Loskot, London, UK.
  5. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
  6. // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
  7. // Use, modification and distribution is subject to the Boost Software License,
  8. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. #ifndef BOOST_GEOMETRY_UTIL_RATIONAL_HPP
  11. #define BOOST_GEOMETRY_UTIL_RATIONAL_HPP
  12. // Contains specializations for Boost.Rational
  13. #include <boost/rational.hpp>
  14. #include <boost/geometry/util/bounds.hpp>
  15. #include <boost/geometry/util/coordinate_cast.hpp>
  16. #include <boost/geometry/util/numeric_cast.hpp>
  17. #include <boost/geometry/util/select_most_precise.hpp>
  18. namespace boost{ namespace geometry
  19. {
  20. // Specialize for Boost.Geometry's coordinate cast
  21. // (from string to coordinate type)
  22. namespace detail
  23. {
  24. template <typename T>
  25. struct coordinate_cast<rational<T> >
  26. {
  27. static inline void split_parts(std::string const& source, std::string::size_type p,
  28. T& before, T& after, bool& negate, std::string::size_type& len)
  29. {
  30. std::string before_part = source.substr(0, p);
  31. std::string const after_part = source.substr(p + 1);
  32. negate = false;
  33. if (before_part.size() > 0 && before_part[0] == '-')
  34. {
  35. negate = true;
  36. before_part.erase(0, 1);
  37. }
  38. before = atol(before_part.c_str());
  39. after = atol(after_part.c_str());
  40. len = after_part.length();
  41. }
  42. static inline rational<T> apply(std::string const& source)
  43. {
  44. T before, after;
  45. bool negate;
  46. std::string::size_type len;
  47. // Note: decimal comma is not (yet) supported, it does (and should) not
  48. // occur in a WKT, where points are comma separated.
  49. std::string::size_type p = source.find('.');
  50. if (p == std::string::npos)
  51. {
  52. p = source.find('/');
  53. if (p == std::string::npos)
  54. {
  55. return rational<T>(atol(source.c_str()));
  56. }
  57. split_parts(source, p, before, after, negate, len);
  58. return negate
  59. ? -rational<T>(before, after)
  60. : rational<T>(before, after)
  61. ;
  62. }
  63. split_parts(source, p, before, after, negate, len);
  64. T den = 1;
  65. for (std::string::size_type i = 0; i < len; i++)
  66. {
  67. den *= 10;
  68. }
  69. return negate
  70. ? -rational<T>(before) - rational<T>(after, den)
  71. : rational<T>(before) + rational<T>(after, den)
  72. ;
  73. }
  74. };
  75. } // namespace detail
  76. // Specialize for Boost.Geometry's select_most_precise
  77. template <typename T1, typename T2>
  78. struct select_most_precise<boost::rational<T1>, boost::rational<T2> >
  79. {
  80. typedef typename boost::rational
  81. <
  82. typename select_most_precise<T1, T2>::type
  83. > type;
  84. };
  85. template <typename T>
  86. struct select_most_precise<boost::rational<T>, double>
  87. {
  88. typedef typename boost::rational<T> type;
  89. };
  90. namespace util
  91. {
  92. #ifndef DOXYGEN_NO_DETAIL
  93. namespace detail
  94. {
  95. // Specialize numeric_caster, needed for geomery::util::numeric_cast, for Boost.Rational
  96. // Without it, code using Boost.Rational does not compile
  97. template <typename Target, typename T>
  98. struct numeric_caster<Target, rational<T>>
  99. {
  100. static inline Target apply(rational<T> const& source)
  101. {
  102. return boost::rational_cast<Target>(source);
  103. }
  104. };
  105. } // namespace detail
  106. #endif
  107. // Specializes geometry::util::bounds for Boost.Rational
  108. // Without it, bounds contains (0,1) by default for Boost.Rational
  109. template<class T>
  110. struct bounds<rational<T> >
  111. {
  112. static inline rational<T> lowest()
  113. {
  114. return rational<T>(bounds<T>::lowest(), 1);
  115. }
  116. static inline rational<T> highest()
  117. {
  118. return rational<T>(bounds<T>::highest(), 1);
  119. }
  120. };
  121. } // namespace util
  122. }} // namespace boost::geometry
  123. #endif // BOOST_GEOMETRY_UTIL_RATIONAL_HPP