1227825Stheraven// -*- C++ -*-
2227825Stheraven//===---------------------------- ratio -----------------------------------===//
3227825Stheraven//
4227825Stheraven//                     The LLVM Compiler Infrastructure
5227825Stheraven//
6227825Stheraven// This file is dual licensed under the MIT and the University of Illinois Open
7227825Stheraven// Source Licenses. See LICENSE.TXT for details.
8227825Stheraven//
9227825Stheraven//===----------------------------------------------------------------------===//
10227825Stheraven
11227825Stheraven#ifndef _LIBCPP_RATIO
12227825Stheraven#define _LIBCPP_RATIO
13227825Stheraven
14227825Stheraven/*
15227825Stheraven    ratio synopsis
16227825Stheraven
17227825Stheravennamespace std
18227825Stheraven{
19227825Stheraven
20227825Stheraventemplate <intmax_t N, intmax_t D = 1>
21227825Stheravenclass ratio
22227825Stheraven{
23227825Stheravenpublic:
24288943Sdim    static constexpr intmax_t num;
25288943Sdim    static constexpr intmax_t den;
26227825Stheraven    typedef ratio<num, den> type;
27227825Stheraven};
28227825Stheraven
29227825Stheraven// ratio arithmetic
30227825Stheraventemplate <class R1, class R2> using ratio_add = ...;
31227825Stheraventemplate <class R1, class R2> using ratio_subtract = ...;
32227825Stheraventemplate <class R1, class R2> using ratio_multiply = ...;
33227825Stheraventemplate <class R1, class R2> using ratio_divide = ...;
34227825Stheraven
35227825Stheraven// ratio comparison
36227825Stheraventemplate <class R1, class R2> struct ratio_equal;
37227825Stheraventemplate <class R1, class R2> struct ratio_not_equal;
38227825Stheraventemplate <class R1, class R2> struct ratio_less;
39227825Stheraventemplate <class R1, class R2> struct ratio_less_equal;
40227825Stheraventemplate <class R1, class R2> struct ratio_greater;
41227825Stheraventemplate <class R1, class R2> struct ratio_greater_equal;
42227825Stheraven
43227825Stheraven// convenience SI typedefs
44227825Stheraventypedef ratio<1, 1000000000000000000000000> yocto;  // not supported
45227825Stheraventypedef ratio<1,    1000000000000000000000> zepto;  // not supported
46227825Stheraventypedef ratio<1,       1000000000000000000> atto;
47227825Stheraventypedef ratio<1,          1000000000000000> femto;
48227825Stheraventypedef ratio<1,             1000000000000> pico;
49227825Stheraventypedef ratio<1,                1000000000> nano;
50227825Stheraventypedef ratio<1,                   1000000> micro;
51227825Stheraventypedef ratio<1,                      1000> milli;
52227825Stheraventypedef ratio<1,                       100> centi;
53227825Stheraventypedef ratio<1,                        10> deci;
54227825Stheraventypedef ratio<                       10, 1> deca;
55227825Stheraventypedef ratio<                      100, 1> hecto;
56227825Stheraventypedef ratio<                     1000, 1> kilo;
57227825Stheraventypedef ratio<                  1000000, 1> mega;
58227825Stheraventypedef ratio<               1000000000, 1> giga;
59227825Stheraventypedef ratio<            1000000000000, 1> tera;
60227825Stheraventypedef ratio<         1000000000000000, 1> peta;
61227825Stheraventypedef ratio<      1000000000000000000, 1> exa;
62227825Stheraventypedef ratio<   1000000000000000000000, 1> zetta;  // not supported
63227825Stheraventypedef ratio<1000000000000000000000000, 1> yotta;  // not supported
64227825Stheraven
65300770Sdim  // 20.11.5, ratio comparison
66300770Sdim  template <class R1, class R2> constexpr bool ratio_equal_v
67300770Sdim    = ratio_equal<R1, R2>::value;                                       // C++17
68300770Sdim  template <class R1, class R2> constexpr bool ratio_not_equal_v
69300770Sdim    = ratio_not_equal<R1, R2>::value;                                   // C++17
70300770Sdim  template <class R1, class R2> constexpr bool ratio_less_v
71300770Sdim    = ratio_less<R1, R2>::value;                                        // C++17
72300770Sdim  template <class R1, class R2> constexpr bool ratio_less_equal_v
73300770Sdim    = ratio_less_equal<R1, R2>::value;                                  // C++17
74300770Sdim  template <class R1, class R2> constexpr bool ratio_greater_v
75300770Sdim    = ratio_greater<R1, R2>::value;                                     // C++17
76300770Sdim  template <class R1, class R2> constexpr bool ratio_greater_equal_v
77300770Sdim    = ratio_greater_equal<R1, R2>::value;                               // C++17
78227825Stheraven}
79227825Stheraven*/
80227825Stheraven
81227825Stheraven#include <__config>
82227825Stheraven#include <cstdint>
83227825Stheraven#include <climits>
84227825Stheraven#include <type_traits>
85227825Stheraven
86232924Stheraven#include <__undef_min_max>
87232924Stheraven
88227825Stheraven#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
89227825Stheraven#pragma GCC system_header
90227825Stheraven#endif
91227825Stheraven
92227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD
93227825Stheraven
94227825Stheraven// __static_gcd
95227825Stheraven
96227825Stheraventemplate <intmax_t _Xp, intmax_t _Yp>
97227825Stheravenstruct __static_gcd
98227825Stheraven{
99227825Stheraven    static const intmax_t value = __static_gcd<_Yp, _Xp % _Yp>::value;
100227825Stheraven};
101227825Stheraven
102227825Stheraventemplate <intmax_t _Xp>
103227825Stheravenstruct __static_gcd<_Xp, 0>
104227825Stheraven{
105227825Stheraven    static const intmax_t value = _Xp;
106227825Stheraven};
107227825Stheraven
108227825Stheraventemplate <>
109227825Stheravenstruct __static_gcd<0, 0>
110227825Stheraven{
111227825Stheraven    static const intmax_t value = 1;
112227825Stheraven};
113227825Stheraven
114227825Stheraven// __static_lcm
115227825Stheraven
116227825Stheraventemplate <intmax_t _Xp, intmax_t _Yp>
117227825Stheravenstruct __static_lcm
118227825Stheraven{
119227825Stheraven    static const intmax_t value = _Xp / __static_gcd<_Xp, _Yp>::value * _Yp;
120227825Stheraven};
121227825Stheraven
122227825Stheraventemplate <intmax_t _Xp>
123227825Stheravenstruct __static_abs
124227825Stheraven{
125227825Stheraven    static const intmax_t value = _Xp < 0 ? -_Xp : _Xp;
126227825Stheraven};
127227825Stheraven
128227825Stheraventemplate <intmax_t _Xp>
129227825Stheravenstruct __static_sign
130227825Stheraven{
131227825Stheraven    static const intmax_t value = _Xp == 0 ? 0 : (_Xp < 0 ? -1 : 1);
132227825Stheraven};
133227825Stheraven
134227825Stheraventemplate <intmax_t _Xp, intmax_t _Yp, intmax_t = __static_sign<_Yp>::value>
135227825Stheravenclass __ll_add;
136227825Stheraven
137227825Stheraventemplate <intmax_t _Xp, intmax_t _Yp>
138227825Stheravenclass __ll_add<_Xp, _Yp, 1>
139227825Stheraven{
140227825Stheraven    static const intmax_t min = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1)) + 1;
141227825Stheraven    static const intmax_t max = -min;
142227825Stheraven
143227825Stheraven    static_assert(_Xp <= max - _Yp, "overflow in __ll_add");
144227825Stheravenpublic:
145227825Stheraven    static const intmax_t value = _Xp + _Yp;
146227825Stheraven};
147227825Stheraven
148227825Stheraventemplate <intmax_t _Xp, intmax_t _Yp>
149227825Stheravenclass __ll_add<_Xp, _Yp, 0>
150227825Stheraven{
151227825Stheravenpublic:
152227825Stheraven    static const intmax_t value = _Xp;
153227825Stheraven};
154227825Stheraven
155227825Stheraventemplate <intmax_t _Xp, intmax_t _Yp>
156227825Stheravenclass __ll_add<_Xp, _Yp, -1>
157227825Stheraven{
158227825Stheraven    static const intmax_t min = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1)) + 1;
159227825Stheraven    static const intmax_t max = -min;
160227825Stheraven
161227825Stheraven    static_assert(min - _Yp <= _Xp, "overflow in __ll_add");
162227825Stheravenpublic:
163227825Stheraven    static const intmax_t value = _Xp + _Yp;
164227825Stheraven};
165227825Stheraven
166227825Stheraventemplate <intmax_t _Xp, intmax_t _Yp, intmax_t = __static_sign<_Yp>::value>
167227825Stheravenclass __ll_sub;
168227825Stheraven
169227825Stheraventemplate <intmax_t _Xp, intmax_t _Yp>
170227825Stheravenclass __ll_sub<_Xp, _Yp, 1>
171227825Stheraven{
172227825Stheraven    static const intmax_t min = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1)) + 1;
173227825Stheraven    static const intmax_t max = -min;
174227825Stheraven
175227825Stheraven    static_assert(min + _Yp <= _Xp, "overflow in __ll_sub");
176227825Stheravenpublic:
177227825Stheraven    static const intmax_t value = _Xp - _Yp;
178227825Stheraven};
179227825Stheraven
180227825Stheraventemplate <intmax_t _Xp, intmax_t _Yp>
181227825Stheravenclass __ll_sub<_Xp, _Yp, 0>
182227825Stheraven{
183227825Stheravenpublic:
184227825Stheraven    static const intmax_t value = _Xp;
185227825Stheraven};
186227825Stheraven
187227825Stheraventemplate <intmax_t _Xp, intmax_t _Yp>
188227825Stheravenclass __ll_sub<_Xp, _Yp, -1>
189227825Stheraven{
190227825Stheraven    static const intmax_t min = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1)) + 1;
191227825Stheraven    static const intmax_t max = -min;
192227825Stheraven
193227825Stheraven    static_assert(_Xp <= max + _Yp, "overflow in __ll_sub");
194227825Stheravenpublic:
195227825Stheraven    static const intmax_t value = _Xp - _Yp;
196227825Stheraven};
197227825Stheraven
198227825Stheraventemplate <intmax_t _Xp, intmax_t _Yp>
199227825Stheravenclass __ll_mul
200227825Stheraven{
201227825Stheraven    static const intmax_t nan = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1));
202227825Stheraven    static const intmax_t min = nan + 1;
203227825Stheraven    static const intmax_t max = -min;
204227825Stheraven    static const intmax_t __a_x = __static_abs<_Xp>::value;
205227825Stheraven    static const intmax_t __a_y = __static_abs<_Yp>::value;
206227825Stheraven
207227825Stheraven    static_assert(_Xp != nan && _Yp != nan && __a_x <= max / __a_y, "overflow in __ll_mul");
208227825Stheravenpublic:
209227825Stheraven    static const intmax_t value = _Xp * _Yp;
210227825Stheraven};
211227825Stheraven
212227825Stheraventemplate <intmax_t _Yp>
213227825Stheravenclass __ll_mul<0, _Yp>
214227825Stheraven{
215227825Stheravenpublic:
216227825Stheraven    static const intmax_t value = 0;
217227825Stheraven};
218227825Stheraven
219227825Stheraventemplate <intmax_t _Xp>
220227825Stheravenclass __ll_mul<_Xp, 0>
221227825Stheraven{
222227825Stheravenpublic:
223227825Stheraven    static const intmax_t value = 0;
224227825Stheraven};
225227825Stheraven
226227825Stheraventemplate <>
227227825Stheravenclass __ll_mul<0, 0>
228227825Stheraven{
229227825Stheravenpublic:
230227825Stheraven    static const intmax_t value = 0;
231227825Stheraven};
232227825Stheraven
233227825Stheraven// Not actually used but left here in case needed in future maintenance
234227825Stheraventemplate <intmax_t _Xp, intmax_t _Yp>
235227825Stheravenclass __ll_div
236227825Stheraven{
237227825Stheraven    static const intmax_t nan = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1));
238227825Stheraven    static const intmax_t min = nan + 1;
239227825Stheraven    static const intmax_t max = -min;
240227825Stheraven
241227825Stheraven    static_assert(_Xp != nan && _Yp != nan && _Yp != 0, "overflow in __ll_div");
242227825Stheravenpublic:
243227825Stheraven    static const intmax_t value = _Xp / _Yp;
244227825Stheraven};
245227825Stheraven
246227825Stheraventemplate <intmax_t _Num, intmax_t _Den = 1>
247261272Sdimclass _LIBCPP_TYPE_VIS_ONLY ratio
248227825Stheraven{
249227825Stheraven    static_assert(__static_abs<_Num>::value >= 0, "ratio numerator is out of range");
250227825Stheraven    static_assert(_Den != 0, "ratio divide by 0");
251227825Stheraven    static_assert(__static_abs<_Den>::value >  0, "ratio denominator is out of range");
252288943Sdim    static _LIBCPP_CONSTEXPR const intmax_t __na = __static_abs<_Num>::value;
253288943Sdim    static _LIBCPP_CONSTEXPR const intmax_t __da = __static_abs<_Den>::value;
254288943Sdim    static _LIBCPP_CONSTEXPR const intmax_t __s = __static_sign<_Num>::value * __static_sign<_Den>::value;
255288943Sdim    static _LIBCPP_CONSTEXPR const intmax_t __gcd = __static_gcd<__na, __da>::value;
256227825Stheravenpublic:
257288943Sdim    static _LIBCPP_CONSTEXPR const intmax_t num = __s * __na / __gcd;
258288943Sdim    static _LIBCPP_CONSTEXPR const intmax_t den = __da / __gcd;
259227825Stheraven
260227825Stheraven    typedef ratio<num, den> type;
261227825Stheraven};
262227825Stheraven
263288943Sdimtemplate <intmax_t _Num, intmax_t _Den>
264288943Sdim_LIBCPP_CONSTEXPR const intmax_t ratio<_Num, _Den>::num;
265227825Stheraven
266288943Sdimtemplate <intmax_t _Num, intmax_t _Den>
267288943Sdim_LIBCPP_CONSTEXPR const intmax_t ratio<_Num, _Den>::den;
268288943Sdim
269227825Stheraventemplate <class _Tp>                    struct __is_ratio                     : false_type {};
270227825Stheraventemplate <intmax_t _Num, intmax_t _Den> struct __is_ratio<ratio<_Num, _Den> > : true_type  {};
271227825Stheraven
272227825Stheraventypedef ratio<1LL, 1000000000000000000LL> atto;
273227825Stheraventypedef ratio<1LL,    1000000000000000LL> femto;
274227825Stheraventypedef ratio<1LL,       1000000000000LL> pico;
275227825Stheraventypedef ratio<1LL,          1000000000LL> nano;
276227825Stheraventypedef ratio<1LL,             1000000LL> micro;
277227825Stheraventypedef ratio<1LL,                1000LL> milli;
278227825Stheraventypedef ratio<1LL,                 100LL> centi;
279227825Stheraventypedef ratio<1LL,                  10LL> deci;
280227825Stheraventypedef ratio<                 10LL, 1LL> deca;
281227825Stheraventypedef ratio<                100LL, 1LL> hecto;
282227825Stheraventypedef ratio<               1000LL, 1LL> kilo;
283227825Stheraventypedef ratio<            1000000LL, 1LL> mega;
284227825Stheraventypedef ratio<         1000000000LL, 1LL> giga;
285227825Stheraventypedef ratio<      1000000000000LL, 1LL> tera;
286227825Stheraventypedef ratio<   1000000000000000LL, 1LL> peta;
287227825Stheraventypedef ratio<1000000000000000000LL, 1LL> exa;
288227825Stheraven
289227825Stheraventemplate <class _R1, class _R2>
290227825Stheravenstruct __ratio_multiply
291227825Stheraven{
292227825Stheravenprivate:
293227825Stheraven    static const intmax_t __gcd_n1_d2 = __static_gcd<_R1::num, _R2::den>::value;
294227825Stheraven    static const intmax_t __gcd_d1_n2 = __static_gcd<_R1::den, _R2::num>::value;
295227825Stheravenpublic:
296227825Stheraven    typedef typename ratio
297227825Stheraven        <
298227825Stheraven            __ll_mul<_R1::num / __gcd_n1_d2, _R2::num / __gcd_d1_n2>::value,
299227825Stheraven            __ll_mul<_R2::den / __gcd_n1_d2, _R1::den / __gcd_d1_n2>::value
300227825Stheraven        >::type type;
301227825Stheraven};
302227825Stheraven
303227825Stheraven#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
304227825Stheraven
305227825Stheraventemplate <class _R1, class _R2> using ratio_multiply
306227825Stheraven                                    = typename __ratio_multiply<_R1, _R2>::type;
307227825Stheraven
308227825Stheraven#else  // _LIBCPP_HAS_NO_TEMPLATE_ALIASES
309227825Stheraven
310227825Stheraventemplate <class _R1, class _R2>
311261272Sdimstruct _LIBCPP_TYPE_VIS_ONLY ratio_multiply
312227825Stheraven    : public __ratio_multiply<_R1, _R2>::type {};
313227825Stheraven
314227825Stheraven#endif  // _LIBCPP_HAS_NO_TEMPLATE_ALIASES
315227825Stheraven
316227825Stheraventemplate <class _R1, class _R2>
317227825Stheravenstruct __ratio_divide
318227825Stheraven{
319227825Stheravenprivate:
320227825Stheraven    static const intmax_t __gcd_n1_n2 = __static_gcd<_R1::num, _R2::num>::value;
321227825Stheraven    static const intmax_t __gcd_d1_d2 = __static_gcd<_R1::den, _R2::den>::value;
322227825Stheravenpublic:
323227825Stheraven    typedef typename ratio
324227825Stheraven        <
325227825Stheraven            __ll_mul<_R1::num / __gcd_n1_n2, _R2::den / __gcd_d1_d2>::value,
326227825Stheraven            __ll_mul<_R2::num / __gcd_n1_n2, _R1::den / __gcd_d1_d2>::value
327227825Stheraven        >::type type;
328227825Stheraven};
329227825Stheraven
330227825Stheraven#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
331227825Stheraven
332227825Stheraventemplate <class _R1, class _R2> using ratio_divide
333227825Stheraven                                      = typename __ratio_divide<_R1, _R2>::type;
334227825Stheraven
335227825Stheraven#else  // _LIBCPP_HAS_NO_TEMPLATE_ALIASES
336227825Stheraven
337227825Stheraventemplate <class _R1, class _R2>
338261272Sdimstruct _LIBCPP_TYPE_VIS_ONLY ratio_divide
339227825Stheraven    : public __ratio_divide<_R1, _R2>::type {};
340227825Stheraven
341227825Stheraven#endif  // _LIBCPP_HAS_NO_TEMPLATE_ALIASES
342227825Stheraven
343227825Stheraventemplate <class _R1, class _R2>
344227825Stheravenstruct __ratio_add
345227825Stheraven{
346227825Stheravenprivate:
347227825Stheraven    static const intmax_t __gcd_n1_n2 = __static_gcd<_R1::num, _R2::num>::value;
348227825Stheraven    static const intmax_t __gcd_d1_d2 = __static_gcd<_R1::den, _R2::den>::value;
349227825Stheravenpublic:
350227825Stheraven    typedef typename ratio_multiply
351227825Stheraven        <
352227825Stheraven            ratio<__gcd_n1_n2, _R1::den / __gcd_d1_d2>,
353227825Stheraven            ratio
354227825Stheraven            <
355227825Stheraven                __ll_add
356227825Stheraven                <
357227825Stheraven                    __ll_mul<_R1::num / __gcd_n1_n2, _R2::den / __gcd_d1_d2>::value,
358227825Stheraven                    __ll_mul<_R2::num / __gcd_n1_n2, _R1::den / __gcd_d1_d2>::value
359227825Stheraven                >::value,
360227825Stheraven                _R2::den
361227825Stheraven            >
362227825Stheraven        >::type type;
363227825Stheraven};
364227825Stheraven
365227825Stheraven#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
366227825Stheraven
367227825Stheraventemplate <class _R1, class _R2> using ratio_add
368227825Stheraven                                         = typename __ratio_add<_R1, _R2>::type;
369227825Stheraven
370227825Stheraven#else  // _LIBCPP_HAS_NO_TEMPLATE_ALIASES
371227825Stheraven
372227825Stheraventemplate <class _R1, class _R2>
373261272Sdimstruct _LIBCPP_TYPE_VIS_ONLY ratio_add
374227825Stheraven    : public __ratio_add<_R1, _R2>::type {};
375227825Stheraven
376227825Stheraven#endif  // _LIBCPP_HAS_NO_TEMPLATE_ALIASES
377227825Stheraven
378227825Stheraventemplate <class _R1, class _R2>
379227825Stheravenstruct __ratio_subtract
380227825Stheraven{
381227825Stheravenprivate:
382227825Stheraven    static const intmax_t __gcd_n1_n2 = __static_gcd<_R1::num, _R2::num>::value;
383227825Stheraven    static const intmax_t __gcd_d1_d2 = __static_gcd<_R1::den, _R2::den>::value;
384227825Stheravenpublic:
385227825Stheraven    typedef typename ratio_multiply
386227825Stheraven        <
387227825Stheraven            ratio<__gcd_n1_n2, _R1::den / __gcd_d1_d2>,
388227825Stheraven            ratio
389227825Stheraven            <
390227825Stheraven                __ll_sub
391227825Stheraven                <
392227825Stheraven                    __ll_mul<_R1::num / __gcd_n1_n2, _R2::den / __gcd_d1_d2>::value,
393227825Stheraven                    __ll_mul<_R2::num / __gcd_n1_n2, _R1::den / __gcd_d1_d2>::value
394227825Stheraven                >::value,
395227825Stheraven                _R2::den
396227825Stheraven            >
397227825Stheraven        >::type type;
398227825Stheraven};
399227825Stheraven
400227825Stheraven#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
401227825Stheraven
402227825Stheraventemplate <class _R1, class _R2> using ratio_subtract
403227825Stheraven                                    = typename __ratio_subtract<_R1, _R2>::type;
404227825Stheraven
405227825Stheraven#else  // _LIBCPP_HAS_NO_TEMPLATE_ALIASES
406227825Stheraven
407227825Stheraventemplate <class _R1, class _R2>
408261272Sdimstruct _LIBCPP_TYPE_VIS_ONLY ratio_subtract
409227825Stheraven    : public __ratio_subtract<_R1, _R2>::type {};
410227825Stheraven
411227825Stheraven#endif  // _LIBCPP_HAS_NO_TEMPLATE_ALIASES
412227825Stheraven
413227825Stheraven// ratio_equal
414227825Stheraven
415227825Stheraventemplate <class _R1, class _R2>
416261272Sdimstruct _LIBCPP_TYPE_VIS_ONLY ratio_equal
417288943Sdim    : public _LIBCPP_BOOL_CONSTANT((_R1::num == _R2::num && _R1::den == _R2::den)) {};
418227825Stheraven
419227825Stheraventemplate <class _R1, class _R2>
420261272Sdimstruct _LIBCPP_TYPE_VIS_ONLY ratio_not_equal
421288943Sdim    : public _LIBCPP_BOOL_CONSTANT((!ratio_equal<_R1, _R2>::value)) {};
422227825Stheraven
423227825Stheraven// ratio_less
424227825Stheraven
425227825Stheraventemplate <class _R1, class _R2, bool _Odd = false,
426227825Stheraven          intmax_t _Q1 = _R1::num / _R1::den, intmax_t _M1 = _R1::num % _R1::den,
427227825Stheraven          intmax_t _Q2 = _R2::num / _R2::den, intmax_t _M2 = _R2::num % _R2::den>
428227825Stheravenstruct __ratio_less1
429227825Stheraven{
430227825Stheraven    static const bool value = _Odd ? _Q2 < _Q1 : _Q1 < _Q2;
431227825Stheraven};
432227825Stheraven
433232924Stheraventemplate <class _R1, class _R2, bool _Odd, intmax_t _Qp>
434232924Stheravenstruct __ratio_less1<_R1, _R2, _Odd, _Qp, 0, _Qp, 0>
435227825Stheraven{
436227825Stheraven    static const bool value = false;
437227825Stheraven};
438227825Stheraven
439232924Stheraventemplate <class _R1, class _R2, bool _Odd, intmax_t _Qp, intmax_t _M2>
440232924Stheravenstruct __ratio_less1<_R1, _R2, _Odd, _Qp, 0, _Qp, _M2>
441227825Stheraven{
442227825Stheraven    static const bool value = !_Odd;
443227825Stheraven};
444227825Stheraven
445232924Stheraventemplate <class _R1, class _R2, bool _Odd, intmax_t _Qp, intmax_t _M1>
446232924Stheravenstruct __ratio_less1<_R1, _R2, _Odd, _Qp, _M1, _Qp, 0>
447227825Stheraven{
448227825Stheraven    static const bool value = _Odd;
449227825Stheraven};
450227825Stheraven
451232924Stheraventemplate <class _R1, class _R2, bool _Odd, intmax_t _Qp, intmax_t _M1,
452227825Stheraven                                                        intmax_t _M2>
453232924Stheravenstruct __ratio_less1<_R1, _R2, _Odd, _Qp, _M1, _Qp, _M2>
454227825Stheraven{
455227825Stheraven    static const bool value = __ratio_less1<ratio<_R1::den, _M1>,
456227825Stheraven                                            ratio<_R2::den, _M2>, !_Odd>::value;
457227825Stheraven};
458227825Stheraven
459227825Stheraventemplate <class _R1, class _R2, intmax_t _S1 = __static_sign<_R1::num>::value,
460227825Stheraven                                intmax_t _S2 = __static_sign<_R2::num>::value>
461227825Stheravenstruct __ratio_less
462227825Stheraven{
463227825Stheraven    static const bool value = _S1 < _S2;
464227825Stheraven};
465227825Stheraven
466227825Stheraventemplate <class _R1, class _R2>
467227825Stheravenstruct __ratio_less<_R1, _R2, 1LL, 1LL>
468227825Stheraven{
469227825Stheraven    static const bool value = __ratio_less1<_R1, _R2>::value;
470227825Stheraven};
471227825Stheraven
472227825Stheraventemplate <class _R1, class _R2>
473227825Stheravenstruct __ratio_less<_R1, _R2, -1LL, -1LL>
474227825Stheraven{
475227825Stheraven    static const bool value = __ratio_less1<ratio<-_R2::num, _R2::den>, ratio<-_R1::num, _R1::den> >::value;
476227825Stheraven};
477227825Stheraven
478227825Stheraventemplate <class _R1, class _R2>
479261272Sdimstruct _LIBCPP_TYPE_VIS_ONLY ratio_less
480288943Sdim    : public _LIBCPP_BOOL_CONSTANT((__ratio_less<_R1, _R2>::value)) {};
481227825Stheraven
482227825Stheraventemplate <class _R1, class _R2>
483261272Sdimstruct _LIBCPP_TYPE_VIS_ONLY ratio_less_equal
484288943Sdim    : public _LIBCPP_BOOL_CONSTANT((!ratio_less<_R2, _R1>::value)) {};
485227825Stheraven
486227825Stheraventemplate <class _R1, class _R2>
487261272Sdimstruct _LIBCPP_TYPE_VIS_ONLY ratio_greater
488288943Sdim    : public _LIBCPP_BOOL_CONSTANT((ratio_less<_R2, _R1>::value)) {};
489227825Stheraven
490227825Stheraventemplate <class _R1, class _R2>
491261272Sdimstruct _LIBCPP_TYPE_VIS_ONLY ratio_greater_equal
492288943Sdim    : public _LIBCPP_BOOL_CONSTANT((!ratio_less<_R1, _R2>::value)) {};
493227825Stheraven
494227825Stheraventemplate <class _R1, class _R2>
495227825Stheravenstruct __ratio_gcd
496227825Stheraven{
497227825Stheraven    typedef ratio<__static_gcd<_R1::num, _R2::num>::value,
498227825Stheraven                  __static_lcm<_R1::den, _R2::den>::value> type;
499227825Stheraven};
500227825Stheraven
501300770Sdim#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
502300770Sdimtemplate <class _R1, class _R2> _LIBCPP_CONSTEXPR bool ratio_equal_v
503300770Sdim    = ratio_equal<_R1, _R2>::value;
504300770Sdim
505300770Sdimtemplate <class _R1, class _R2> _LIBCPP_CONSTEXPR bool ratio_not_equal_v
506300770Sdim    = ratio_not_equal<_R1, _R2>::value;
507300770Sdim
508300770Sdimtemplate <class _R1, class _R2> _LIBCPP_CONSTEXPR bool ratio_less_v
509300770Sdim    = ratio_less<_R1, _R2>::value;
510300770Sdim
511300770Sdimtemplate <class _R1, class _R2> _LIBCPP_CONSTEXPR bool ratio_less_equal_v
512300770Sdim    = ratio_less_equal<_R1, _R2>::value;
513300770Sdim
514300770Sdimtemplate <class _R1, class _R2> _LIBCPP_CONSTEXPR bool ratio_greater_v
515300770Sdim    = ratio_greater<_R1, _R2>::value;
516300770Sdim
517300770Sdimtemplate <class _R1, class _R2> _LIBCPP_CONSTEXPR bool ratio_greater_equal_v
518300770Sdim    = ratio_greater_equal<_R1, _R2>::value;
519300770Sdim#endif
520300770Sdim
521227825Stheraven_LIBCPP_END_NAMESPACE_STD
522227825Stheraven
523227825Stheraven#endif  // _LIBCPP_RATIO
524