-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathToporBitArray.hpp
143 lines (121 loc) · 3.77 KB
/
ToporBitArray.hpp
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// Copyright(C) 2021 Intel Corporation
// SPDX - License - Identifier: MIT
#pragma once
#include "ToporDynArray.hpp"
#include "ToporBitArrayBuffer.hpp"
using namespace BitArray;
namespace Topor
{
class CBitArray : public CDynArray<uint64_t>
{
public:
void bit_reserve_new_chunk(uint64_t newBitsRequired, unsigned char initVal = 0)
{
const auto newCap = BitEntry2Uint64Entry(m_NextBit + newBitsRequired) + 1;
if (newCap > cap())
{
reserve_atleast(newCap, initVal);
}
}
inline void bit_remove_last_bits(uint64_t bitsRemoved)
{
assert(m_NextBit >= bitsRemoved);
m_NextBit -= bitsRemoved;
}
void bit_resize_and_compress(uint64_t newBitsRequired)
{
m_NextBit = newBitsRequired;
reserve_exactly(BitEntry2Uint64Entry(m_NextBit) + (m_NextBit != 0));
}
void compress()
{
bit_resize_and_compress(m_NextBit);
}
template <class TConvertableToUint64>
void bit_push(TConvertableToUint64 elem, uint8_t elemWidth)
{
CSetElemAndGoToNext(m_B, m_NextBit, elemWidth, (uint64_t)elem);
}
template <class TConvertableToUint64>
void bit_set(TConvertableToUint64 elem, uint8_t elemWidth, uint64_t bitNum)
{
CSetElem(m_B, bitNum, elemWidth, (uint64_t)elem);
}
template <class TConvertableToUint64>
void bit_set_and_advance(TConvertableToUint64 elem, uint8_t elemWidth, uint64_t& bitNum)
{
CSetElemAndGoToNext(m_B, bitNum, elemWidth, (uint64_t)elem);
}
uint64_t bit_get(uint64_t b, uint8_t elemWidth) const
{
return CGetElem(m_B, b, elemWidth);
}
uint64_t bit_get_and_advance(uint64_t& b, uint8_t elemWidth) const
{
return CGetElemAndGoToNext(m_B, b, elemWidth);
}
inline uint64_t bit_get_next_bit() const { return m_NextBit; }
inline void bit_set_next_bit(uint64_t nextBit) { m_NextBit = nextBit; }
void copy(uint64_t bFrom, uint64_t bTo, uint8_t elemWidth)
{
assert(m_NextBit - elemWidth < m_NextBit);
assert(bFrom <= m_NextBit - elemWidth);
assert(bTo <= m_NextBit - elemWidth);
const auto v = CGetElem(m_B, bFrom, elemWidth);
CSetElem(m_B, bTo, elemWidth, v);
assert(CGetElem(m_B, bTo, elemWidth) == v);
}
void copy_block(uint64_t bFrom, uint64_t bTo, uint64_t overallWidth)
{
assert(m_NextBit - overallWidth < m_NextBit);
assert(bFrom <= m_NextBit - overallWidth);
assert(bTo <= m_NextBit - overallWidth);
if (overallWidth <= 64)
{
copy(bFrom, bTo, (uint8_t)overallWidth);
return;
}
auto GetDiv = [&](uint64_t n) { return n >> 6; };
auto GetRem = [&](uint64_t n) { return n & 63; };
if (GetRem(bFrom) == 0 && GetRem(bTo) == 0)
{
auto MemMove = [&](size_t outStartInd, size_t inpStartInd, size_t entriesToCopy)
{
if (outStartInd >= inpStartInd + entriesToCopy || inpStartInd >= outStartInd + entriesToCopy)
{
std::memcpy(m_B + outStartInd, m_B + inpStartInd, entriesToCopy * sizeof(*m_B));
}
else
{
std::memmove(m_B + outStartInd, m_B + inpStartInd, entriesToCopy * sizeof(*m_B));
}
};
MemMove((size_t)GetDiv(bTo), (size_t)GetDiv(bFrom), (size_t)GetDiv(overallWidth));
const auto overallWidthRem = GetRem(overallWidth);
if (overallWidthRem != 0)
{
copy(bFrom + overallWidth - overallWidthRem, bTo + overallWidth - overallWidthRem, (uint8_t)overallWidthRem);
}
}
else
{
const auto bToRem = GetRem(bTo);
if (bToRem != 0)
{
copy(bFrom, bTo, (uint8_t)bToRem);
}
for (bFrom += bToRem, bTo += bToRem, overallWidth -= bToRem; overallWidth >= 64; overallWidth -= 64, bFrom += 64, bTo += 64)
{
copy(bFrom, bTo, 64);
}
if (overallWidth != 0)
{
copy(bFrom, bTo, (uint8_t)overallWidth);
}
}
}
protected:
uint64_t m_NextBit = 0;
constexpr size_t BitEntry2Uint64Entry(uint64_t bitEntry) { return (size_t)(bitEntry >> 6); }
};
};