@@ -33,6 +33,8 @@ SOFTWARE.
33
33
34
34
#include " platform.h"
35
35
36
+ #include " type_traits.h"
37
+
36
38
#include < stddef.h>
37
39
#include < stdint.h>
38
40
@@ -41,17 +43,17 @@ SOFTWARE.
41
43
42
44
namespace etl
43
45
{
44
- template <size_t NUM, size_t DEN = 1UL >
46
+ template <intmax_t NUM, intmax_t DEN = 1UL >
45
47
struct ratio
46
48
{
47
49
static ETL_CONSTANT intmax_t num = NUM;
48
50
static ETL_CONSTANT intmax_t den = DEN;
49
51
};
50
52
51
- template <size_t NUM, size_t DEN>
53
+ template <intmax_t NUM, intmax_t DEN>
52
54
ETL_CONSTANT intmax_t ratio<NUM, DEN>::num;
53
55
54
- template <size_t NUM, size_t DEN>
56
+ template <intmax_t NUM, intmax_t DEN>
55
57
ETL_CONSTANT intmax_t ratio<NUM, DEN>::den;
56
58
57
59
#if INT_MAX > INT32_MAX
@@ -97,6 +99,153 @@ namespace etl
97
99
98
100
// / An approximation of e.
99
101
typedef ratio<326 , 120 > ratio_e;
102
+
103
+ #if ETL_USING_CPP11
104
+ namespace private_ratio
105
+ {
106
+ // Primary template for GCD calculation
107
+ template <typename T, T A, T B, bool = (B == 0 )>
108
+ struct ratio_gcd ;
109
+
110
+ // Specialisation for the case when B is not zero
111
+ template <typename T, T A, T B>
112
+ struct ratio_gcd <T, A, B, false >
113
+ {
114
+ static constexpr T value = ratio_gcd<T, B, A % B>::value;
115
+ };
116
+
117
+ // Specialisation for the case when B is zero
118
+ template <typename T, T A, T B>
119
+ struct ratio_gcd <T, A, B, true >
120
+ {
121
+ static constexpr T value = (A < 0 ) ? -A : A;
122
+ };
123
+
124
+ // Primary template for LCM calculation
125
+ template <typename T, T A, T B>
126
+ struct ratio_lcm
127
+ {
128
+ private:
129
+
130
+ static constexpr T product = ((A * B) < 0 ) ? -(A * B) : A * B;
131
+
132
+ public:
133
+
134
+ static constexpr T value = product / ratio_gcd<T, A, B>::value;
135
+ };
136
+
137
+ template <typename R1>
138
+ struct ratio_reduce
139
+ {
140
+ private:
141
+
142
+ static ETL_CONSTEXPR11 intmax_t gcd = etl::private_ratio::ratio_gcd<intmax_t , R1::num, R1::den>::value;
143
+
144
+ public:
145
+
146
+ using value = ratio<R1::num / gcd, R1::den / gcd>;
147
+ };
148
+
149
+ template <typename R1, typename R2>
150
+ struct ratio_add
151
+ {
152
+ private:
153
+
154
+ static ETL_CONSTEXPR11 intmax_t lcm = etl::private_ratio::ratio_lcm<intmax_t , R1::den, R2::den>::value;
155
+
156
+ public:
157
+
158
+ using value = typename ratio_reduce<ratio<R1::num * lcm / R1::den + R2::num * lcm / R2::den, lcm>>::value;
159
+ };
160
+
161
+ template <typename R1, typename R2>
162
+ struct ratio_subtract
163
+ {
164
+ public:
165
+ using value = typename ratio_add<R1, ratio<-R2::num, R2::den>>::value;
166
+ };
167
+
168
+ template <typename R1, typename R2>
169
+ struct ratio_multiply
170
+ {
171
+ private:
172
+ static ETL_CONSTEXPR11 intmax_t gcd1 = etl::private_ratio::ratio_gcd<intmax_t , R1::num, R2::den>::value;
173
+ static ETL_CONSTEXPR11 intmax_t gcd2 = etl::private_ratio::ratio_gcd<intmax_t , R2::num, R1::den>::value;
174
+
175
+ public:
176
+ using value = ratio<(R1::num / gcd1) * (R2::num / gcd2), (R1::den / gcd2) * (R2::den / gcd1)>;
177
+ };
178
+
179
+ template <typename R1, typename R2>
180
+ struct ratio_divide
181
+ {
182
+ public:
183
+ using value = typename ratio_multiply<R1, ratio<R2::den, R2::num>>::value;
184
+ };
185
+ }
186
+
187
+ template <typename R1, typename R2>
188
+ using ratio_add = typename private_ratio::ratio_add<R1, R2>::value;
189
+
190
+ template <typename R1, typename R2>
191
+ using ratio_subtract = typename private_ratio::ratio_subtract<R1, R2>::value;
192
+
193
+ template <typename R1, typename R2>
194
+ using ratio_multiply = typename private_ratio::ratio_multiply<R1, R2>::value;
195
+
196
+ template <typename R1, typename R2>
197
+ using ratio_divide = typename private_ratio::ratio_divide<R1, R2>::value;
198
+
199
+ template <typename R1, typename R2>
200
+ struct ratio_equal : etl::integral_constant<bool , (R1::num == R2::num && R1::den == R2::den)>
201
+ {
202
+ };
203
+
204
+ template <typename R1, typename R2>
205
+ struct ratio_not_equal : etl::integral_constant<bool , (R1::num != R2::num || R1::den != R2::den)>
206
+ {
207
+ };
208
+
209
+ template <typename R1, typename R2>
210
+ struct ratio_less : etl::integral_constant<bool , (R1::num * R2::den < R2::num * R1::den)>
211
+ {
212
+ };
213
+
214
+ template <typename R1, typename R2>
215
+ struct ratio_less_equal : etl::integral_constant<bool , (R1::num * R2::den <= R2::num * R1::den)>
216
+ {
217
+ };
218
+
219
+ template <typename R1, typename R2>
220
+ struct ratio_greater : etl::integral_constant<bool , (R1::num * R2::den > R2::num * R1::den)>
221
+ {
222
+ };
223
+
224
+ template <typename R1, typename R2>
225
+ struct ratio_greater_equal : etl::integral_constant<bool , (R1::num * R2::den >= R2::num * R1::den)>
226
+ {
227
+ };
228
+
229
+ #if ETL_USING_CPP14
230
+ template <typename R1, typename R2>
231
+ ETL_CONSTEXPR14 bool ratio_equal_v = ratio_equal<R1, R2>::value;
232
+
233
+ template <typename R1, typename R2>
234
+ ETL_CONSTEXPR14 bool ratio_not_equal_v = ratio_not_equal<R1, R2>::value;
235
+
236
+ template <typename R1, typename R2>
237
+ ETL_CONSTEXPR14 bool ratio_less_v = ratio_less<R1, R2>::value;
238
+
239
+ template <typename R1, typename R2>
240
+ ETL_CONSTEXPR14 bool ratio_less_equal_v = ratio_less_equal<R1, R2>::value;
241
+
242
+ template <typename R1, typename R2>
243
+ ETL_CONSTEXPR14 bool ratio_greater_v = ratio_greater<R1, R2>::value;
244
+
245
+ template <typename R1, typename R2>
246
+ ETL_CONSTEXPR14 bool ratio_greater_equal_v = ratio_greater_equal<R1, R2>::value;
247
+ #endif
248
+ #endif
100
249
}
101
250
102
251
#endif
0 commit comments