]>
Commit | Line | Data |
---|---|---|
5b9daa7e | 1 | // ratio -*- C++ -*- |
4acedca1 | 2 | |
a945c346 | 3 | // Copyright (C) 2008-2024 Free Software Foundation, Inc. |
4acedca1 CF |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free | |
33ac58d5 JW |
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 | |
33ac58d5 | 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4acedca1 CF |
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 | 26 | * This is a Standard C++ Library header. |
c34d3fd3 | 27 | * @ingroup ratio |
4acedca1 CF |
28 | */ |
29 | ||
30 | #ifndef _GLIBCXX_RATIO | |
31 | #define _GLIBCXX_RATIO 1 | |
32 | ||
33 | #pragma GCC system_header | |
34 | ||
734f5023 | 35 | #if __cplusplus < 201103L |
ab65a4c7 | 36 | # include <bits/c++0x_warning.h> |
4acedca1 CF |
37 | #else |
38 | ||
39 | #include <type_traits> | |
8ba7f29e | 40 | #include <cstdint> // intmax_t, uintmax_t |
4acedca1 | 41 | |
c47430bb JW |
42 | #define __glibcxx_want_ratio |
43 | #include <bits/version.h> | |
44 | ||
12ffa228 BK |
45 | namespace std _GLIBCXX_VISIBILITY(default) |
46 | { | |
47 | _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
53dc5044 | 48 | |
5b9daa7e BK |
49 | /** |
50 | * @defgroup ratio Rational Arithmetic | |
51 | * @ingroup utilities | |
52 | * | |
79e2c7b0 | 53 | * Compile time representation of finite rational numbers. |
5b9daa7e BK |
54 | * @{ |
55 | */ | |
56 | ||
c34d3fd3 JW |
57 | /// @cond undocumented |
58 | ||
4acedca1 CF |
59 | template<intmax_t _Pn> |
60 | struct __static_sign | |
61 | : integral_constant<intmax_t, (_Pn < 0) ? -1 : 1> | |
62 | { }; | |
63 | ||
64 | template<intmax_t _Pn> | |
65 | struct __static_abs | |
66 | : integral_constant<intmax_t, _Pn * __static_sign<_Pn>::value> | |
67 | { }; | |
68 | ||
4acedca1 CF |
69 | template<intmax_t _Pn, intmax_t _Qn> |
70 | struct __static_gcd | |
71 | : __static_gcd<_Qn, (_Pn % _Qn)> | |
72 | { }; | |
73 | ||
74 | template<intmax_t _Pn> | |
75 | struct __static_gcd<_Pn, 0> | |
76 | : integral_constant<intmax_t, __static_abs<_Pn>::value> | |
77 | { }; | |
78 | ||
79 | template<intmax_t _Qn> | |
80 | struct __static_gcd<0, _Qn> | |
81 | : integral_constant<intmax_t, __static_abs<_Qn>::value> | |
82 | { }; | |
83 | ||
84 | // Let c = 2^(half # of bits in an intmax_t) | |
85 | // then we find a1, a0, b1, b0 s.t. N = a1*c + a0, M = b1*c + b0 | |
86 | // The multiplication of N and M becomes, | |
87 | // N * M = (a1 * b1)c^2 + (a0 * b1 + b0 * a1)c + a0 * b0 | |
88 | // Multiplication is safe if each term and the sum of the terms | |
89 | // is representable by intmax_t. | |
90 | template<intmax_t _Pn, intmax_t _Qn> | |
91 | struct __safe_multiply | |
92 | { | |
93 | private: | |
94 | static const uintmax_t __c = uintmax_t(1) << (sizeof(intmax_t) * 4); | |
95 | ||
96 | static const uintmax_t __a0 = __static_abs<_Pn>::value % __c; | |
97 | static const uintmax_t __a1 = __static_abs<_Pn>::value / __c; | |
98 | static const uintmax_t __b0 = __static_abs<_Qn>::value % __c; | |
99 | static const uintmax_t __b1 = __static_abs<_Qn>::value / __c; | |
100 | ||
33ac58d5 | 101 | static_assert(__a1 == 0 || __b1 == 0, |
91e4938b | 102 | "overflow in multiplication"); |
33ac58d5 | 103 | static_assert(__a0 * __b1 + __b0 * __a1 < (__c >> 1), |
91e4938b | 104 | "overflow in multiplication"); |
33ac58d5 | 105 | static_assert(__b0 * __a0 <= __INTMAX_MAX__, |
91e4938b MG |
106 | "overflow in multiplication"); |
107 | static_assert((__a0 * __b1 + __b0 * __a1) * __c | |
108 | <= __INTMAX_MAX__ - __b0 * __a0, | |
109 | "overflow in multiplication"); | |
4acedca1 CF |
110 | |
111 | public: | |
112 | static const intmax_t value = _Pn * _Qn; | |
113 | }; | |
114 | ||
91e4938b MG |
115 | // Some double-precision utilities, where numbers are represented as |
116 | // __hi*2^(8*sizeof(uintmax_t)) + __lo. | |
117 | template<uintmax_t __hi1, uintmax_t __lo1, uintmax_t __hi2, uintmax_t __lo2> | |
118 | struct __big_less | |
119 | : integral_constant<bool, (__hi1 < __hi2 | |
120 | || (__hi1 == __hi2 && __lo1 < __lo2))> | |
4acedca1 CF |
121 | { }; |
122 | ||
91e4938b MG |
123 | template<uintmax_t __hi1, uintmax_t __lo1, uintmax_t __hi2, uintmax_t __lo2> |
124 | struct __big_add | |
125 | { | |
126 | static constexpr uintmax_t __lo = __lo1 + __lo2; | |
127 | static constexpr uintmax_t __hi = (__hi1 + __hi2 + | |
128 | (__lo1 + __lo2 < __lo1)); // carry | |
129 | }; | |
4acedca1 | 130 | |
91e4938b MG |
131 | // Subtract a number from a bigger one. |
132 | template<uintmax_t __hi1, uintmax_t __lo1, uintmax_t __hi2, uintmax_t __lo2> | |
133 | struct __big_sub | |
134 | { | |
135 | static_assert(!__big_less<__hi1, __lo1, __hi2, __lo2>::value, | |
136 | "Internal library error"); | |
137 | static constexpr uintmax_t __lo = __lo1 - __lo2; | |
138 | static constexpr uintmax_t __hi = (__hi1 - __hi2 - | |
139 | (__lo1 < __lo2)); // carry | |
140 | }; | |
4acedca1 | 141 | |
91e4938b MG |
142 | // Same principle as __safe_multiply. |
143 | template<uintmax_t __x, uintmax_t __y> | |
144 | struct __big_mul | |
145 | { | |
146 | private: | |
147 | static constexpr uintmax_t __c = uintmax_t(1) << (sizeof(intmax_t) * 4); | |
148 | static constexpr uintmax_t __x0 = __x % __c; | |
149 | static constexpr uintmax_t __x1 = __x / __c; | |
150 | static constexpr uintmax_t __y0 = __y % __c; | |
151 | static constexpr uintmax_t __y1 = __y / __c; | |
152 | static constexpr uintmax_t __x0y0 = __x0 * __y0; | |
153 | static constexpr uintmax_t __x0y1 = __x0 * __y1; | |
154 | static constexpr uintmax_t __x1y0 = __x1 * __y0; | |
155 | static constexpr uintmax_t __x1y1 = __x1 * __y1; | |
156 | static constexpr uintmax_t __mix = __x0y1 + __x1y0; // possible carry... | |
157 | static constexpr uintmax_t __mix_lo = __mix * __c; | |
158 | static constexpr uintmax_t __mix_hi | |
159 | = __mix / __c + ((__mix < __x0y1) ? __c : 0); // ... added here | |
160 | typedef __big_add<__mix_hi, __mix_lo, __x1y1, __x0y0> _Res; | |
161 | public: | |
162 | static constexpr uintmax_t __hi = _Res::__hi; | |
163 | static constexpr uintmax_t __lo = _Res::__lo; | |
164 | }; | |
165 | ||
166 | // Adapted from __udiv_qrnnd_c in longlong.h | |
167 | // This version assumes that the high bit of __d is 1. | |
168 | template<uintmax_t __n1, uintmax_t __n0, uintmax_t __d> | |
169 | struct __big_div_impl | |
170 | { | |
171 | private: | |
172 | static_assert(__d >= (uintmax_t(1) << (sizeof(intmax_t) * 8 - 1)), | |
173 | "Internal library error"); | |
174 | static_assert(__n1 < __d, "Internal library error"); | |
175 | static constexpr uintmax_t __c = uintmax_t(1) << (sizeof(intmax_t) * 4); | |
176 | static constexpr uintmax_t __d1 = __d / __c; | |
177 | static constexpr uintmax_t __d0 = __d % __c; | |
178 | ||
179 | static constexpr uintmax_t __q1x = __n1 / __d1; | |
180 | static constexpr uintmax_t __r1x = __n1 % __d1; | |
181 | static constexpr uintmax_t __m = __q1x * __d0; | |
182 | static constexpr uintmax_t __r1y = __r1x * __c + __n0 / __c; | |
183 | static constexpr uintmax_t __r1z = __r1y + __d; | |
184 | static constexpr uintmax_t __r1 | |
185 | = ((__r1y < __m) ? ((__r1z >= __d) && (__r1z < __m)) | |
186 | ? (__r1z + __d) : __r1z : __r1y) - __m; | |
187 | static constexpr uintmax_t __q1 | |
188 | = __q1x - ((__r1y < __m) | |
189 | ? ((__r1z >= __d) && (__r1z < __m)) ? 2 : 1 : 0); | |
190 | static constexpr uintmax_t __q0x = __r1 / __d1; | |
191 | static constexpr uintmax_t __r0x = __r1 % __d1; | |
192 | static constexpr uintmax_t __n = __q0x * __d0; | |
193 | static constexpr uintmax_t __r0y = __r0x * __c + __n0 % __c; | |
194 | static constexpr uintmax_t __r0z = __r0y + __d; | |
195 | static constexpr uintmax_t __r0 | |
196 | = ((__r0y < __n) ? ((__r0z >= __d) && (__r0z < __n)) | |
197 | ? (__r0z + __d) : __r0z : __r0y) - __n; | |
198 | static constexpr uintmax_t __q0 | |
199 | = __q0x - ((__r0y < __n) ? ((__r0z >= __d) | |
200 | && (__r0z < __n)) ? 2 : 1 : 0); | |
201 | ||
202 | public: | |
203 | static constexpr uintmax_t __quot = __q1 * __c + __q0; | |
204 | static constexpr uintmax_t __rem = __r0; | |
205 | ||
206 | private: | |
207 | typedef __big_mul<__quot, __d> _Prod; | |
208 | typedef __big_add<_Prod::__hi, _Prod::__lo, 0, __rem> _Sum; | |
209 | static_assert(_Sum::__hi == __n1 && _Sum::__lo == __n0, | |
210 | "Internal library error"); | |
211 | }; | |
212 | ||
213 | template<uintmax_t __n1, uintmax_t __n0, uintmax_t __d> | |
214 | struct __big_div | |
4acedca1 | 215 | { |
91e4938b MG |
216 | private: |
217 | static_assert(__d != 0, "Internal library error"); | |
218 | static_assert(sizeof (uintmax_t) == sizeof (unsigned long long), | |
219 | "This library calls __builtin_clzll on uintmax_t, which " | |
220 | "is unsafe on your platform. Please complain to " | |
221 | "http://gcc.gnu.org/bugzilla/"); | |
222 | static constexpr int __shift = __builtin_clzll(__d); | |
223 | static constexpr int __coshift_ = sizeof(uintmax_t) * 8 - __shift; | |
224 | static constexpr int __coshift = (__shift != 0) ? __coshift_ : 0; | |
225 | static constexpr uintmax_t __c1 = uintmax_t(1) << __shift; | |
226 | static constexpr uintmax_t __c2 = uintmax_t(1) << __coshift; | |
227 | static constexpr uintmax_t __new_d = __d * __c1; | |
228 | static constexpr uintmax_t __new_n0 = __n0 * __c1; | |
229 | static constexpr uintmax_t __n1_shifted = (__n1 % __d) * __c1; | |
230 | static constexpr uintmax_t __n0_top = (__shift != 0) ? (__n0 / __c2) : 0; | |
231 | static constexpr uintmax_t __new_n1 = __n1_shifted + __n0_top; | |
232 | typedef __big_div_impl<__new_n1, __new_n0, __new_d> _Res; | |
233 | ||
234 | public: | |
235 | static constexpr uintmax_t __quot_hi = __n1 / __d; | |
236 | static constexpr uintmax_t __quot_lo = _Res::__quot; | |
237 | static constexpr uintmax_t __rem = _Res::__rem / __c1; | |
4acedca1 | 238 | |
91e4938b MG |
239 | private: |
240 | typedef __big_mul<__quot_lo, __d> _P0; | |
241 | typedef __big_mul<__quot_hi, __d> _P1; | |
242 | typedef __big_add<_P0::__hi, _P0::__lo, _P1::__lo, __rem> _Sum; | |
243 | // No overflow. | |
244 | static_assert(_P1::__hi == 0, "Internal library error"); | |
245 | static_assert(_Sum::__hi >= _P0::__hi, "Internal library error"); | |
246 | // Matches the input data. | |
247 | static_assert(_Sum::__hi == __n1 && _Sum::__lo == __n0, | |
248 | "Internal library error"); | |
249 | static_assert(__rem < __d, "Internal library error"); | |
4acedca1 CF |
250 | }; |
251 | ||
c34d3fd3 JW |
252 | /// @endcond |
253 | ||
ea31932d PC |
254 | /** |
255 | * @brief Provides compile-time rational arithmetic. | |
5b9daa7e | 256 | * |
ea31932d PC |
257 | * This class template represents any finite rational number with a |
258 | * numerator and denominator representable by compile-time constants of | |
259 | * type intmax_t. The ratio is simplified when instantiated. | |
260 | * | |
261 | * For example: | |
262 | * @code | |
263 | * std::ratio<7,-21>::num == -1; | |
264 | * std::ratio<7,-21>::den == 3; | |
265 | * @endcode | |
33ac58d5 | 266 | * |
ea31932d | 267 | */ |
4acedca1 CF |
268 | template<intmax_t _Num, intmax_t _Den = 1> |
269 | struct ratio | |
270 | { | |
271 | static_assert(_Den != 0, "denominator cannot be zero"); | |
ea31932d PC |
272 | static_assert(_Num >= -__INTMAX_MAX__ && _Den >= -__INTMAX_MAX__, |
273 | "out of range"); | |
274 | ||
4acedca1 | 275 | // Note: sign(N) * abs(N) == N |
94a86be0 | 276 | static constexpr intmax_t num = |
4acedca1 CF |
277 | _Num * __static_sign<_Den>::value / __static_gcd<_Num, _Den>::value; |
278 | ||
94a86be0 | 279 | static constexpr intmax_t den = |
4acedca1 | 280 | __static_abs<_Den>::value / __static_gcd<_Num, _Den>::value; |
e1d4e035 PC |
281 | |
282 | typedef ratio<num, den> type; | |
4acedca1 CF |
283 | }; |
284 | ||
a77a46d9 | 285 | #if ! __cpp_inline_variables |
4acedca1 | 286 | template<intmax_t _Num, intmax_t _Den> |
94a86be0 | 287 | constexpr intmax_t ratio<_Num, _Den>::num; |
4acedca1 CF |
288 | |
289 | template<intmax_t _Num, intmax_t _Den> | |
94a86be0 | 290 | constexpr intmax_t ratio<_Num, _Den>::den; |
a77a46d9 | 291 | #endif |
4acedca1 | 292 | |
c34d3fd3 JW |
293 | /// @cond undocumented |
294 | ||
2d614822 JW |
295 | template<typename _Tp> |
296 | struct __is_ratio | |
297 | : std::false_type | |
298 | { }; | |
299 | ||
300 | template<intmax_t _Num, intmax_t _Den> | |
301 | struct __is_ratio<ratio<_Num, _Den>> | |
302 | : std::true_type | |
303 | { }; | |
304 | ||
305 | #if __cpp_variable_templates | |
306 | template<typename _Tp> | |
307 | constexpr bool __is_ratio_v = false; | |
308 | template<intmax_t _Num, intmax_t _Den> | |
309 | constexpr bool __is_ratio_v<ratio<_Num, _Den>> = true; | |
310 | #endif | |
311 | ||
312 | template<typename _R1, typename _R2> | |
313 | constexpr bool | |
314 | __are_both_ratios() noexcept | |
315 | { | |
316 | #if __cpp_variable_templates && __cpp_if_constexpr | |
317 | if constexpr (__is_ratio_v<_R1>) | |
318 | if constexpr (__is_ratio_v<_R2>) | |
319 | return true; | |
320 | return false; | |
321 | #else | |
322 | return __and_<__is_ratio<_R1>, __is_ratio<_R2>>::value; | |
323 | #endif | |
324 | } | |
325 | ||
4acedca1 | 326 | template<typename _R1, typename _R2> |
c128d203 | 327 | struct __ratio_multiply |
4acedca1 | 328 | { |
2d614822 JW |
329 | static_assert(std::__are_both_ratios<_R1, _R2>(), |
330 | "both template arguments must be a std::ratio"); | |
331 | ||
4acedca1 CF |
332 | private: |
333 | static const intmax_t __gcd1 = | |
334 | __static_gcd<_R1::num, _R2::den>::value; | |
335 | static const intmax_t __gcd2 = | |
336 | __static_gcd<_R2::num, _R1::den>::value; | |
337 | ||
338 | public: | |
339 | typedef ratio< | |
340 | __safe_multiply<(_R1::num / __gcd1), | |
341 | (_R2::num / __gcd2)>::value, | |
342 | __safe_multiply<(_R1::den / __gcd2), | |
343 | (_R2::den / __gcd1)>::value> type; | |
e1d4e035 | 344 | |
76d0be83 PC |
345 | static constexpr intmax_t num = type::num; |
346 | static constexpr intmax_t den = type::den; | |
4acedca1 CF |
347 | }; |
348 | ||
a77a46d9 | 349 | #if ! __cpp_inline_variables |
e1d4e035 | 350 | template<typename _R1, typename _R2> |
c128d203 | 351 | constexpr intmax_t __ratio_multiply<_R1, _R2>::num; |
e1d4e035 PC |
352 | |
353 | template<typename _R1, typename _R2> | |
c128d203 | 354 | constexpr intmax_t __ratio_multiply<_R1, _R2>::den; |
a77a46d9 | 355 | #endif |
c128d203 | 356 | |
c34d3fd3 JW |
357 | /// @endcond |
358 | ||
c128d203 PC |
359 | /// ratio_multiply |
360 | template<typename _R1, typename _R2> | |
361 | using ratio_multiply = typename __ratio_multiply<_R1, _R2>::type; | |
e1d4e035 | 362 | |
c34d3fd3 JW |
363 | /// @cond undocumented |
364 | ||
4acedca1 | 365 | template<typename _R1, typename _R2> |
c128d203 | 366 | struct __ratio_divide |
4acedca1 CF |
367 | { |
368 | static_assert(_R2::num != 0, "division by 0"); | |
369 | ||
c128d203 | 370 | typedef typename __ratio_multiply< |
4acedca1 CF |
371 | _R1, |
372 | ratio<_R2::den, _R2::num>>::type type; | |
e1d4e035 | 373 | |
76d0be83 PC |
374 | static constexpr intmax_t num = type::num; |
375 | static constexpr intmax_t den = type::den; | |
4acedca1 CF |
376 | }; |
377 | ||
a77a46d9 | 378 | #if ! __cpp_inline_variables |
e1d4e035 | 379 | template<typename _R1, typename _R2> |
c128d203 PC |
380 | constexpr intmax_t __ratio_divide<_R1, _R2>::num; |
381 | ||
382 | template<typename _R1, typename _R2> | |
383 | constexpr intmax_t __ratio_divide<_R1, _R2>::den; | |
a77a46d9 | 384 | #endif |
e1d4e035 | 385 | |
c34d3fd3 JW |
386 | /// @endcond |
387 | ||
c128d203 | 388 | /// ratio_divide |
e1d4e035 | 389 | template<typename _R1, typename _R2> |
c128d203 | 390 | using ratio_divide = typename __ratio_divide<_R1, _R2>::type; |
e1d4e035 | 391 | |
ad68e9fc | 392 | /// ratio_equal |
4acedca1 CF |
393 | template<typename _R1, typename _R2> |
394 | struct ratio_equal | |
395 | : integral_constant<bool, _R1::num == _R2::num && _R1::den == _R2::den> | |
2d614822 JW |
396 | { |
397 | static_assert(std::__are_both_ratios<_R1, _R2>(), | |
398 | "both template arguments must be a std::ratio"); | |
399 | }; | |
33ac58d5 | 400 | |
ad68e9fc | 401 | /// ratio_not_equal |
4acedca1 CF |
402 | template<typename _R1, typename _R2> |
403 | struct ratio_not_equal | |
404 | : integral_constant<bool, !ratio_equal<_R1, _R2>::value> | |
405 | { }; | |
cd6b4a4b | 406 | |
c34d3fd3 JW |
407 | /// @cond undocumented |
408 | ||
91e4938b MG |
409 | // Both numbers are positive. |
410 | template<typename _R1, typename _R2, | |
411 | typename _Left = __big_mul<_R1::num,_R2::den>, | |
412 | typename _Right = __big_mul<_R2::num,_R1::den> > | |
cd6b4a4b | 413 | struct __ratio_less_impl_1 |
91e4938b MG |
414 | : integral_constant<bool, __big_less<_Left::__hi, _Left::__lo, |
415 | _Right::__hi, _Right::__lo>::value> | |
33ac58d5 | 416 | { }; |
cd6b4a4b PC |
417 | |
418 | template<typename _R1, typename _R2, | |
419 | bool = (_R1::num == 0 || _R2::num == 0 | |
420 | || (__static_sign<_R1::num>::value | |
421 | != __static_sign<_R2::num>::value)), | |
422 | bool = (__static_sign<_R1::num>::value == -1 | |
423 | && __static_sign<_R2::num>::value == -1)> | |
424 | struct __ratio_less_impl | |
d154f927 | 425 | : __ratio_less_impl_1<_R1, _R2>::type |
cd6b4a4b PC |
426 | { }; |
427 | ||
4acedca1 | 428 | template<typename _R1, typename _R2> |
cd6b4a4b PC |
429 | struct __ratio_less_impl<_R1, _R2, true, false> |
430 | : integral_constant<bool, _R1::num < _R2::num> | |
ea31932d PC |
431 | { }; |
432 | ||
ea31932d | 433 | template<typename _R1, typename _R2> |
cd6b4a4b | 434 | struct __ratio_less_impl<_R1, _R2, false, true> |
d154f927 PC |
435 | : __ratio_less_impl_1<ratio<-_R2::num, _R2::den>, |
436 | ratio<-_R1::num, _R1::den> >::type | |
ea31932d PC |
437 | { }; |
438 | ||
c34d3fd3 JW |
439 | /// @endcond |
440 | ||
ad68e9fc | 441 | /// ratio_less |
ea31932d PC |
442 | template<typename _R1, typename _R2> |
443 | struct ratio_less | |
444 | : __ratio_less_impl<_R1, _R2>::type | |
2d614822 JW |
445 | { |
446 | static_assert(std::__are_both_ratios<_R1, _R2>(), | |
447 | "both template arguments must be a std::ratio"); | |
448 | }; | |
33ac58d5 | 449 | |
ad68e9fc | 450 | /// ratio_less_equal |
4acedca1 CF |
451 | template<typename _R1, typename _R2> |
452 | struct ratio_less_equal | |
453 | : integral_constant<bool, !ratio_less<_R2, _R1>::value> | |
454 | { }; | |
33ac58d5 | 455 | |
ad68e9fc | 456 | /// ratio_greater |
4acedca1 CF |
457 | template<typename _R1, typename _R2> |
458 | struct ratio_greater | |
459 | : integral_constant<bool, ratio_less<_R2, _R1>::value> | |
460 | { }; | |
461 | ||
ad68e9fc | 462 | /// ratio_greater_equal |
4acedca1 CF |
463 | template<typename _R1, typename _R2> |
464 | struct ratio_greater_equal | |
465 | : integral_constant<bool, !ratio_less<_R1, _R2>::value> | |
466 | { }; | |
467 | ||
137422c8 VV |
468 | #if __cplusplus > 201402L |
469 | template <typename _R1, typename _R2> | |
288695f7 | 470 | inline constexpr bool ratio_equal_v = ratio_equal<_R1, _R2>::value; |
137422c8 | 471 | template <typename _R1, typename _R2> |
288695f7 | 472 | inline constexpr bool ratio_not_equal_v = ratio_not_equal<_R1, _R2>::value; |
137422c8 | 473 | template <typename _R1, typename _R2> |
288695f7 | 474 | inline constexpr bool ratio_less_v = ratio_less<_R1, _R2>::value; |
137422c8 | 475 | template <typename _R1, typename _R2> |
2d614822 JW |
476 | inline constexpr bool ratio_less_equal_v |
477 | = ratio_less_equal<_R1, _R2>::value; | |
137422c8 | 478 | template <typename _R1, typename _R2> |
288695f7 | 479 | inline constexpr bool ratio_greater_v = ratio_greater<_R1, _R2>::value; |
137422c8 | 480 | template <typename _R1, typename _R2> |
288695f7 | 481 | inline constexpr bool ratio_greater_equal_v |
2d614822 | 482 | = ratio_greater_equal<_R1, _R2>::value; |
137422c8 VV |
483 | #endif // C++17 |
484 | ||
c34d3fd3 JW |
485 | /// @cond undocumented |
486 | ||
91e4938b MG |
487 | template<typename _R1, typename _R2, |
488 | bool = (_R1::num >= 0), | |
489 | bool = (_R2::num >= 0), | |
490 | bool = ratio_less<ratio<__static_abs<_R1::num>::value, _R1::den>, | |
491 | ratio<__static_abs<_R2::num>::value, _R2::den> >::value> | |
492 | struct __ratio_add_impl | |
493 | { | |
494 | private: | |
495 | typedef typename __ratio_add_impl< | |
496 | ratio<-_R1::num, _R1::den>, | |
497 | ratio<-_R2::num, _R2::den> >::type __t; | |
498 | public: | |
499 | typedef ratio<-__t::num, __t::den> type; | |
500 | }; | |
501 | ||
502 | // True addition of nonnegative numbers. | |
503 | template<typename _R1, typename _R2, bool __b> | |
504 | struct __ratio_add_impl<_R1, _R2, true, true, __b> | |
505 | { | |
506 | private: | |
507 | static constexpr uintmax_t __g = __static_gcd<_R1::den, _R2::den>::value; | |
508 | static constexpr uintmax_t __d2 = _R2::den / __g; | |
509 | typedef __big_mul<_R1::den, __d2> __d; | |
510 | typedef __big_mul<_R1::num, _R2::den / __g> __x; | |
511 | typedef __big_mul<_R2::num, _R1::den / __g> __y; | |
512 | typedef __big_add<__x::__hi, __x::__lo, __y::__hi, __y::__lo> __n; | |
513 | static_assert(__n::__hi >= __x::__hi, "Internal library error"); | |
514 | typedef __big_div<__n::__hi, __n::__lo, __g> __ng; | |
515 | static constexpr uintmax_t __g2 = __static_gcd<__ng::__rem, __g>::value; | |
516 | typedef __big_div<__n::__hi, __n::__lo, __g2> __n_final; | |
517 | static_assert(__n_final::__rem == 0, "Internal library error"); | |
518 | static_assert(__n_final::__quot_hi == 0 && | |
519 | __n_final::__quot_lo <= __INTMAX_MAX__, "overflow in addition"); | |
520 | typedef __big_mul<_R1::den / __g2, __d2> __d_final; | |
521 | static_assert(__d_final::__hi == 0 && | |
522 | __d_final::__lo <= __INTMAX_MAX__, "overflow in addition"); | |
523 | public: | |
524 | typedef ratio<__n_final::__quot_lo, __d_final::__lo> type; | |
525 | }; | |
526 | ||
527 | template<typename _R1, typename _R2> | |
528 | struct __ratio_add_impl<_R1, _R2, false, true, true> | |
529 | : __ratio_add_impl<_R2, _R1> | |
530 | { }; | |
531 | ||
532 | // True subtraction of nonnegative numbers yielding a nonnegative result. | |
533 | template<typename _R1, typename _R2> | |
534 | struct __ratio_add_impl<_R1, _R2, true, false, false> | |
535 | { | |
536 | private: | |
537 | static constexpr uintmax_t __g = __static_gcd<_R1::den, _R2::den>::value; | |
538 | static constexpr uintmax_t __d2 = _R2::den / __g; | |
539 | typedef __big_mul<_R1::den, __d2> __d; | |
540 | typedef __big_mul<_R1::num, _R2::den / __g> __x; | |
541 | typedef __big_mul<-_R2::num, _R1::den / __g> __y; | |
542 | typedef __big_sub<__x::__hi, __x::__lo, __y::__hi, __y::__lo> __n; | |
543 | typedef __big_div<__n::__hi, __n::__lo, __g> __ng; | |
544 | static constexpr uintmax_t __g2 = __static_gcd<__ng::__rem, __g>::value; | |
545 | typedef __big_div<__n::__hi, __n::__lo, __g2> __n_final; | |
546 | static_assert(__n_final::__rem == 0, "Internal library error"); | |
547 | static_assert(__n_final::__quot_hi == 0 && | |
548 | __n_final::__quot_lo <= __INTMAX_MAX__, "overflow in addition"); | |
549 | typedef __big_mul<_R1::den / __g2, __d2> __d_final; | |
550 | static_assert(__d_final::__hi == 0 && | |
551 | __d_final::__lo <= __INTMAX_MAX__, "overflow in addition"); | |
552 | public: | |
553 | typedef ratio<__n_final::__quot_lo, __d_final::__lo> type; | |
554 | }; | |
555 | ||
91e4938b | 556 | template<typename _R1, typename _R2> |
c128d203 | 557 | struct __ratio_add |
91e4938b | 558 | { |
2d614822 JW |
559 | static_assert(std::__are_both_ratios<_R1, _R2>(), |
560 | "both template arguments must be a std::ratio"); | |
561 | ||
91e4938b MG |
562 | typedef typename __ratio_add_impl<_R1, _R2>::type type; |
563 | static constexpr intmax_t num = type::num; | |
564 | static constexpr intmax_t den = type::den; | |
565 | }; | |
566 | ||
a77a46d9 | 567 | #if ! __cpp_inline_variables |
91e4938b | 568 | template<typename _R1, typename _R2> |
c128d203 | 569 | constexpr intmax_t __ratio_add<_R1, _R2>::num; |
91e4938b MG |
570 | |
571 | template<typename _R1, typename _R2> | |
c128d203 | 572 | constexpr intmax_t __ratio_add<_R1, _R2>::den; |
a77a46d9 | 573 | #endif |
91e4938b | 574 | |
c34d3fd3 JW |
575 | /// @endcond |
576 | ||
c128d203 | 577 | /// ratio_add |
91e4938b | 578 | template<typename _R1, typename _R2> |
c128d203 PC |
579 | using ratio_add = typename __ratio_add<_R1, _R2>::type; |
580 | ||
c34d3fd3 JW |
581 | /// @cond undocumented |
582 | ||
c128d203 PC |
583 | template<typename _R1, typename _R2> |
584 | struct __ratio_subtract | |
91e4938b | 585 | { |
c128d203 | 586 | typedef typename __ratio_add< |
91e4938b MG |
587 | _R1, |
588 | ratio<-_R2::num, _R2::den>>::type type; | |
589 | ||
590 | static constexpr intmax_t num = type::num; | |
591 | static constexpr intmax_t den = type::den; | |
592 | }; | |
593 | ||
a77a46d9 | 594 | #if ! __cpp_inline_variables |
91e4938b | 595 | template<typename _R1, typename _R2> |
c128d203 | 596 | constexpr intmax_t __ratio_subtract<_R1, _R2>::num; |
91e4938b MG |
597 | |
598 | template<typename _R1, typename _R2> | |
c128d203 | 599 | constexpr intmax_t __ratio_subtract<_R1, _R2>::den; |
a77a46d9 | 600 | #endif |
91e4938b | 601 | |
c34d3fd3 JW |
602 | /// @endcond |
603 | ||
c128d203 PC |
604 | /// ratio_subtract |
605 | template<typename _R1, typename _R2> | |
606 | using ratio_subtract = typename __ratio_subtract<_R1, _R2>::type; | |
91e4938b | 607 | |
c47430bb JW |
608 | #if __INTMAX_WIDTH__ >= 96 |
609 | # if __cpp_lib_ratio >= 202306L | |
610 | # if __INTMAX_WIDTH__ >= 128 | |
611 | using quecto = ratio< 1, 1000000000000000000000000000000>; | |
612 | # endif | |
613 | using ronto = ratio< 1, 1000000000000000000000000000>; | |
614 | # endif | |
615 | using yocto = ratio< 1, 1000000000000000000000000>; | |
616 | using zepto = ratio< 1, 1000000000000000000000>; | |
617 | #endif | |
618 | using atto = ratio< 1, 1000000000000000000>; | |
619 | using femto = ratio< 1, 1000000000000000>; | |
620 | using pico = ratio< 1, 1000000000000>; | |
621 | using nano = ratio< 1, 1000000000>; | |
622 | using micro = ratio< 1, 1000000>; | |
623 | using milli = ratio< 1, 1000>; | |
624 | using centi = ratio< 1, 100>; | |
625 | using deci = ratio< 1, 10>; | |
626 | using deca = ratio< 10, 1>; | |
627 | using hecto = ratio< 100, 1>; | |
628 | using kilo = ratio< 1000, 1>; | |
629 | using mega = ratio< 1000000, 1>; | |
630 | using giga = ratio< 1000000000, 1>; | |
631 | using tera = ratio< 1000000000000, 1>; | |
632 | using peta = ratio< 1000000000000000, 1>; | |
633 | using exa = ratio< 1000000000000000000, 1>; | |
634 | #if __INTMAX_WIDTH__ >= 96 | |
635 | using zetta = ratio< 1000000000000000000000, 1>; | |
636 | using yotta = ratio<1000000000000000000000000, 1>; | |
637 | # if __cpp_lib_ratio >= 202306L | |
638 | using ronna = ratio<1000000000000000000000000000, 1>; | |
639 | # if __INTMAX_WIDTH__ >= 128 | |
640 | using quetta = ratio<1000000000000000000000000000000, 1>; | |
641 | # endif | |
642 | # endif | |
643 | #endif | |
5b9daa7e | 644 | |
f0b88346 | 645 | /// @} group ratio |
12ffa228 BK |
646 | _GLIBCXX_END_NAMESPACE_VERSION |
647 | } // namespace | |
4acedca1 | 648 | |
734f5023 | 649 | #endif // C++11 |
4acedca1 CF |
650 | |
651 | #endif //_GLIBCXX_RATIO |