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
44#ifndef NEFORCE_STANDARD_17
45template <intmax_t Numerator, intmax_t Denominator>
47
48template <intmax_t Numerator, intmax_t Denominator>
50#endif
51
52
58template <typename Ratio>
59struct is_ratio : false_type {};
60
62template <intmax_t Numerator, intmax_t Denominator>
63struct is_ratio<ratio<Numerator, Denominator>> : true_type {};
65
66#ifdef NEFORCE_STANDARD_14
71template <typename T>
72NEFORCE_INLINE17 constexpr bool is_ratio_v = is_ratio<T>::value;
73#endif
74
75
77NEFORCE_BEGIN_INNER__
78
87template <typename ratio1, typename ratio2>
88struct __ratio_multiply_impl {
89private:
92
93public:
94 using type = ratio<safe_multiply<(ratio1::num / gcd1), (ratio2::num / gcd2)>::value,
95 safe_multiply<(ratio1::den / gcd2), (ratio2::den / gcd1)>::value>;
96
97 static constexpr intmax_t num = type::num;
98 static constexpr intmax_t den = type::den;
99};
100
101#ifndef NEFORCE_STANDARD_17
102template <typename ratio1, typename ratio2>
103constexpr intmax_t __ratio_multiply_impl<ratio1, ratio2>::num;
104
105template <typename ratio1, typename ratio2>
106constexpr intmax_t __ratio_multiply_impl<ratio1, ratio2>::den;
107#endif
108
109NEFORCE_END_INNER__
111
118template <typename ratio1, typename ratio2>
119using ratio_multiply = typename inner::__ratio_multiply_impl<ratio1, ratio2>::type;
120
122NEFORCE_BEGIN_INNER__
123
132template <typename ratio1, typename ratio2>
133struct __ratio_divide_impl {
134 static_assert(ratio2::num != 0, "division by 0");
135
136 using type = typename __ratio_multiply_impl<ratio1, ratio<ratio2::den, ratio2::num>>::type;
137
138 static constexpr intmax_t num = type::num;
139 static constexpr intmax_t den = type::den;
140};
141
142#ifndef NEFORCE_STANDARD_17
143template <typename ratio1, typename ratio2>
144constexpr intmax_t __ratio_divide_impl<ratio1, ratio2>::num;
145
146template <typename ratio1, typename ratio2>
147constexpr intmax_t __ratio_divide_impl<ratio1, ratio2>::den;
148#endif
149
150NEFORCE_END_INNER__
152
159template <typename ratio1, typename ratio2>
160using ratio_divide = typename inner::__ratio_divide_impl<ratio1, ratio2>::type;
161
162
169template <typename ratio1, typename ratio2>
170struct ratio_equal : bool_constant<ratio1::num == ratio2::num && ratio1::den == ratio2::den> {};
171
178template <typename ratio1, typename ratio2>
179struct ratio_not_equal : bool_constant<!ratio_equal<ratio1, ratio2>::value> {};
180
182NEFORCE_BEGIN_INNER__
183
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> {
198};
199
210template <typename ratio1, typename ratio2,
211 bool has_zero_or_different_sign = (ratio1::num == 0 || ratio2::num == 0 ||
213 bool both_negative = (static_sign<ratio1::num>::value == -1 && static_sign<ratio2::num>::value == -1)>
214struct __ratio_less_impl : __ratio_less_impl_base<ratio1, ratio2>::type {};
215
216template <typename ratio1, typename ratio2>
217 struct __ratio_less_impl<ratio1, ratio2, true, false> : bool_constant < ratio1::num<ratio2::num> {};
218
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 {};
222
223NEFORCE_END_INNER__
225
232template <typename ratio1, typename ratio2>
233struct ratio_less : inner::__ratio_less_impl<ratio1, ratio2>::type {};
234
241template <typename ratio1, typename ratio2>
242struct ratio_less_equal : bool_constant<!ratio_less<ratio2, ratio1>::value> {};
243
250template <typename ratio1, typename ratio2>
251struct ratio_greater : bool_constant<ratio_less<ratio2, ratio1>::value> {};
252
259template <typename ratio1, typename ratio2>
260struct ratio_greater_equal : bool_constant<!ratio_less<ratio1, ratio2>::value> {};
261
262
263#ifdef NEFORCE_STANDARD_14
264
269template <typename ratio1, typename ratio2>
270NEFORCE_INLINE17 constexpr bool ratio_equal_v = ratio_equal<ratio1, ratio2>::value;
271
276template <typename ratio1, typename ratio2>
277NEFORCE_INLINE17 constexpr bool ratio_not_equal_v = ratio_not_equal<ratio1, ratio2>::value;
278
283template <typename ratio1, typename ratio2>
284NEFORCE_INLINE17 constexpr bool ratio_less_v = ratio_less<ratio1, ratio2>::value;
285
290template <typename ratio1, typename ratio2>
291NEFORCE_INLINE17 constexpr bool ratio_less_equal_v = ratio_less_equal<ratio1, ratio2>::value;
292
297template <typename ratio1, typename ratio2>
298NEFORCE_INLINE17 constexpr bool ratio_greater_v = ratio_greater<ratio1, ratio2>::value;
299
304template <typename ratio1, typename ratio2>
305NEFORCE_INLINE17 constexpr bool ratio_greater_equal_v = ratio_greater_equal<ratio1, ratio2>::value;
306#endif
307
308
310NEFORCE_BEGIN_INNER__
311
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 {
328private:
329 using negative_result =
330 typename __ratio_add_impl<ratio<-ratio1::num, ratio1::den>, ratio<-ratio2::num, ratio2::den>>::type;
331
332public:
333 using type = ratio<-negative_result::num, negative_result::den>;
334};
335
339template <typename ratio1, typename ratio2, bool abs_less>
340struct __ratio_add_impl<ratio1, ratio2, true, true, abs_less> {
341private:
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;
344
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>;
351
352 static_assert(numerator_sum::result_high >= numerator1_scaled::result_high, "Internal library error");
353
354 using numerator_gcd_reduced = big_div<numerator_sum::result_high, numerator_sum::result_low,
355 gcd_val>;
356 static constexpr uintmax_t gcd_val2 = static_gcd<numerator_gcd_reduced::remainder,
357 gcd_val>::value;
358 using numerator_final = big_div<numerator_sum::result_high, numerator_sum::result_low,
359 gcd_val2>;
360
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");
365
366 using denominator_final = big_mul<ratio1::den / gcd_val2, den2_scaled>;
367
368 static_assert(denominator_final::result_high == 0 &&
369 denominator_final::result_low <= numeric_traits<intmax_t>::max(),
370 "overflow in addition");
371
372public:
373 using type = ratio<numerator_final::quotient_low, denominator_final::result_low>;
374};
375
379template <typename ratio1, typename ratio2>
380struct __ratio_add_impl<ratio1, ratio2, false, true, true> : __ratio_add_impl<ratio2, ratio1> {};
381
385template <typename ratio1, typename ratio2>
386struct __ratio_add_impl<ratio1, ratio2, true, false, false> {
387private:
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;
390
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>;
394
395 using numerator_diff = big_sub<numerator1_scaled::result_high, numerator1_scaled::result_low,
396 numerator2_scaled::result_high, numerator2_scaled::result_low>;
397
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>;
401
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");
406
407 using denominator_final = big_mul<ratio1::den / gcd_val2, den2_scaled>;
408
409 static_assert(denominator_final::result_high == 0 &&
410 denominator_final::result_low <= numeric_traits<intmax_t>::max(),
411 "overflow in addition");
412
413public:
414 using type = ratio<numerator_final::quotient_low, denominator_final::result_low>;
415};
416
423template <typename ratio1, typename ratio2>
424struct ratio_add {
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;
428};
429
430#ifndef NEFORCE_STANDARD_17
431template <typename ratio1, typename ratio2>
433
434template <typename ratio1, typename ratio2>
436#endif
437
438NEFORCE_END_INNER__
440
447template <typename ratio1, typename ratio2>
448using ratio_add = typename inner::ratio_add<ratio1, ratio2>::type;
449
451NEFORCE_BEGIN_INNER__
452
461template <typename ratio1, typename ratio2>
462struct ratio_subtract {
463 using type = typename ratio_add<ratio1, ratio<-ratio2::num, ratio2::den>>::type;
464
465 static constexpr intmax_t num = type::num;
466 static constexpr intmax_t den = type::den;
467};
468
469#ifndef NEFORCE_STANDARD_17
470template <typename ratio1, typename ratio2>
472
473template <typename ratio1, typename ratio2>
475#endif
476
477NEFORCE_END_INNER__
479
486template <typename ratio1, typename ratio2>
487using ratio_subtract = typename inner::ratio_subtract<ratio1, ratio2>::type;
488 // RatioClass
490
496
513 // SIUnits
515
516NEFORCE_END_NAMESPACE__
517#endif // NEFORCE_CORE_NUMERIC_RATIO_HPP__
static constexpr T min() noexcept
获取类型的最小值
int64_t intmax_t
最大有符号整数类型
uint64_t uintmax_t
最大无符号整数类型
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
布尔常量包装器
静态数值计算
检查类型是否为ratio
检查两个比率是否相等
检查第一个比率是否小于第二个比率
检查两个比率是否不相等
比率类模板
static constexpr intmax_t num
ratio< num, den > type
自身的类型
static constexpr intmax_t den
安全的编译期乘法,检查溢出
计算两个整数的最大公约数
计算整数的符号