MSTL 1.4.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
ratio.hpp
浏览该文件的文档.
1#ifndef MSTL_CORE_NUMERIC_RATIO_HPP__
2#define MSTL_CORE_NUMERIC_RATIO_HPP__
3
11
14
20
30template <intmax_t Numerator, intmax_t Denominator = 1>
31struct ratio {
32 static_assert(Denominator != 0, "denominator cannot be zero");
33 static_assert(
34 Numerator > numeric_traits<intmax_t>::min() &&
35 Denominator > numeric_traits<intmax_t>::min(),
36 "out of range");
37
38 static constexpr intmax_t num =
41 static constexpr intmax_t den =
44
46};
47
48template <intmax_t Numerator, intmax_t Denominator>
50
51template <intmax_t Numerator, intmax_t Denominator>
53
54
60template <typename Ratio>
61struct is_ratio : false_type {};
62
64template <intmax_t Numerator, intmax_t Denominator>
65struct is_ratio<ratio<Numerator, Denominator>> : true_type {};
67
68#ifdef MSTL_STANDARD_14__
73template <typename T>
74MSTL_INLINE17 constexpr bool is_ratio_v = is_ratio<T>::value;
75#endif
76
77
80
89template <typename ratio1, typename ratio2>
90struct __ratio_multiply_impl {
91private:
92 static const intmax_t gcd1 = static_gcd<ratio1::num, ratio2::den>::value;
93 static const intmax_t gcd2 = static_gcd<ratio2::num, ratio1::den>::value;
94
95public:
96 using type = ratio<
97 safe_multiply<(ratio1::num / gcd1), (ratio2::num / gcd2)>::value,
98 safe_multiply<(ratio1::den / gcd2), (ratio2::den / gcd1)>::value>;
99
100 static constexpr intmax_t num = type::num;
101 static constexpr intmax_t den = type::den;
102};
103
104template <typename ratio1, typename ratio2>
105constexpr intmax_t __ratio_multiply_impl<ratio1, ratio2>::num;
106
107template <typename ratio1, typename ratio2>
108constexpr intmax_t __ratio_multiply_impl<ratio1, ratio2>::den;
109
112
119template <typename ratio1, typename ratio2>
120using ratio_multiply = typename _INNER __ratio_multiply_impl<ratio1, ratio2>::type;
121
124
133template <typename ratio1, typename ratio2>
134struct __ratio_divide_impl {
135 static_assert(ratio2::num != 0, "division by 0");
136
137 using type = typename __ratio_multiply_impl<
138 ratio1, ratio<ratio2::den, ratio2::num>>::type;
139
140 static constexpr intmax_t num = type::num;
141 static constexpr intmax_t den = type::den;
142};
143
144template <typename ratio1, typename ratio2>
145constexpr intmax_t __ratio_divide_impl<ratio1, ratio2>::num;
146
147template <typename ratio1, typename ratio2>
148constexpr intmax_t __ratio_divide_impl<ratio1, ratio2>::den;
149
152
159template <typename ratio1, typename ratio2>
160using ratio_divide = typename _INNER __ratio_divide_impl<ratio1, ratio2>::type;
161
162
169template <typename ratio1, typename ratio2>
171 ratio1::num == ratio2::num && ratio1::den == ratio2::den> {};
172
179template <typename ratio1, typename ratio2>
180struct ratio_not_equal : bool_constant<!ratio_equal<ratio1, ratio2>::value> {};
181
184
195template <typename ratio1, typename ratio2,
196 typename left_product = big_mul<ratio1::num, ratio2::den>,
197 typename right_product = big_mul<ratio2::num, ratio1::den>>
198struct __ratio_less_impl_base : bool_constant<big_less<
199 left_product::result_high, left_product::result_low,
200 right_product::result_high, right_product::result_low
201>::value> {};
202
213template <typename ratio1, typename ratio2,
214 bool has_zero_or_different_sign = (
215 ratio1::num == 0 || ratio2::num == 0 ||
217 bool both_negative = (
220struct __ratio_less_impl : __ratio_less_impl_base<ratio1, ratio2>::type {};
221
222template <typename ratio1, typename ratio2>
223struct __ratio_less_impl<ratio1, ratio2, true, false> : bool_constant<ratio1::num < ratio2::num> {};
224
225template <typename ratio1, typename ratio2>
226struct __ratio_less_impl<ratio1, ratio2, false, true>
227 : __ratio_less_impl_base<ratio<-ratio2::num, ratio2::den>, ratio<-ratio1::num, ratio1::den>>::type {};
228
229MSTL_END_INNER__
231
238template <typename ratio1, typename ratio2>
239struct ratio_less : _INNER __ratio_less_impl<ratio1, ratio2>::type {};
240
247template <typename ratio1, typename ratio2>
248struct ratio_less_equal : bool_constant<!ratio_less<ratio2, ratio1>::value> {};
249
256template <typename ratio1, typename ratio2>
257struct ratio_greater : bool_constant<ratio_less<ratio2, ratio1>::value> {};
258
265template <typename ratio1, typename ratio2>
266struct ratio_greater_equal : bool_constant<!ratio_less<ratio1, ratio2>::value> {};
267
268
269#ifdef MSTL_STANDARD_14__
270
275template <typename ratio1, typename ratio2>
276MSTL_INLINE17 constexpr bool ratio_equal_v = ratio_equal<ratio1, ratio2>::value;
277
282template <typename ratio1, typename ratio2>
283MSTL_INLINE17 constexpr bool ratio_not_equal_v = ratio_not_equal<ratio1, ratio2>::value;
284
289template <typename ratio1, typename ratio2>
290MSTL_INLINE17 constexpr bool ratio_less_v = ratio_less<ratio1, ratio2>::value;
291
296template <typename ratio1, typename ratio2>
297MSTL_INLINE17 constexpr bool ratio_less_equal_v = ratio_less_equal<ratio1, ratio2>::value;
298
303template <typename ratio1, typename ratio2>
304MSTL_INLINE17 constexpr bool ratio_greater_v = ratio_greater<ratio1, ratio2>::value;
305
310template <typename ratio1, typename ratio2>
311MSTL_INLINE17 constexpr bool ratio_greater_equal_v = ratio_greater_equal<ratio1, ratio2>::value;
312#endif
313
314
316MSTL_BEGIN_INNER__
317
329template <typename ratio1, typename ratio2,
330 bool ratio1_non_negative = (ratio1::num >= 0),
331 bool ratio2_non_negative = (ratio2::num >= 0),
332 bool abs_ratio1_less_than_abs_ratio2 = ratio_less<
333 ratio<static_abs<ratio1::num>::value, ratio1::den>,
334 ratio<static_abs<ratio2::num>::value, ratio2::den>
335 >::value>
336struct __ratio_add_impl {
337private:
338 using negative_result = typename __ratio_add_impl<
339 ratio<-ratio1::num, ratio1::den>,
340 ratio<-ratio2::num, ratio2::den>>::type;
341
342public:
343 using type = ratio<-negative_result::num, negative_result::den>;
344};
345
349template <typename ratio1, typename ratio2, bool abs_less>
350struct __ratio_add_impl<ratio1, ratio2, true, true, abs_less> {
351private:
352 static constexpr uintmax_t gcd_val = static_gcd<ratio1::den, ratio2::den>::value;
353 static constexpr uintmax_t den2_scaled = ratio2::den / gcd_val;
354
355 using denominator_product = big_mul<ratio1::den, den2_scaled>;
356 using numerator1_scaled = big_mul<ratio1::num, ratio2::den / gcd_val>;
357 using numerator2_scaled = big_mul<ratio2::num, ratio1::den / gcd_val>;
358 using numerator_sum = big_add<
359 numerator1_scaled::result_high,
360 numerator1_scaled::result_low,
361 numerator2_scaled::result_high,
362 numerator2_scaled::result_low>;
363
364 static_assert(
365 numerator_sum::result_high >= numerator1_scaled::result_high,
366 "Internal library error");
367
368 using numerator_gcd_reduced = big_div<
369 numerator_sum::result_high,
370 numerator_sum::result_low,
371 gcd_val>;
372 static constexpr uintmax_t gcd_val2 = static_gcd<
373 numerator_gcd_reduced::remainder,
374 gcd_val>::value;
375 using numerator_final = big_div<
376 numerator_sum::result_high,
377 numerator_sum::result_low,
378 gcd_val2>;
379
380 static_assert(numerator_final::remainder == 0, "Internal library error");
381 static_assert(
382 numerator_final::quotient_high == 0 &&
383 numerator_final::quotient_low <= numeric_traits<intmax_t>::max(),
384 "overflow in addition");
385
386 using denominator_final = big_mul<ratio1::den / gcd_val2, den2_scaled>;
387
388 static_assert(
389 denominator_final::result_high == 0 &&
390 denominator_final::result_low <= numeric_traits<intmax_t>::max(),
391 "overflow in addition");
392public:
394};
395
399template <typename ratio1, typename ratio2>
400struct __ratio_add_impl<ratio1, ratio2, false, true, true> :
401 __ratio_add_impl<ratio2, ratio1> {};
402
406template <typename ratio1, typename ratio2>
407struct __ratio_add_impl<ratio1, ratio2, true, false, false> {
408private:
409 static constexpr uintmax_t gcd_val = static_gcd<ratio1::den, ratio2::den>::value;
410 static constexpr uintmax_t den2_scaled = ratio2::den / gcd_val;
411
412 using denominator_product = big_mul<ratio1::den, den2_scaled>;
413 using numerator1_scaled = big_mul<ratio1::num, ratio2::den / gcd_val>;
414 using numerator2_scaled = big_mul<-ratio2::num, ratio1::den / gcd_val>;
415
416 using numerator_diff = big_sub<
417 numerator1_scaled::result_high,
418 numerator1_scaled::result_low,
419 numerator2_scaled::result_high,
420 numerator2_scaled::result_low>;
421
422 using numerator_gcd_reduced = big_div<
423 numerator_diff::result_high,
424 numerator_diff::result_low,
425 gcd_val>;
426 static constexpr uintmax_t gcd_val2 = static_gcd<
427 numerator_gcd_reduced::remainder,
428 gcd_val>::value;
429 using numerator_final = big_div<
430 numerator_diff::result_high,
431 numerator_diff::result_low,
432 gcd_val2>;
433
434 static_assert(numerator_final::remainder == 0, "Internal library error");
435 static_assert(
436 numerator_final::quotient_high == 0 &&
437 numerator_final::quotient_low <= numeric_traits<intmax_t>::max(),
438 "overflow in addition");
439
440 using denominator_final = big_mul<ratio1::den / gcd_val2, den2_scaled>;
441
442 static_assert(
443 denominator_final::result_high == 0 &&
444 denominator_final::result_low <= numeric_traits<intmax_t>::max(),
445 "overflow in addition");
446public:
447 using type = ratio<numerator_final::quotient_low, denominator_final::result_low>;
448};
449
456template <typename ratio1, typename ratio2>
457struct ratio_add {
458 using type = typename __ratio_add_impl<ratio1, ratio2>::type;
459 static constexpr intmax_t num = type::num;
460 static constexpr intmax_t den = type::den;
461};
462
463template <typename ratio1, typename ratio2>
465
466template <typename ratio1, typename ratio2>
468
471
478template <typename ratio1, typename ratio2>
480
483
492template <typename ratio1, typename ratio2>
493struct ratio_subtract {
494 using type = typename ratio_add<ratio1, ratio<-ratio2::num, ratio2::den>>::type;
495
496 static constexpr intmax_t num = type::num;
497 static constexpr intmax_t den = type::den;
498};
499
500template <typename ratio1, typename ratio2>
502
503template <typename ratio1, typename ratio2>
505
508
515template <typename ratio1, typename ratio2>
517 // RatioClass
519
525
542 // SIUnits
544
546#endif // MSTL_CORE_NUMERIC_RATIO_HPP__
static MSTL_NODISCARD constexpr T min() noexcept
获取类型的最小值
#define MSTL_END_INNER__
结束inner命名空间
#define _INNER
inner命名空间前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
#define MSTL_BEGIN_INNER__
开始inner命名空间
int64_t intmax_t
最大有符号整数类型
uint64_t uintmax_t
最大无符号整数类型
typename _INNER __ratio_divide_impl< ratio1, ratio2 >::type ratio_divide
比率除法类型别名
typename _INNER ratio_add< ratio1, ratio2 >::type ratio_add
比率加法类型别名
typename _INNER ratio_subtract< ratio1, ratio2 >::type ratio_subtract
比率减法类型别名
typename _INNER __ratio_multiply_impl< ratio1, ratio2 >::type ratio_multiply
比率乘法类型别名
ratio< 1, 1000 > milli
毫(10^-3)
ratio< 1, 10 > deci
分(10^-1)
ratio< 1, 1000000000 > nano
纳(10^-9)
ratio< 1, 1000000000000000000 > atto
阿托(10^-18)
ratio< 1000000, 1 > mega
兆(10^6)
ratio< 10, 1 > deca
十(10^1)
ratio< 1, 1000000000000 > pico
皮(10^-12)
ratio< 1, 100 > centi
厘(10^-2)
ratio< 1000000000000000, 1 > peta
拍(10^15)
ratio< 1, 1000000000000000 > femto
飞(10^-15)
ratio< 1, 1000000 > micro
微(10^-6)
ratio< 1000, 1 > kilo
千(10^3)
ratio< 1000000000000, 1 > tera
太(10^12)
ratio< 1000000000000000000, 1 > exa
艾(10^18)
ratio< 100, 1 > hecto
百(10^2)
ratio< 1000000000, 1 > giga
吉(10^9)
bool_constant< true > true_type
表示true的类型
bool_constant< false > false_type
表示false的类型
integral_constant< bool, Value > bool_constant
布尔常量包装器
MSTL静态数值计算
无符号大整数加法
大整数除法
无符号大整数乘法
integral_constant< bool, Value > type
检查类型是否为ratio
检查两个比率是否相等
检查第一个比率是否小于第二个比率
检查两个比率是否不相等
比率类模板
static constexpr intmax_t num
ratio< num, den > type
自身的类型
static constexpr intmax_t den
计算两个整数的最大公约数
计算整数的符号