1#ifndef MSTL_CORE_NUMERIC_RATIO_HPP__
2#define MSTL_CORE_NUMERIC_RATIO_HPP__
30template <
intmax_t Numerator,
intmax_t Denominator = 1>
32 static_assert(Denominator != 0,
"denominator cannot be zero");
48template <
intmax_t Numerator,
intmax_t Denominator>
51template <
intmax_t Numerator,
intmax_t Denominator>
60template <
typename Ratio>
64template <
intmax_t Numerator,
intmax_t Denominator>
68#ifdef MSTL_STANDARD_14__
89template <
typename ratio1,
typename ratio2>
90struct __ratio_multiply_impl {
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;
97 safe_multiply<(ratio1::num / gcd1), (ratio2::num / gcd2)>::value,
98 safe_multiply<(ratio1::den / gcd2), (ratio2::den / gcd1)>::value>;
100 static constexpr intmax_t num = type::num;
101 static constexpr intmax_t den = type::den;
104template <
typename ratio1,
typename ratio2>
105constexpr intmax_t __ratio_multiply_impl<ratio1, ratio2>::num;
107template <
typename ratio1,
typename ratio2>
108constexpr intmax_t __ratio_multiply_impl<ratio1, ratio2>::den;
119template <
typename ratio1,
typename ratio2>
133template <
typename ratio1,
typename ratio2>
134struct __ratio_divide_impl {
135 static_assert(ratio2::num != 0,
"division by 0");
137 using type =
typename __ratio_multiply_impl<
140 static constexpr intmax_t num = type::num;
141 static constexpr intmax_t den = type::den;
144template <
typename ratio1,
typename ratio2>
145constexpr intmax_t __ratio_divide_impl<ratio1, ratio2>::num;
147template <
typename ratio1,
typename ratio2>
148constexpr intmax_t __ratio_divide_impl<ratio1, ratio2>::den;
159template <
typename ratio1,
typename ratio2>
169template <
typename ratio1,
typename ratio2>
171 ratio1::num == ratio2::num && ratio1::den == ratio2::den> {};
179template <
typename ratio1,
typename ratio2>
195template <
typename ratio1,
typename ratio2,
199 left_product::result_high, left_product::result_low,
200 right_product::result_high, right_product::result_low
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 {};
222template <
typename ratio1,
typename ratio2>
223struct __ratio_less_impl<ratio1, ratio2, true, false> :
bool_constant<ratio1::num < ratio2::num> {};
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 {};
238template <typename ratio1, typename ratio2>
239struct ratio_less : _INNER __ratio_less_impl<ratio1, ratio2>::type {};
247template <typename ratio1, typename ratio2>
248struct ratio_less_equal : bool_constant<!ratio_less<ratio2, ratio1>::value> {};
256template <typename ratio1, typename ratio2>
257struct ratio_greater : bool_constant<ratio_less<ratio2, ratio1>::value> {};
265template <typename ratio1, typename ratio2>
266struct ratio_greater_equal : bool_constant<!ratio_less<ratio1, ratio2>::value> {};
269#ifdef MSTL_STANDARD_14__
275template <typename ratio1, typename ratio2>
276MSTL_INLINE17 constexpr bool ratio_equal_v = ratio_equal<ratio1, ratio2>::value;
282template <typename ratio1, typename ratio2>
283MSTL_INLINE17 constexpr bool ratio_not_equal_v = ratio_not_equal<ratio1, ratio2>::value;
289template <typename ratio1, typename ratio2>
290MSTL_INLINE17 constexpr bool ratio_less_v = ratio_less<ratio1, ratio2>::value;
296template <typename ratio1, typename ratio2>
297MSTL_INLINE17 constexpr bool ratio_less_equal_v = ratio_less_equal<ratio1, ratio2>::value;
303template <typename ratio1, typename ratio2>
304MSTL_INLINE17 constexpr bool ratio_greater_v = ratio_greater<ratio1, ratio2>::value;
310template <typename ratio1, typename ratio2>
311MSTL_INLINE17 constexpr bool ratio_greater_equal_v = ratio_greater_equal<ratio1, ratio2>::value;
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>
336struct __ratio_add_impl {
338 using negative_result =
typename __ratio_add_impl<
339 ratio<-ratio1::num, ratio1::den>,
343 using type =
ratio<-negative_result::num, negative_result::den>;
349template <
typename ratio1,
typename ratio2,
bool abs_less>
350struct __ratio_add_impl<ratio1, ratio2, true, true, abs_less> {
353 static constexpr uintmax_t den2_scaled = ratio2::den / gcd_val;
356 using numerator1_scaled =
big_mul<ratio1::num, ratio2::den / gcd_val>;
357 using numerator2_scaled =
big_mul<ratio2::num, ratio1::den / gcd_val>;
359 numerator1_scaled::result_high,
360 numerator1_scaled::result_low,
361 numerator2_scaled::result_high,
362 numerator2_scaled::result_low>;
365 numerator_sum::result_high >= numerator1_scaled::result_high,
366 "Internal library error");
368 using numerator_gcd_reduced =
big_div<
369 numerator_sum::result_high,
370 numerator_sum::result_low,
373 numerator_gcd_reduced::remainder,
375 using numerator_final =
big_div<
376 numerator_sum::result_high,
377 numerator_sum::result_low,
380 static_assert(numerator_final::remainder == 0,
"Internal library error");
382 numerator_final::quotient_high == 0 &&
383 numerator_final::quotient_low <= numeric_traits<intmax_t>::max(),
384 "overflow in addition");
386 using denominator_final =
big_mul<ratio1::den / gcd_val2, den2_scaled>;
389 denominator_final::result_high == 0 &&
390 denominator_final::result_low <= numeric_traits<intmax_t>::max(),
391 "overflow in addition");
399template <
typename ratio1,
typename ratio2>
400struct __ratio_add_impl<ratio1, ratio2, false, true, true> :
401 __ratio_add_impl<ratio2, ratio1> {};
406template <
typename ratio1,
typename ratio2>
407struct __ratio_add_impl<ratio1, ratio2, true, false, false> {
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;
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>;
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>;
422 using numerator_gcd_reduced = big_div<
423 numerator_diff::result_high,
424 numerator_diff::result_low,
426 static constexpr uintmax_t gcd_val2 = static_gcd<
427 numerator_gcd_reduced::remainder,
429 using numerator_final = big_div<
430 numerator_diff::result_high,
431 numerator_diff::result_low,
434 static_assert(numerator_final::remainder == 0,
"Internal library error");
436 numerator_final::quotient_high == 0 &&
437 numerator_final::quotient_low <= numeric_traits<intmax_t>::max(),
438 "overflow in addition");
440 using denominator_final = big_mul<ratio1::den / gcd_val2, den2_scaled>;
443 denominator_final::result_high == 0 &&
444 denominator_final::result_low <= numeric_traits<intmax_t>::max(),
445 "overflow in addition");
447 using type = ratio<numerator_final::quotient_low, denominator_final::result_low>;
456template <
typename ratio1,
typename ratio2>
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;
463template <
typename ratio1,
typename ratio2>
466template <
typename ratio1,
typename ratio2>
478template <
typename ratio1,
typename ratio2>
492template <
typename ratio1,
typename ratio2>
494 using type =
typename ratio_add<ratio1,
ratio<-ratio2::num, ratio2::den>>::type;
496 static constexpr intmax_t num = type::num;
497 static constexpr intmax_t den = type::den;
500template <
typename ratio1,
typename ratio2>
503template <
typename ratio1,
typename ratio2>
515template <
typename ratio1,
typename ratio2>
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命名空间
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
布尔常量包装器
integral_constant< bool, Value > type
static constexpr intmax_t value
static constexpr intmax_t num
ratio< num, den > type
自身的类型
static constexpr intmax_t den