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 =
118 (High1 + High2 + static_cast<uintmax_t>(Low1 + Low2 < Low1));
131template <uintmax_t High1, uintmax_t Low1, uintmax_t High2, uintmax_t Low2>
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));
147template <uintmax_t X, uintmax_t Y>
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>;
164 static constexpr uintmax_t result_high = result_type::result_high;
165 static constexpr uintmax_t result_low = result_type::result_low;
179template <uintmax_t NumHigh, uintmax_t NumLow, uintmax_t Den>
180struct __big_div_impl {
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;
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
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) -
207 static constexpr uintmax_t quot_low_final =
208 quot_low1 - ((rem_low2 < temp2) ? ((rem_low3 >= Den) && (rem_low3 < temp2)) ? 2 : 1 : 0);
211 static constexpr uintmax_t quotient = quot_high_final * half_range + quot_low_final;
212 static constexpr uintmax_t remainder = rem_low_final;
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");
231template <uintmax_t NumHigh, uintmax_t NumLow, uintmax_t Den>
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>;
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;
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>;
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");
262 static_assert(total_sum::result_high == NumHigh && total_sum::result_low == NumLow, "Internal library error");
263 static_assert(remainder < Den, "Internal library error");
283template <uint32_t Base, char Digit>
284struct static_char_digit;
286template <uint32_t Base>
287struct static_char_digit<Base, '0'> : uint32_constant<0> {
288 using is_valid = true_type;
291template <uint32_t Base>
292struct static_char_digit<Base, '1'> : uint32_constant<1> {
293 using is_valid = true_type;
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;
314template <uint32_t Base>
315struct static_char_digit<Base, '2'> : inner::__static_char_digit_aux<Base, 2> {};
317template <uint32_t Base>
318struct static_char_digit<Base, '3'> : inner::__static_char_digit_aux<Base, 3> {};
320template <uint32_t Base>
321struct static_char_digit<Base, '4'> : inner::__static_char_digit_aux<Base, 4> {};
323template <uint32_t Base>
324struct static_char_digit<Base, '5'> : inner::__static_char_digit_aux<Base, 5> {};
326template <uint32_t Base>
327struct static_char_digit<Base, '6'> : inner::__static_char_digit_aux<Base, 6> {};
329template <uint32_t Base>
330struct static_char_digit<Base, '7'> : inner::__static_char_digit_aux<Base, 7> {};
332template <uint32_t Base>
333struct static_char_digit<Base, '8'> : inner::__static_char_digit_aux<Base, 8> {};
335template <uint32_t Base>
336struct static_char_digit<Base, '9'> : inner::__static_char_digit_aux<Base, 9> {};
338template <uint32_t Base>
339struct static_char_digit<Base, 'a'> : inner::__static_char_digit_aux<Base, 0xa> {};
341template <uint32_t Base>
342struct static_char_digit<Base, 'A'> : inner::__static_char_digit_aux<Base, 0xa> {};
344template <uint32_t Base>
345struct static_char_digit<Base, 'b'> : inner::__static_char_digit_aux<Base, 0xb> {};
347template <uint32_t Base>
348struct static_char_digit<Base, 'B'> : inner::__static_char_digit_aux<Base, 0xb> {};
350template <uint32_t Base>
351struct static_char_digit<Base, 'c'> : inner::__static_char_digit_aux<Base, 0xc> {};
353template <uint32_t Base>
354struct static_char_digit<Base, 'C'> : inner::__static_char_digit_aux<Base, 0xc> {};
356template <uint32_t Base>
357struct static_char_digit<Base, 'd'> : inner::__static_char_digit_aux<Base, 0xd> {};
359template <uint32_t Base>
360struct static_char_digit<Base, 'D'> : inner::__static_char_digit_aux<Base, 0xd> {};
362template <uint32_t Base>
363struct static_char_digit<Base, 'e'> : inner::__static_char_digit_aux<Base, 0xe> {};
365template <uint32_t Base>
366struct static_char_digit<Base, 'E'> : inner::__static_char_digit_aux<Base, 0xe> {};
368template <uint32_t Base>
369struct static_char_digit<Base, 'f'> : inner::__static_char_digit_aux<Base, 0xf> {};
371template <uint32_t Base>
372struct static_char_digit<Base, 'F'> : inner::__static_char_digit_aux<Base, 0xf> {};
374template <uint32_t Base>
375struct static_char_digit<Base, '\''> : uint32_constant<0> {
376 using is_valid = false_type;
392template <uint32_t Base, char ThisDigit, char... RestDigits>
393struct __power_helper {
395 using next_power = typename __power_helper<Base, RestDigits...>::type;
396 using current_digit = static_char_digit<Base, ThisDigit>;
399 using type = uint64_constant<next_power::value*(current_digit::is_valid::value ? Base : 1ULL)>;
402template <uint32_t Base, char Digit>
403struct __power_helper<Base, Digit> {
405 using current_digit = static_char_digit<Base, Digit>;
408 using type = uint64_constant<current_digit::is_valid::value>;
422template <uint32_t Base, char... Digits>
423struct static_power : inner::__power_helper<Base, Digits...>::type {};
425template <uint32_t Base>
426struct static_power<Base> : uint64_constant<0> {};
442template <uint32_t Base, uint64_t ThisPower, char ThisDigit, char... RestDigits>
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...>;
449 using type = uint64_constant<ThisPower * digit_value::value + next_number::type::value>;
451 static_assert((type::value / ThisPower) == digit_value::value,
452 "Integer literal does not fit in unsigned long long");
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...> {};
459template <uint32_t Base, char Digit>
460struct __number_aux<Base, 1ULL, Digit> {
461 using type = uint64_constant<static_char_digit<Base, Digit>::value>;
475template <uint32_t Base, char... Digits>
476struct static_number : inner::__number_aux<Base, static_power<Base, Digits...>::value, Digits...>::type {};
478template <uint32_t Base>
479struct static_number<Base> : uint64_constant<0> {};
493template <char... Digits>
494struct static_parse_int;
496template <char... Digits>
497struct static_parse_int<'0', 'b', Digits...> : static_number<2U, Digits...>::type {};
499template <char... Digits>
500struct static_parse_int<'0', 'B', Digits...> : static_number<2U, Digits...>::type {};
502template <char... Digits>
503struct static_parse_int<'0', 'x', Digits...> : static_number<16U, Digits...>::type {};
505template <char... Digits>
506struct static_parse_int<'0', 'X', Digits...> : static_number<16U, Digits...>::type {};
508template <char... Digits>
509struct static_parse_int<'0', Digits...> : static_number<8U, Digits...>::type {};
511template <char... Digits>
512struct static_parse_int : static_number<10U, Digits...>::type {};
526template <uint64_t Value, typename... IntTypes>
527struct __select_int_base;
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...>> {};
534template <uint64_t Value>
535struct __select_int_base<Value> {};
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;
554NEFORCE_END_NAMESPACE__