root / lab4 / .minix-src / include / c++ / ratio @ 13
History | View | Annotate | Download (14.4 KB)
1 | 13 | up20180614 | // -*- C++ -*- |
---|---|---|---|
2 | //===---------------------------- ratio -----------------------------------===// |
||
3 | // |
||
4 | // The LLVM Compiler Infrastructure |
||
5 | // |
||
6 | // This file is dual licensed under the MIT and the University of Illinois Open |
||
7 | // Source Licenses. See LICENSE.TXT for details. |
||
8 | // |
||
9 | //===----------------------------------------------------------------------===// |
||
10 | |||
11 | #ifndef _LIBCPP_RATIO |
||
12 | #define _LIBCPP_RATIO |
||
13 | |||
14 | /* |
||
15 | ratio synopsis |
||
16 | |||
17 | namespace std |
||
18 | { |
||
19 | |||
20 | template <intmax_t N, intmax_t D = 1> |
||
21 | class ratio |
||
22 | { |
||
23 | public: |
||
24 | static constexpr intmax_t num; |
||
25 | static constexpr intmax_t den; |
||
26 | typedef ratio<num, den> type; |
||
27 | }; |
||
28 | |||
29 | // ratio arithmetic |
||
30 | template <class R1, class R2> using ratio_add = ...; |
||
31 | template <class R1, class R2> using ratio_subtract = ...; |
||
32 | template <class R1, class R2> using ratio_multiply = ...; |
||
33 | template <class R1, class R2> using ratio_divide = ...; |
||
34 | |||
35 | // ratio comparison |
||
36 | template <class R1, class R2> struct ratio_equal; |
||
37 | template <class R1, class R2> struct ratio_not_equal; |
||
38 | template <class R1, class R2> struct ratio_less; |
||
39 | template <class R1, class R2> struct ratio_less_equal; |
||
40 | template <class R1, class R2> struct ratio_greater; |
||
41 | template <class R1, class R2> struct ratio_greater_equal; |
||
42 | |||
43 | // convenience SI typedefs |
||
44 | typedef ratio<1, 1000000000000000000000000> yocto; // not supported |
||
45 | typedef ratio<1, 1000000000000000000000> zepto; // not supported |
||
46 | typedef ratio<1, 1000000000000000000> atto; |
||
47 | typedef ratio<1, 1000000000000000> femto; |
||
48 | typedef ratio<1, 1000000000000> pico; |
||
49 | typedef ratio<1, 1000000000> nano; |
||
50 | typedef ratio<1, 1000000> micro; |
||
51 | typedef ratio<1, 1000> milli; |
||
52 | typedef ratio<1, 100> centi; |
||
53 | typedef ratio<1, 10> deci; |
||
54 | typedef ratio< 10, 1> deca; |
||
55 | typedef ratio< 100, 1> hecto; |
||
56 | typedef ratio< 1000, 1> kilo; |
||
57 | typedef ratio< 1000000, 1> mega; |
||
58 | typedef ratio< 1000000000, 1> giga; |
||
59 | typedef ratio< 1000000000000, 1> tera; |
||
60 | typedef ratio< 1000000000000000, 1> peta; |
||
61 | typedef ratio< 1000000000000000000, 1> exa; |
||
62 | typedef ratio< 1000000000000000000000, 1> zetta; // not supported |
||
63 | typedef ratio<1000000000000000000000000, 1> yotta; // not supported |
||
64 | |||
65 | } |
||
66 | */ |
||
67 | |||
68 | #include <__config> |
||
69 | #include <cstdint> |
||
70 | #include <climits> |
||
71 | #include <type_traits> |
||
72 | |||
73 | #include <__undef_min_max> |
||
74 | |||
75 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
||
76 | #pragma GCC system_header |
||
77 | #endif |
||
78 | |||
79 | _LIBCPP_BEGIN_NAMESPACE_STD |
||
80 | |||
81 | // __static_gcd |
||
82 | |||
83 | template <intmax_t _Xp, intmax_t _Yp> |
||
84 | struct __static_gcd |
||
85 | { |
||
86 | static const intmax_t value = __static_gcd<_Yp, _Xp % _Yp>::value; |
||
87 | }; |
||
88 | |||
89 | template <intmax_t _Xp> |
||
90 | struct __static_gcd<_Xp, 0> |
||
91 | { |
||
92 | static const intmax_t value = _Xp; |
||
93 | }; |
||
94 | |||
95 | template <> |
||
96 | struct __static_gcd<0, 0> |
||
97 | { |
||
98 | static const intmax_t value = 1; |
||
99 | }; |
||
100 | |||
101 | // __static_lcm |
||
102 | |||
103 | template <intmax_t _Xp, intmax_t _Yp> |
||
104 | struct __static_lcm |
||
105 | { |
||
106 | static const intmax_t value = _Xp / __static_gcd<_Xp, _Yp>::value * _Yp; |
||
107 | }; |
||
108 | |||
109 | template <intmax_t _Xp> |
||
110 | struct __static_abs |
||
111 | { |
||
112 | static const intmax_t value = _Xp < 0 ? -_Xp : _Xp; |
||
113 | }; |
||
114 | |||
115 | template <intmax_t _Xp> |
||
116 | struct __static_sign |
||
117 | { |
||
118 | static const intmax_t value = _Xp == 0 ? 0 : (_Xp < 0 ? -1 : 1); |
||
119 | }; |
||
120 | |||
121 | template <intmax_t _Xp, intmax_t _Yp, intmax_t = __static_sign<_Yp>::value> |
||
122 | class __ll_add; |
||
123 | |||
124 | template <intmax_t _Xp, intmax_t _Yp> |
||
125 | class __ll_add<_Xp, _Yp, 1> |
||
126 | { |
||
127 | static const intmax_t min = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1)) + 1; |
||
128 | static const intmax_t max = -min; |
||
129 | |||
130 | static_assert(_Xp <= max - _Yp, "overflow in __ll_add"); |
||
131 | public: |
||
132 | static const intmax_t value = _Xp + _Yp; |
||
133 | }; |
||
134 | |||
135 | template <intmax_t _Xp, intmax_t _Yp> |
||
136 | class __ll_add<_Xp, _Yp, 0> |
||
137 | { |
||
138 | public: |
||
139 | static const intmax_t value = _Xp; |
||
140 | }; |
||
141 | |||
142 | template <intmax_t _Xp, intmax_t _Yp> |
||
143 | class __ll_add<_Xp, _Yp, -1> |
||
144 | { |
||
145 | static const intmax_t min = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1)) + 1; |
||
146 | static const intmax_t max = -min; |
||
147 | |||
148 | static_assert(min - _Yp <= _Xp, "overflow in __ll_add"); |
||
149 | public: |
||
150 | static const intmax_t value = _Xp + _Yp; |
||
151 | }; |
||
152 | |||
153 | template <intmax_t _Xp, intmax_t _Yp, intmax_t = __static_sign<_Yp>::value> |
||
154 | class __ll_sub; |
||
155 | |||
156 | template <intmax_t _Xp, intmax_t _Yp> |
||
157 | class __ll_sub<_Xp, _Yp, 1> |
||
158 | { |
||
159 | static const intmax_t min = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1)) + 1; |
||
160 | static const intmax_t max = -min; |
||
161 | |||
162 | static_assert(min + _Yp <= _Xp, "overflow in __ll_sub"); |
||
163 | public: |
||
164 | static const intmax_t value = _Xp - _Yp; |
||
165 | }; |
||
166 | |||
167 | template <intmax_t _Xp, intmax_t _Yp> |
||
168 | class __ll_sub<_Xp, _Yp, 0> |
||
169 | { |
||
170 | public: |
||
171 | static const intmax_t value = _Xp; |
||
172 | }; |
||
173 | |||
174 | template <intmax_t _Xp, intmax_t _Yp> |
||
175 | class __ll_sub<_Xp, _Yp, -1> |
||
176 | { |
||
177 | static const intmax_t min = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1)) + 1; |
||
178 | static const intmax_t max = -min; |
||
179 | |||
180 | static_assert(_Xp <= max + _Yp, "overflow in __ll_sub"); |
||
181 | public: |
||
182 | static const intmax_t value = _Xp - _Yp; |
||
183 | }; |
||
184 | |||
185 | template <intmax_t _Xp, intmax_t _Yp> |
||
186 | class __ll_mul |
||
187 | { |
||
188 | static const intmax_t nan = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1)); |
||
189 | static const intmax_t min = nan + 1; |
||
190 | static const intmax_t max = -min; |
||
191 | static const intmax_t __a_x = __static_abs<_Xp>::value; |
||
192 | static const intmax_t __a_y = __static_abs<_Yp>::value; |
||
193 | |||
194 | static_assert(_Xp != nan && _Yp != nan && __a_x <= max / __a_y, "overflow in __ll_mul"); |
||
195 | public: |
||
196 | static const intmax_t value = _Xp * _Yp; |
||
197 | }; |
||
198 | |||
199 | template <intmax_t _Yp> |
||
200 | class __ll_mul<0, _Yp> |
||
201 | { |
||
202 | public: |
||
203 | static const intmax_t value = 0; |
||
204 | }; |
||
205 | |||
206 | template <intmax_t _Xp> |
||
207 | class __ll_mul<_Xp, 0> |
||
208 | { |
||
209 | public: |
||
210 | static const intmax_t value = 0; |
||
211 | }; |
||
212 | |||
213 | template <> |
||
214 | class __ll_mul<0, 0> |
||
215 | { |
||
216 | public: |
||
217 | static const intmax_t value = 0; |
||
218 | }; |
||
219 | |||
220 | // Not actually used but left here in case needed in future maintenance |
||
221 | template <intmax_t _Xp, intmax_t _Yp> |
||
222 | class __ll_div |
||
223 | { |
||
224 | static const intmax_t nan = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1)); |
||
225 | static const intmax_t min = nan + 1; |
||
226 | static const intmax_t max = -min; |
||
227 | |||
228 | static_assert(_Xp != nan && _Yp != nan && _Yp != 0, "overflow in __ll_div"); |
||
229 | public: |
||
230 | static const intmax_t value = _Xp / _Yp; |
||
231 | }; |
||
232 | |||
233 | template <intmax_t _Num, intmax_t _Den = 1> |
||
234 | class _LIBCPP_TYPE_VIS_ONLY ratio |
||
235 | { |
||
236 | static_assert(__static_abs<_Num>::value >= 0, "ratio numerator is out of range"); |
||
237 | static_assert(_Den != 0, "ratio divide by 0"); |
||
238 | static_assert(__static_abs<_Den>::value > 0, "ratio denominator is out of range"); |
||
239 | static _LIBCPP_CONSTEXPR const intmax_t __na = __static_abs<_Num>::value; |
||
240 | static _LIBCPP_CONSTEXPR const intmax_t __da = __static_abs<_Den>::value; |
||
241 | static _LIBCPP_CONSTEXPR const intmax_t __s = __static_sign<_Num>::value * __static_sign<_Den>::value; |
||
242 | static _LIBCPP_CONSTEXPR const intmax_t __gcd = __static_gcd<__na, __da>::value; |
||
243 | public: |
||
244 | static _LIBCPP_CONSTEXPR const intmax_t num = __s * __na / __gcd; |
||
245 | static _LIBCPP_CONSTEXPR const intmax_t den = __da / __gcd; |
||
246 | |||
247 | typedef ratio<num, den> type; |
||
248 | }; |
||
249 | |||
250 | template <intmax_t _Num, intmax_t _Den> |
||
251 | _LIBCPP_CONSTEXPR const intmax_t ratio<_Num, _Den>::num; |
||
252 | |||
253 | template <intmax_t _Num, intmax_t _Den> |
||
254 | _LIBCPP_CONSTEXPR const intmax_t ratio<_Num, _Den>::den; |
||
255 | |||
256 | template <class _Tp> struct __is_ratio : false_type {}; |
||
257 | template <intmax_t _Num, intmax_t _Den> struct __is_ratio<ratio<_Num, _Den> > : true_type {}; |
||
258 | |||
259 | typedef ratio<1LL, 1000000000000000000LL> atto; |
||
260 | typedef ratio<1LL, 1000000000000000LL> femto; |
||
261 | typedef ratio<1LL, 1000000000000LL> pico; |
||
262 | typedef ratio<1LL, 1000000000LL> nano; |
||
263 | typedef ratio<1LL, 1000000LL> micro; |
||
264 | typedef ratio<1LL, 1000LL> milli; |
||
265 | typedef ratio<1LL, 100LL> centi; |
||
266 | typedef ratio<1LL, 10LL> deci; |
||
267 | typedef ratio< 10LL, 1LL> deca; |
||
268 | typedef ratio< 100LL, 1LL> hecto; |
||
269 | typedef ratio< 1000LL, 1LL> kilo; |
||
270 | typedef ratio< 1000000LL, 1LL> mega; |
||
271 | typedef ratio< 1000000000LL, 1LL> giga; |
||
272 | typedef ratio< 1000000000000LL, 1LL> tera; |
||
273 | typedef ratio< 1000000000000000LL, 1LL> peta; |
||
274 | typedef ratio<1000000000000000000LL, 1LL> exa; |
||
275 | |||
276 | template <class _R1, class _R2> |
||
277 | struct __ratio_multiply |
||
278 | { |
||
279 | private: |
||
280 | static const intmax_t __gcd_n1_d2 = __static_gcd<_R1::num, _R2::den>::value; |
||
281 | static const intmax_t __gcd_d1_n2 = __static_gcd<_R1::den, _R2::num>::value; |
||
282 | public: |
||
283 | typedef typename ratio |
||
284 | < |
||
285 | __ll_mul<_R1::num / __gcd_n1_d2, _R2::num / __gcd_d1_n2>::value, |
||
286 | __ll_mul<_R2::den / __gcd_n1_d2, _R1::den / __gcd_d1_n2>::value |
||
287 | >::type type; |
||
288 | }; |
||
289 | |||
290 | #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
291 | |||
292 | template <class _R1, class _R2> using ratio_multiply |
||
293 | = typename __ratio_multiply<_R1, _R2>::type; |
||
294 | |||
295 | #else // _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
296 | |||
297 | template <class _R1, class _R2> |
||
298 | struct _LIBCPP_TYPE_VIS_ONLY ratio_multiply |
||
299 | : public __ratio_multiply<_R1, _R2>::type {}; |
||
300 | |||
301 | #endif // _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
302 | |||
303 | template <class _R1, class _R2> |
||
304 | struct __ratio_divide |
||
305 | { |
||
306 | private: |
||
307 | static const intmax_t __gcd_n1_n2 = __static_gcd<_R1::num, _R2::num>::value; |
||
308 | static const intmax_t __gcd_d1_d2 = __static_gcd<_R1::den, _R2::den>::value; |
||
309 | public: |
||
310 | typedef typename ratio |
||
311 | < |
||
312 | __ll_mul<_R1::num / __gcd_n1_n2, _R2::den / __gcd_d1_d2>::value, |
||
313 | __ll_mul<_R2::num / __gcd_n1_n2, _R1::den / __gcd_d1_d2>::value |
||
314 | >::type type; |
||
315 | }; |
||
316 | |||
317 | #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
318 | |||
319 | template <class _R1, class _R2> using ratio_divide |
||
320 | = typename __ratio_divide<_R1, _R2>::type; |
||
321 | |||
322 | #else // _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
323 | |||
324 | template <class _R1, class _R2> |
||
325 | struct _LIBCPP_TYPE_VIS_ONLY ratio_divide |
||
326 | : public __ratio_divide<_R1, _R2>::type {}; |
||
327 | |||
328 | #endif // _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
329 | |||
330 | template <class _R1, class _R2> |
||
331 | struct __ratio_add |
||
332 | { |
||
333 | private: |
||
334 | static const intmax_t __gcd_n1_n2 = __static_gcd<_R1::num, _R2::num>::value; |
||
335 | static const intmax_t __gcd_d1_d2 = __static_gcd<_R1::den, _R2::den>::value; |
||
336 | public: |
||
337 | typedef typename ratio_multiply |
||
338 | < |
||
339 | ratio<__gcd_n1_n2, _R1::den / __gcd_d1_d2>, |
||
340 | ratio |
||
341 | < |
||
342 | __ll_add |
||
343 | < |
||
344 | __ll_mul<_R1::num / __gcd_n1_n2, _R2::den / __gcd_d1_d2>::value, |
||
345 | __ll_mul<_R2::num / __gcd_n1_n2, _R1::den / __gcd_d1_d2>::value |
||
346 | >::value, |
||
347 | _R2::den |
||
348 | > |
||
349 | >::type type; |
||
350 | }; |
||
351 | |||
352 | #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
353 | |||
354 | template <class _R1, class _R2> using ratio_add |
||
355 | = typename __ratio_add<_R1, _R2>::type; |
||
356 | |||
357 | #else // _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
358 | |||
359 | template <class _R1, class _R2> |
||
360 | struct _LIBCPP_TYPE_VIS_ONLY ratio_add |
||
361 | : public __ratio_add<_R1, _R2>::type {}; |
||
362 | |||
363 | #endif // _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
364 | |||
365 | template <class _R1, class _R2> |
||
366 | struct __ratio_subtract |
||
367 | { |
||
368 | private: |
||
369 | static const intmax_t __gcd_n1_n2 = __static_gcd<_R1::num, _R2::num>::value; |
||
370 | static const intmax_t __gcd_d1_d2 = __static_gcd<_R1::den, _R2::den>::value; |
||
371 | public: |
||
372 | typedef typename ratio_multiply |
||
373 | < |
||
374 | ratio<__gcd_n1_n2, _R1::den / __gcd_d1_d2>, |
||
375 | ratio |
||
376 | < |
||
377 | __ll_sub |
||
378 | < |
||
379 | __ll_mul<_R1::num / __gcd_n1_n2, _R2::den / __gcd_d1_d2>::value, |
||
380 | __ll_mul<_R2::num / __gcd_n1_n2, _R1::den / __gcd_d1_d2>::value |
||
381 | >::value, |
||
382 | _R2::den |
||
383 | > |
||
384 | >::type type; |
||
385 | }; |
||
386 | |||
387 | #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
388 | |||
389 | template <class _R1, class _R2> using ratio_subtract |
||
390 | = typename __ratio_subtract<_R1, _R2>::type; |
||
391 | |||
392 | #else // _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
393 | |||
394 | template <class _R1, class _R2> |
||
395 | struct _LIBCPP_TYPE_VIS_ONLY ratio_subtract |
||
396 | : public __ratio_subtract<_R1, _R2>::type {}; |
||
397 | |||
398 | #endif // _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
399 | |||
400 | // ratio_equal |
||
401 | |||
402 | template <class _R1, class _R2> |
||
403 | struct _LIBCPP_TYPE_VIS_ONLY ratio_equal |
||
404 | : public _LIBCPP_BOOL_CONSTANT((_R1::num == _R2::num && _R1::den == _R2::den)) {}; |
||
405 | |||
406 | template <class _R1, class _R2> |
||
407 | struct _LIBCPP_TYPE_VIS_ONLY ratio_not_equal |
||
408 | : public _LIBCPP_BOOL_CONSTANT((!ratio_equal<_R1, _R2>::value)) {}; |
||
409 | |||
410 | // ratio_less |
||
411 | |||
412 | template <class _R1, class _R2, bool _Odd = false, |
||
413 | intmax_t _Q1 = _R1::num / _R1::den, intmax_t _M1 = _R1::num % _R1::den, |
||
414 | intmax_t _Q2 = _R2::num / _R2::den, intmax_t _M2 = _R2::num % _R2::den> |
||
415 | struct __ratio_less1 |
||
416 | { |
||
417 | static const bool value = _Odd ? _Q2 < _Q1 : _Q1 < _Q2; |
||
418 | }; |
||
419 | |||
420 | template <class _R1, class _R2, bool _Odd, intmax_t _Qp> |
||
421 | struct __ratio_less1<_R1, _R2, _Odd, _Qp, 0, _Qp, 0> |
||
422 | { |
||
423 | static const bool value = false; |
||
424 | }; |
||
425 | |||
426 | template <class _R1, class _R2, bool _Odd, intmax_t _Qp, intmax_t _M2> |
||
427 | struct __ratio_less1<_R1, _R2, _Odd, _Qp, 0, _Qp, _M2> |
||
428 | { |
||
429 | static const bool value = !_Odd; |
||
430 | }; |
||
431 | |||
432 | template <class _R1, class _R2, bool _Odd, intmax_t _Qp, intmax_t _M1> |
||
433 | struct __ratio_less1<_R1, _R2, _Odd, _Qp, _M1, _Qp, 0> |
||
434 | { |
||
435 | static const bool value = _Odd; |
||
436 | }; |
||
437 | |||
438 | template <class _R1, class _R2, bool _Odd, intmax_t _Qp, intmax_t _M1, |
||
439 | intmax_t _M2> |
||
440 | struct __ratio_less1<_R1, _R2, _Odd, _Qp, _M1, _Qp, _M2> |
||
441 | { |
||
442 | static const bool value = __ratio_less1<ratio<_R1::den, _M1>, |
||
443 | ratio<_R2::den, _M2>, !_Odd>::value; |
||
444 | }; |
||
445 | |||
446 | template <class _R1, class _R2, intmax_t _S1 = __static_sign<_R1::num>::value, |
||
447 | intmax_t _S2 = __static_sign<_R2::num>::value> |
||
448 | struct __ratio_less |
||
449 | { |
||
450 | static const bool value = _S1 < _S2; |
||
451 | }; |
||
452 | |||
453 | template <class _R1, class _R2> |
||
454 | struct __ratio_less<_R1, _R2, 1LL, 1LL> |
||
455 | { |
||
456 | static const bool value = __ratio_less1<_R1, _R2>::value; |
||
457 | }; |
||
458 | |||
459 | template <class _R1, class _R2> |
||
460 | struct __ratio_less<_R1, _R2, -1LL, -1LL> |
||
461 | { |
||
462 | static const bool value = __ratio_less1<ratio<-_R2::num, _R2::den>, ratio<-_R1::num, _R1::den> >::value; |
||
463 | }; |
||
464 | |||
465 | template <class _R1, class _R2> |
||
466 | struct _LIBCPP_TYPE_VIS_ONLY ratio_less |
||
467 | : public _LIBCPP_BOOL_CONSTANT((__ratio_less<_R1, _R2>::value)) {}; |
||
468 | |||
469 | template <class _R1, class _R2> |
||
470 | struct _LIBCPP_TYPE_VIS_ONLY ratio_less_equal |
||
471 | : public _LIBCPP_BOOL_CONSTANT((!ratio_less<_R2, _R1>::value)) {}; |
||
472 | |||
473 | template <class _R1, class _R2> |
||
474 | struct _LIBCPP_TYPE_VIS_ONLY ratio_greater |
||
475 | : public _LIBCPP_BOOL_CONSTANT((ratio_less<_R2, _R1>::value)) {}; |
||
476 | |||
477 | template <class _R1, class _R2> |
||
478 | struct _LIBCPP_TYPE_VIS_ONLY ratio_greater_equal |
||
479 | : public _LIBCPP_BOOL_CONSTANT((!ratio_less<_R1, _R2>::value)) {}; |
||
480 | |||
481 | template <class _R1, class _R2> |
||
482 | struct __ratio_gcd |
||
483 | { |
||
484 | typedef ratio<__static_gcd<_R1::num, _R2::num>::value, |
||
485 | __static_lcm<_R1::den, _R2::den>::value> type; |
||
486 | }; |
||
487 | |||
488 | _LIBCPP_END_NAMESPACE_STD |
||
489 | |||
490 | #endif // _LIBCPP_RATIO |