Skip to content

Commit 7c987cd

Browse files
committed
Base bigint + addition test
1 parent c6e6371 commit 7c987cd

File tree

2 files changed

+183
-0
lines changed

2 files changed

+183
-0
lines changed

cp-algo/math/bigint.hpp

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
#ifndef CP_ALGO_MATH_BIGINT_HPP
2+
#define CP_ALGO_MATH_BIGINT_HPP
3+
#include "../util/big_alloc.hpp"
4+
#include <bits/stdc++.h>
5+
6+
namespace cp_algo::math {
7+
enum base_v {
8+
x10 = uint64_t(1e18),
9+
x16 = 0
10+
};
11+
template<base_v base = x10>
12+
struct bigint {
13+
big_vector<uint64_t> digits;
14+
bool negative;
15+
16+
bigint() {}
17+
18+
bigint& normalize() {
19+
while (!empty(digits) && digits.back() == 0) {
20+
digits.pop_back();
21+
}
22+
if (digits.empty()) {
23+
negative = false;
24+
}
25+
return *this;
26+
}
27+
bigint& negate() {
28+
negative ^= 1;
29+
return *this;
30+
}
31+
bigint operator -() {
32+
return bigint(*this).negate();
33+
}
34+
bigint& operator -= (const bigint& other) {
35+
if (negative != other.negative) {
36+
return (negate() += other).negate().normalize();
37+
}
38+
digits.resize(std::max(size(digits), size(other.digits)));
39+
bool carry = false;
40+
auto d_ptr = std::assume_aligned<32>(digits.data());
41+
auto o_ptr = std::assume_aligned<32>(other.digits.data());
42+
size_t N = size(other.digits);
43+
size_t i = 0;
44+
for (; i < N; i++) {
45+
if constexpr (base == x10) {
46+
d_ptr[i] -= o_ptr[i] + carry;
47+
carry = d_ptr[i] >= base;
48+
d_ptr[i] += carry ? uint64_t(base) : 0;
49+
}
50+
}
51+
if (carry) {
52+
N = size(digits);
53+
for (; i < N && d_ptr[i] == 0; i++) {
54+
d_ptr[i] = base - 1;
55+
}
56+
if (i < N) {
57+
d_ptr[i]--;
58+
} else {
59+
d_ptr[0]--;
60+
for (i = 0; i < N; i++) {
61+
d_ptr[i] = base - d_ptr[i] - 1;
62+
}
63+
negate();
64+
}
65+
}
66+
return normalize();
67+
}
68+
bigint& operator += (const bigint& other) {
69+
if (negative != other.negative) {
70+
return (negate() -= other).negate().normalize();
71+
}
72+
digits.resize(std::max(size(digits), size(other.digits)));
73+
bool carry = false;
74+
auto d_ptr = std::assume_aligned<32>(digits.data());
75+
auto o_ptr = std::assume_aligned<32>(other.digits.data());
76+
size_t N = size(other.digits);
77+
size_t i = 0;
78+
for (; i < N; i++) {
79+
if constexpr (base == x10) {
80+
d_ptr[i] += o_ptr[i] + carry;
81+
carry = d_ptr[i] >= base;
82+
d_ptr[i] -= carry ? uint64_t(base) : 0;
83+
}
84+
}
85+
if (carry) {
86+
N = size(digits);
87+
for (; i < N && d_ptr[i] == base - 1; i++) {
88+
d_ptr[i] = 0;
89+
}
90+
if (i < N) {
91+
d_ptr[i]++;
92+
} else {
93+
digits.push_back(1);
94+
}
95+
}
96+
return *this;
97+
}
98+
99+
bigint(std::span<char> s): negative(false) {
100+
if (!empty(s) && s[0] == '-') {
101+
negative = true;
102+
s = s.subspan(1);
103+
}
104+
size_t len = size(s);
105+
assert(len > 0);
106+
constexpr auto digit_length = base == x10 ? 18 : base == x16 ? 16 : 0;
107+
size_t num_digits = (len + digit_length - 1) / digit_length;
108+
digits.resize(num_digits);
109+
size_t i = len;
110+
constexpr auto sub_base = base == x10 ? 10 : base == x16 ? 16 : 0;
111+
for (size_t j = 0; j < num_digits - 1; j++) {
112+
std::from_chars(s.data() + i - digit_length, s.data() + i, digits[j], sub_base);
113+
i -= digit_length;
114+
}
115+
std::from_chars(s.data(), s.data() + i, digits.back(), sub_base);
116+
normalize();
117+
}
118+
119+
bigint operator + (const bigint& other) const {
120+
return bigint(*this) += other;
121+
}
122+
bigint operator - (const bigint& other) const {
123+
return bigint(*this) -= other;
124+
}
125+
};
126+
127+
template<base_v base>
128+
decltype(std::cin)& operator >> (decltype(std::cin) &in, cp_algo::math::bigint<base> &x) {
129+
std::string s;
130+
in >> s;
131+
x = {s};
132+
return in;
133+
}
134+
135+
template<base_v base>
136+
decltype(std::cout)& operator << (decltype(std::cout) &out, cp_algo::math::bigint<base> const& x) {
137+
if (x.negative) {
138+
out << '-';
139+
}
140+
if (empty(x.digits)) {
141+
return out << '0';
142+
}
143+
if constexpr (base == x10) {
144+
out << x.digits.back();
145+
for (auto d: x.digits | std::views::reverse | std::views::drop(1)) {
146+
out << std::string(18 - size(std::to_string(d)), '0') << d;
147+
}
148+
}
149+
return out;
150+
}
151+
}
152+
153+
#endif // CP_ALGO_MATH_BIGINT_HPP
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// @brief Addition of Big Integers
2+
#define PROBLEM "https://judge.yosupo.jp/problem/addition_of_big_integers"
3+
#pragma GCC optimize("O3,unroll-loops")
4+
//#pragma GCC target("avx2")
5+
#define CP_ALGO_CHECKPOINT
6+
#include <iostream>
7+
//#include "blazingio/blazingio.min.hpp"
8+
#include "cp-algo/math/bigint.hpp"
9+
#include "cp-algo/util/checkpoint.hpp"
10+
#include <bits/stdc++.h>
11+
12+
using namespace std;
13+
using cp_algo::math::bigint;
14+
15+
void solve() {
16+
bigint a, b;
17+
cin >> a >> b;
18+
cout << (a += b) << "\n";
19+
}
20+
21+
signed main() {
22+
ios::sync_with_stdio(0);
23+
cin.tie(0);
24+
int t = 1;
25+
cin >> t;
26+
while(t--) {
27+
solve();
28+
}
29+
cp_algo::checkpoint<1>();
30+
}

0 commit comments

Comments
 (0)