]>
Commit | Line | Data |
---|---|---|
5b9daa7e | 1 | // ratio -*- C++ -*- |
4acedca1 | 2 | |
ab65a4c7 | 3 | // Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. |
4acedca1 CF |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free | |
6 | // software; you can redistribute it and/or modify it under the | |
7 | // terms of the GNU General Public License as published by the | |
748086b7 | 8 | // Free Software Foundation; either version 3, or (at your option) |
4acedca1 CF |
9 | // any later version. |
10 | ||
11 | // This library is distributed in the hope that it will be useful, | |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | // GNU General Public License for more details. | |
15 | ||
748086b7 JJ |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version | |
18 | // 3.1, as published by the Free Software Foundation. | |
4acedca1 | 19 | |
748086b7 JJ |
20 | // You should have received a copy of the GNU General Public License and |
21 | // a copy of the GCC Runtime Library Exception along with this program; | |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | // <http://www.gnu.org/licenses/>. | |
4acedca1 | 24 | |
f910786b | 25 | /** @file include/ratio |
4acedca1 CF |
26 | * This is a Standard C++ Library header. |
27 | */ | |
28 | ||
29 | #ifndef _GLIBCXX_RATIO | |
30 | #define _GLIBCXX_RATIO 1 | |
31 | ||
32 | #pragma GCC system_header | |
33 | ||
34 | #ifndef __GXX_EXPERIMENTAL_CXX0X__ | |
ab65a4c7 | 35 | # include <bits/c++0x_warning.h> |
4acedca1 CF |
36 | #else |
37 | ||
38 | #include <type_traits> | |
39 | #include <cstdint> | |
40 | ||
41 | #ifdef _GLIBCXX_USE_C99_STDINT_TR1 | |
42 | ||
12ffa228 BK |
43 | namespace std _GLIBCXX_VISIBILITY(default) |
44 | { | |
45 | _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
53dc5044 | 46 | |
5b9daa7e BK |
47 | /** |
48 | * @defgroup ratio Rational Arithmetic | |
49 | * @ingroup utilities | |
50 | * | |
79e2c7b0 | 51 | * Compile time representation of finite rational numbers. |
5b9daa7e BK |
52 | * @{ |
53 | */ | |
54 | ||
4acedca1 CF |
55 | template<intmax_t _Pn> |
56 | struct __static_sign | |
57 | : integral_constant<intmax_t, (_Pn < 0) ? -1 : 1> | |
58 | { }; | |
59 | ||
60 | template<intmax_t _Pn> | |
61 | struct __static_abs | |
62 | : integral_constant<intmax_t, _Pn * __static_sign<_Pn>::value> | |
63 | { }; | |
64 | ||
65 | template<intmax_t _Pn, intmax_t _Qn> | |
66 | struct __static_gcd; | |
67 | ||
68 | template<intmax_t _Pn, intmax_t _Qn> | |
69 | struct __static_gcd | |
70 | : __static_gcd<_Qn, (_Pn % _Qn)> | |
71 | { }; | |
72 | ||
73 | template<intmax_t _Pn> | |
74 | struct __static_gcd<_Pn, 0> | |
75 | : integral_constant<intmax_t, __static_abs<_Pn>::value> | |
76 | { }; | |
77 | ||
78 | template<intmax_t _Qn> | |
79 | struct __static_gcd<0, _Qn> | |
80 | : integral_constant<intmax_t, __static_abs<_Qn>::value> | |
81 | { }; | |
82 | ||
83 | // Let c = 2^(half # of bits in an intmax_t) | |
84 | // then we find a1, a0, b1, b0 s.t. N = a1*c + a0, M = b1*c + b0 | |
85 | // The multiplication of N and M becomes, | |
86 | // N * M = (a1 * b1)c^2 + (a0 * b1 + b0 * a1)c + a0 * b0 | |
87 | // Multiplication is safe if each term and the sum of the terms | |
88 | // is representable by intmax_t. | |
89 | template<intmax_t _Pn, intmax_t _Qn> | |
90 | struct __safe_multiply | |
91 | { | |
92 | private: | |
93 | static const uintmax_t __c = uintmax_t(1) << (sizeof(intmax_t) * 4); | |
94 | ||
95 | static const uintmax_t __a0 = __static_abs<_Pn>::value % __c; | |
96 | static const uintmax_t __a1 = __static_abs<_Pn>::value / __c; | |
97 | static const uintmax_t __b0 = __static_abs<_Qn>::value % __c; | |
98 | static const uintmax_t __b1 = __static_abs<_Qn>::value / __c; | |
99 | ||
100 | static_assert(__a1 == 0 || __b1 == 0, | |
101 | "overflow in multiplication"); | |
102 | static_assert(__a0 * __b1 + __b0 * __a1 < (__c >> 1), | |
103 | "overflow in multiplication"); | |
ea31932d | 104 | static_assert(__b0 * __a0 <= __INTMAX_MAX__, |
4acedca1 CF |
105 | "overflow in multiplication"); |
106 | static_assert((__a0 * __b1 + __b0 * __a1) * __c <= | |
ea31932d | 107 | __INTMAX_MAX__ - __b0 * __a0, "overflow in multiplication"); |
4acedca1 CF |
108 | |
109 | public: | |
110 | static const intmax_t value = _Pn * _Qn; | |
111 | }; | |
112 | ||
113 | // Helpers for __safe_add | |
114 | template<intmax_t _Pn, intmax_t _Qn, bool> | |
115 | struct __add_overflow_check_impl | |
ea31932d | 116 | : integral_constant<bool, (_Pn <= __INTMAX_MAX__ - _Qn)> |
4acedca1 CF |
117 | { }; |
118 | ||
119 | template<intmax_t _Pn, intmax_t _Qn> | |
120 | struct __add_overflow_check_impl<_Pn, _Qn, false> | |
ea31932d | 121 | : integral_constant<bool, (_Pn >= -__INTMAX_MAX__ - _Qn)> |
4acedca1 CF |
122 | { }; |
123 | ||
124 | template<intmax_t _Pn, intmax_t _Qn> | |
125 | struct __add_overflow_check | |
126 | : __add_overflow_check_impl<_Pn, _Qn, (_Qn >= 0)> | |
127 | { }; | |
128 | ||
129 | template<intmax_t _Pn, intmax_t _Qn> | |
130 | struct __safe_add | |
131 | { | |
132 | static_assert(__add_overflow_check<_Pn, _Qn>::value != 0, | |
133 | "overflow in addition"); | |
134 | ||
135 | static const intmax_t value = _Pn + _Qn; | |
136 | }; | |
137 | ||
ea31932d PC |
138 | /** |
139 | * @brief Provides compile-time rational arithmetic. | |
5b9daa7e | 140 | * |
ea31932d PC |
141 | * This class template represents any finite rational number with a |
142 | * numerator and denominator representable by compile-time constants of | |
143 | * type intmax_t. The ratio is simplified when instantiated. | |
144 | * | |
145 | * For example: | |
146 | * @code | |
147 | * std::ratio<7,-21>::num == -1; | |
148 | * std::ratio<7,-21>::den == 3; | |
149 | * @endcode | |
150 | * | |
151 | */ | |
4acedca1 CF |
152 | template<intmax_t _Num, intmax_t _Den = 1> |
153 | struct ratio | |
154 | { | |
155 | static_assert(_Den != 0, "denominator cannot be zero"); | |
ea31932d PC |
156 | static_assert(_Num >= -__INTMAX_MAX__ && _Den >= -__INTMAX_MAX__, |
157 | "out of range"); | |
158 | ||
4acedca1 | 159 | // Note: sign(N) * abs(N) == N |
94a86be0 | 160 | static constexpr intmax_t num = |
4acedca1 CF |
161 | _Num * __static_sign<_Den>::value / __static_gcd<_Num, _Den>::value; |
162 | ||
94a86be0 | 163 | static constexpr intmax_t den = |
4acedca1 | 164 | __static_abs<_Den>::value / __static_gcd<_Num, _Den>::value; |
e1d4e035 PC |
165 | |
166 | typedef ratio<num, den> type; | |
4acedca1 CF |
167 | }; |
168 | ||
169 | template<intmax_t _Num, intmax_t _Den> | |
94a86be0 | 170 | constexpr intmax_t ratio<_Num, _Den>::num; |
4acedca1 CF |
171 | |
172 | template<intmax_t _Num, intmax_t _Den> | |
94a86be0 | 173 | constexpr intmax_t ratio<_Num, _Den>::den; |
4acedca1 | 174 | |
ad68e9fc | 175 | /// ratio_add |
4acedca1 CF |
176 | template<typename _R1, typename _R2> |
177 | struct ratio_add | |
178 | { | |
179 | private: | |
180 | static const intmax_t __gcd = | |
181 | __static_gcd<_R1::den, _R2::den>::value; | |
182 | ||
183 | public: | |
184 | typedef ratio< | |
185 | __safe_add< | |
186 | __safe_multiply<_R1::num, (_R2::den / __gcd)>::value, | |
187 | __safe_multiply<_R2::num, (_R1::den / __gcd)>::value>::value, | |
188 | __safe_multiply<_R1::den, (_R2::den / __gcd)>::value> type; | |
e1d4e035 | 189 | |
76d0be83 PC |
190 | static constexpr intmax_t num = type::num; |
191 | static constexpr intmax_t den = type::den; | |
4acedca1 CF |
192 | }; |
193 | ||
e1d4e035 | 194 | template<typename _R1, typename _R2> |
76d0be83 | 195 | constexpr intmax_t ratio_add<_R1, _R2>::num; |
e1d4e035 PC |
196 | |
197 | template<typename _R1, typename _R2> | |
76d0be83 | 198 | constexpr intmax_t ratio_add<_R1, _R2>::den; |
e1d4e035 | 199 | |
ad68e9fc | 200 | /// ratio_subtract |
4acedca1 CF |
201 | template<typename _R1, typename _R2> |
202 | struct ratio_subtract | |
203 | { | |
204 | typedef typename ratio_add< | |
205 | _R1, | |
206 | ratio<-_R2::num, _R2::den>>::type type; | |
e1d4e035 | 207 | |
76d0be83 PC |
208 | static constexpr intmax_t num = type::num; |
209 | static constexpr intmax_t den = type::den; | |
4acedca1 CF |
210 | }; |
211 | ||
e1d4e035 | 212 | template<typename _R1, typename _R2> |
76d0be83 | 213 | constexpr intmax_t ratio_subtract<_R1, _R2>::num; |
e1d4e035 PC |
214 | |
215 | template<typename _R1, typename _R2> | |
76d0be83 | 216 | constexpr intmax_t ratio_subtract<_R1, _R2>::den; |
e1d4e035 | 217 | |
ad68e9fc | 218 | /// ratio_multiply |
4acedca1 CF |
219 | template<typename _R1, typename _R2> |
220 | struct ratio_multiply | |
221 | { | |
222 | private: | |
223 | static const intmax_t __gcd1 = | |
224 | __static_gcd<_R1::num, _R2::den>::value; | |
225 | static const intmax_t __gcd2 = | |
226 | __static_gcd<_R2::num, _R1::den>::value; | |
227 | ||
228 | public: | |
229 | typedef ratio< | |
230 | __safe_multiply<(_R1::num / __gcd1), | |
231 | (_R2::num / __gcd2)>::value, | |
232 | __safe_multiply<(_R1::den / __gcd2), | |
233 | (_R2::den / __gcd1)>::value> type; | |
e1d4e035 | 234 | |
76d0be83 PC |
235 | static constexpr intmax_t num = type::num; |
236 | static constexpr intmax_t den = type::den; | |
4acedca1 CF |
237 | }; |
238 | ||
e1d4e035 | 239 | template<typename _R1, typename _R2> |
76d0be83 | 240 | constexpr intmax_t ratio_multiply<_R1, _R2>::num; |
e1d4e035 PC |
241 | |
242 | template<typename _R1, typename _R2> | |
76d0be83 | 243 | constexpr intmax_t ratio_multiply<_R1, _R2>::den; |
e1d4e035 | 244 | |
ad68e9fc | 245 | /// ratio_divide |
4acedca1 CF |
246 | template<typename _R1, typename _R2> |
247 | struct ratio_divide | |
248 | { | |
249 | static_assert(_R2::num != 0, "division by 0"); | |
250 | ||
251 | typedef typename ratio_multiply< | |
252 | _R1, | |
253 | ratio<_R2::den, _R2::num>>::type type; | |
e1d4e035 | 254 | |
76d0be83 PC |
255 | static constexpr intmax_t num = type::num; |
256 | static constexpr intmax_t den = type::den; | |
4acedca1 CF |
257 | }; |
258 | ||
e1d4e035 | 259 | template<typename _R1, typename _R2> |
76d0be83 | 260 | constexpr intmax_t ratio_divide<_R1, _R2>::num; |
e1d4e035 PC |
261 | |
262 | template<typename _R1, typename _R2> | |
76d0be83 | 263 | constexpr intmax_t ratio_divide<_R1, _R2>::den; |
e1d4e035 | 264 | |
ad68e9fc | 265 | /// ratio_equal |
4acedca1 CF |
266 | template<typename _R1, typename _R2> |
267 | struct ratio_equal | |
268 | : integral_constant<bool, _R1::num == _R2::num && _R1::den == _R2::den> | |
269 | { }; | |
270 | ||
ad68e9fc | 271 | /// ratio_not_equal |
4acedca1 CF |
272 | template<typename _R1, typename _R2> |
273 | struct ratio_not_equal | |
274 | : integral_constant<bool, !ratio_equal<_R1, _R2>::value> | |
275 | { }; | |
cd6b4a4b PC |
276 | |
277 | template<typename _R1> | |
278 | struct __ratio_less_impl_1 | |
279 | : integral_constant<bool, _R1::num < _R1::den> | |
280 | { }; | |
281 | ||
282 | template<typename _R1, typename _R2, | |
283 | bool = (_R1::num == 0 || _R2::num == 0 | |
284 | || (__static_sign<_R1::num>::value | |
285 | != __static_sign<_R2::num>::value)), | |
286 | bool = (__static_sign<_R1::num>::value == -1 | |
287 | && __static_sign<_R2::num>::value == -1)> | |
288 | struct __ratio_less_impl | |
289 | : __ratio_less_impl_1<typename ratio_divide<_R1, _R2>::type>::type | |
290 | { }; | |
291 | ||
4acedca1 | 292 | template<typename _R1, typename _R2> |
cd6b4a4b PC |
293 | struct __ratio_less_impl<_R1, _R2, true, false> |
294 | : integral_constant<bool, _R1::num < _R2::num> | |
ea31932d PC |
295 | { }; |
296 | ||
ea31932d | 297 | template<typename _R1, typename _R2> |
cd6b4a4b PC |
298 | struct __ratio_less_impl<_R1, _R2, false, true> |
299 | : __ratio_less_impl_1<typename ratio_divide<_R2, _R1>::type>::type | |
ea31932d PC |
300 | { }; |
301 | ||
ad68e9fc | 302 | /// ratio_less |
ea31932d PC |
303 | template<typename _R1, typename _R2> |
304 | struct ratio_less | |
305 | : __ratio_less_impl<_R1, _R2>::type | |
4acedca1 CF |
306 | { }; |
307 | ||
ad68e9fc | 308 | /// ratio_less_equal |
4acedca1 CF |
309 | template<typename _R1, typename _R2> |
310 | struct ratio_less_equal | |
311 | : integral_constant<bool, !ratio_less<_R2, _R1>::value> | |
312 | { }; | |
313 | ||
ad68e9fc | 314 | /// ratio_greater |
4acedca1 CF |
315 | template<typename _R1, typename _R2> |
316 | struct ratio_greater | |
317 | : integral_constant<bool, ratio_less<_R2, _R1>::value> | |
318 | { }; | |
319 | ||
ad68e9fc | 320 | /// ratio_greater_equal |
4acedca1 CF |
321 | template<typename _R1, typename _R2> |
322 | struct ratio_greater_equal | |
323 | : integral_constant<bool, !ratio_less<_R1, _R2>::value> | |
324 | { }; | |
325 | ||
326 | typedef ratio<1, 1000000000000000000> atto; | |
327 | typedef ratio<1, 1000000000000000> femto; | |
328 | typedef ratio<1, 1000000000000> pico; | |
329 | typedef ratio<1, 1000000000> nano; | |
330 | typedef ratio<1, 1000000> micro; | |
331 | typedef ratio<1, 1000> milli; | |
332 | typedef ratio<1, 100> centi; | |
333 | typedef ratio<1, 10> deci; | |
334 | typedef ratio< 10, 1> deca; | |
335 | typedef ratio< 100, 1> hecto; | |
336 | typedef ratio< 1000, 1> kilo; | |
337 | typedef ratio< 1000000, 1> mega; | |
338 | typedef ratio< 1000000000, 1> giga; | |
339 | typedef ratio< 1000000000000, 1> tera; | |
340 | typedef ratio< 1000000000000000, 1> peta; | |
341 | typedef ratio< 1000000000000000000, 1> exa; | |
5b9daa7e BK |
342 | |
343 | // @} group ratio | |
12ffa228 BK |
344 | _GLIBCXX_END_NAMESPACE_VERSION |
345 | } // namespace | |
4acedca1 CF |
346 | |
347 | #endif //_GLIBCXX_USE_C99_STDINT_TR1 | |
348 | ||
349 | #endif //__GXX_EXPERIMENTAL_CXX0X__ | |
350 | ||
351 | #endif //_GLIBCXX_RATIO |