Skip to content

Commit 7e2e034

Browse files
committed
Improve bitpack, support dynamic
1 parent 5cd457c commit 7e2e034

File tree

3 files changed

+88
-47
lines changed

3 files changed

+88
-47
lines changed

cp-algo/structures/bit_array.hpp

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,63 @@
11
#ifndef CP_ALGO_STRUCTURES_BIT_ARRAY_HPP
22
#define CP_ALGO_STRUCTURES_BIT_ARRAY_HPP
33
#include "../util/bit.hpp"
4+
#include "../util/bump_alloc.hpp"
45
namespace cp_algo::structures {
5-
template<size_t N, typename Uint = uint64_t>
6-
struct bit_array {
7-
static constexpr size_t width = bit_width<Uint>;
8-
static constexpr size_t blocks = N / width + 1;
9-
std::array<Uint, blocks> data = {};
6+
template<class Cont>
7+
struct _bit_array {
8+
static constexpr size_t width = bit_width<uint64_t>;
9+
size_t words, n;
10+
alignas(32) Cont data;
1011

12+
_bit_array(): words(0), n(0) {}
13+
_bit_array(size_t N): words((N + width - 1) / width), n(N), data() {}
14+
15+
uint64_t& word(size_t x) {
16+
return data[x];
17+
}
1118
uint64_t word(size_t x) const {
1219
return data[x];
1320
}
1421
void set(size_t x) {
15-
data[x / width] |= 1ULL << (x % width);
22+
word(x / width) |= 1ULL << (x % width);
1623
}
1724
void reset(size_t x) {
18-
data[x / width] &= ~(1ULL << (x % width));
25+
word(x / width) &= ~(1ULL << (x % width));
26+
}
27+
void reset() {
28+
for(auto& w: data) {
29+
w = 0;
30+
}
1931
}
2032
void flip(size_t x) {
21-
data[x / width] ^= 1ULL << (x % width);
33+
word(x / width) ^= 1ULL << (x % width);
2234
}
2335
bool test(size_t x) const {
24-
return (data[x / width] >> (x % width)) & 1;
36+
return (word(x / width) >> (x % width)) & 1;
2537
}
2638
bool operator[](size_t x) const {
2739
return test(x);
2840
}
41+
size_t size() const {
42+
return n;
43+
}
2944
};
45+
46+
template<int N>
47+
struct bit_array: _bit_array<std::array<uint64_t, (N + 63) / 64>> {
48+
using Base = _bit_array<std::array<uint64_t, (N + 63) / 64>>;
49+
using Base::Base, Base::words, Base::data;
50+
bit_array(): Base(N) {
51+
data.fill(0);
52+
}
53+
};
54+
struct dynamic_bit_array: _bit_array<std::vector<uint64_t>> {
55+
using Base = _bit_array<std::vector<uint64_t>>;
56+
using Base::Base, Base::words;
57+
dynamic_bit_array(size_t N): Base(N) {
58+
data.resize(words);
59+
}
60+
};
61+
3062
}
3163
#endif // CP_ALGO_STRUCTURES_BIT_ARRAY_HPP

cp-algo/structures/bitpack.hpp

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,38 +7,36 @@
77
#include <string>
88
#include <array>
99
namespace cp_algo::structures {
10-
template<size_t n>
11-
struct bitpack: bit_array<n, uint64_t> {
12-
using Base = bit_array<n, uint64_t>;
13-
using Base::width, Base::blocks, Base::data;
14-
using Base::set, Base::reset;
15-
auto operator <=> (bitpack const& t) const = default;
10+
template<typename BitArray>
11+
struct _bitpack: BitArray {
12+
using Base = BitArray;
13+
using Base::Base, Base::width, Base::words, Base::data, Base::n, Base::word;
14+
auto operator <=> (_bitpack const& t) const = default;
1615

17-
bitpack() {}
18-
bitpack(std::string &bits) {
19-
bits.resize((size(bits) + width - 1) / width * width);
20-
for(size_t i = 0; i < blocks; i++) {
21-
data[i] = read_bits64(bits.data() + i * width);
16+
_bitpack(std::string &bits): _bitpack(std::size(bits)) {
17+
bits += std::string(-std::size(bits) % width, '0');
18+
for(size_t i = 0; i < words; i++) {
19+
word(i) = read_bits64(bits.data() + i * width);
2220
}
2321
}
2422

25-
bitpack& xor_hint(bitpack const& t, size_t hint) {
26-
for(size_t i = hint / width; i < blocks; i++) {
23+
_bitpack& xor_hint(_bitpack const& t, size_t hint) {
24+
for(size_t i = hint / width; i < std::size(data); i++) {
2725
data[i] ^= t.data[i];
2826
}
2927
return *this;
3028
}
31-
bitpack& operator ^= (bitpack const& t) {
29+
_bitpack& operator ^= (_bitpack const& t) {
3230
return xor_hint(t, 0);
3331
}
34-
bitpack operator ^ (bitpack const& t) const {
35-
return bitpack(*this) ^= t;
32+
_bitpack operator ^ (_bitpack const& t) const {
33+
return _bitpack(*this) ^= t;
3634
}
3735

3836
std::string to_string() const {
39-
std::string res(blocks * width, '0');
40-
for(size_t i = 0; i < blocks; i++) {
41-
write_bits64(res.data() + i * width, data[i]);
37+
std::string res(words * width, '0');
38+
for(size_t i = 0; i < words; i++) {
39+
write_bits64(res.data() + i * width, word(i));
4240
}
4341
res.resize(n);
4442
return res;
@@ -47,15 +45,19 @@ namespace cp_algo::structures {
4745
size_t ctz() const {
4846
size_t res = 0;
4947
size_t i = 0;
50-
while(i < blocks && data[i] == 0) {
48+
while(i < words && word(i) == 0) {
5149
res += width;
5250
i++;
5351
}
54-
if(i < blocks) {
55-
res += std::countr_zero(data[i]);
52+
if(i < words) {
53+
res += std::countr_zero(word(i));
5654
}
5755
return std::min(res, n);
5856
}
5957
};
58+
59+
template<int N>
60+
using bitpack = _bitpack<bit_array<N>>;
61+
using dynamic_bitpack = _bitpack<dynamic_bit_array>;
6062
}
6163
#endif // CP_ALGO_STRUCTURES_BITPACK_HPP

verify/structures/bitpack/prod_mod_2.test.cpp

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,52 +7,59 @@
77
#include <bits/stdc++.h>
88

99
using namespace std;
10-
using cp_algo::structures::bitpack;
1110

1211
const int maxn = 1 << 12;
13-
bitpack<maxn> a[maxn], b[maxn], c[maxn];
14-
const int K = 8;
15-
bitpack<maxn> precalc[1 << K];
12+
const size_t K = 8;
13+
14+
using bitpack = cp_algo::structures::bitpack<maxn>;
15+
16+
bitpack a[maxn], b[maxn], c[maxn];
17+
bitpack precalc[1 << K];
1618

1719
void process_precalc(int i) {
18-
for(auto &it: precalc) {
19-
it = bitpack<maxn>();
20-
}
21-
for(int j = 0; j < K; j++) {
20+
for(size_t j = 0; j < K; j++) {
2221
int step = 1 << j;
2322
for(int k = 0; k < step; k++) {
24-
precalc[k + step] = precalc[k] ^ b[K * i + j];
23+
precalc[k + step] = precalc[k] ^ b[i + j];
2524
}
2625
}
2726
}
2827

2928
void solve() {
30-
cp_algo::checkpoint("init");
3129
int n, m, k;
3230
cin >> n >> m >> k;
31+
cp_algo::checkpoint("init");
3332
string row;
3433
for(int i = 0; i < n; i++) {
3534
cin >> row;
3635
a[i] = row;
3736
}
37+
for(auto &it: b) {
38+
it = bitpack(k);
39+
}
3840
for(int i = 0; i < m; i++) {
3941
cin >> row;
4042
b[i] = row;
4143
}
44+
for(auto &it: c) {
45+
it = bitpack(k);
46+
}
47+
for(auto &it: precalc) {
48+
it = bitpack(k);
49+
}
4250
cp_algo::checkpoint("read");
43-
const int width = bitpack<maxn>::width;
51+
const int width = bitpack::width;
4452
for(int j = 0; j < m; j += width) {
45-
for(int z = 0; z < width / K; z++) {
46-
process_precalc(j / K + z);
53+
for(int offset = 0; offset < width; offset += K) {
54+
process_precalc(j + offset);
4755
for(int i = 0; i < n; i++) {
48-
c[i] ^= precalc[uint8_t(a[i].word(j / width) >> K * z)];
56+
c[i] ^= precalc[uint8_t(a[i].word(j / width) >> offset)];
4957
}
5058
}
5159
}
5260
cp_algo::checkpoint("mul");
5361
for(int i = 0; i < n; i++) {
54-
row = c[i].to_string().substr(0, k);
55-
cout << row << "\n";
62+
cout << c[i].to_string() << "\n";
5663
}
5764
cp_algo::checkpoint("write");
5865
cp_algo::checkpoint<1>();

0 commit comments

Comments
 (0)