NexusForce 1.0.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
static_numeric.hpp
浏览该文件的文档.
1#ifndef NEFORCE_CORE_NUMERIC_STATIC_NUMERIC_HPP__
2#define NEFORCE_CORE_NUMERIC_STATIC_NUMERIC_HPP__
3
11
15NEFORCE_BEGIN_NAMESPACE__
16
22
30template <intmax_t Numerator>
31struct static_sign : integral_constant<intmax_t, (Numerator < 0) ? -1 : 1> {};
32
40template <intmax_t Value>
41struct static_abs : integral_constant<intmax_t, Value * static_sign<Value>::value> {};
42
52template <intmax_t A, intmax_t B>
53struct static_gcd : static_gcd<B, (A % B)> {};
54
56template <intmax_t A>
57struct static_gcd<A, 0> : integral_constant<intmax_t, static_abs<A>::value> {};
58template <intmax_t B>
59struct static_gcd<0, B> : integral_constant<intmax_t, static_abs<B>::value> {};
61
62
71template <intmax_t A, intmax_t B>
72struct safe_multiply {
73private:
74 static constexpr uintmax_t half_range = static_cast<uintmax_t>(1) << (sizeof(intmax_t) * 4);
75
76 static const uintmax_t a_low = static_abs<A>::value % half_range;
77 static const uintmax_t a_high = static_abs<A>::value / half_range;
78 static const uintmax_t b_low = static_abs<B>::value % half_range;
79 static const uintmax_t b_high = static_abs<B>::value / half_range;
80
81 static_assert(a_high == 0 || b_high == 0, "overflow in multiplication");
82 static_assert(a_low * b_high + b_low * a_high < (half_range >> 1), "overflow in multiplication");
83 static_assert(b_low * a_low <= numeric_traits<intmax_t>::max(), "overflow in multiplication");
84 static_assert((a_low * b_high + b_low * a_high) * half_range <= numeric_traits<intmax_t>::max() - b_low * a_low,
85 "overflow in multiplication");
86
87public:
88 static const intmax_t value = A * B;
89};
90
101template <uintmax_t High1, uintmax_t Low1, uintmax_t High2, uintmax_t Low2>
102struct big_less : integral_constant<bool, (High1 < High2 || (High1 == High2 && Low1 < Low2))> {};
103
114template <uintmax_t High1, uintmax_t Low1, uintmax_t High2, uintmax_t Low2>
115struct big_add {
116 static constexpr uintmax_t result_low = Low1 + Low2;
117 static constexpr uintmax_t result_high =
118 (High1 + High2 + static_cast<uintmax_t>(Low1 + Low2 < Low1));
119};
120
131template <uintmax_t High1, uintmax_t Low1, uintmax_t High2, uintmax_t Low2>
132struct big_sub {
133 static_assert(!big_less<High1, Low1, High2, Low2>::value, "Internal library error");
134 static constexpr uintmax_t result_low = Low1 - Low2;
135 static constexpr uintmax_t result_high =
136 (High1 - High2 - static_cast<uintmax_t>(Low1 < Low2));
137};
138
147template <uintmax_t X, uintmax_t Y>
148struct big_mul {
149private:
150 static constexpr uintmax_t half_range = static_cast<uintmax_t>(1) << (sizeof(intmax_t) * 4);
151 static constexpr uintmax_t x_low = X % half_range;
152 static constexpr uintmax_t x_high = X / half_range;
153 static constexpr uintmax_t y_low = Y % half_range;
154 static constexpr uintmax_t y_high = Y / half_range;
155 static constexpr uintmax_t low_product = x_low * y_low;
156 static constexpr uintmax_t cross_product1 = x_low * y_high;
157 static constexpr uintmax_t cross_product2 = x_high * y_low;
158 static constexpr uintmax_t cross_sum = cross_product1 + cross_product2;
159 static constexpr uintmax_t cross_sum_low = cross_sum * half_range;
160 static constexpr uintmax_t cross_sum_high =
161 cross_sum / half_range + ((cross_sum < cross_product1) ? half_range : 0);
162 using result_type = big_add<cross_sum_high, cross_sum_low, x_high * y_high, low_product>;
163public:
164 static constexpr uintmax_t result_high = result_type::result_high;
165 static constexpr uintmax_t result_low = result_type::result_low;
166};
167
169NEFORCE_BEGIN_INNER__
179template <uintmax_t NumHigh, uintmax_t NumLow, uintmax_t Den>
180struct __big_div_impl {
181private:
182 static_assert(Den >= (static_cast<uintmax_t>(1) << (sizeof(intmax_t) * 8 - 1)), "Internal library error");
183 static_assert(NumHigh < Den, "Internal library error");
184 static constexpr uintmax_t half_range = static_cast<uintmax_t>(1) << (sizeof(intmax_t) * 4);
185 static constexpr uintmax_t den_high = Den / half_range;
186 static constexpr uintmax_t den_low = Den % half_range;
187
188 static constexpr uintmax_t quot_high1 = NumHigh / den_high;
189 static constexpr uintmax_t rem_high1 = NumHigh % den_high;
190 static constexpr uintmax_t temp1 = quot_high1 * den_low;
191 static constexpr uintmax_t rem_high2 = rem_high1 * half_range + NumLow / half_range;
192 static constexpr uintmax_t rem_high3 = rem_high2 + Den;
193 static constexpr uintmax_t rem_high_final =
194 ((rem_high2 < temp1) ? ((rem_high3 >= Den) && (rem_high3 < temp1)) ? (rem_high3 + Den) : rem_high3
195 : rem_high2) -
196 temp1;
197 static constexpr uintmax_t quot_high_final =
198 quot_high1 - ((rem_high2 < temp1) ? ((rem_high3 >= Den) && (rem_high3 < temp1)) ? 2 : 1 : 0);
199 static constexpr uintmax_t quot_low1 = rem_high_final / den_high;
200 static constexpr uintmax_t rem_low1 = rem_high_final % den_high;
201 static constexpr uintmax_t temp2 = quot_low1 * den_low;
202 static constexpr uintmax_t rem_low2 = rem_low1 * half_range + NumLow % half_range;
203 static constexpr uintmax_t rem_low3 = rem_low2 + Den;
204 static constexpr uintmax_t rem_low_final =
205 ((rem_low2 < temp2) ? ((rem_low3 >= Den) && (rem_low3 < temp2)) ? (rem_low3 + Den) : rem_low3 : rem_low2) -
206 temp2;
207 static constexpr uintmax_t quot_low_final =
208 quot_low1 - ((rem_low2 < temp2) ? ((rem_low3 >= Den) && (rem_low3 < temp2)) ? 2 : 1 : 0);
209
210public:
211 static constexpr uintmax_t quotient = quot_high_final * half_range + quot_low_final;
212 static constexpr uintmax_t remainder = rem_low_final;
213
214private:
215 using product = big_mul<quotient, Den>;
216 using sum = big_add<product::result_high, product::result_low, 0, remainder>;
217 static_assert(sum::result_high == NumHigh && sum::result_low == NumLow, "Internal library error");
218};
219NEFORCE_END_INNER__
221
231template <uintmax_t NumHigh, uintmax_t NumLow, uintmax_t Den>
232struct big_div {
233private:
234 static_assert(Den != 0, "Internal library error");
235 static_assert(sizeof(uintmax_t) == sizeof(unsigned long long), "clzll is unsafe on your platform.");
236 static constexpr int leading_zeros = _NEFORCE countl_zero(Den);
237 static constexpr int complement_shift = sizeof(uintmax_t) * 8 - leading_zeros;
238 static constexpr int actual_shift = (leading_zeros != 0) ? complement_shift : 0;
239 static constexpr uintmax_t shift_factor1 = static_cast<uintmax_t>(1) << leading_zeros;
240 static constexpr uintmax_t shift_factor2 = static_cast<uintmax_t>(1) << actual_shift;
241 static constexpr uintmax_t scaled_den = Den * shift_factor1;
242 static constexpr uintmax_t scaled_num_low = NumLow * shift_factor1;
243 static constexpr uintmax_t num_high_shifted = (NumHigh % Den) * shift_factor1;
244 static constexpr uintmax_t num_low_high =
245 (leading_zeros != 0) ? (NumLow / shift_factor2) : 0;
246 static constexpr uintmax_t scaled_num_high = num_high_shifted + num_low_high;
247 using division_result = inner::__big_div_impl<scaled_num_high, scaled_num_low, scaled_den>;
248
249public:
250 static constexpr uintmax_t quotient_high = NumHigh / Den;
251 static constexpr uintmax_t quotient_low = division_result::quotient;
252 static constexpr uintmax_t remainder = division_result::remainder / shift_factor1;
253
254private:
255 using product_low = big_mul<quotient_low, Den>;
256 using product_high = big_mul<quotient_high, Den>;
257 using total_sum = big_add<product_low::result_high, product_low::result_low, product_high::result_low, remainder>;
258
259 static_assert(product_high::result_high == 0, "Internal library error");
260 static_assert(total_sum::result_high >= product_low::result_high, "Internal library error");
261
262 static_assert(total_sum::result_high == NumHigh && total_sum::result_low == NumLow, "Internal library error");
263 static_assert(remainder < Den, "Internal library error");
264};
265 // StaticArithmetic
267
273
283template <uint32_t Base, char Digit>
284struct static_char_digit;
285
286template <uint32_t Base>
287struct static_char_digit<Base, '0'> : uint32_constant<0> {
288 using is_valid = true_type;
289};
290
291template <uint32_t Base>
292struct static_char_digit<Base, '1'> : uint32_constant<1> {
293 using is_valid = true_type;
294};
295
297NEFORCE_BEGIN_INNER__
306template <uint32_t Base, uint32_t Value>
307struct __static_char_digit_aux : uint32_constant<Value> {
308 static_assert(Base > Value, "Invalid digit for given base");
309 using is_valid = true_type;
310};
311NEFORCE_END_INNER__
313
314template <uint32_t Base>
315struct static_char_digit<Base, '2'> : inner::__static_char_digit_aux<Base, 2> {};
316
317template <uint32_t Base>
318struct static_char_digit<Base, '3'> : inner::__static_char_digit_aux<Base, 3> {};
319
320template <uint32_t Base>
321struct static_char_digit<Base, '4'> : inner::__static_char_digit_aux<Base, 4> {};
322
323template <uint32_t Base>
324struct static_char_digit<Base, '5'> : inner::__static_char_digit_aux<Base, 5> {};
325
326template <uint32_t Base>
327struct static_char_digit<Base, '6'> : inner::__static_char_digit_aux<Base, 6> {};
328
329template <uint32_t Base>
330struct static_char_digit<Base, '7'> : inner::__static_char_digit_aux<Base, 7> {};
331
332template <uint32_t Base>
333struct static_char_digit<Base, '8'> : inner::__static_char_digit_aux<Base, 8> {};
334
335template <uint32_t Base>
336struct static_char_digit<Base, '9'> : inner::__static_char_digit_aux<Base, 9> {};
337
338template <uint32_t Base>
339struct static_char_digit<Base, 'a'> : inner::__static_char_digit_aux<Base, 0xa> {};
340
341template <uint32_t Base>
342struct static_char_digit<Base, 'A'> : inner::__static_char_digit_aux<Base, 0xa> {};
343
344template <uint32_t Base>
345struct static_char_digit<Base, 'b'> : inner::__static_char_digit_aux<Base, 0xb> {};
346
347template <uint32_t Base>
348struct static_char_digit<Base, 'B'> : inner::__static_char_digit_aux<Base, 0xb> {};
349
350template <uint32_t Base>
351struct static_char_digit<Base, 'c'> : inner::__static_char_digit_aux<Base, 0xc> {};
352
353template <uint32_t Base>
354struct static_char_digit<Base, 'C'> : inner::__static_char_digit_aux<Base, 0xc> {};
355
356template <uint32_t Base>
357struct static_char_digit<Base, 'd'> : inner::__static_char_digit_aux<Base, 0xd> {};
358
359template <uint32_t Base>
360struct static_char_digit<Base, 'D'> : inner::__static_char_digit_aux<Base, 0xd> {};
361
362template <uint32_t Base>
363struct static_char_digit<Base, 'e'> : inner::__static_char_digit_aux<Base, 0xe> {};
364
365template <uint32_t Base>
366struct static_char_digit<Base, 'E'> : inner::__static_char_digit_aux<Base, 0xe> {};
367
368template <uint32_t Base>
369struct static_char_digit<Base, 'f'> : inner::__static_char_digit_aux<Base, 0xf> {};
370
371template <uint32_t Base>
372struct static_char_digit<Base, 'F'> : inner::__static_char_digit_aux<Base, 0xf> {};
373
374template <uint32_t Base>
375struct static_char_digit<Base, '\''> : uint32_constant<0> {
376 using is_valid = false_type;
377};
378
379
381NEFORCE_BEGIN_INNER__
382
392template <uint32_t Base, char ThisDigit, char... RestDigits>
393struct __power_helper {
394private:
395 using next_power = typename __power_helper<Base, RestDigits...>::type;
396 using current_digit = static_char_digit<Base, ThisDigit>;
397
398public:
399 using type = uint64_constant<next_power::value*(current_digit::is_valid::value ? Base : 1ULL)>;
400};
401
402template <uint32_t Base, char Digit>
403struct __power_helper<Base, Digit> {
404private:
405 using current_digit = static_char_digit<Base, Digit>;
406
407public:
408 using type = uint64_constant<current_digit::is_valid::value>;
409};
410
411NEFORCE_END_INNER__
413
422template <uint32_t Base, char... Digits>
423struct static_power : inner::__power_helper<Base, Digits...>::type {};
424
425template <uint32_t Base>
426struct static_power<Base> : uint64_constant<0> {};
427
428
430NEFORCE_BEGIN_INNER__
431
442template <uint32_t Base, uint64_t ThisPower, char ThisDigit, char... RestDigits>
443struct __number_aux {
444private:
445 using digit_value = static_char_digit<Base, ThisDigit>;
446 using next_number = __number_aux<Base, digit_value::is_valid::value ? ThisPower / Base : ThisPower, RestDigits...>;
447
448public:
449 using type = uint64_constant<ThisPower * digit_value::value + next_number::type::value>;
450
451 static_assert((type::value / ThisPower) == digit_value::value,
452 "Integer literal does not fit in unsigned long long");
453};
454
455template <uint32_t Base, uint64_t ThisPower, char ThisDigit, char... RestDigits>
456struct __number_aux<Base, ThisPower, '\'', ThisDigit, RestDigits...>
457: __number_aux<Base, ThisPower, ThisDigit, RestDigits...> {};
458
459template <uint32_t Base, char Digit>
460struct __number_aux<Base, 1ULL, Digit> {
461 using type = uint64_constant<static_char_digit<Base, Digit>::value>;
462};
463
464NEFORCE_END_INNER__
466
475template <uint32_t Base, char... Digits>
476struct static_number : inner::__number_aux<Base, static_power<Base, Digits...>::value, Digits...>::type {};
477
478template <uint32_t Base>
479struct static_number<Base> : uint64_constant<0> {};
480
481
493template <char... Digits>
494struct static_parse_int;
495
496template <char... Digits>
497struct static_parse_int<'0', 'b', Digits...> : static_number<2U, Digits...>::type {};
498
499template <char... Digits>
500struct static_parse_int<'0', 'B', Digits...> : static_number<2U, Digits...>::type {};
501
502template <char... Digits>
503struct static_parse_int<'0', 'x', Digits...> : static_number<16U, Digits...>::type {};
504
505template <char... Digits>
506struct static_parse_int<'0', 'X', Digits...> : static_number<16U, Digits...>::type {};
507
508template <char... Digits>
509struct static_parse_int<'0', Digits...> : static_number<8U, Digits...>::type {};
510
511template <char... Digits>
512struct static_parse_int : static_number<10U, Digits...>::type {};
513
514
516NEFORCE_BEGIN_INNER__
517
526template <uint64_t Value, typename... IntTypes>
527struct __select_int_base;
528
529template <uint64_t Value, typename IntType, typename... RestIntTypes>
530struct __select_int_base<Value, IntType, RestIntTypes...>
531: conditional_t<(Value <= numeric_traits<IntType>::max()), integral_constant<IntType, static_cast<IntType>(Value)>,
532 __select_int_base<Value, RestIntTypes...>> {};
533
534template <uint64_t Value>
535struct __select_int_base<Value> {};
536
537NEFORCE_END_INNER__
539
547template <char... Digits>
548using static_select_int_t =
549 typename inner::__select_int_base<static_parse_int<Digits...>::value, unsigned char, unsigned short,
550 unsigned int, unsigned long, unsigned long long>::type;
551 // StaticCharDigit
553
554NEFORCE_END_NAMESPACE__
555#endif // NEFORCE_CORE_NUMERIC_STATIC_NUMERIC_HPP__
位操作函数
数值特征
整数常量包装器
计算整数的符号
类型萃取