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