20#include "bi_exceptions.hpp"
21#include "constants.hpp"
31 static void increment_abs(bi_t& x);
32 static void decrement_abs(bi_t& x);
35 static void add_abs(bi_t& result,
const bi_t& a,
const bi_t& b);
36 static void add(bi_t& result,
const bi_t& a,
const bi_t& b);
37 static void sub_abs_gt(bi_t& result,
const bi_t& a,
const bi_t& b);
38 static void sub_abs(bi_t& result,
const bi_t& a,
const bi_t& b);
39 static void sub(bi_t& result,
const bi_t& a,
const bi_t& b);
42 static void imul1add1(bi_t& x, digit v, digit k);
43 static void mul_algo_square(bi_t& result,
const bi_t& a,
const size_t m);
44 static void mul_algo_knuth(bi_t& result,
const bi_t& a,
const bi_t& b,
45 const size_t m,
const size_t n);
46 static void mul_karatsuba(bi_t& result,
const bi_t& a,
const bi_t& b);
47 static void mul_standard(bi_t& result,
const bi_t& a,
const bi_t& b);
48 static void mul(bi_t& result,
const bi_t& a,
const bi_t& b);
49 static digit div_algo_digit(bi_t& q,
const bi_t& u, digit v)
noexcept;
50 static void div_algo_single(bi_t& q, bi_t& r,
const bi_t& n,
51 const bi_t& d)
noexcept;
52 static void div_algo_binary(bi_t& q, bi_t& r,
const bi_t& n,
const bi_t& d);
53 static void div_algo_knuth(bi_t& q, bi_t& r,
const bi_t& n,
const bi_t& d);
54 static void divide(bi_t& q, bi_t& r,
const bi_t& n,
const bi_t& d);
57 static void left_shift(bi_t& result,
const bi_t& a, bi_bitcount_t shift);
58 static void right_shift(bi_t& result,
const bi_t& a, bi_bitcount_t shift);
59 enum class BitwiseOperation { AND, OR, XOR };
60 template <BitwiseOperation Op>
61 static void bitwise_operation_impl(bi_t& res,
const bi_t& a,
const bi_t& b);
62 template <BitwiseOperation Op>
63 static bi_t bitwise_operation(
const bi_t& a,
const bi_t& b);
64 template <BitwiseOperation Op>
65 static bi_t& ibitwise_operation(bi_t&,
const bi_t& other);
68 static int cmp_abs(
const bi_t&,
const bi_t&)
noexcept;
69 static int cmp(
const bi_t&,
const bi_t&)
noexcept;
70 template <std::
integral T>
71 static int cmp(
const bi_t& a, T b)
noexcept;
74 static uint8_t idiv10(bi_t& x)
noexcept;
75 static size_t base_length(
const bi_t& x,
int base);
78 template <std::
integral T>
79 static void init_one_digit(bi_t& x, T value);
80 template <std::
integral T>
81 static void init_atleast_one_digit(bi_t& x, T value);
83 static void init_string(bi_t& x,
const std::string& str,
int base = 10);
86 static dvector to_twos_complement(
const dvector& vec);
87 static void to_twos_complement_in_place(dvector& vec)
noexcept;
88 static void bisect(
const bi_t&, bi_t&, bi_t&,
size_t m);
91 static void assign_from_double(bi_t&,
double);
92 static int cmp_abs(
const bi_t&,
double)
noexcept;
93 static int cmp(
const bi_t&,
double)
noexcept;
96 template <std::
unsigned_
integral T>
97 static bi_t expo_left_to_right(
const bi_t& base, T exp);
100 static thread_local std::mt19937 rng_;
101 static bi_t random_(bi_bitcount_t z);
104thread_local std::mt19937 h_::rng_{std::random_device{}()};
106void h_::increment_abs(bi_t& x) {
107 if (x.size() == 0 || x[x.size() - 1] == std::numeric_limits<digit>::max()) {
108 x.reserve_(x.size() + 1);
120 while (carry && i < x.size()) {
121 if (x[i] == std::numeric_limits<digit>::max()) {
135void h_::decrement_abs(bi_t& x) {
146 while (borrow && i < x.size()) {
149 x[i] = std::numeric_limits<digit>::max();
224void h_::add_abs(bi_t& r,
const bi_t& x,
const bi_t& y) {
226 const bi_t& large = x.size() >= y.size() ? x : y;
227 const bi_t& small = x.size() >= y.size() ? y : x;
229 r.reserve_(large.size() + 1);
234 for (; i < small.size(); ++i) {
235 uints::uaddc(temp, large[i], small[i], carry);
239 while (i < large.size()) {
240 temp = large[i] + carry;
241 carry = temp < static_cast<uint8_t>(carry);
246 r.resize_(large.size() + 1);
252void h_::add(bi_t& r,
const bi_t& x,
const bi_t& y) {
274void h_::sub_abs_gt(bi_t& r,
const bi_t& x,
const bi_t& y) {
275 assert(x.size() >= y.size());
277 r.reserve_(x.size());
282 for (; i < y.size(); ++i) {
283 uints::usubb(temp, x[i], y[i], borrow);
286 while (i < x.size()) {
287 temp = x[i] - borrow;
288 borrow = temp > x[i];
298void h_::sub_abs(bi_t& r,
const bi_t& x,
const bi_t& y) {
299 if (x.size() == y.size()) {
300 const auto [it_x, it_y] = std::mismatch(x.rbegin(), x.rend(), y.rbegin());
302 if (it_x == x.rend()) {
315 }
else if (x.size() > y.size()) {
324void h_::sub(bi_t& r,
const bi_t& x,
const bi_t& y) {
392inline void h_::imul1add1(bi_t& x, digit v, digit k = 0) {
393 for (
auto& d : x.vec_) {
394 const ddigit t =
static_cast<ddigit
>(d) * v + k;
396 d =
static_cast<digit
>(t);
416void h_::mul_algo_square(bi_t& w,
const bi_t& a,
const size_t t) {
417 std::fill(w.begin(), w.end(), 0);
419 for (
size_t i = 0; i < t; ++i) {
420 ddigit uv = w[2 * i] +
static_cast<ddigit
>(a[i]) * a[i];
421 w[2 * i] =
static_cast<digit
>(uv);
422 ddigit c = uv >> bi_dwidth;
424 for (
size_t j = i + 1; j < t; ++j) {
427 ddigit lo =
static_cast<ddigit
>(a[j]) * a[i];
430 hi = lo >> (std::numeric_limits<ddigit>::digits - 1);
434 hi += uints::uadd_overflow(lo, lo,
static_cast<ddigit
>(w[i + j]));
435 hi += uints::uadd_overflow(lo, lo, c);
437 w[i + j] =
static_cast<digit
>(lo);
438 c = (hi << bi_dwidth) | (lo >> bi_dwidth);
441 for (
size_t k = i + t; c > 0; ++k) {
443 w[k] =
static_cast<digit
>(c);
449void h_::mul_algo_knuth(bi_t& w,
const bi_t& a,
const bi_t& b,
const size_t m,
452 std::fill(w.begin(), w.begin() + m, 0);
454 for (
size_t j = 0; j < n; ++j) {
456 for (
size_t i = 0; i < m; ++i) {
458 static_cast<ddigit
>(a[i]) * b[j] +
static_cast<ddigit
>(w[i + j]) + k;
460 w[i + j] =
static_cast<digit
>(t);
498 const size_t bisect_point = std::min(n, x.
size());
500 lower.vec_ = dvector(x.vec_.begin(), x.vec_.begin() + bisect_point);
501 upper.vec_ = dvector(x.vec_.begin() + bisect_point, x.vec_.end());
507void h_::mul_karatsuba(bi_t& w,
const bi_t& u,
const bi_t& v) {
508 const size_t n = std::min(u.size(), v.size()) >> 1;
511 bisect(u, u0, u1, n);
512 bisect(v, v0, v1, n);
523 a <<= (2 * n * bi_dbits);
524 c <<= (n * bi_dbits);
535void h_::mul_standard(bi_t& result,
const bi_t& a,
const bi_t& b) {
536 if (a.size() == 0 || b.size() == 0) {
538 result.negative_ =
false;
542 const size_t m = a.size();
543 const size_t n = b.size();
545 const bool overlap = &result == &a || &result == &b;
548 bi_t& target = overlap ? temp : result;
550 target.resize_(m + n);
553 h_::mul_algo_knuth(target, a, b, m, n);
555 h_::mul_algo_square(target, a, m);
565void h_::mul(bi_t& w,
const bi_t& u,
const bi_t& v) {
566 if (u.size() < karatsuba_threshold || v.size() < karatsuba_threshold) {
567 h_::mul_standard(w, u, v);
569 h_::mul_karatsuba(w, u, v);
572 w.negative_ = u.negative() != v.negative();
605digit h_::div_algo_digit(bi_t& q,
const bi_t& u, digit v)
noexcept {
608 for (
size_t j = u.size() - 1; j < std::numeric_limits<size_t>::max(); --j) {
609 const ddigit temp = (rem << bi_dwidth) | u[j];
615 return static_cast<digit
>(rem);
618void h_::div_algo_single(bi_t& q, bi_t& r,
const bi_t& u,
619 const bi_t& v)
noexcept {
622 for (
size_t j = u.size() - 1; j < std::numeric_limits<size_t>::max(); --j) {
623 const ddigit temp = (rem << bi_dwidth) | u[j];
628 r[0] =
static_cast<digit
>(rem);
661void h_::div_algo_binary(bi_t& q, bi_t& r,
const bi_t& u,
const bi_t& v) {
667 for (
unsigned long i = u.bit_length() - 1; i < ULONG_MAX; --i) {
677 if (h_::cmp_abs(r, v) >= 0) {
679 h_::sub_abs(r, r, v);
748void h_::div_algo_knuth(bi_t& q, bi_t& r,
const bi_t& u,
const bi_t& v) {
749#if defined(BI_DIGIT_64_BIT)
750 using sddigit = __int128;
752 using sddigit = int64_t;
755 const size_t m = u.size();
756 const size_t n = v.size();
760 constexpr digit b_half = bi_base >> 1;
761 const digit v_msd = v[n - 1];
763 while ((v_msd << e) < b_half) {
766 const unsigned compl_e = bi_dwidth - e;
769 u_norm.resize_(m + 1);
773 u_norm[0] = u[0] << e;
774 for (
size_t i = 1; i < m; ++i) {
775 u_norm[i] = (u[i] << e) | (
static_cast<ddigit
>(u[i - 1]) >> compl_e);
777 u_norm[m] =
static_cast<ddigit
>(u[m - 1]) >> compl_e;
780 v_norm[0] = v[0] << e;
781 for (
size_t i = 1; i < n; ++i) {
782 v_norm[i] = (v[i] << e) | (
static_cast<ddigit
>(v[i - 1]) >> compl_e);
785 const digit vp = v_norm[n - 1], vpp = v_norm[n - 2];
787 for (
size_t j = m - n; j < std::numeric_limits<size_t>::max(); --j) {
789 const ddigit tmp = u_norm[j + n] * bi_base + u_norm[j + n - 1];
790 ddigit q_hat = tmp / vp;
791 ddigit r_hat = tmp % vp;
793 while (q_hat == bi_base ||
794 q_hat * vpp > bi_base * r_hat + u_norm[j + n - 2]) {
797 if (r_hat >= bi_base)
803 for (
size_t i = 0; i < n; ++i) {
804 const ddigit product = q_hat * v_norm[i];
806 static_cast<sddigit
>(u_norm[j + i]) -
static_cast<digit
>(product) - b;
807 u_norm[j + i] =
static_cast<digit
>(stmp);
808 b =
static_cast<sddigit
>(product >> bi_dbits) - (stmp >> bi_dbits);
810 const bool neg{u_norm[j + n] < b};
811 u_norm[j + n] =
static_cast<digit
>(u_norm[j + n] - b);
823 for (
size_t i = 0; i < n; ++i) {
824 const ddigit tmp = (
static_cast<ddigit
>(u_norm[j + i]) + v_norm[i]) + c;
826 c = tmp >> bi_dwidth;
830 assert(u_norm[j + n] == 0);
836 const size_t last_idx = n - 1;
837 r[last_idx] = u_norm[last_idx] >> e;
838 for (
size_t i = last_idx; i-- > 0;) {
839 r[i] = (
static_cast<ddigit
>(u_norm[i + 1]) << compl_e) | (u_norm[i] >> e);
859void h_::divide(bi_t& Q, bi_t& R,
const bi_t& N,
const bi_t& D) {
861 throw division_by_zero(
"Division by zero attempt.");
864 const size_t size_N = N.size();
865 const size_t size_D = D.size();
868 if ((size_N == size_D && N[size_N - 1] < D[size_D - 1]) || size_N < size_D) {
877 const size_t size_Q = size_N - size_D + 1;
885 div_algo_single(Q, R, N, D);
887 div_algo_knuth(Q, R, N, D);
890 Q.negative_ = D.negative() ^ N.negative();
891 R.negative_ = R.size() > 0 && N.negative();
907void h_::left_shift(bi_t& result,
const bi_t& x, bi_bitcount_t n_bits) {
909 result.resize_unsafe_(0);
910 result.negative_ =
false;
919 const size_t size_x = x.size();
920 const bi_bitcount_t digit_shift = n_bits / bi_dwidth;
921 const unsigned bit_shift = n_bits % bi_dwidth;
923 const size_t size_result = size_x + digit_shift + (bit_shift ? 1 : 0);
924 if (size_result < size_x) {
925 throw overflow_error(
"Result size exceeds SIZE_MAX.");
930 dvector& target_vec = (&result == &x) ? temp_vec : result.vec_;
932 target_vec.resize(size_result);
936 for (; i < digit_shift; ++i) {
940 const auto compl_bit_shift = bi_dwidth - bit_shift;
943 for (
size_t j = 0; j < size_x; ++j, ++i) {
944 const digit current = x[j];
945 target_vec[i] = (current << bit_shift) | carry;
946 carry = bit_shift ? (current >> compl_bit_shift) : 0;
950 target_vec[i] = carry;
954 result.vec_ = std::move(temp_vec);
958 result.negative_ = x.negative();
969void h_::right_shift(bi_t& result,
const bi_t& x, bi_bitcount_t n_bits) {
971 const size_t size_x = x.size();
973 const bi_bitcount_t digit_shift = n_bits / bi_dwidth;
974 const unsigned bit_shift = n_bits % bi_dwidth;
976 if (size_x <= digit_shift) {
981 result.negative_ =
true;
984 result.resize_unsafe_(0);
985 result.negative_ =
false;
990 result.resize_(size_x - digit_shift);
992 if (bit_shift == 0) {
993 for (
size_t i = 0; i < result.size(); ++i) {
994 result[i] = x[i + digit_shift];
997 const unsigned compl_bit_shift = bi_dwidth - bit_shift;
999 for (
size_t i = 0, k = digit_shift + 1; i < result.size(); ++i, ++k) {
1000 result[i] = x[k - 1] >> bit_shift;
1002 result[i] |= x[k] << compl_bit_shift;
1008 result.negative_ = x.negative();
1014 bool subtract_one =
false;
1015 if (bit_shift > 0) {
1016 const digit mask = (
static_cast<digit
>(1) << bit_shift) - 1;
1017 if ((x[digit_shift] & mask) != 0) {
1018 subtract_one =
true;
1021 if (!subtract_one && digit_shift > 0) {
1022 for (
size_t i = 0; i < digit_shift; ++i) {
1024 subtract_one =
true;
1038template <h_::BitwiseOperation Op>
1039void h_::bitwise_operation_impl(bi_t& result,
const bi_t& x,
const bi_t& y) {
1040 size_t max_size = std::max(x.size(), y.size());
1042 const dvector& lhs_digits = x.negative_ ? to_twos_complement(x.vec_) : x.vec_;
1043 const dvector& rhs_digits = y.negative_ ? to_twos_complement(y.vec_) : y.vec_;
1045 bool result_negative;
1046 if constexpr (Op == BitwiseOperation::AND) {
1047 result_negative = x.negative_ && y.negative_;
1048 }
else if constexpr (Op == BitwiseOperation::OR) {
1049 result_negative = x.negative_ || y.negative_;
1050 }
else if constexpr (Op == BitwiseOperation::XOR) {
1051 result_negative = x.negative_ != y.negative_;
1055 result.resize_(max_size);
1057 for (
size_t i = 0; i < result.size(); ++i) {
1058 const digit lhs_digit =
1059 i < lhs_digits.size() ? lhs_digits[i] : (x.negative_ ? bi_dmax : 0);
1060 const digit rhs_digit =
1061 i < rhs_digits.size() ? rhs_digits[i] : (y.negative_ ? bi_dmax : 0);
1063 if constexpr (Op == BitwiseOperation::AND) {
1064 result[i] = lhs_digit & rhs_digit;
1065 }
else if constexpr (Op == BitwiseOperation::OR) {
1066 result[i] = lhs_digit | rhs_digit;
1067 }
else if constexpr (Op == BitwiseOperation::XOR) {
1068 result[i] = lhs_digit ^ rhs_digit;
1072 result.negative_ = result_negative;
1074 if (result.negative_) {
1075 to_twos_complement_in_place(result.vec_);
1082template <h_::BitwiseOperation Op>
1083bi_t h_::bitwise_operation(
const bi_t& a,
const bi_t& b) {
1085 bitwise_operation_impl<Op>(result, a, b);
1090template <h_::BitwiseOperation Op>
1091bi_t& h_::ibitwise_operation(bi_t& x,
const bi_t& other) {
1092 bitwise_operation_impl<Op>(x, x, other);
1097int h_::cmp_abs(
const bi_t& x,
const bi_t& y)
noexcept {
1098 if (x.size() > y.size()) {
1100 }
else if (x.size() < y.size()) {
1103 for (
size_t i = x.size(); i-- > 0;) {
1104 if (x.vec_[i] > y.vec_[i]) {
1106 }
else if (x.vec_[i] < y.vec_[i]) {
1115int h_::cmp(
const bi_t& x,
const bi_t& y)
noexcept {
1116 if (!x.negative() && y.negative()) {
1119 }
else if (x.negative() && !y.negative()) {
1122 }
else if (x.negative() && y.negative()) {
1124 if (x.size() > y.size()) {
1126 }
else if (x.size() < y.size()) {
1129 for (
size_t i = x.size(); i-- > 0;) {
1130 if (x.vec_[i] < y.vec_[i]) {
1132 }
else if (x.vec_[i] > y.vec_[i]) {
1140 return h_::cmp_abs(x, y);
1144template <std::
integral T>
1145int h_::cmp(
const bi_t& a, T b)
noexcept {
1147 if (a.size() == 0) {
1150 return a.negative() ? -1 : 1;
1153 using UnsignedT =
typename std::make_unsigned<T>::type;
1154 const bool b_negative = b < 0;
1155 const UnsignedT unsigned_b =
1156 b_negative ? -
static_cast<UnsignedT
>(b) : static_cast<UnsignedT>(b);
1158 if (a.negative() && !b_negative) {
1161 if (!a.negative() && b_negative) {
1165 size_t n_b_digits = 0;
1166 if constexpr (std::numeric_limits<UnsignedT>::max() <= bi_dmax) {
1167 n_b_digits = (unsigned_b != 0) ? 1 : 0;
1169 UnsignedT temp_b = unsigned_b;
1170 while (temp_b != 0) {
1171 temp_b >>= bi_dwidth;
1176 const size_t a_size = a.size();
1177 if (a_size < n_b_digits) {
1178 return a.negative() ? 1 : -1;
1181 if (a_size > n_b_digits) {
1182 return a.negative() ? -1 : 1;
1185 for (
size_t i = n_b_digits; i-- > 0;) {
1186 const digit a_digit = a[i];
1187 const digit b_digit =
static_cast<digit
>(unsigned_b >> (bi_dwidth * i));
1189 if (a_digit < b_digit) {
1190 return a.negative() ? 1 : -1;
1192 if (a_digit > b_digit) {
1193 return a.negative() ? -1 : 1;
1205uint8_t h_::idiv10(bi_t& x)
noexcept {
1206 constexpr ddigit base =
static_cast<ddigit
>(bi_dmax) + 1;
1210 for (
size_t i = x.size(); i-- > 0;) {
1211 const ddigit current = (base * carry) + x.vec_[i];
1212 x.vec_[i] =
static_cast<digit
>(current / 10);
1213 carry =
static_cast<uint8_t
>(current % 10);
1257constexpr std::array<double, 37> log_base_2 = {
1258 0, 0, 1.0, 0.631, 0.5, 0.431, 0.387, 0.357, 0.334, 0.316,
1259 0.302, 0.290, 0.279, 0.271, 0.263, 0.256, 0.25, 0.245, 0.240, 0.236,
1260 0.232, 0.228, 0.225, 0.222, 0.219, 0.216, 0.213, 0.211, 0.209, 0.206,
1261 0.204, 0.202, 0.200, 0.199, 0.197, 0.195, 0.194};
1263size_t h_::base_length(
const bi_t& x,
int base) {
1265 constexpr const char* s =
"Digit estimation exceeds practical limit.";
1267 const bi_bitcount_t bitlen = x.bit_length();
1268 if (bitlen > dbl_max_int) {
1269 throw overflow_error(s);
1272 const bi_bitcount_t r =
static_cast<bi_bitcount_t
>(
1274 std::floor(
static_cast<double>(bitlen) * log_base_2[base]) + 1);
1275 if (r > std::numeric_limits<size_t>::max() - 2) {
1276 throw overflow_error(s);
1284template <std::
integral T>
1285void h_::init_one_digit(bi_t& x, T value) {
1289 x[0] =
static_cast<digit
>(value);
1290 x.negative_ =
false;
1292 x[0] =
static_cast<digit
>(0) -
static_cast<digit
>(value);
1297template <std::
integral T>
1298void h_::init_atleast_one_digit(bi_t& x, T value) {
1299 using UnsignedT =
typename std::make_unsigned<T>::type;
1302 UnsignedT temp, uvalue;
1306 x.negative_ =
false;
1308 uvalue =
static_cast<UnsignedT
>(0) -
static_cast<UnsignedT
>(value);
1314 while (temp >>= bi_dwidth) {
1320 for (
size_t i = 0; uvalue != 0; ++i) {
1321 x[i] =
static_cast<digit
>(uvalue);
1322 uvalue >>= bi_dwidth;
1540constexpr auto pow2_8 = 1 << 8;
1542constexpr std::array<uint8_t, pow2_8> create_char_to_b36_map() {
1544 constexpr auto n_digits = 10;
1545 constexpr auto n_letters = 26;
1546 constexpr std::array<char, n_letters> lowercase{
1547 'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
1548 'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z'};
1549 constexpr std::array<char, n_letters> uppercase{
1550 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
1551 'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z'};
1553 std::array<uint8_t, pow2_8> map{};
1556 for (uint8_t i = 0; i < n_digits; ++i) {
1557 map.at(
static_cast<uint8_t
>(
'0') + i) = i;
1560 for (uint8_t i = 0; i < n_letters; ++i) {
1561 map.at(
static_cast<uint8_t
>(lowercase.at(i))) = 10 + i;
1562 map.at(
static_cast<uint8_t
>(uppercase.at(i))) = 10 + i;
1569constexpr auto char_to_int_map = create_char_to_b36_map();
1571constexpr uint8_t char_to_b36(
char ch) {
1573 return char_to_int_map[
static_cast<uint8_t
>(ch)];
1577constexpr digit pow(
int base,
size_t n) {
1579 for (
size_t i = 0; i < n; ++i) {
1585constexpr int calculate_max_batch_size(digit base) {
1589 while (b < bi_dmax) {
1607constexpr std::array<BaseMBS, 37> create_base_mbs_array() {
1608 std::array<BaseMBS, 37> base_mbs{};
1609 for (
int base = 2; base <= 36; ++base) {
1610 unsigned max_batch_size = calculate_max_batch_size(base);
1611 base_mbs.at(base) = {max_batch_size, pow(base, max_batch_size)};
1617constexpr auto base_mbs = create_base_mbs_array();
1619void h_::init_string(bi_t& x,
const std::string& s,
int base) {
1621 if (base <= 1 || base > 36) {
1622 throw std::invalid_argument(
"base argument must be in [2, 36]");
1626 const auto [max_batch_size, base_pow_max_batch_size] = base_mbs[base];
1632 auto it = std::find_if_not(s.begin(), s.end(),
1633 [](
char ch) { return std::isspace(ch); });
1636 x.negative_ =
false;
1637 if (it != s.end()) {
1641 }
else if (*it ==
'+') {
1646 const auto start_digit = it;
1648 it = std::find_if_not(start_digit, s.end(),
1649 [](
char ch) { return std::isalnum(ch); });
1651 if (start_digit == it) {
1652 throw std::invalid_argument(
"Invalid string format.");
1655 size_t n_base = std::distance(start_digit, it);
1656 const size_t n_digits = uints::div_ceil(n_base, max_batch_size);
1658 x.reserve_(n_digits);
1659 x.resize_unsafe_(0);
1661 auto dec_it = start_digit;
1662 const size_t rem_batch_size = n_base % max_batch_size;
1667 for (
size_t j = 0; j < rem_batch_size; ++j, ++dec_it) {
1669 batch = char_to_int_map[*dec_it] + batch * base;
1673 x.vec_.push_back(batch);
1676 while (dec_it < it) {
1680 for (
size_t j = 0; j < max_batch_size; ++j, ++dec_it) {
1682 batch = char_to_int_map[*dec_it] + batch * base;
1684 h_::imul1add1(x, base_pow_max_batch_size, batch);
1693inline dvector h_::to_twos_complement(
const dvector& vec) {
1694 const size_t vec_size = vec.size();
1696 result.resize(vec_size);
1699 for (
size_t i = 0; i < vec_size; ++i) {
1700 const digit sum = ~vec[i] + carry;
1701 carry = sum < static_cast<uint8_t>(carry);
1709inline void h_::to_twos_complement_in_place(dvector& vec)
noexcept {
1710 const size_t vec_size = vec.size();
1713 for (
size_t i = 0; i < vec_size; ++i) {
1714 const digit sum = ~vec[i] + carry;
1715 carry = sum < static_cast<uint8_t>(carry);
1726void h_::assign_from_double(bi_t& x,
double d) {
1727 if (std::isnan(d) || std::isinf(d)) {
1729 "Conversion error: NaN or infinity cannot be converted to an integer.");
1732 if (d > -1 && d < 1) {
1737 const bool neg = d < 0;
1743 while (bi_base_dbl <= d) {
1745 d *= bi_base_dbl_reciprocal;
1749 x.resize_(n_digits);
1751 for (
size_t i = n_digits; i-- > 0;) {
1752 x[i] =
static_cast<digit
>(d);
1753 d = (d -
static_cast<double>(x[i])) * bi_base_dbl;
1760int h_::cmp_abs(
const bi_t& z,
double dbl)
noexcept {
1761 if (z.size() == 0) {
1762 return dbl > 0 ? -1 : 0;
1765 if (z.size() >= bi_cmp_dbl_size_upper) {
1771 for (
size_t j = 1; j < z.size(); ++j) {
1773 dbl *= bi_base_dbl_reciprocal;
1776 if (bi_base_dbl <= dbl) {
1780 for (
auto it = z.rbegin(); it != z.rend(); ++it) {
1781 const digit cur =
static_cast<digit
>(dbl);
1785 }
else if (*it > cur) {
1788 dbl = (dbl -
static_cast<double>(cur)) * bi_base_dbl;
1792 return dbl > 0 ? -1 : 0;
1795int h_::cmp(
const bi_t& z,
double dbl)
noexcept {
1796 if (!z.negative()) {
1797 return dbl < 0 ? 1 : h_::cmp_abs(z, dbl);
1799 return dbl < 0 ? -h_::cmp_abs(z, -dbl) : -1;
1808template <std::
unsigned_
integral T>
1809bi_t h_::expo_left_to_right(
const bi_t& base, T exp) {
1816 for (
int j = uints::bit_length(exp); j-- > 0;) {
1819 if (exp & (
static_cast<T
>(1) << j)) {
1830bi_t h_::random_(bi_bitcount_t z) {
1837 size_t num_digits = z / bi_dbits;
1838 size_t remainder = z % bi_dbits;
1840 if (remainder != 0) {
1844 result.resize_(num_digits);
1846 std::uniform_int_distribution<digit> dist(0, bi_dmax);
1848 for (
size_t i = 0; i < num_digits - 1; ++i) {
1849 result[i] = dist(rng_);
1852 if (remainder != 0) {
1853 const digit mask = (
static_cast<digit
>(1) << remainder) - 1;
1854 result[num_digits - 1] = dist(rng_) & mask;
1856 result[num_digits - 1] = dist(rng_);
Arbitrary-precision integer type and related functions.
Definition bi.hpp:52
size_t size() const noexcept
Return the number of digits used. Instance represents 0 iff size() == 0.