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");
44template <
intmax_t Numerator,
intmax_t Denominator>
47template <
intmax_t Numerator,
intmax_t Denominator>
56template <
typename Ratio>
60template <
intmax_t Numerator,
intmax_t Denominator>
64#ifdef NEFORCE_STANDARD_14
85template <
typename ratio1,
typename ratio2>
86struct __ratio_multiply_impl {
93 safe_multiply<(ratio1::den / gcd2), (ratio2::den / gcd1)>::value>;
95 static constexpr intmax_t num = type::num;
96 static constexpr intmax_t den = type::den;
99template <
typename ratio1,
typename ratio2>
100constexpr intmax_t __ratio_multiply_impl<ratio1, ratio2>::num;
102template <
typename ratio1,
typename ratio2>
103constexpr intmax_t __ratio_multiply_impl<ratio1, ratio2>::den;
114template <
typename ratio1,
typename ratio2>
115using ratio_multiply =
typename inner::__ratio_multiply_impl<ratio1, ratio2>::type;
128template <
typename ratio1,
typename ratio2>
129struct __ratio_divide_impl {
130 static_assert(ratio2::num != 0,
"division by 0");
132 using type =
typename __ratio_multiply_impl<ratio1, ratio<ratio2::den, ratio2::num>>::type;
134 static constexpr intmax_t num = type::num;
135 static constexpr intmax_t den = type::den;
138template <
typename ratio1,
typename ratio2>
139constexpr intmax_t __ratio_divide_impl<ratio1, ratio2>::num;
141template <
typename ratio1,
typename ratio2>
142constexpr intmax_t __ratio_divide_impl<ratio1, ratio2>::den;
153template <
typename ratio1,
typename ratio2>
154using ratio_divide =
typename inner::__ratio_divide_impl<ratio1, ratio2>::type;
163template <
typename ratio1,
typename ratio2>
172template <
typename ratio1,
typename ratio2>
188template <
typename ratio1,
typename ratio2,
typename left_product = big_mul<ratio1::num, ratio2::den>,
189 typename right_product = big_mul<ratio2::num, ratio1::den>>
190struct __ratio_less_impl_base :
bool_constant<big_less<left_product::result_high, left_product::result_low,
191 right_product::result_high, right_product::result_low>::value> {
204template <
typename ratio1,
typename ratio2,
205 bool has_zero_or_different_sign = (ratio1::num == 0 || ratio2::num == 0 ||
208struct __ratio_less_impl : __ratio_less_impl_base<ratio1, ratio2>::type {};
210template <
typename ratio1,
typename ratio2>
211 struct __ratio_less_impl<ratio1, ratio2, true, false> :
bool_constant < ratio1::num<ratio2::num> {};
213template <typename ratio1, typename ratio2>
214struct __ratio_less_impl<ratio1, ratio2, false, true>
215: __ratio_less_impl_base<ratio<-ratio2::num, ratio2::den>, ratio<-ratio1::num, ratio1::den>>::type {};
226template <typename ratio1, typename ratio2>
227struct ratio_less : inner::__ratio_less_impl<ratio1, ratio2>::type {};
235template <typename ratio1, typename ratio2>
236struct ratio_less_equal : bool_constant<!ratio_less<ratio2, ratio1>::value> {};
244template <typename ratio1, typename ratio2>
245struct ratio_greater : bool_constant<ratio_less<ratio2, ratio1>::value> {};
253template <typename ratio1, typename ratio2>
254struct ratio_greater_equal : bool_constant<!ratio_less<ratio1, ratio2>::value> {};
257#ifdef NEFORCE_STANDARD_14
263template <typename ratio1, typename ratio2>
264NEFORCE_INLINE17 constexpr bool ratio_equal_v = ratio_equal<ratio1, ratio2>::value;
270template <typename ratio1, typename ratio2>
271NEFORCE_INLINE17 constexpr bool ratio_not_equal_v = ratio_not_equal<ratio1, ratio2>::value;
277template <typename ratio1, typename ratio2>
278NEFORCE_INLINE17 constexpr bool ratio_less_v = ratio_less<ratio1, ratio2>::value;
284template <typename ratio1, typename ratio2>
285NEFORCE_INLINE17 constexpr bool ratio_less_equal_v = ratio_less_equal<ratio1, ratio2>::value;
291template <typename ratio1, typename ratio2>
292NEFORCE_INLINE17 constexpr bool ratio_greater_v = ratio_greater<ratio1, ratio2>::value;
298template <typename ratio1, typename ratio2>
299NEFORCE_INLINE17 constexpr bool ratio_greater_equal_v = ratio_greater_equal<ratio1, ratio2>::value;
317template <typename ratio1, typename ratio2, bool ratio1_non_negative = (ratio1::num >= 0),
318 bool ratio2_non_negative = (ratio2::num >= 0),
319 bool abs_ratio1_less_than_abs_ratio2 =
ratio_less<ratio<static_abs<ratio1::num>::value, ratio1::den>,
320 ratio<static_abs<ratio2::num>::value, ratio2::den>>::value>
321struct __ratio_add_impl {
323 using negative_result =
324 typename __ratio_add_impl<
ratio<-ratio1::num, ratio1::den>,
ratio<-ratio2::num, ratio2::den>>::type;
327 using type =
ratio<-negative_result::num, negative_result::den>;
333template <
typename ratio1,
typename ratio2,
bool abs_less>
334struct __ratio_add_impl<ratio1, ratio2, true, true, abs_less> {
336 static constexpr uintmax_t gcd_val = static_gcd<ratio1::den, ratio2::den>::value;
337 static constexpr uintmax_t den2_scaled = ratio2::den / gcd_val;
339 using denominator_product = big_mul<ratio1::den, den2_scaled>;
340 using numerator1_scaled = big_mul<ratio1::num, ratio2::den / gcd_val>;
341 using numerator2_scaled = big_mul<ratio2::num, ratio1::den / gcd_val>;
342 using numerator_sum =
343 big_add<numerator1_scaled::result_high, numerator1_scaled::result_low, numerator2_scaled::result_high,
344 numerator2_scaled::result_low>;
346 static_assert(numerator_sum::result_high >= numerator1_scaled::result_high,
"Internal library error");
348 using numerator_gcd_reduced = big_div<numerator_sum::result_high, numerator_sum::result_low,
350 static constexpr uintmax_t gcd_val2 = static_gcd<numerator_gcd_reduced::remainder,
352 using numerator_final = big_div<numerator_sum::result_high, numerator_sum::result_low,
355 static_assert(numerator_final::remainder == 0,
"Internal library error");
356 static_assert(numerator_final::quotient_high == 0 &&
357 numerator_final::quotient_low <= numeric_traits<intmax_t>::max(),
358 "overflow in addition");
360 using denominator_final = big_mul<ratio1::den / gcd_val2, den2_scaled>;
362 static_assert(denominator_final::result_high == 0 &&
363 denominator_final::result_low <= numeric_traits<intmax_t>::max(),
364 "overflow in addition");
367 using type = ratio<numerator_final::quotient_low, denominator_final::result_low>;
373template <
typename ratio1,
typename ratio2>
374struct __ratio_add_impl<ratio1, ratio2, false, true, true> : __ratio_add_impl<ratio2, ratio1> {};
379template <
typename ratio1,
typename ratio2>
380struct __ratio_add_impl<ratio1, ratio2, true, false, false> {
382 static constexpr uintmax_t gcd_val = static_gcd<ratio1::den, ratio2::den>::value;
383 static constexpr uintmax_t den2_scaled = ratio2::den / gcd_val;
385 using denominator_product = big_mul<ratio1::den, den2_scaled>;
386 using numerator1_scaled = big_mul<ratio1::num, ratio2::den / gcd_val>;
387 using numerator2_scaled = big_mul<-ratio2::num, ratio1::den / gcd_val>;
389 using numerator_diff = big_sub<numerator1_scaled::result_high, numerator1_scaled::result_low,
390 numerator2_scaled::result_high, numerator2_scaled::result_low>;
392 using numerator_gcd_reduced = big_div<numerator_diff::result_high, numerator_diff::result_low, gcd_val>;
393 static constexpr uintmax_t gcd_val2 = static_gcd<numerator_gcd_reduced::remainder, gcd_val>::value;
394 using numerator_final = big_div<numerator_diff::result_high, numerator_diff::result_low, gcd_val2>;
396 static_assert(numerator_final::remainder == 0,
"Internal library error");
397 static_assert(numerator_final::quotient_high == 0 &&
398 numerator_final::quotient_low <= numeric_traits<intmax_t>::max(),
399 "overflow in addition");
401 using denominator_final = big_mul<ratio1::den / gcd_val2, den2_scaled>;
403 static_assert(denominator_final::result_high == 0 &&
404 denominator_final::result_low <= numeric_traits<intmax_t>::max(),
405 "overflow in addition");
408 using type = ratio<numerator_final::quotient_low, denominator_final::result_low>;
417template <
typename ratio1,
typename ratio2>
419 using type =
typename __ratio_add_impl<ratio1, ratio2>::type;
420 static constexpr intmax_t num = type::num;
421 static constexpr intmax_t den = type::den;
424template <
typename ratio1,
typename ratio2>
427template <
typename ratio1,
typename ratio2>
439template <
typename ratio1,
typename ratio2>
440using ratio_add =
typename inner::ratio_add<ratio1, ratio2>::type;
453template <
typename ratio1,
typename ratio2>
455 using type =
typename ratio_add<ratio1,
ratio<-ratio2::num, ratio2::den>>::type;
457 static constexpr intmax_t num = type::num;
458 static constexpr intmax_t den = type::den;
461template <
typename ratio1,
typename ratio2>
464template <
typename ratio1,
typename ratio2>
476template <
typename ratio1,
typename ratio2>
506NEFORCE_END_NAMESPACE__
static NEFORCE_NODISCARD constexpr T min() noexcept
获取类型的最小值
NEFORCE_INLINE17 constexpr bool is_ratio_v
is_ratio的便捷变量模板
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
比率减法类型别名
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