-
Notifications
You must be signed in to change notification settings - Fork 1
/
bitmatrix.cpp
82 lines (77 loc) · 3.11 KB
/
bitmatrix.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include "bitmatrix.h"
BitMatrix::BitMatrix(const utils::Matrix<bool> &mat)
: utils::Matrix<uchar>((mat.n + bitMask) >> logBits, mat.m), n_bits(mat.n), m_bits(mat.m) {
int cnt = 0;
for (int y = 0; y < m_bits; ++y) {
for (int x = 0; x < n - 1; ++x) {
uchar val = 0;
int offset = x << logBits;
for (int i = bitMask; i >= 0; --i)
val = (val << 1) | static_cast<uchar>(mat(offset | i, y));
arr[cnt++] = val;
}
{
uchar val = 0;
int offset = (n - 1) << logBits;
for (int i = ((n_bits - 1) & bitMask); i >= 0; --i)
val = (val << 1) | static_cast<uchar>(mat(offset | i, y));
arr[cnt++] = val;
}
}
}
void BitMatrix::fill1() {
memset(arr, (1 << (bitMask + 1)) - 1, sizeof(uchar) * (m_bits * n));
auto bitMaskEOL = static_cast<uchar>((1 << ((n_bits - 1) & bitMask) + 1) - 1);
for (int y = 0; y < m_bits; ++y)
arr[y * n + n - 1] = bitMaskEOL;
}
void BitMatrix::invert() {
auto bitMaskEOL = static_cast<uchar>((1 << ((n_bits - 1) & bitMask) + 1) - 1);
for (int i = 0; i < m_bits * n; ++i)
arr[i] = ~arr[i];
// for (int y = 0; y < m_bits; ++y)
// arr[y * n + n - 1] &= bitMaskEOL;
}
void BitMatrix::subMatrixAnd(const BitMatrix &mat, int offsetX, int offsetY) {
assert(mat.m_bits + offsetY <= m_bits && mat.n_bits + offsetX <= n_bits);
assert(offsetX >= 0 && offsetY >= 0);
int blocks = offsetX >> logBits, bits = offsetX & bitMask;
if (bits == 0) {
for (int y = 0; y < mat.m_bits; ++y) {
int st = (y + offsetY) * n + blocks, matSt = y * mat.n;
for (int x = 0; x < mat.n; ++x)
arr[st + x] &= mat.arr[matSt + x];
}
} else {
auto fullMask = static_cast<uchar>((1 << (bitMask + 1)) - 1);
uchar maskLo = ~(fullMask << bits);
uchar maskHi = ~(fullMask >> (bitMask + 1 - bits));
for (int y = 0; y < mat.m_bits; ++y) {
int st = (y + offsetY) * n + blocks, matSt = y * mat.n;
for (int x = 0; x < mat.n; ++x) {
arr[st + x] &= maskLo | (mat.arr[matSt + x] << bits);
arr[st + x + 1] &= maskHi | (mat.arr[matSt + x] >> (bitMask + 1 - bits));
}
}
}
}
void BitMatrix::subMatrixOr(const BitMatrix &mat, int offsetX, int offsetY) {
assert(mat.m_bits + offsetY <= m_bits && mat.n_bits + offsetX <= n_bits);
assert(offsetX >= 0 && offsetY >= 0);
int blocks = offsetX >> logBits, bits = offsetX & bitMask;
if (bits == 0) {
for (int y = 0; y < mat.m_bits; ++y) {
int st = (y + offsetY) * n + blocks, matSt = y * mat.n;
for (int x = 0; x < mat.n; ++x)
arr[st + x] |= mat.arr[matSt + x];
}
} else {
for (int y = 0; y < mat.m_bits; ++y) {
int st = (y + offsetY) * n + blocks, matSt = y * mat.n;
for (int x = 0; x < mat.n; ++x) {
arr[st + x] |= mat.arr[matSt + x] << bits;
arr[st + x + 1] |= mat.arr[matSt + x] >> (bitMask + 1 - bits);
}
}
}
}