NexusForce 1.0.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
ratio.hpp
浏览该文件的文档.
1#ifndef NEFORCE_CORE_NUMERIC_RATIO_HPP__
2#define NEFORCE_CORE_NUMERIC_RATIO_HPP__
3
11
13NEFORCE_BEGIN_NAMESPACE__
14
20
30template <intmax_t Numerator, intmax_t Denominator = 1>
31struct ratio {
32 static_assert(Denominator != 0, "denominator cannot be zero");
33 static_assert(Numerator > numeric_traits<intmax_t>::min() && Denominator > numeric_traits<intmax_t>::min(),
34 "out of range");
35
36 static constexpr intmax_t num =
38 static constexpr intmax_t den =
40
42};
43
44template <intmax_t Numerator, intmax_t Denominator>
46
47template <intmax_t Numerator, intmax_t Denominator>
49
50
56template <typename Ratio>
57struct is_ratio : false_type {};
58
60template <intmax_t Numerator, intmax_t Denominator>
61struct is_ratio<ratio<Numerator, Denominator>> : true_type {};
63
64#ifdef NEFORCE_STANDARD_14
69template <typename T>
70NEFORCE_INLINE17 constexpr bool is_ratio_v = is_ratio<T>::value;
71#endif
72
73
75NEFORCE_BEGIN_INNER__
76
85template <typename ratio1, typename ratio2>
86struct __ratio_multiply_impl {
87private:
90
91public:
92 using type = ratio<safe_multiply<(ratio1::num / gcd1), (ratio2::num / gcd2)>::value,
93 safe_multiply<(ratio1::den / gcd2), (ratio2::den / gcd1)>::value>;
94
95 static constexpr intmax_t num = type::num;
96 static constexpr intmax_t den = type::den;
97};
98
99template <typename ratio1, typename ratio2>
100constexpr intmax_t __ratio_multiply_impl<ratio1, ratio2>::num;
101
102template <typename ratio1, typename ratio2>
103constexpr intmax_t __ratio_multiply_impl<ratio1, ratio2>::den;
104
105NEFORCE_END_INNER__
107
114template <typename ratio1, typename ratio2>
115using ratio_multiply = typename inner::__ratio_multiply_impl<ratio1, ratio2>::type;
116
118NEFORCE_BEGIN_INNER__
119
128template <typename ratio1, typename ratio2>
129struct __ratio_divide_impl {
130 static_assert(ratio2::num != 0, "division by 0");
131
132 using type = typename __ratio_multiply_impl<ratio1, ratio<ratio2::den, ratio2::num>>::type;
133
134 static constexpr intmax_t num = type::num;
135 static constexpr intmax_t den = type::den;
136};
137
138template <typename ratio1, typename ratio2>
139constexpr intmax_t __ratio_divide_impl<ratio1, ratio2>::num;
140
141template <typename ratio1, typename ratio2>
142constexpr intmax_t __ratio_divide_impl<ratio1, ratio2>::den;
143
144NEFORCE_END_INNER__
146
153template <typename ratio1, typename ratio2>
154using ratio_divide = typename inner::__ratio_divide_impl<ratio1, ratio2>::type;
155
156
163template <typename ratio1, typename ratio2>
164struct ratio_equal : bool_constant<ratio1::num == ratio2::num && ratio1::den == ratio2::den> {};
165
172template <typename ratio1, typename ratio2>
173struct ratio_not_equal : bool_constant<!ratio_equal<ratio1, ratio2>::value> {};
174
176NEFORCE_BEGIN_INNER__
177
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> {
192};
193
204template <typename ratio1, typename ratio2,
205 bool has_zero_or_different_sign = (ratio1::num == 0 || ratio2::num == 0 ||
207 bool both_negative = (static_sign<ratio1::num>::value == -1 && static_sign<ratio2::num>::value == -1)>
208struct __ratio_less_impl : __ratio_less_impl_base<ratio1, ratio2>::type {};
209
210template <typename ratio1, typename ratio2>
211 struct __ratio_less_impl<ratio1, ratio2, true, false> : bool_constant < ratio1::num<ratio2::num> {};
212
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 {};
216
217NEFORCE_END_INNER__
219
226template <typename ratio1, typename ratio2>
227struct ratio_less : inner::__ratio_less_impl<ratio1, ratio2>::type {};
228
235template <typename ratio1, typename ratio2>
236struct ratio_less_equal : bool_constant<!ratio_less<ratio2, ratio1>::value> {};
237
244template <typename ratio1, typename ratio2>
245struct ratio_greater : bool_constant<ratio_less<ratio2, ratio1>::value> {};
246
253template <typename ratio1, typename ratio2>
254struct ratio_greater_equal : bool_constant<!ratio_less<ratio1, ratio2>::value> {};
255
256
257#ifdef NEFORCE_STANDARD_14
258
263template <typename ratio1, typename ratio2>
264NEFORCE_INLINE17 constexpr bool ratio_equal_v = ratio_equal<ratio1, ratio2>::value;
265
270template <typename ratio1, typename ratio2>
271NEFORCE_INLINE17 constexpr bool ratio_not_equal_v = ratio_not_equal<ratio1, ratio2>::value;
272
277template <typename ratio1, typename ratio2>
278NEFORCE_INLINE17 constexpr bool ratio_less_v = ratio_less<ratio1, ratio2>::value;
279
284template <typename ratio1, typename ratio2>
285NEFORCE_INLINE17 constexpr bool ratio_less_equal_v = ratio_less_equal<ratio1, ratio2>::value;
286
291template <typename ratio1, typename ratio2>
292NEFORCE_INLINE17 constexpr bool ratio_greater_v = ratio_greater<ratio1, ratio2>::value;
293
298template <typename ratio1, typename ratio2>
299NEFORCE_INLINE17 constexpr bool ratio_greater_equal_v = ratio_greater_equal<ratio1, ratio2>::value;
300#endif
301
302
304NEFORCE_BEGIN_INNER__
305
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 {
322private:
323 using negative_result =
324 typename __ratio_add_impl<ratio<-ratio1::num, ratio1::den>, ratio<-ratio2::num, ratio2::den>>::type;
325
326public:
327 using type = ratio<-negative_result::num, negative_result::den>;
328};
329
333template <typename ratio1, typename ratio2, bool abs_less>
334struct __ratio_add_impl<ratio1, ratio2, true, true, abs_less> {
335private:
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;
338
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>;
345
346 static_assert(numerator_sum::result_high >= numerator1_scaled::result_high, "Internal library error");
347
348 using numerator_gcd_reduced = big_div<numerator_sum::result_high, numerator_sum::result_low,
349 gcd_val>;
350 static constexpr uintmax_t gcd_val2 = static_gcd<numerator_gcd_reduced::remainder,
351 gcd_val>::value;
352 using numerator_final = big_div<numerator_sum::result_high, numerator_sum::result_low,
353 gcd_val2>;
354
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");
359
360 using denominator_final = big_mul<ratio1::den / gcd_val2, den2_scaled>;
361
362 static_assert(denominator_final::result_high == 0 &&
363 denominator_final::result_low <= numeric_traits<intmax_t>::max(),
364 "overflow in addition");
365
366public:
367 using type = ratio<numerator_final::quotient_low, denominator_final::result_low>;
368};
369
373template <typename ratio1, typename ratio2>
374struct __ratio_add_impl<ratio1, ratio2, false, true, true> : __ratio_add_impl<ratio2, ratio1> {};
375
379template <typename ratio1, typename ratio2>
380struct __ratio_add_impl<ratio1, ratio2, true, false, false> {
381private:
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;
384
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>;
388
389 using numerator_diff = big_sub<numerator1_scaled::result_high, numerator1_scaled::result_low,
390 numerator2_scaled::result_high, numerator2_scaled::result_low>;
391
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>;
395
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");
400
401 using denominator_final = big_mul<ratio1::den / gcd_val2, den2_scaled>;
402
403 static_assert(denominator_final::result_high == 0 &&
404 denominator_final::result_low <= numeric_traits<intmax_t>::max(),
405 "overflow in addition");
406
407public:
408 using type = ratio<numerator_final::quotient_low, denominator_final::result_low>;
409};
410
417template <typename ratio1, typename ratio2>
418struct ratio_add {
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;
422};
423
424template <typename ratio1, typename ratio2>
426
427template <typename ratio1, typename ratio2>
429
430NEFORCE_END_INNER__
432
439template <typename ratio1, typename ratio2>
440using ratio_add = typename inner::ratio_add<ratio1, ratio2>::type;
441
443NEFORCE_BEGIN_INNER__
444
453template <typename ratio1, typename ratio2>
454struct ratio_subtract {
455 using type = typename ratio_add<ratio1, ratio<-ratio2::num, ratio2::den>>::type;
456
457 static constexpr intmax_t num = type::num;
458 static constexpr intmax_t den = type::den;
459};
460
461template <typename ratio1, typename ratio2>
463
464template <typename ratio1, typename ratio2>
466
467NEFORCE_END_INNER__
469
476template <typename ratio1, typename ratio2>
477using ratio_subtract = typename inner::ratio_subtract<ratio1, ratio2>::type;
478 // RatioClass
480
486
503 // SIUnits
505
506NEFORCE_END_NAMESPACE__
507#endif // NEFORCE_CORE_NUMERIC_RATIO_HPP__
static NEFORCE_NODISCARD constexpr T min() noexcept
获取类型的最小值
int64_t intmax_t
最大有符号整数类型
uint64_t uintmax_t
最大无符号整数类型
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
布尔常量包装器
静态数值计算
检查类型是否为ratio
检查两个比率是否相等
检查第一个比率是否小于第二个比率
检查两个比率是否不相等
比率类模板
static constexpr intmax_t num
ratio< num, den > type
自身的类型
static constexpr intmax_t den
安全的编译期乘法,检查溢出
计算两个整数的最大公约数
计算整数的符号