1#ifndef MSTL_CORE_NUMERIC_STATIC_NUMERIC_HPP__
2#define MSTL_CORE_NUMERIC_STATIC_NUMERIC_HPP__
30template <
intmax_t Numerator>
40template <intmax_t Value>
41struct static_abs : integral_constant<intmax_t, Value * static_sign<Value>::value> {};
52template <intmax_t A, intmax_t B>
53struct static_gcd : static_gcd<B, (A % B)> {};
57struct static_gcd<A, 0> : integral_constant<intmax_t, static_abs<A>::value> {};
59struct static_gcd<0, B> : integral_constant<intmax_t, static_abs<B>::value> {};
71template <intmax_t A, intmax_t B>
74 static constexpr uintmax_t half_range = static_cast<uintmax_t>(1) << (sizeof(intmax_t) * 4);
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;
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");
87 static const intmax_t value = A * B;
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))> {};
113template <uintmax_t High1, uintmax_t Low1, uintmax_t High2, uintmax_t Low2>
115 static constexpr uintmax_t result_low = Low1 + Low2;
116 static constexpr uintmax_t result_high = (High1 + High2 + (Low1 + Low2 < Low1));
129template <uintmax_t High1, uintmax_t Low1, uintmax_t High2, uintmax_t Low2>
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));
144template <uintmax_t X, uintmax_t Y>
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>;
160 static constexpr uintmax_t result_high = result_type::result_high;
161 static constexpr uintmax_t result_low = result_type::result_low;
175template <uintmax_t NumHigh, uintmax_t NumLow, uintmax_t Den>
176struct __big_div_impl {
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;
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);
200 static constexpr uintmax_t quotient = quot_high_final * half_range + quot_low_final;
201 static constexpr uintmax_t remainder = rem_low_final;
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");
220template <uintmax_t NumHigh, uintmax_t NumLow, uintmax_t Den>
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>;
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;
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>;
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");
250 static_assert(total_sum::result_high == NumHigh && total_sum::result_low == NumLow, "Internal library error");
251 static_assert(remainder < Den, "Internal library error");
271template <uint32_t Base, char Digit>
272struct static_char_digit;
274template <uint32_t Base>
275struct static_char_digit<Base, '0'> : uint32_constant<0> {
276 using is_valid = true_type;
279template <uint32_t Base>
280struct static_char_digit<Base, '1'> : uint32_constant<1> {
281 using is_valid = true_type;
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;
302template <uint32_t Base>
303struct static_char_digit<Base, '2'> : _INNER __static_char_digit_aux<Base, 2> {};
305template <uint32_t Base>
306struct static_char_digit<Base, '3'> : _INNER __static_char_digit_aux<Base, 3> {};
308template <uint32_t Base>
309struct static_char_digit<Base, '4'> : _INNER __static_char_digit_aux<Base, 4> {};
311template <uint32_t Base>
312struct static_char_digit<Base, '5'> : _INNER __static_char_digit_aux<Base, 5> {};
314template <uint32_t Base>
315struct static_char_digit<Base, '6'> : _INNER __static_char_digit_aux<Base, 6> {};
317template <uint32_t Base>
318struct static_char_digit<Base, '7'> : _INNER __static_char_digit_aux<Base, 7> {};
320template <uint32_t Base>
321struct static_char_digit<Base, '8'> : _INNER __static_char_digit_aux<Base, 8> {};
323template <uint32_t Base>
324struct static_char_digit<Base, '9'> : _INNER __static_char_digit_aux<Base, 9> {};
326template <uint32_t Base>
327struct static_char_digit<Base, 'a'> : _INNER __static_char_digit_aux<Base, 0xa> {};
329template <uint32_t Base>
330struct static_char_digit<Base, 'A'> : _INNER __static_char_digit_aux<Base, 0xa> {};
332template <uint32_t Base>
333struct static_char_digit<Base, 'b'> : _INNER __static_char_digit_aux<Base, 0xb> {};
335template <uint32_t Base>
336struct static_char_digit<Base, 'B'> : _INNER __static_char_digit_aux<Base, 0xb> {};
338template <uint32_t Base>
339struct static_char_digit<Base, 'c'> : _INNER __static_char_digit_aux<Base, 0xc> {};
341template <uint32_t Base>
342struct static_char_digit<Base, 'C'> : _INNER __static_char_digit_aux<Base, 0xc> {};
344template <uint32_t Base>
345struct static_char_digit<Base, 'd'> : _INNER __static_char_digit_aux<Base, 0xd> {};
347template <uint32_t Base>
348struct static_char_digit<Base, 'D'> : _INNER __static_char_digit_aux<Base, 0xd> {};
350template <uint32_t Base>
351struct static_char_digit<Base, 'e'> : _INNER __static_char_digit_aux<Base, 0xe> {};
353template <uint32_t Base>
354struct static_char_digit<Base, 'E'> : _INNER __static_char_digit_aux<Base, 0xe> {};
356template <uint32_t Base>
357struct static_char_digit<Base, 'f'> : _INNER __static_char_digit_aux<Base, 0xf> {};
359template <uint32_t Base>
360struct static_char_digit<Base, 'F'> : _INNER __static_char_digit_aux<Base, 0xf> {};
362template <uint32_t Base>
363struct static_char_digit<Base, '\''> : uint32_constant<0> {
364 using is_valid = false_type;
380template <uint32_t Base, char ThisDigit, char... RestDigits>
381struct __power_helper {
383 using next_power = typename __power_helper<Base, RestDigits...>::type;
384 using current_digit = static_char_digit<Base, ThisDigit>;
387 using type = uint64_constant<next_power::value * (current_digit::is_valid::value ? Base : 1ULL)>;
390template <uint32_t Base, char Digit>
391struct __power_helper<Base, Digit> {
393 using current_digit = static_char_digit<Base, Digit>;
396 using type = uint64_constant<current_digit::is_valid::value>;
410template <uint32_t Base, char... Digits>
411struct static_power : _INNER __power_helper<Base, Digits...>::type {};
413template <uint32_t Base>
414struct static_power<Base> : uint64_constant<0> {};
430template <uint32_t Base, uint64_t ThisPower, char ThisDigit, char... RestDigits>
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,
440 using type = uint64_constant<ThisPower * digit_value::value + next_number::type::value>;
443 (type::value / ThisPower) == digit_value::value,
444 "Integer literal does not fit in unsigned long long"
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...> {};
452template <uint32_t Base, char Digit>
453struct __number_aux<Base, 1ULL, Digit> {
454 using type = uint64_constant<static_char_digit<Base, Digit>::value>;
468template <uint32_t Base, char... Digits>
469struct static_number :
470 _INNER __number_aux<Base, static_power<Base, Digits...>::value, Digits...>::type {};
472template <uint32_t Base>
473struct static_number<Base> : uint64_constant<0> {};
487template <char... Digits>
488struct static_parse_int;
490template <char... Digits>
491struct static_parse_int<'0', 'b', Digits...> : static_number<2U, Digits...>::type {};
493template <char... Digits>
494struct static_parse_int<'0', 'B', Digits...> : static_number<2U, Digits...>::type {};
496template <char... Digits>
497struct static_parse_int<'0', 'x', Digits...> : static_number<16U, Digits...>::type {};
499template <char... Digits>
500struct static_parse_int<'0', 'X', Digits...> : static_number<16U, Digits...>::type {};
502template <char... Digits>
503struct static_parse_int<'0', Digits...> : static_number<8U, Digits...>::type {};
505template <char... Digits>
506struct static_parse_int : static_number<10U, Digits...>::type {};
520template <uint64_t Value, typename... IntTypes>
521struct __select_int_base;
523template <uint64_t Value, typename IntType, typename... RestIntTypes>
524struct __select_int_base<Value, IntType, RestIntTypes...>
526 (Value <= numeric_traits<IntType>::max()),
527 integral_constant<IntType, static_cast<IntType>(Value)>,
528 __select_int_base<Value, RestIntTypes...>
531template <uint64_t Value>
532struct __select_int_base<Value> {};
544template <char... Digits>
545using static_select_int_t = typename _INNER __select_int_base<
546 static_parse_int<Digits...>::value,
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL