1#ifndef NEFORCE_CORE_NUMERIC_RATIO_HPP__
2#define NEFORCE_CORE_NUMERIC_RATIO_HPP__
13NEFORCE_BEGIN_NAMESPACE__
30template <
intmax_t Numerator,
intmax_t Denominator = 1>
32 static_assert(Denominator != 0,
"denominator cannot be zero");
44#ifndef NEFORCE_STANDARD_17
45template <
intmax_t Numerator,
intmax_t Denominator>
48template <
intmax_t Numerator,
intmax_t Denominator>
58template <
typename Ratio>
62template <
intmax_t Numerator,
intmax_t Denominator>
66#ifdef NEFORCE_STANDARD_14
87template <
typename ratio1,
typename ratio2>
88struct __ratio_multiply_impl {
95 safe_multiply<(ratio1::den / gcd2), (ratio2::den / gcd1)>::value>;
97 static constexpr intmax_t num = type::num;
98 static constexpr intmax_t den = type::den;
101#ifndef NEFORCE_STANDARD_17
102template <
typename ratio1,
typename ratio2>
103constexpr intmax_t __ratio_multiply_impl<ratio1, ratio2>::num;
105template <
typename ratio1,
typename ratio2>
106constexpr intmax_t __ratio_multiply_impl<ratio1, ratio2>::den;
118template <
typename ratio1,
typename ratio2>
119using ratio_multiply =
typename inner::__ratio_multiply_impl<ratio1, ratio2>::type;
132template <
typename ratio1,
typename ratio2>
133struct __ratio_divide_impl {
134 static_assert(ratio2::num != 0,
"division by 0");
136 using type =
typename __ratio_multiply_impl<ratio1, ratio<ratio2::den, ratio2::num>>::type;
138 static constexpr intmax_t num = type::num;
139 static constexpr intmax_t den = type::den;
142#ifndef NEFORCE_STANDARD_17
143template <
typename ratio1,
typename ratio2>
144constexpr intmax_t __ratio_divide_impl<ratio1, ratio2>::num;
146template <
typename ratio1,
typename ratio2>
147constexpr intmax_t __ratio_divide_impl<ratio1, ratio2>::den;
159template <
typename ratio1,
typename ratio2>
160using ratio_divide =
typename inner::__ratio_divide_impl<ratio1, ratio2>::type;
169template <
typename ratio1,
typename ratio2>
178template <
typename ratio1,
typename ratio2>
194template <
typename ratio1,
typename ratio2,
typename left_product = big_mul<ratio1::num, ratio2::den>,
195 typename right_product = big_mul<ratio2::num, ratio1::den>>
196struct __ratio_less_impl_base :
bool_constant<big_less<left_product::result_high, left_product::result_low,
197 right_product::result_high, right_product::result_low>::value> {
210template <
typename ratio1,
typename ratio2,
211 bool has_zero_or_different_sign = (ratio1::num == 0 || ratio2::num == 0 ||
214struct __ratio_less_impl : __ratio_less_impl_base<ratio1, ratio2>::type {};
216template <
typename ratio1,
typename ratio2>
217 struct __ratio_less_impl<ratio1, ratio2, true, false> :
bool_constant < ratio1::num<ratio2::num> {};
219template <typename ratio1, typename ratio2>
220struct __ratio_less_impl<ratio1, ratio2, false, true>
221: __ratio_less_impl_base<ratio<-ratio2::num, ratio2::den>, ratio<-ratio1::num, ratio1::den>>::type {};
232template <typename ratio1, typename ratio2>
233struct ratio_less : inner::__ratio_less_impl<ratio1, ratio2>::type {};
241template <typename ratio1, typename ratio2>
242struct ratio_less_equal : bool_constant<!ratio_less<ratio2, ratio1>::value> {};
250template <typename ratio1, typename ratio2>
251struct ratio_greater : bool_constant<ratio_less<ratio2, ratio1>::value> {};
259template <typename ratio1, typename ratio2>
260struct ratio_greater_equal : bool_constant<!ratio_less<ratio1, ratio2>::value> {};
263#ifdef NEFORCE_STANDARD_14
269template <typename ratio1, typename ratio2>
270NEFORCE_INLINE17 constexpr bool ratio_equal_v = ratio_equal<ratio1, ratio2>::value;
276template <typename ratio1, typename ratio2>
277NEFORCE_INLINE17 constexpr bool ratio_not_equal_v = ratio_not_equal<ratio1, ratio2>::value;
283template <typename ratio1, typename ratio2>
284NEFORCE_INLINE17 constexpr bool ratio_less_v = ratio_less<ratio1, ratio2>::value;
290template <typename ratio1, typename ratio2>
291NEFORCE_INLINE17 constexpr bool ratio_less_equal_v = ratio_less_equal<ratio1, ratio2>::value;
297template <typename ratio1, typename ratio2>
298NEFORCE_INLINE17 constexpr bool ratio_greater_v = ratio_greater<ratio1, ratio2>::value;
304template <typename ratio1, typename ratio2>
305NEFORCE_INLINE17 constexpr bool ratio_greater_equal_v = ratio_greater_equal<ratio1, ratio2>::value;
323template <typename ratio1, typename ratio2, bool ratio1_non_negative = (ratio1::num >= 0),
324 bool ratio2_non_negative = (ratio2::num >= 0),
325 bool abs_ratio1_less_than_abs_ratio2 =
ratio_less<ratio<static_abs<ratio1::num>::value, ratio1::den>,
326 ratio<static_abs<ratio2::num>::value, ratio2::den>>::value>
327struct __ratio_add_impl {
329 using negative_result =
330 typename __ratio_add_impl<
ratio<-ratio1::num, ratio1::den>,
ratio<-ratio2::num, ratio2::den>>::type;
333 using type =
ratio<-negative_result::num, negative_result::den>;
339template <
typename ratio1,
typename ratio2,
bool abs_less>
340struct __ratio_add_impl<ratio1, ratio2, true, true, abs_less> {
342 static constexpr uintmax_t gcd_val = static_gcd<ratio1::den, ratio2::den>::value;
343 static constexpr uintmax_t den2_scaled = ratio2::den / gcd_val;
345 using denominator_product = big_mul<ratio1::den, den2_scaled>;
346 using numerator1_scaled = big_mul<ratio1::num, ratio2::den / gcd_val>;
347 using numerator2_scaled = big_mul<ratio2::num, ratio1::den / gcd_val>;
348 using numerator_sum =
349 big_add<numerator1_scaled::result_high, numerator1_scaled::result_low, numerator2_scaled::result_high,
350 numerator2_scaled::result_low>;
352 static_assert(numerator_sum::result_high >= numerator1_scaled::result_high,
"Internal library error");
354 using numerator_gcd_reduced = big_div<numerator_sum::result_high, numerator_sum::result_low,
356 static constexpr uintmax_t gcd_val2 = static_gcd<numerator_gcd_reduced::remainder,
358 using numerator_final = big_div<numerator_sum::result_high, numerator_sum::result_low,
361 static_assert(numerator_final::remainder == 0,
"Internal library error");
362 static_assert(numerator_final::quotient_high == 0 &&
363 numerator_final::quotient_low <= numeric_traits<intmax_t>::max(),
364 "overflow in addition");
366 using denominator_final = big_mul<ratio1::den / gcd_val2, den2_scaled>;
368 static_assert(denominator_final::result_high == 0 &&
369 denominator_final::result_low <= numeric_traits<intmax_t>::max(),
370 "overflow in addition");
373 using type = ratio<numerator_final::quotient_low, denominator_final::result_low>;
379template <
typename ratio1,
typename ratio2>
380struct __ratio_add_impl<ratio1, ratio2, false, true, true> : __ratio_add_impl<ratio2, ratio1> {};
385template <
typename ratio1,
typename ratio2>
386struct __ratio_add_impl<ratio1, ratio2, true, false, false> {
388 static constexpr uintmax_t gcd_val = static_gcd<ratio1::den, ratio2::den>::value;
389 static constexpr uintmax_t den2_scaled = ratio2::den / gcd_val;
391 using denominator_product = big_mul<ratio1::den, den2_scaled>;
392 using numerator1_scaled = big_mul<ratio1::num, ratio2::den / gcd_val>;
393 using numerator2_scaled = big_mul<-ratio2::num, ratio1::den / gcd_val>;
395 using numerator_diff = big_sub<numerator1_scaled::result_high, numerator1_scaled::result_low,
396 numerator2_scaled::result_high, numerator2_scaled::result_low>;
398 using numerator_gcd_reduced = big_div<numerator_diff::result_high, numerator_diff::result_low, gcd_val>;
399 static constexpr uintmax_t gcd_val2 = static_gcd<numerator_gcd_reduced::remainder, gcd_val>::value;
400 using numerator_final = big_div<numerator_diff::result_high, numerator_diff::result_low, gcd_val2>;
402 static_assert(numerator_final::remainder == 0,
"Internal library error");
403 static_assert(numerator_final::quotient_high == 0 &&
404 numerator_final::quotient_low <= numeric_traits<intmax_t>::max(),
405 "overflow in addition");
407 using denominator_final = big_mul<ratio1::den / gcd_val2, den2_scaled>;
409 static_assert(denominator_final::result_high == 0 &&
410 denominator_final::result_low <= numeric_traits<intmax_t>::max(),
411 "overflow in addition");
414 using type = ratio<numerator_final::quotient_low, denominator_final::result_low>;
423template <
typename ratio1,
typename ratio2>
425 using type =
typename __ratio_add_impl<ratio1, ratio2>::type;
426 static constexpr intmax_t num = type::num;
427 static constexpr intmax_t den = type::den;
430#ifndef NEFORCE_STANDARD_17
431template <
typename ratio1,
typename ratio2>
434template <
typename ratio1,
typename ratio2>
447template <
typename ratio1,
typename ratio2>
448using ratio_add =
typename inner::ratio_add<ratio1, ratio2>::type;
461template <
typename ratio1,
typename ratio2>
463 using type =
typename ratio_add<ratio1,
ratio<-ratio2::num, ratio2::den>>::type;
465 static constexpr intmax_t num = type::num;
466 static constexpr intmax_t den = type::den;
469#ifndef NEFORCE_STANDARD_17
470template <
typename ratio1,
typename ratio2>
473template <
typename ratio1,
typename ratio2>
486template <
typename ratio1,
typename ratio2>
516NEFORCE_END_NAMESPACE__
static constexpr T min() noexcept
获取类型的最小值
typename inner::ratio_add< ratio1, ratio2 >::type ratio_add
比率加法类型别名
typename inner::__ratio_multiply_impl< ratio1, ratio2 >::type ratio_multiply
比率乘法类型别名
typename inner::ratio_subtract< ratio1, ratio2 >::type ratio_subtract
比率减法类型别名
constexpr bool is_ratio_v
is_ratio的便捷变量模板
typename inner::__ratio_divide_impl< ratio1, ratio2 >::type ratio_divide
比率除法类型别名
ratio< 1, 100 > centi
厘(10^-2)
ratio< 1, 1000 > milli
毫(10^-3)
ratio< 1000000, 1 > mega
兆(10^6)
ratio< 1, 1000000 > micro
微(10^-6)
ratio< 1, 1000000000000000 > femto
飞(10^-15)
ratio< 1, 1000000000000000000 > atto
阿托(10^-18)
ratio< 1000000000000, 1 > tera
太(10^12)
ratio< 1, 10 > deci
分(10^-1)
ratio< 1000000000000000, 1 > peta
拍(10^15)
ratio< 1000000000, 1 > giga
吉(10^9)
ratio< 1, 1000000000 > nano
纳(10^-9)
ratio< 1, 1000000000000 > pico
皮(10^-12)
ratio< 1000000000000000000, 1 > exa
艾(10^18)
ratio< 10, 1 > deca
十(10^1)
ratio< 100, 1 > hecto
百(10^2)
ratio< 1000, 1 > kilo
千(10^3)
bool_constant< true > true_type
表示true的类型
bool_constant< false > false_type
表示false的类型
integral_constant< bool, Value > bool_constant
布尔常量包装器
static constexpr intmax_t value
static constexpr intmax_t num
ratio< num, den > type
自身的类型
static constexpr intmax_t den