ratio.hpp 8.7 KB

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