File indexing completed on 2025-01-30 09:42:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef BOOST_GEOMETRY_UTIL_RATIONAL_HPP
0015 #define BOOST_GEOMETRY_UTIL_RATIONAL_HPP
0016
0017 #include <boost/rational.hpp>
0018 #include <boost/numeric/conversion/bounds.hpp>
0019
0020 #include <boost/geometry/util/coordinate_cast.hpp>
0021 #include <boost/geometry/util/select_most_precise.hpp>
0022
0023
0024 namespace boost{ namespace geometry
0025 {
0026
0027
0028
0029
0030 namespace detail
0031 {
0032
0033 template <typename T>
0034 struct coordinate_cast<rational<T> >
0035 {
0036 static inline void split_parts(std::string const& source, std::string::size_type p,
0037 T& before, T& after, bool& negate, std::string::size_type& len)
0038 {
0039 std::string before_part = source.substr(0, p);
0040 std::string const after_part = source.substr(p + 1);
0041
0042 negate = false;
0043
0044 if (before_part.size() > 0 && before_part[0] == '-')
0045 {
0046 negate = true;
0047 before_part.erase(0, 1);
0048 }
0049 before = atol(before_part.c_str());
0050 after = atol(after_part.c_str());
0051 len = after_part.length();
0052 }
0053
0054
0055 static inline rational<T> apply(std::string const& source)
0056 {
0057 T before, after;
0058 bool negate;
0059 std::string::size_type len;
0060
0061
0062
0063 std::string::size_type p = source.find('.');
0064 if (p == std::string::npos)
0065 {
0066 p = source.find('/');
0067 if (p == std::string::npos)
0068 {
0069 return rational<T>(atol(source.c_str()));
0070 }
0071 split_parts(source, p, before, after, negate, len);
0072
0073 return negate
0074 ? -rational<T>(before, after)
0075 : rational<T>(before, after)
0076 ;
0077
0078 }
0079
0080 split_parts(source, p, before, after, negate, len);
0081
0082 T den = 1;
0083 for (std::string::size_type i = 0; i < len; i++)
0084 {
0085 den *= 10;
0086 }
0087
0088 return negate
0089 ? -rational<T>(before) - rational<T>(after, den)
0090 : rational<T>(before) + rational<T>(after, den)
0091 ;
0092 }
0093 };
0094
0095 }
0096
0097
0098 template <typename T1, typename T2>
0099 struct select_most_precise<boost::rational<T1>, boost::rational<T2> >
0100 {
0101 typedef typename boost::rational
0102 <
0103 typename select_most_precise<T1, T2>::type
0104 > type;
0105 };
0106
0107 template <typename T>
0108 struct select_most_precise<boost::rational<T>, double>
0109 {
0110 typedef typename boost::rational<T> type;
0111 };
0112
0113
0114 }}
0115
0116
0117
0118 namespace boost { namespace numeric
0119 {
0120
0121 template<class T>
0122 struct bounds<rational<T> >
0123 {
0124 static inline rational<T> lowest()
0125 {
0126 return rational<T>(bounds<T>::lowest(), 1);
0127 }
0128 static inline rational<T> highest()
0129 {
0130 return rational<T>(bounds<T>::highest(), 1);
0131 }
0132 };
0133
0134 }}
0135
0136
0137
0138 namespace boost { namespace numeric
0139 {
0140
0141 template
0142 <
0143 typename T,
0144 typename Traits,
0145 typename OverflowHandler,
0146 typename Float2IntRounder,
0147 typename RawConverter,
0148 typename UserRangeChecker
0149 >
0150 struct converter<int, rational<T>, Traits, OverflowHandler, Float2IntRounder, RawConverter, UserRangeChecker>
0151 {
0152 static inline int convert(rational<T> const& arg)
0153 {
0154 return int(rational_cast<double>(arg));
0155 }
0156 };
0157
0158 template
0159 <
0160 typename T,
0161 typename Traits,
0162 typename OverflowHandler,
0163 typename Float2IntRounder,
0164 typename RawConverter,
0165 typename UserRangeChecker
0166 >
0167 struct converter<double, rational<T>, Traits, OverflowHandler, Float2IntRounder, RawConverter, UserRangeChecker>
0168 {
0169 static inline double convert(rational<T> const& arg)
0170 {
0171 return rational_cast<double>(arg);
0172 }
0173 };
0174
0175
0176 }}
0177
0178
0179 #endif