1 // ratio.hpp ---------------------------------------------------------------//
3 // Copyright 2008 Howard Hinnant
4 // Copyright 2008 Beman Dawes
5 // Copyright 2009 Vicente J. Botet Escriba
7 // Distributed under the Boost Software License, Version 1.0.
8 // See http://www.boost.org/LICENSE_1_0.txt
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
17 See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf.
19 time2_demo contained this comment:
21 Much thanks to Andrei Alexandrescu,
30 // The way overflow is managed for ratio_less is taken from llvm/libcxx/include/ratio
32 #ifndef BOOST_RATIO_RATIO_HPP
33 #define BOOST_RATIO_RATIO_HPP
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>
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>
55 // We simply cannot include this header on gcc without getting copious warnings of the kind:
57 // boost/integer.hpp:77:30: warning: use of C99 long long integer constant
59 // And yet there is no other reasonable implementation, so we declare this a system header
60 // to suppress these warnings.
62 #if defined(__GNUC__) && (__GNUC__ >= 4)
63 #pragma GCC system_header
70 //----------------------------------------------------------------------------//
72 // 20.6.1 Class template ratio [ratio.ratio] //
74 //----------------------------------------------------------------------------//
76 template <boost::intmax_t N, boost::intmax_t D>
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;
88 BOOST_STATIC_CONSTEXPR boost::intmax_t num = SIGN_N * ABS_N / GCD;
89 BOOST_STATIC_CONSTEXPR boost::intmax_t den = ABS_D / GCD;
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;
98 template <boost::intmax_t _N2, boost::intmax_t _D2>
99 ratio(const ratio<_N2, _D2>&,
102 (ratio<_N2, _D2>::num == num &&
103 ratio<_N2, _D2>::den == den)
107 template <boost::intmax_t _N2, boost::intmax_t _D2>
110 (ratio<_N2, _D2>::num == num &&
111 ratio<_N2, _D2>::den == den),
114 operator=(const ratio<_N2, _D2>&) {return *this;}
116 static value_type value() {return value_type(num,den);}
117 value_type operator()() const {return value();}
119 typedef ratio<num, den> type;
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;
129 //----------------------------------------------------------------------------//
131 // 20.6.2 Arithmetic on ratio types [ratio.arithmetic] //
133 //----------------------------------------------------------------------------//
135 template <class R1, class R2>
137 : boost::ratio_detail::ratio_add<R1, R2>::type
141 template <class R1, class R2>
142 struct ratio_subtract
143 : boost::ratio_detail::ratio_subtract<R1, R2>::type
147 template <class R1, class R2>
148 struct ratio_multiply
149 : boost::ratio_detail::ratio_multiply<R1, R2>::type
153 template <class R1, class R2>
155 : boost::ratio_detail::ratio_divide<R1, R2>::type
159 //----------------------------------------------------------------------------//
161 // 20.6.3 Comparision of ratio types [ratio.comparison] //
163 //----------------------------------------------------------------------------//
167 template <class R1, class R2>
169 : public boost::integral_constant<bool,
170 (R1::num == R2::num && R1::den == R2::den)>
173 template <class R1, class R2>
174 struct ratio_not_equal
175 : public boost::integral_constant<bool, !ratio_equal<R1, R2>::value>
180 template <class R1, class R2>
182 : boost::integral_constant<bool, boost::ratio_detail::ratio_less<R1, R2>::value>
185 template <class R1, class R2>
186 struct ratio_less_equal
187 : boost::integral_constant<bool, !ratio_less<R2, R1>::value>
190 template <class R1, class R2>
192 : boost::integral_constant<bool, ratio_less<R2, R1>::value>
195 template <class R1, class R2>
196 struct ratio_greater_equal
197 : boost::integral_constant<bool, !ratio_less<R1, R2>::value>
200 template <class R1, class R2>
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
207 //----------------------------------------------------------------------------//
209 // More arithmetic on ratio types [ratio.arithmetic] //
211 //----------------------------------------------------------------------------//
213 #ifdef BOOST_RATIO_EXTENSIONS
216 : ratio<-R::num, R::den>::type
221 : ratio<mpl::abs_c<boost::intmax_t, R::num>::value, R::den>::type
226 : mpl::sign_c<boost::intmax_t, R::num>
232 : ratio<R::den, R::num>::type
237 template <class R1, class R2>
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
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
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 {};
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 {};
262 template <class R1, class R2>
263 struct ratio_min : detail::ratio_min<R1, R2, ratio_less<R1,R2>::value>::type
267 template <class R1, class R2>
268 struct ratio_max : detail::ratio_max<R1, R2, ratio_less<R1,R2>::value>::type
272 template<typename R, int p>
275 typename ratio_power<R, p%2>::type,
276 typename ratio_power<typename ratio_multiply<R, R>::type, p/2>::type
281 struct ratio_power<R, 0> : ratio<1>::type {};
284 struct ratio_power<R, 1> : R {};
287 struct ratio_power<R, -1> : ratio_divide<ratio<1>, R>::type {};
293 #endif // BOOST_RATIO_RATIO_HPP