1
// -*- C++ -*- Time-stamp: <2011-04-21 16:37:26 ptr>
2
3
/*
4
 * Copyright (c) 2009-2011
5
 * Petr Ovtchenkov
6
 *
7
 * This material is provided "as is", with absolutely no warranty expressed
8
 * or implied. Any use is at your own risk.
9
 *
10
 * Permission to use or copy this software for any purpose is hereby granted
11
 * without fee, provided the above notices are retained on all copies.
12
 * Permission to modify the code and to distribute modified code is granted,
13
 * provided the above notices are retained, and a notice that the code was
14
 * modified is included with the above copyright notice.
15
 *
16
 */
17
18
#ifndef _STLP_RATIO
19
#define _STLP_RATIO
20
21
# include <cstdint>
22
# include <type_traits>
23
24
#ifndef _STLP_OUTERMOST_HEADER_ID
25
#  define _STLP_OUTERMOST_HEADER_ID 0x23
26
#  include <stl/_prolog.h>
27
#endif
28
29
_STLP_BEGIN_NAMESPACE
30
31
template <intmax_t N, intmax_t D = 1LL> class ratio;
32
33
// ratio arithmetic
34
35
template <class R1, class R2> struct ratio_add;
36
template <class R1, class R2> struct ratio_subtract;
37
template <class R1, class R2> struct ratio_multiply;
38
template <class R1, class R2> struct ratio_divide;
39
40
// ratio comparison
41
42
template <class R1, class R2> struct ratio_equal;
43
template <class R1, class R2> struct ratio_not_equal;
44
template <class R1, class R2> struct ratio_less;
45
template <class R1, class R2> struct ratio_less_equal;
46
template <class R1, class R2> struct ratio_greater;
47
template <class R1, class R2> struct ratio_greater_equal;
48
49
// convenience SI typedefs
50
51
// typedef ratio<1LL, 1000000000000000000000000LL> yocto; // see 20.6.4
52
// typedef ratio<1LL, 1000000000000000000000LL> zepto; // see 20.6.4
53
typedef ratio<1LL, 1000000000000000000LL> atto;
54
typedef ratio<1LL,    1000000000000000LL> femto;
55
typedef ratio<1LL,       1000000000000LL> pico;
56
typedef ratio<1LL,          1000000000LL> nano;
57
typedef ratio<1LL,             1000000LL> micro;
58
typedef ratio<1LL,                1000LL> milli;
59
typedef ratio<1LL,                 100LL> centi;
60
typedef ratio<1LL,                  10LL> deci;
61
typedef ratio<10LL,                  1LL> deca;
62
typedef ratio<100LL,                 1LL> hecto;
63
typedef ratio<1000LL,                1LL> kilo;
64
typedef ratio<1000000LL,             1LL> mega;
65
typedef ratio<1000000000LL,          1LL> giga;
66
typedef ratio<1000000000000LL,       1LL> tera;
67
typedef ratio<1000000000000000LL,    1LL> peta;
68
typedef ratio<1000000000000000000LL, 1LL> exa;
69
// typedef ratio<1000000000000000000000LL, 1LL> zetta; // see 20.6.4
70
// typedef ratio<1000000000000000000000000LL, 1LL> yotta; // see 20.6.4
71
72
namespace detail {
73
74
template <intmax_t R>
75
struct __select_sign :
76
    public _STLP_STD::integral_constant<intmax_t,(R>=0) ? 1LL : -1LL>
77
{
78
};
79
80
template <intmax_t R>
81
struct __select_abs :
82
    public _STLP_STD::integral_constant<intmax_t,(R>=0) ? R : -R>
83
{
84
};
85
86
template <intmax_t U, intmax_t V>
87
struct __gcd :
88
    public _STLP_STD::integral_constant<intmax_t,__gcd<__select_abs<V>::value,__select_abs<U>::value % __select_abs<V>::value>::value>
89
{
90
};
91
92
template <intmax_t U>
93
struct __gcd<U, 0LL> :
94
    public _STLP_STD::integral_constant<intmax_t,__select_abs<U>::value>
95
{
96
};
97
98
} // namespace detail
99
100
template <intmax_t N, intmax_t D>
101
class ratio
102
{
103
  public:
104
//#ifdef __FIT_CPP_0X
105
    static constexpr intmax_t num = _STLP_STD::detail::__select_sign<D>::value * N / _STLP_STD::detail::__gcd<N,D>::value;
106
    static constexpr intmax_t den = _STLP_STD::detail::__select_abs<D>::value / _STLP_STD::detail::__gcd<N,D>::value;
107
//#else
108
//    static const intmax_t num = _STLP_STD::detail::__select_sign<D>::value * N / _STLP_STD::detail::__gcd<N,D>::value;
109
//    static const intmax_t den = _STLP_STD::detail::__select_abs<D>::value / _STLP_STD::detail::__gcd<N,D>::value;
110
//#endif
111
};
112
113
namespace detail {
114
115
template <class T>
116
struct __is_ratio :
117
        public _STLP_STD::false_type
118
{ };
119
120
template <intmax_t N, intmax_t D>
121
struct __is_ratio<ratio<N,D> > :
122
        public _STLP_STD::true_type
123
{ };
124
125
template <class R1, class R2>
126
struct _ratio_add // ratio<R1::num * R2::den + R2::num * R1::den, R1::den * R2::den>
127
{
128
    typedef _STLP_STD::ratio<R1::num * (R2::den/_STLP_STD::detail::__gcd<R1::den,R2::den>::value) + R2::num * (R1::den/_STLP_STD::detail::__gcd<R1::den,R2::den>::value), R1::den * (R2::den/_STLP_STD::detail::__gcd<R1::den,R2::den>::value)> type;
129
};
130
131
template <class R1, class R2>
132
struct _ratio_subtract // ratio<R1::num * R2::den - R2::num * R1::den, R1::den * R2::den>
133
{
134
    typedef _STLP_STD::ratio<R1::num * (R2::den/_STLP_STD::detail::__gcd<R1::den,R2::den>::value) - R2::num * (R1::den/_STLP_STD::detail::__gcd<R1::den,R2::den>::value), R1::den * (R2::den/_STLP_STD::detail::__gcd<R1::den,R2::den>::value)> type;
135
};
136
137
template <class R1, class R2>
138
struct _ratio_multiply // ratio<R1::num * R2::num, R1::den * R2::den>
139
{
140
    typedef _STLP_STD::ratio<(R1::num/_STLP_STD::detail::__gcd<R1::num,R2::den>::value)*(R2::num/_STLP_STD::detail::__gcd<R2::num,R1::den>::value),(R1::den/_STLP_STD::detail::__gcd<R2::num,R1::den>::value) * (R2::den/_STLP_STD::detail::__gcd<R1::num,R2::den>::value)> type;
141
};
142
143
template <class R1, class R2>
144
struct _ratio_divide // ratio<R1::num * R2::den, R2::num * R1::den>
145
{
146
    typedef _STLP_STD::ratio<(R1::num/_STLP_STD::detail::__gcd<R1::num,R2::num>::value) * (R2::den/_STLP_STD::detail::__gcd<R2::den,R1::den>::value),(R2::num/_STLP_STD::detail::__gcd<R1::num,R2::num>::value) * (R1::den/_STLP_STD::detail::__gcd<R2::den,R1::den>::value)> type;
147
};
148
149
} // namespace detail
150
151
template <class R1, class R2>
152
struct ratio_add : // ratio<R1::num * R2::den + R2::num * R1::den, R1::den * R2::den>
153
    public _STLP_STD::detail::_ratio_add<R1,R2>::type
154
{
155
    static_assert( _STLP_STD::detail::__is_ratio<R1>::value && _STLP_STD::detail::__is_ratio<R2>::value, "paramers must be a ratio" );
156
};
157
158
template <class R1, class R2>
159
struct ratio_subtract : // ratio<R1::num * R2::den - R2::num * R1::den, R1::den * R2::den>
160
    public _STLP_STD::detail::_ratio_subtract<R1,R2>::type
161
{
162
    static_assert( _STLP_STD::detail::__is_ratio<R1>::value && _STLP_STD::detail::__is_ratio<R2>::value, "paramers must be a ratio" );
163
};
164
165
template <class R1, class R2>
166
struct ratio_multiply : // ratio<R1::num * R2::num, R1::den * R2::den>
167
    public _STLP_STD::detail::_ratio_multiply<R1,R2>::type
168
{
169
    static_assert( _STLP_STD::detail::__is_ratio<R1>::value && _STLP_STD::detail::__is_ratio<R2>::value, "paramers must be a ratio" );
170
};
171
172
template <class R1, class R2>
173
struct ratio_divide : // ratio<R1::num * R2::den, R2::num * R1::den>
174
    public _STLP_STD::detail::_ratio_divide<R1,R2>::type
175
{
176
    static_assert( _STLP_STD::detail::__is_ratio<R1>::value && _STLP_STD::detail::__is_ratio<R2>::value, "paramers must be a ratio" );
177
};
178
179
template <class R1, class R2>
180
struct ratio_equal :
181
    public integral_constant<bool, (R1::num == R2::num) && (R1::den == R2::den)>
182
{
183
    static_assert( _STLP_STD::detail::__is_ratio<R1>::value && _STLP_STD::detail::__is_ratio<R2>::value, "paramers must be a ratio" );
184
};
185
186
template <class R1, class R2>
187
struct ratio_not_equal :
188
    public integral_constant<bool, !ratio_equal<R1, R2>::value>
189
{
190
};
191
192
template <class R1, class R2>
193
struct ratio_less :
194
    // public integral_constant<bool, (R1::num * R2::den) < (R2::num * R1::den)>
195
    public integral_constant<bool, (ratio_divide<R1,R2>::num < ratio_divide<R1,R2>::den)>
196
{
197
};
198
199
template <class R1, class R2>
200
struct ratio_less_equal :
201
    public integral_constant<bool, !ratio_less<R2, R1>::value>
202
{
203
};
204
205
template <class R1, class R2>
206
struct ratio_greater :
207
    public integral_constant<bool, ratio_less<R2, R1>::value>
208
{
209
};
210
211
template <class R1, class R2>
212
struct ratio_greater_equal :
213
    public integral_constant<bool, !ratio_less<R1, R2>::value>
214
{
215
};
216
217
_STLP_END_NAMESPACE
218
219
#if (_STLP_OUTERMOST_HEADER_ID == 0x23)
220
#  include <stl/_epilog.h>
221
#  undef _STLP_OUTERMOST_HEADER_ID
222
#endif
223
224
#endif // _STLP_RATIO