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