1 // ratio.hpp ---------------------------------------------------------------// 2 3 // Copyright 2008 Howard Hinnant 4 // Copyright 2008 Beman Dawes 5 // Copyright 2009 Vicente J. Botet Escriba 6 7 // Distributed under the Boost Software License, Version 1.0. 8 // See http://www.boost.org/LICENSE_1_0.txt 9 10 /* 11 12 This code was derived by Beman Dawes from Howard Hinnant's time2_demo prototype. 13 Many thanks to Howard for making his code available under the Boost license. 14 The original code was modified to conform to Boost conventions and to section 15 20.4 Compile-time rational arithmetic [ratio], of the C++ committee working 16 paper N2798. 17 See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf. 18 19 time2_demo contained this comment: 20 21 Much thanks to Andrei Alexandrescu, 22 Walter Brown, 23 Peter Dimov, 24 Jeff Garland, 25 Terry Golubiewski, 26 Daniel Krugler, 27 Anthony Williams. 28 */ 29 30 // The way overflow is managed for ratio_less is taken from llvm/libcxx/include/ratio 31 32 #ifndef BOOST_RATIO_RATIO_HPP 33 #define BOOST_RATIO_RATIO_HPP 34 35 #include <boost/ratio/config.hpp> 36 #include <boost/ratio/detail/mpl/abs.hpp> 37 #include <boost/ratio/detail/mpl/sign.hpp> 38 #include <boost/ratio/detail/mpl/gcd.hpp> 39 #include <boost/ratio/detail/mpl/lcm.hpp> 40 #include <cstdlib> 41 #include <climits> 42 #include <limits> 43 #include <boost/cstdint.hpp> 44 #include <boost/type_traits/integral_constant.hpp> 45 #include <boost/core/enable_if.hpp> 46 #include <boost/integer_traits.hpp> 47 #include <boost/ratio/ratio_fwd.hpp> 48 #include <boost/ratio/detail/overflow_helpers.hpp> 49 #ifdef BOOST_RATIO_EXTENSIONS 50 #include <boost/rational.hpp> 51 #include <boost/ratio/mpl/rational_c_tag.hpp> 52 #endif 53 54 // 55 // We simply cannot include this header on gcc without getting copious warnings of the kind: 56 // 57 // boost/integer.hpp:77:30: warning: use of C99 long long integer constant 58 // 59 // And yet there is no other reasonable implementation, so we declare this a system header 60 // to suppress these warnings. 61 // 62 #if defined(__GNUC__) && (__GNUC__ >= 4) 63 #pragma GCC system_header 64 #endif 65 66 namespace boost 67 { 68 69 70 //----------------------------------------------------------------------------// 71 // // 72 // 20.6.1 Class template ratio [ratio.ratio] // 73 // // 74 //----------------------------------------------------------------------------// 75 76 template <boost::intmax_t N, boost::intmax_t D> 77 class ratio 78 { 79 static const boost::intmax_t ABS_N = mpl::abs_c<boost::intmax_t, N>::value; 80 static const boost::intmax_t ABS_D = mpl::abs_c<boost::intmax_t, D>::value; 81 BOOST_RATIO_STATIC_ASSERT(ABS_N >= 0, BOOST_RATIO_NUMERATOR_IS_OUT_OF_RANGE, ()); 82 BOOST_RATIO_STATIC_ASSERT(ABS_D > 0, BOOST_RATIO_DENOMINATOR_IS_OUT_OF_RANGE, ()); 83 BOOST_RATIO_STATIC_ASSERT(D != 0, BOOST_RATIO_DIVIDE_BY_0 , ()); 84 static const boost::intmax_t SIGN_N = mpl::sign_c<boost::intmax_t,N>::value 85 * mpl::sign_c<boost::intmax_t,D>::value; 86 static const boost::intmax_t GCD = mpl::gcd_c<boost::intmax_t, ABS_N, ABS_D>::value; 87 public: 88 BOOST_STATIC_CONSTEXPR boost::intmax_t num = SIGN_N * ABS_N / GCD; 89 BOOST_STATIC_CONSTEXPR boost::intmax_t den = ABS_D / GCD; 90 91 #ifdef BOOST_RATIO_EXTENSIONS 92 typedef mpl::rational_c_tag tag; 93 typedef boost::rational<boost::intmax_t> value_type; 94 typedef boost::intmax_t num_type; 95 typedef boost::intmax_t den_type; ratio()96 ratio() 97 {} 98 template <boost::intmax_t _N2, boost::intmax_t _D2> ratio(const ratio<_N2,_D2> &,typename enable_if_c<(ratio<_N2,_D2>::num==num && ratio<_N2,_D2>::den==den)>::type * =0)99 ratio(const ratio<_N2, _D2>&, 100 typename enable_if_c 101 < 102 (ratio<_N2, _D2>::num == num && 103 ratio<_N2, _D2>::den == den) 104 >::type* = 0) 105 {} 106 107 template <boost::intmax_t _N2, boost::intmax_t _D2> 108 typename enable_if_c 109 < 110 (ratio<_N2, _D2>::num == num && 111 ratio<_N2, _D2>::den == den), 112 ratio& 113 >::type operator =(const ratio<_N2,_D2> &)114 operator=(const ratio<_N2, _D2>&) {return *this;} 115 value()116 static value_type value() {return value_type(num,den);} operator ()() const117 value_type operator()() const {return value();} 118 #endif 119 typedef ratio<num, den> type; 120 }; 121 122 #if defined(BOOST_NO_CXX11_CONSTEXPR) 123 template <boost::intmax_t N, boost::intmax_t D> 124 const boost::intmax_t ratio<N, D>::num; 125 template <boost::intmax_t N, boost::intmax_t D> 126 const boost::intmax_t ratio<N, D>::den; 127 #endif 128 129 //----------------------------------------------------------------------------// 130 // // 131 // 20.6.2 Arithmetic on ratio types [ratio.arithmetic] // 132 // // 133 //----------------------------------------------------------------------------// 134 135 template <class R1, class R2> 136 struct ratio_add 137 : boost::ratio_detail::ratio_add<R1, R2>::type 138 { 139 }; 140 141 template <class R1, class R2> 142 struct ratio_subtract 143 : boost::ratio_detail::ratio_subtract<R1, R2>::type 144 { 145 }; 146 147 template <class R1, class R2> 148 struct ratio_multiply 149 : boost::ratio_detail::ratio_multiply<R1, R2>::type 150 { 151 }; 152 153 template <class R1, class R2> 154 struct ratio_divide 155 : boost::ratio_detail::ratio_divide<R1, R2>::type 156 { 157 }; 158 159 //----------------------------------------------------------------------------// 160 // // 161 // 20.6.3 Comparision of ratio types [ratio.comparison] // 162 // // 163 //----------------------------------------------------------------------------// 164 165 // ratio_equal 166 167 template <class R1, class R2> 168 struct ratio_equal 169 : public boost::integral_constant<bool, 170 (R1::num == R2::num && R1::den == R2::den)> 171 {}; 172 173 template <class R1, class R2> 174 struct ratio_not_equal 175 : public boost::integral_constant<bool, !ratio_equal<R1, R2>::value> 176 {}; 177 178 // ratio_less 179 180 template <class R1, class R2> 181 struct ratio_less 182 : boost::integral_constant<bool, boost::ratio_detail::ratio_less<R1, R2>::value> 183 {}; 184 185 template <class R1, class R2> 186 struct ratio_less_equal 187 : boost::integral_constant<bool, !ratio_less<R2, R1>::value> 188 {}; 189 190 template <class R1, class R2> 191 struct ratio_greater 192 : boost::integral_constant<bool, ratio_less<R2, R1>::value> 193 {}; 194 195 template <class R1, class R2> 196 struct ratio_greater_equal 197 : boost::integral_constant<bool, !ratio_less<R1, R2>::value> 198 {}; 199 200 template <class R1, class R2> 201 struct ratio_gcd : 202 ratio<mpl::gcd_c<boost::intmax_t, R1::num, R2::num>::value, 203 mpl::lcm_c<boost::intmax_t, R1::den, R2::den>::value>::type 204 { 205 }; 206 207 //----------------------------------------------------------------------------// 208 // // 209 // More arithmetic on ratio types [ratio.arithmetic] // 210 // // 211 //----------------------------------------------------------------------------// 212 213 #ifdef BOOST_RATIO_EXTENSIONS 214 template <class R> 215 struct ratio_negate 216 : ratio<-R::num, R::den>::type 217 { 218 }; 219 template <class R> 220 struct ratio_abs 221 : ratio<mpl::abs_c<boost::intmax_t, R::num>::value, R::den>::type 222 { 223 }; 224 template <class R> 225 struct ratio_sign 226 : mpl::sign_c<boost::intmax_t, R::num> 227 { 228 }; 229 230 template <class R> 231 struct ratio_inverse 232 : ratio<R::den, R::num>::type 233 { 234 }; 235 236 237 template <class R1, class R2> 238 struct ratio_lcm : 239 ratio<mpl::lcm_c<boost::intmax_t, R1::num, R2::num>::value, 240 mpl::gcd_c<boost::intmax_t, R1::den, R2::den>::value>::type 241 { 242 }; 243 244 template <class R1, class R2> 245 struct ratio_modulo : 246 ratio<(R1::num * R2::den) % (R2::num * R1::den), R1::den * R2::den>::type 247 { 248 }; 249 250 namespace detail { 251 template <class R1, class R2, bool r1ltr2> 252 struct ratio_min : R1 {}; 253 template <class R1, class R2> 254 struct ratio_min<R1,R2,false> : R2 {}; 255 256 template <class R1, class R2, bool r1ltr2> 257 struct ratio_max : R2 {}; 258 template <class R1, class R2> 259 struct ratio_max<R1,R2,false> : R1 {}; 260 } 261 262 template <class R1, class R2> 263 struct ratio_min : detail::ratio_min<R1, R2, ratio_less<R1,R2>::value>::type 264 { 265 }; 266 267 template <class R1, class R2> 268 struct ratio_max : detail::ratio_max<R1, R2, ratio_less<R1,R2>::value>::type 269 { 270 }; 271 272 template<typename R, int p> 273 struct ratio_power : 274 ratio_multiply< 275 typename ratio_power<R, p%2>::type, 276 typename ratio_power<typename ratio_multiply<R, R>::type, p/2>::type 277 >::type 278 {}; 279 280 template<typename R> 281 struct ratio_power<R, 0> : ratio<1>::type {}; 282 283 template<typename R> 284 struct ratio_power<R, 1> : R {}; 285 286 template<typename R> 287 struct ratio_power<R, -1> : ratio_divide<ratio<1>, R>::type {}; 288 289 #endif 290 } // namespace boost 291 292 293 #endif // BOOST_RATIO_RATIO_HPP 294