@@ -14,7 +14,7 @@ namespace cp_algo::math {
1414 static constexpr uint16_t digit_length = base == x10 ? 16 : 15 ;
1515 static constexpr uint16_t sub_base = base == x10 ? 10 : 16 ;
1616 static constexpr uint32_t meta_base = base == x10 ? uint32_t (1e4 ) : uint32_t (1 << 15 );
17- big_vector <uint64_t > digits;
17+ big_basic_string <uint64_t > digits;
1818 bool negative;
1919
2020 bigint () {}
@@ -95,8 +95,18 @@ namespace cp_algo::math {
9595 }
9696 return *this ;
9797 }
98-
98+ bigint (int64_t x) {
99+ negative = x < 0 ;
100+ x = negative ? -x : x;
101+ digits = x ? big_basic_string<uint64_t >{uint64_t (x)} : big_basic_string<uint64_t >{};
102+ }
99103 bigint (std::span<char > s): negative(false ) {
104+ if (size (s) < digit_length) {
105+ int64_t val = 0 ;
106+ std::from_chars (s.data (), s.data () + size (s), val, sub_base);
107+ *this = bigint (val);
108+ return ;
109+ }
100110 if (!empty (s) && s[0 ] == ' -' ) {
101111 negative = true ;
102112 s = s.subspan (1 );
@@ -153,25 +163,43 @@ namespace cp_algo::math {
153163 carry /= base;
154164 }
155165 }
166+ bigint& operator *= (int64_t other) {
167+ if (other < 0 ) {
168+ negative ^= 1 ;
169+ other = -other;
170+ }
171+ if (other == 0 ) {
172+ return *this = bigint (0 );
173+ } else if (other == 1 ) {
174+ return *this ;
175+ }
176+ uint64_t carry = 0 ;
177+ for (auto &d: digits) {
178+ __uint128_t val = __uint128_t (d) * other + carry;
179+ d = uint64_t (val % base);
180+ carry = uint64_t (val / base);
181+ }
182+ if (carry) {
183+ digits.push_back (carry % base);
184+ carry /= base;
185+ }
186+ return *this ;
187+ }
188+ bigint operator * (int64_t other) const {
189+ return bigint (*this ) *= other;
190+ }
191+ friend bigint operator * (int64_t lhs, const bigint& rhs) {
192+ return bigint (rhs) *= lhs;
193+ }
156194 bigint& mul_inplace (auto &&other) {
157- size_t n = size (digits);
158- size_t m = size (other.digits );
159195 negative ^= other.negative ;
160- if (std::min (n, m) < 128 ) {
161- big_vector<uint64_t > result (n + m);
162- for (size_t i = 0 ; i < n; i++) {
163- uint64_t carry = 0 ;
164- for (size_t j = 0 ; j < m || carry; j++) {
165- __uint128_t cur = result[i + j] + carry;
166- if (j < m) {
167- cur += __uint128_t (digits[i]) * other.digits [j];
168- }
169- result[i + j] = uint64_t (cur % base);
170- carry = uint64_t (cur / base);
171- }
172- }
173- digits = std::move (result);
174- return normalize ();
196+ auto n = size (digits), m = size (other.digits );
197+ if (n < m) {
198+ std::swap (n, m);
199+ std::swap (digits, other.digits );
200+ }
201+ if (m <= 1 ) {
202+ return *this *= int64_t (m == 0 ? 0 : other.digits [0 ]);
175203 }
176204 to_metabase ();
177205 other.to_metabase ();
@@ -197,13 +225,25 @@ namespace cp_algo::math {
197225
198226 template <base_v base>
199227 decltype (std::cout)& operator << (decltype (std::cout) &out, cp_algo::math::bigint<base> const & x) {
228+ char buf[16 ];
229+ if (size (x.digits ) <= 1 ) {
230+ if (x.negative ) {
231+ out << ' -' ;
232+ }
233+ if constexpr (base == x16) {
234+ auto [ptr, ec] = std::to_chars (buf, buf + sizeof (buf), empty (x.digits ) ? 0 : x.digits [0 ], bigint<base>::sub_base);
235+ std::ranges::transform (buf, buf, toupper);
236+ return out << std::string_view (buf, ptr - buf);
237+ } else {
238+ return out << (empty (x.digits ) ? 0 : x.digits [0 ]);
239+ }
240+ }
200241 if (x.negative ) {
201242 out << ' -' ;
202243 }
203244 if (empty (x.digits )) {
204245 return out << ' 0' ;
205246 }
206- char buf[20 ];
207247 auto [ptr, ec] = std::to_chars (buf, buf + sizeof (buf), x.digits .back (), bigint<base>::sub_base);
208248 if constexpr (base == x16) {
209249 std::ranges::transform (buf, buf, toupper);
0 commit comments