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@16
|
45 #include <boost/utility/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@16
|
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@16
|
161 // 20.6.3 Comparasion 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@16
|
207 #ifdef BOOST_RATIO_EXTENSIONS
|
Chris@16
|
208 template <class R>
|
Chris@16
|
209 struct ratio_negate
|
Chris@16
|
210 : ratio<-R::num, R::den>::type
|
Chris@16
|
211 {
|
Chris@16
|
212 };
|
Chris@16
|
213 template <class R>
|
Chris@16
|
214 struct ratio_abs
|
Chris@16
|
215 : ratio<mpl::abs_c<boost::intmax_t, R::num>::value, R::den>::type
|
Chris@16
|
216 {
|
Chris@16
|
217 };
|
Chris@16
|
218 template <class R>
|
Chris@16
|
219 struct ratio_sign
|
Chris@16
|
220 : mpl::sign_c<boost::intmax_t, R::num>
|
Chris@16
|
221 {
|
Chris@16
|
222 };
|
Chris@16
|
223 template <class R1, class R2>
|
Chris@16
|
224 struct ratio_lcm :
|
Chris@16
|
225 ratio<mpl::lcm_c<boost::intmax_t, R1::num, R2::num>::value,
|
Chris@16
|
226 mpl::gcd_c<boost::intmax_t, R1::den, R2::den>::value>::type
|
Chris@16
|
227 {
|
Chris@16
|
228 };
|
Chris@16
|
229 #endif
|
Chris@16
|
230 } // namespace boost
|
Chris@16
|
231
|
Chris@16
|
232
|
Chris@16
|
233 #endif // BOOST_RATIO_RATIO_HPP
|