1#ifndef NEFORCE_CORE_NUMERIC_STATIC_NUMERIC_HPP__
2#define NEFORCE_CORE_NUMERIC_STATIC_NUMERIC_HPP__
15NEFORCE_BEGIN_NAMESPACE__
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,
85 "overflow in multiplication");
88 static const intmax_t value = A * B;
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))> {};
114template <uintmax_t High1, uintmax_t Low1, uintmax_t High2, uintmax_t Low2>
116 static constexpr uintmax_t result_low = Low1 + Low2;
117 static constexpr uintmax_t result_high = (High1 + High2 + (Low1 + Low2 < Low1));
130template <uintmax_t High1, uintmax_t Low1, uintmax_t High2, uintmax_t Low2>
132 static_assert(!big_less<High1, Low1, High2, Low2>::value, "Internal library error");
133 static constexpr uintmax_t result_low = Low1 - Low2;
134 static constexpr uintmax_t result_high = (High1 - High2 - (Low1 < Low2));
145template <uintmax_t X, uintmax_t Y>
148 static constexpr uintmax_t half_range = static_cast<uintmax_t>(1) << (sizeof(intmax_t) * 4);
149 static constexpr uintmax_t x_low = X % half_range;
150 static constexpr uintmax_t x_high = X / half_range;
151 static constexpr uintmax_t y_low = Y % half_range;
152 static constexpr uintmax_t y_high = Y / half_range;
153 static constexpr uintmax_t low_product = x_low * y_low;
154 static constexpr uintmax_t cross_product1 = x_low * y_high;
155 static constexpr uintmax_t cross_product2 = x_high * y_low;
156 static constexpr uintmax_t cross_sum = cross_product1 + cross_product2;
157 static constexpr uintmax_t cross_sum_low = cross_sum * half_range;
158 static constexpr uintmax_t cross_sum_high =
159 cross_sum / half_range + ((cross_sum < cross_product1) ? half_range : 0);
160 using result_type = big_add<cross_sum_high, cross_sum_low, x_high * y_high, low_product>;
162 static constexpr uintmax_t result_high = result_type::result_high;
163 static constexpr uintmax_t result_low = result_type::result_low;
177template <uintmax_t NumHigh, uintmax_t NumLow, uintmax_t Den>
178struct __big_div_impl {
180 static_assert(Den >= (static_cast<uintmax_t>(1) << (sizeof(intmax_t) * 8 - 1)), "Internal library error");
181 static_assert(NumHigh < Den, "Internal library error");
182 static constexpr uintmax_t half_range = static_cast<uintmax_t>(1) << (sizeof(intmax_t) * 4);
183 static constexpr uintmax_t den_high = Den / half_range;
184 static constexpr uintmax_t den_low = Den % half_range;
186 static constexpr uintmax_t quot_high1 = NumHigh / den_high;
187 static constexpr uintmax_t rem_high1 = NumHigh % den_high;
188 static constexpr uintmax_t temp1 = quot_high1 * den_low;
189 static constexpr uintmax_t rem_high2 = rem_high1 * half_range + NumLow / half_range;
190 static constexpr uintmax_t rem_high3 = rem_high2 + Den;
191 static constexpr uintmax_t rem_high_final =
192 ((rem_high2 < temp1) ? ((rem_high3 >= Den) && (rem_high3 < temp1)) ? (rem_high3 + Den) : rem_high3
195 static constexpr uintmax_t quot_high_final =
196 quot_high1 - ((rem_high2 < temp1) ? ((rem_high3 >= Den) && (rem_high3 < temp1)) ? 2 : 1 : 0);
197 static constexpr uintmax_t quot_low1 = rem_high_final / den_high;
198 static constexpr uintmax_t rem_low1 = rem_high_final % den_high;
199 static constexpr uintmax_t temp2 = quot_low1 * den_low;
200 static constexpr uintmax_t rem_low2 = rem_low1 * half_range + NumLow % half_range;
201 static constexpr uintmax_t rem_low3 = rem_low2 + Den;
202 static constexpr uintmax_t rem_low_final =
203 ((rem_low2 < temp2) ? ((rem_low3 >= Den) && (rem_low3 < temp2)) ? (rem_low3 + Den) : rem_low3 : rem_low2) -
205 static constexpr uintmax_t quot_low_final =
206 quot_low1 - ((rem_low2 < temp2) ? ((rem_low3 >= Den) && (rem_low3 < temp2)) ? 2 : 1 : 0);
209 static constexpr uintmax_t quotient = quot_high_final * half_range + quot_low_final;
210 static constexpr uintmax_t remainder = rem_low_final;
213 using product = big_mul<quotient, Den>;
214 using sum = big_add<product::result_high, product::result_low, 0, remainder>;
215 static_assert(sum::result_high == NumHigh && sum::result_low == NumLow, "Internal library error");
229template <uintmax_t NumHigh, uintmax_t NumLow, uintmax_t Den>
232 static_assert(Den != 0, "Internal library error");
233 static_assert(sizeof(uintmax_t) == sizeof(unsigned long long), "clzll is unsafe on your platform.");
234 static constexpr int leading_zeros = _NEFORCE countl_zero(Den);
235 static constexpr int complement_shift = sizeof(uintmax_t) * 8 - leading_zeros;
236 static constexpr int actual_shift = (leading_zeros != 0) ? complement_shift : 0;
237 static constexpr uintmax_t shift_factor1 = static_cast<uintmax_t>(1) << leading_zeros;
238 static constexpr uintmax_t shift_factor2 = static_cast<uintmax_t>(1) << actual_shift;
239 static constexpr uintmax_t scaled_den = Den * shift_factor1;
240 static constexpr uintmax_t scaled_num_low = NumLow * shift_factor1;
241 static constexpr uintmax_t num_high_shifted = (NumHigh % Den) * shift_factor1;
242 static constexpr uintmax_t num_low_high =
243 (leading_zeros != 0) ? (NumLow / shift_factor2) : 0;
244 static constexpr uintmax_t scaled_num_high = num_high_shifted + num_low_high;
245 using division_result = inner::__big_div_impl<scaled_num_high, scaled_num_low, scaled_den>;
248 static constexpr uintmax_t quotient_high = NumHigh / Den;
249 static constexpr uintmax_t quotient_low = division_result::quotient;
250 static constexpr uintmax_t remainder = division_result::remainder / shift_factor1;
253 using product_low = big_mul<quotient_low, Den>;
254 using product_high = big_mul<quotient_high, Den>;
255 using total_sum = big_add<product_low::result_high, product_low::result_low, product_high::result_low, remainder>;
257 static_assert(product_high::result_high == 0, "Internal library error");
258 static_assert(total_sum::result_high >= product_low::result_high, "Internal library error");
260 static_assert(total_sum::result_high == NumHigh && total_sum::result_low == NumLow, "Internal library error");
261 static_assert(remainder < Den, "Internal library error");
281template <uint32_t Base, char Digit>
282struct static_char_digit;
284template <uint32_t Base>
285struct static_char_digit<Base, '0'> : uint32_constant<0> {
286 using is_valid = true_type;
289template <uint32_t Base>
290struct static_char_digit<Base, '1'> : uint32_constant<1> {
291 using is_valid = true_type;
304template <uint32_t Base, uint32_t Value>
305struct __static_char_digit_aux : uint32_constant<Value> {
306 static_assert(Base > Value, "Invalid digit for given base");
307 using is_valid = true_type;
312template <uint32_t Base>
313struct static_char_digit<Base, '2'> : inner::__static_char_digit_aux<Base, 2> {};
315template <uint32_t Base>
316struct static_char_digit<Base, '3'> : inner::__static_char_digit_aux<Base, 3> {};
318template <uint32_t Base>
319struct static_char_digit<Base, '4'> : inner::__static_char_digit_aux<Base, 4> {};
321template <uint32_t Base>
322struct static_char_digit<Base, '5'> : inner::__static_char_digit_aux<Base, 5> {};
324template <uint32_t Base>
325struct static_char_digit<Base, '6'> : inner::__static_char_digit_aux<Base, 6> {};
327template <uint32_t Base>
328struct static_char_digit<Base, '7'> : inner::__static_char_digit_aux<Base, 7> {};
330template <uint32_t Base>
331struct static_char_digit<Base, '8'> : inner::__static_char_digit_aux<Base, 8> {};
333template <uint32_t Base>
334struct static_char_digit<Base, '9'> : inner::__static_char_digit_aux<Base, 9> {};
336template <uint32_t Base>
337struct static_char_digit<Base, 'a'> : inner::__static_char_digit_aux<Base, 0xa> {};
339template <uint32_t Base>
340struct static_char_digit<Base, 'A'> : inner::__static_char_digit_aux<Base, 0xa> {};
342template <uint32_t Base>
343struct static_char_digit<Base, 'b'> : inner::__static_char_digit_aux<Base, 0xb> {};
345template <uint32_t Base>
346struct static_char_digit<Base, 'B'> : inner::__static_char_digit_aux<Base, 0xb> {};
348template <uint32_t Base>
349struct static_char_digit<Base, 'c'> : inner::__static_char_digit_aux<Base, 0xc> {};
351template <uint32_t Base>
352struct static_char_digit<Base, 'C'> : inner::__static_char_digit_aux<Base, 0xc> {};
354template <uint32_t Base>
355struct static_char_digit<Base, 'd'> : inner::__static_char_digit_aux<Base, 0xd> {};
357template <uint32_t Base>
358struct static_char_digit<Base, 'D'> : inner::__static_char_digit_aux<Base, 0xd> {};
360template <uint32_t Base>
361struct static_char_digit<Base, 'e'> : inner::__static_char_digit_aux<Base, 0xe> {};
363template <uint32_t Base>
364struct static_char_digit<Base, 'E'> : inner::__static_char_digit_aux<Base, 0xe> {};
366template <uint32_t Base>
367struct static_char_digit<Base, 'f'> : inner::__static_char_digit_aux<Base, 0xf> {};
369template <uint32_t Base>
370struct static_char_digit<Base, 'F'> : inner::__static_char_digit_aux<Base, 0xf> {};
372template <uint32_t Base>
373struct static_char_digit<Base, '\''> : uint32_constant<0> {
374 using is_valid = false_type;
390template <uint32_t Base, char ThisDigit, char... RestDigits>
391struct __power_helper {
393 using next_power = typename __power_helper<Base, RestDigits...>::type;
394 using current_digit = static_char_digit<Base, ThisDigit>;
397 using type = uint64_constant<next_power::value*(current_digit::is_valid::value ? Base : 1ULL)>;
400template <uint32_t Base, char Digit>
401struct __power_helper<Base, Digit> {
403 using current_digit = static_char_digit<Base, Digit>;
406 using type = uint64_constant<current_digit::is_valid::value>;
420template <uint32_t Base, char... Digits>
421struct static_power : inner::__power_helper<Base, Digits...>::type {};
423template <uint32_t Base>
424struct static_power<Base> : uint64_constant<0> {};
440template <uint32_t Base, uint64_t ThisPower, char ThisDigit, char... RestDigits>
443 using digit_value = static_char_digit<Base, ThisDigit>;
444 using next_number = __number_aux<Base, digit_value::is_valid::value ? ThisPower / Base : ThisPower, RestDigits...>;
447 using type = uint64_constant<ThisPower * digit_value::value + next_number::type::value>;
449 static_assert((type::value / ThisPower) == digit_value::value,
450 "Integer literal does not fit in unsigned long long");
453template <uint32_t Base, uint64_t ThisPower, char ThisDigit, char... RestDigits>
454struct __number_aux<Base, ThisPower, '\'', ThisDigit, RestDigits...>
455: __number_aux<Base, ThisPower, ThisDigit, RestDigits...> {};
457template <uint32_t Base, char Digit>
458struct __number_aux<Base, 1ULL, Digit> {
459 using type = uint64_constant<static_char_digit<Base, Digit>::value>;
473template <uint32_t Base, char... Digits>
474struct static_number : inner::__number_aux<Base, static_power<Base, Digits...>::value, Digits...>::type {};
476template <uint32_t Base>
477struct static_number<Base> : uint64_constant<0> {};
491template <char... Digits>
492struct static_parse_int;
494template <char... Digits>
495struct static_parse_int<'0', 'b', Digits...> : static_number<2U, Digits...>::type {};
497template <char... Digits>
498struct static_parse_int<'0', 'B', Digits...> : static_number<2U, Digits...>::type {};
500template <char... Digits>
501struct static_parse_int<'0', 'x', Digits...> : static_number<16U, Digits...>::type {};
503template <char... Digits>
504struct static_parse_int<'0', 'X', Digits...> : static_number<16U, Digits...>::type {};
506template <char... Digits>
507struct static_parse_int<'0', Digits...> : static_number<8U, Digits...>::type {};
509template <char... Digits>
510struct static_parse_int : static_number<10U, Digits...>::type {};
524template <uint64_t Value, typename... IntTypes>
525struct __select_int_base;
527template <uint64_t Value, typename IntType, typename... RestIntTypes>
528struct __select_int_base<Value, IntType, RestIntTypes...>
529: conditional_t<(Value <= numeric_traits<IntType>::max()), integral_constant<IntType, static_cast<IntType>(Value)>,
530 __select_int_base<Value, RestIntTypes...>> {};
532template <uint64_t Value>
533struct __select_int_base<Value> {};
545template <char... Digits>
546using static_select_int_t =
547 typename inner::__select_int_base<static_parse_int<Digits...>::value, unsigned char, unsigned short,
548 unsigned int, unsigned long, unsigned long long>::type;
552NEFORCE_END_NAMESPACE__