MSTL 1.4.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
static_numeric.hpp
浏览该文件的文档.
1#ifndef MSTL_CORE_NUMERIC_STATIC_NUMERIC_HPP__
2#define MSTL_CORE_NUMERIC_STATIC_NUMERIC_HPP__
3
11
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, "overflow in multiplication");
85
86public:
87 static const intmax_t value = A * B;
88};
89
100template <uintmax_t High1, uintmax_t Low1, uintmax_t High2, uintmax_t Low2>
101struct big_less : integral_constant<bool, (High1 < High2 || (High1 == High2 && Low1 < Low2))> {};
102
113template <uintmax_t High1, uintmax_t Low1, uintmax_t High2, uintmax_t Low2>
114struct big_add {
115 static constexpr uintmax_t result_low = Low1 + Low2;
116 static constexpr uintmax_t result_high = (High1 + High2 + (Low1 + Low2 < Low1));
117};
118
129template <uintmax_t High1, uintmax_t Low1, uintmax_t High2, uintmax_t Low2>
130struct big_sub {
131 static_assert(!big_less<High1, Low1, High2, Low2>::value, "Internal library error");
132 static constexpr uintmax_t result_low = Low1 - Low2;
133 static constexpr uintmax_t result_high = (High1 - High2 - (Low1 < Low2));
134};
135
144template <uintmax_t X, uintmax_t Y>
145struct big_mul {
146private:
147 static constexpr uintmax_t half_range = static_cast<uintmax_t>(1) << (sizeof(intmax_t) * 4);
148 static constexpr uintmax_t x_low = X % half_range;
149 static constexpr uintmax_t x_high = X / half_range;
150 static constexpr uintmax_t y_low = Y % half_range;
151 static constexpr uintmax_t y_high = Y / half_range;
152 static constexpr uintmax_t low_product = x_low * y_low;
153 static constexpr uintmax_t cross_product1 = x_low * y_high;
154 static constexpr uintmax_t cross_product2 = x_high * y_low;
155 static constexpr uintmax_t cross_sum = cross_product1 + cross_product2;
156 static constexpr uintmax_t cross_sum_low = cross_sum * half_range;
157 static constexpr uintmax_t cross_sum_high = cross_sum / half_range + ((cross_sum < cross_product1) ? half_range : 0);
158 using result_type = big_add<cross_sum_high, cross_sum_low, x_high * y_high, low_product>;
159public:
160 static constexpr uintmax_t result_high = result_type::result_high;
161 static constexpr uintmax_t result_low = result_type::result_low;
162};
163
165MSTL_BEGIN_INNER__
175template <uintmax_t NumHigh, uintmax_t NumLow, uintmax_t Den>
176struct __big_div_impl {
177private:
178 static_assert(Den >= (static_cast<uintmax_t>(1) << (sizeof(intmax_t) * 8 - 1)), "Internal library error");
179 static_assert(NumHigh < Den, "Internal library error");
180 static constexpr uintmax_t half_range = static_cast<uintmax_t>(1) << (sizeof(intmax_t) * 4);
181 static constexpr uintmax_t den_high = Den / half_range;
182 static constexpr uintmax_t den_low = Den % half_range;
183
184 static constexpr uintmax_t quot_high1 = NumHigh / den_high;
185 static constexpr uintmax_t rem_high1 = NumHigh % den_high;
186 static constexpr uintmax_t temp1 = quot_high1 * den_low;
187 static constexpr uintmax_t rem_high2 = rem_high1 * half_range + NumLow / half_range;
188 static constexpr uintmax_t rem_high3 = rem_high2 + Den;
189 static constexpr uintmax_t rem_high_final = ((rem_high2 < temp1) ? ((rem_high3 >= Den) && (rem_high3 < temp1)) ? (rem_high3 + Den) : rem_high3 : rem_high2) - temp1;
190 static constexpr uintmax_t quot_high_final = quot_high1 - ((rem_high2 < temp1) ? ((rem_high3 >= Den) && (rem_high3 < temp1)) ? 2 : 1 : 0);
191 static constexpr uintmax_t quot_low1 = rem_high_final / den_high;
192 static constexpr uintmax_t rem_low1 = rem_high_final % den_high;
193 static constexpr uintmax_t temp2 = quot_low1 * den_low;
194 static constexpr uintmax_t rem_low2 = rem_low1 * half_range + NumLow % half_range;
195 static constexpr uintmax_t rem_low3 = rem_low2 + Den;
196 static constexpr uintmax_t rem_low_final = ((rem_low2 < temp2) ? ((rem_low3 >= Den) && (rem_low3 < temp2)) ? (rem_low3 + Den) : rem_low3 : rem_low2) - temp2;
197 static constexpr uintmax_t quot_low_final = quot_low1 - ((rem_low2 < temp2) ? ((rem_low3 >= Den) && (rem_low3 < temp2)) ? 2 : 1 : 0);
198
199public:
200 static constexpr uintmax_t quotient = quot_high_final * half_range + quot_low_final;
201 static constexpr uintmax_t remainder = rem_low_final;
202
203private:
204 using product = big_mul<quotient, Den>;
205 using sum = big_add<product::result_high, product::result_low, 0, remainder>;
206 static_assert(sum::result_high == NumHigh && sum::result_low == NumLow, "Internal library error");
207};
208MSTL_END_INNER__
210
220template <uintmax_t NumHigh, uintmax_t NumLow, uintmax_t Den>
221struct big_div {
222private:
223 static_assert(Den != 0, "Internal library error");
224 static_assert(sizeof (uintmax_t) == sizeof (unsigned long long), "clzll is unsafe on your platform.");
225 static constexpr int leading_zeros = _MSTL clz64(Den);
226 static constexpr int complement_shift = sizeof(uintmax_t) * 8 - leading_zeros;
227 static constexpr int actual_shift = (leading_zeros != 0) ? complement_shift : 0;
228 static constexpr uintmax_t shift_factor1 = static_cast<uintmax_t>(1) << leading_zeros;
229 static constexpr uintmax_t shift_factor2 = static_cast<uintmax_t>(1) << actual_shift;
230 static constexpr uintmax_t scaled_den = Den * shift_factor1;
231 static constexpr uintmax_t scaled_num_low = NumLow * shift_factor1;
232 static constexpr uintmax_t num_high_shifted = (NumHigh % Den) * shift_factor1;
233 static constexpr uintmax_t num_low_high = (leading_zeros != 0) ? (NumLow / shift_factor2) : 0;
234 static constexpr uintmax_t scaled_num_high = num_high_shifted + num_low_high;
235 using division_result = _INNER __big_div_impl<scaled_num_high, scaled_num_low, scaled_den>;
236
237public:
238 static constexpr uintmax_t quotient_high = NumHigh / Den;
239 static constexpr uintmax_t quotient_low = division_result::quotient;
240 static constexpr uintmax_t remainder = division_result::remainder / shift_factor1;
241
242private:
243 using product_low = big_mul<quotient_low, Den>;
244 using product_high = big_mul<quotient_high, Den>;
245 using total_sum = big_add<product_low::result_high, product_low::result_low, product_high::result_low, remainder>;
246
247 static_assert(product_high::result_high == 0, "Internal library error");
248 static_assert(total_sum::result_high >= product_low::result_high, "Internal library error");
249
250 static_assert(total_sum::result_high == NumHigh && total_sum::result_low == NumLow, "Internal library error");
251 static_assert(remainder < Den, "Internal library error");
252};
253 // StaticArithmetic
255
261
271template <uint32_t Base, char Digit>
272struct static_char_digit;
273
274template <uint32_t Base>
275struct static_char_digit<Base, '0'> : uint32_constant<0> {
276 using is_valid = true_type;
277};
278
279template <uint32_t Base>
280struct static_char_digit<Base, '1'> : uint32_constant<1> {
281 using is_valid = true_type;
282};
283
285MSTL_BEGIN_INNER__
294template <uint32_t Base, uint32_t Value>
295struct __static_char_digit_aux : uint32_constant<Value> {
296 static_assert(Base > Value, "Invalid digit for given base");
297 using is_valid = true_type;
298};
299MSTL_END_INNER__
301
302template <uint32_t Base>
303struct static_char_digit<Base, '2'> : _INNER __static_char_digit_aux<Base, 2> {};
304
305template <uint32_t Base>
306struct static_char_digit<Base, '3'> : _INNER __static_char_digit_aux<Base, 3> {};
307
308template <uint32_t Base>
309struct static_char_digit<Base, '4'> : _INNER __static_char_digit_aux<Base, 4> {};
310
311template <uint32_t Base>
312struct static_char_digit<Base, '5'> : _INNER __static_char_digit_aux<Base, 5> {};
313
314template <uint32_t Base>
315struct static_char_digit<Base, '6'> : _INNER __static_char_digit_aux<Base, 6> {};
316
317template <uint32_t Base>
318struct static_char_digit<Base, '7'> : _INNER __static_char_digit_aux<Base, 7> {};
319
320template <uint32_t Base>
321struct static_char_digit<Base, '8'> : _INNER __static_char_digit_aux<Base, 8> {};
322
323template <uint32_t Base>
324struct static_char_digit<Base, '9'> : _INNER __static_char_digit_aux<Base, 9> {};
325
326template <uint32_t Base>
327struct static_char_digit<Base, 'a'> : _INNER __static_char_digit_aux<Base, 0xa> {};
328
329template <uint32_t Base>
330struct static_char_digit<Base, 'A'> : _INNER __static_char_digit_aux<Base, 0xa> {};
331
332template <uint32_t Base>
333struct static_char_digit<Base, 'b'> : _INNER __static_char_digit_aux<Base, 0xb> {};
334
335template <uint32_t Base>
336struct static_char_digit<Base, 'B'> : _INNER __static_char_digit_aux<Base, 0xb> {};
337
338template <uint32_t Base>
339struct static_char_digit<Base, 'c'> : _INNER __static_char_digit_aux<Base, 0xc> {};
340
341template <uint32_t Base>
342struct static_char_digit<Base, 'C'> : _INNER __static_char_digit_aux<Base, 0xc> {};
343
344template <uint32_t Base>
345struct static_char_digit<Base, 'd'> : _INNER __static_char_digit_aux<Base, 0xd> {};
346
347template <uint32_t Base>
348struct static_char_digit<Base, 'D'> : _INNER __static_char_digit_aux<Base, 0xd> {};
349
350template <uint32_t Base>
351struct static_char_digit<Base, 'e'> : _INNER __static_char_digit_aux<Base, 0xe> {};
352
353template <uint32_t Base>
354struct static_char_digit<Base, 'E'> : _INNER __static_char_digit_aux<Base, 0xe> {};
355
356template <uint32_t Base>
357struct static_char_digit<Base, 'f'> : _INNER __static_char_digit_aux<Base, 0xf> {};
358
359template <uint32_t Base>
360struct static_char_digit<Base, 'F'> : _INNER __static_char_digit_aux<Base, 0xf> {};
361
362template <uint32_t Base>
363struct static_char_digit<Base, '\''> : uint32_constant<0> {
364 using is_valid = false_type;
365};
366
367
369MSTL_BEGIN_INNER__
370
380template <uint32_t Base, char ThisDigit, char... RestDigits>
381struct __power_helper {
382private:
383 using next_power = typename __power_helper<Base, RestDigits...>::type;
384 using current_digit = static_char_digit<Base, ThisDigit>;
385
386public:
387 using type = uint64_constant<next_power::value * (current_digit::is_valid::value ? Base : 1ULL)>;
388};
389
390template <uint32_t Base, char Digit>
391struct __power_helper<Base, Digit> {
392private:
393 using current_digit = static_char_digit<Base, Digit>;
394
395public:
396 using type = uint64_constant<current_digit::is_valid::value>;
397};
398
399MSTL_END_INNER__
401
410template <uint32_t Base, char... Digits>
411struct static_power : _INNER __power_helper<Base, Digits...>::type {};
412
413template <uint32_t Base>
414struct static_power<Base> : uint64_constant<0> {};
415
416
418MSTL_BEGIN_INNER__
419
430template <uint32_t Base, uint64_t ThisPower, char ThisDigit, char... RestDigits>
431struct __number_aux {
432private:
433 using digit_value = static_char_digit<Base, ThisDigit>;
434 using next_number = __number_aux<Base,
435 digit_value::is_valid::value ? ThisPower / Base : ThisPower,
436 RestDigits...
437 >;
438
439public:
440 using type = uint64_constant<ThisPower * digit_value::value + next_number::type::value>;
441
442 static_assert(
443 (type::value / ThisPower) == digit_value::value,
444 "Integer literal does not fit in unsigned long long"
445 );
446};
447
448template <uint32_t Base, uint64_t ThisPower, char ThisDigit, char... RestDigits>
449struct __number_aux<Base, ThisPower, '\'', ThisDigit, RestDigits...>
450 : __number_aux<Base, ThisPower, ThisDigit, RestDigits...> {};
451
452template <uint32_t Base, char Digit>
453struct __number_aux<Base, 1ULL, Digit> {
454 using type = uint64_constant<static_char_digit<Base, Digit>::value>;
455};
456
457MSTL_END_INNER__
459
468template <uint32_t Base, char... Digits>
469struct static_number :
470 _INNER __number_aux<Base, static_power<Base, Digits...>::value, Digits...>::type {};
471
472template <uint32_t Base>
473struct static_number<Base> : uint64_constant<0> {};
474
475
487template <char... Digits>
488struct static_parse_int;
489
490template <char... Digits>
491struct static_parse_int<'0', 'b', Digits...> : static_number<2U, Digits...>::type {};
492
493template <char... Digits>
494struct static_parse_int<'0', 'B', Digits...> : static_number<2U, Digits...>::type {};
495
496template <char... Digits>
497struct static_parse_int<'0', 'x', Digits...> : static_number<16U, Digits...>::type {};
498
499template <char... Digits>
500struct static_parse_int<'0', 'X', Digits...> : static_number<16U, Digits...>::type {};
501
502template <char... Digits>
503struct static_parse_int<'0', Digits...> : static_number<8U, Digits...>::type {};
504
505template <char... Digits>
506struct static_parse_int : static_number<10U, Digits...>::type {};
507
508
510MSTL_BEGIN_INNER__
511
520template <uint64_t Value, typename... IntTypes>
521struct __select_int_base;
522
523template <uint64_t Value, typename IntType, typename... RestIntTypes>
524struct __select_int_base<Value, IntType, RestIntTypes...>
525 : conditional_t<
526 (Value <= numeric_traits<IntType>::max()),
527 integral_constant<IntType, static_cast<IntType>(Value)>,
528 __select_int_base<Value, RestIntTypes...>
529 > {};
530
531template <uint64_t Value>
532struct __select_int_base<Value> {};
533
534MSTL_END_INNER__
536
544template <char... Digits>
545using static_select_int_t = typename _INNER __select_int_base<
546 static_parse_int<Digits...>::value,
547 unsigned char,
548 unsigned short,
549 unsigned int,
550 unsigned long,
551 unsigned long long
552>::type;
553 // StaticCharDigit
555
556MSTL_END_NAMESPACE__
557#endif // MSTL_CORE_NUMERIC_STATIC_NUMERIC_HPP__
MSTL位操作函数
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
MSTL数值特征
整数常量包装器
计算整数的符号
MSTL类型萃取