b-tree-plus-alpha
Loading...
Searching...
No Matches
bit_deque_container.hpp
1#pragma once
2#include "../bp_tree.hpp"
3
4namespace stool
5{
6 namespace bptree
7 {
12 template <uint64_t MAX_BIT_SIZE = 8192ULL>
14 {
15 //using BitArrayDeque = typename stool::BitArrayDeque<MAX_BIT_SIZE>;
16 using BitArrayDeque = typename stool::NaiveBitVector<MAX_BIT_SIZE>;
17
18 BitArrayDeque bits;
19
20 public:
21 //using BitVectorContainerIterator = typename BitArrayDeque::BitArrayDequeIterator;
22
23 using BitVectorContainerIterator = typename BitArrayDeque::NaiveBitVectorIterator;
25 {
26 }
27 BitVectorContainer(std::vector<uint64_t> &_items)
28 {
29 for (uint64_t x : _items)
30 {
31 this->push_back(x);
32 }
33 }
34 BitVectorContainer(std::vector<bool> &_items)
35 {
36 for (uint64_t i = 0; i < _items.size(); i++)
37 {
38 this->push_back(_items[i]);
39 }
40 }
41
42 void swap(BitVectorContainer &item)
43 {
44 std::swap(this->bits, item.bits);
45 }
46 uint64_t size() const
47 {
48 return this->bits.size();
49 }
50 uint64_t size_in_bytes(bool only_extra_bytes) const
51 {
52 return this->bits.size_in_bytes(only_extra_bytes);
53 }
54 uint64_t unused_size_in_bytes() const
55 {
56 return this->bits.unused_size_in_bytes();
57 }
58
59 uint64_t at(uint64_t pos) const
60 {
61 return this->bits.at(pos);
62 }
63 void print() const
64 {
65 throw std::runtime_error("Error: BitVectorContainer");
66 }
67
68 void clear()
69 {
70 this->bits.clear();
71 }
72 static std::string name()
73 {
74 return "BitVectorContainer";
75 }
76 uint64_t psum(uint64_t i) const noexcept
77 {
78 return this->bits.psum(i);
79 }
80 uint64_t psum() const noexcept
81 {
82 return this->bits.psum();
83 }
84 int64_t search(uint64_t x) const noexcept
85 {
86 uint64_t v = this->bits.search(x);
87 return v;
88 }
89
90 std::string to_string() const
91 {
92 return this->bits.to_string();
93 }
94 std::vector<uint64_t> to_value_vector() const
95 {
96 std::vector<uint64_t> r;
97 for (uint64_t i = 0; i < this->size(); i++)
98 {
99 r.push_back(this->at(i));
100 }
101 return r;
102 }
103 uint64_t to_uint64() const
104 {
105 uint64_t size = this->size();
106 if (size > 0)
107 {
108 uint64_t value = this->bits.read_64_bit_string();
109 if (size >= 64)
110 {
111 return value;
112 }
113 else
114 {
115 return value >> (64 - size);
116 }
117 }
118 else
119 {
120 return 0;
121 }
122 }
123
124 template <typename VEC>
125 void to_values(VEC &output_vec) const
126 {
127 output_vec.clear();
128 output_vec.resize(this->size());
129 for (uint64_t i = 0; i < this->size(); i++)
130 {
131 output_vec[i] = this->at(i);
132 }
133
134
135
136 }
137
138 void insert(uint64_t pos, uint64_t value)
139 {
140 this->bits.insert(pos, value >= 1);
141 }
142 void remove(uint64_t pos)
143 {
144 assert(this->size() > 0);
145 this->bits.erase(pos);
146 }
147 uint64_t to_bit_array(const std::vector<uint64_t> &new_items, std::array<uint64_t, MAX_BIT_SIZE / 64> &output){
148 uint64_t added_block_size = ((new_items.size()-1) / 64) + 1;
149 for(uint64_t i = 0; i < added_block_size; i++){
150 output[i] = 0;
151 }
152 for(uint64_t i = 0; i < new_items.size(); i++){
153 uint64_t v = i / 64;
154 uint64_t w = i % 64;
155 output[v] |= ((new_items[i] >= 1) ? 1ULL : 0ULL) << (63 - w);
156 }
157 return added_block_size;
158 }
159 void push_front_many(const std::vector<uint64_t> &new_items)
160 {
161 if(new_items.size() > 0){
162 std::array<uint64_t, MAX_BIT_SIZE / 64> tmp_buffer;
163 uint64_t added_block_size = this->to_bit_array(new_items, tmp_buffer);
164
165 #ifdef DEBUG
166 uint64_t sum1 = this->bits.psum();
167 uint64_t sum2 = 0;
168 for(uint64_t i = 0; i < new_items.size(); i++){
169 sum2 += new_items[i] >= 1 ? 1 : 0;
170 }
171 uint64_t x_size = this->size();
172 #endif
173
174 this->bits.push_front64(tmp_buffer, new_items.size(), added_block_size);
175
176 #ifdef DEBUG
177 if(sum1 + sum2 != this->bits.psum()){
178 std::cout << new_items.size() << "/" << x_size << std::endl;
179 std::cout << sum1 << "/" << sum2 << std::endl;
180 std::cout << this->bits.psum() << std::endl;
181 }
182 assert(sum1 + sum2 == this->bits.psum());
183 #endif
184 }
185
186 }
187 void push_front(uint64_t new_item)
188 {
189
190 this->bits.push_back64(new_item >= 1);
191 }
192
193 void push_back_many(const std::vector<uint64_t> &new_items)
194 {
195
196 if(new_items.size() > 0){
197 std::array<uint64_t, MAX_BIT_SIZE / 64> tmp_buffer;
198 uint64_t added_block_size = this->to_bit_array(new_items, tmp_buffer);
199 this->bits.push_back64(tmp_buffer, new_items.size(), added_block_size);
200 }
201 }
202 void push_back(uint64_t value)
203 {
204
205 this->bits.push_back(value >= 1);
206 }
207 void pop_front()
208 {
209
210 assert(this->size() > 0);
211 this->bits.pop_front();
212 }
213 std::vector<uint64_t> pop_front_many(uint64_t len)
214 {
215
216 assert(len <= this->size());
217 std::array<uint64_t, MAX_BIT_SIZE / 64> tmp_buffer;
218 this->bits.pop_front(len, tmp_buffer, MAX_BIT_SIZE / 64);
219 std::vector<uint64_t> r;
220
221 for(uint64_t i = 0; i < len; i++){
222 uint64_t v = i / 64;
223 uint64_t w = i % 64;
224 r.push_back((tmp_buffer[v] >> (63 - w)) & 1);
225 }
226
227 /*
228 for (uint64_t i = 0; i < len; i++)
229 {
230 bool b = this->at(0);
231 r.push_back(b ? 1 : 0);
232 this->pop_front();
233 }
234 */
235 return r;
236 }
237 void pop_back()
238 {
239
240 assert(this->size() > 0);
241 this->bits.pop_back();
242 }
243
244 std::vector<uint64_t> pop_back_many(uint64_t len)
245 {
246
247 assert(len <= this->size());
248 std::vector<uint64_t> r;
249 r.resize(len);
250
251 for (uint64_t i = 0; i < len; i++)
252 {
253 bool b = this->at(this->size() - 1);
254 r[len - i - 1] = b ? 1 : 0;
255 this->pop_back();
256 }
257 return r;
258 }
259
260 uint64_t reverse_psum(uint64_t i) const
261 {
262 return this->bits.reverse_psum(i);
263 }
264
265 uint64_t psum(uint64_t i, uint64_t j) const
266 {
267 return this->bits.psum(i, j);
268 }
269
270 void increment(uint64_t i, int64_t delta)
271 {
272 this->bits.increment(i, delta);
273 }
274
275 int64_t rank1(uint64_t i) const
276 {
277 return this->bits.rank1(i);
278 }
279
280 int64_t rank0(uint64_t i) const
281 {
282 return i - this->rank1(i);
283 }
284 int64_t rank(uint64_t i, bool b) const
285 {
286 return b ? this->rank1(i) : this->rank0(i);
287 }
288
289 int64_t select(uint64_t i, bool b) const
290 {
291 return b ? this->select1(i) : this->select0(i);
292 }
293
294 int64_t select1(uint64_t i) const
295 {
296 return this->bits.select1(i);
297 }
298 int64_t select0(uint64_t i) const
299 {
300 return this->bits.select0(i);
301 }
302
303 void to_data(std::vector<uint8_t> &output) const
304 {
305 uint64_t byte_size = BitArrayDeque::get_byte_size(this->bits);
306 uint64_t size = this->size();
307 for (uint64_t i = 0; i < byte_size; i++)
308 {
309 output.push_back(0);
310 }
311 BitArrayDeque::store_to_bytes(this->bits, output, size);
312 }
313 /*
314 void load_from_data(std::vector<uint64_t> &output){
315
316 }
317 */
318
319 static uint64_t get_byte_size(const std::vector<BitVectorContainer> &items)
320 {
321 uint64_t size = sizeof(uint64_t);
322 for (const auto &item : items)
323 {
324 size += BitArrayDeque::get_byte_size(item.bits);
325 }
326 return size;
327 }
328 static void store_to_bytes(const std::vector<BitVectorContainer> &items, std::vector<uint8_t> &output, uint64_t &pos)
329 {
330 uint64_t size = get_byte_size(items);
331 if (pos + size > output.size())
332 {
333 output.resize(pos + size);
334 }
335
336 uint64_t items_size = items.size();
337 std::memcpy(output.data() + pos, &items_size, sizeof(uint64_t));
338 pos += sizeof(uint64_t);
339
340 for (const auto &item : items)
341 {
342 BitArrayDeque::store_to_bytes(item.bits, output, pos);
343 }
344 }
345 static void store_to_file(const std::vector<BitVectorContainer> &items, std::ofstream &os)
346 {
347 uint64_t items_size = items.size();
348 os.write(reinterpret_cast<const char *>(&items_size), sizeof(uint64_t));
349
350 for (const auto &item : items)
351 {
352 BitArrayDeque::store_to_file(item.bits, os);
353 }
354 }
355 static BitVectorContainer load_from_bytes(const std::vector<uint8_t> &data, uint64_t &pos){
357 r.bits = BitArrayDeque::load_from_bytes(data, pos);
358 return r;
359 }
360 static BitVectorContainer load_from_file(std::ifstream &ifs)
361 {
363 r.bits = BitArrayDeque::load_from_file(ifs);
364 return r;
365 }
366 static std::vector<BitVectorContainer> load_vector_from_bytes(const std::vector<uint8_t> &data, uint64_t &pos)
367 {
368 uint64_t size = 0;
369 std::memcpy(&size, data.data() + pos, sizeof(uint64_t));
370 pos += sizeof(uint64_t);
371
372 std::vector<BitVectorContainer> output;
373 output.resize(size);
374 for (uint64_t i = 0; i < size; i++)
375 {
376 output[i] = BitVectorContainer::load_from_bytes(data, pos);
377 }
378 return output;
379 }
380 static std::vector<BitVectorContainer> load_vector_from_file(std::ifstream &ifs)
381 {
382 uint64_t size = 0;
383 ifs.read(reinterpret_cast<char *>(&size), sizeof(uint64_t));
384
385 std::vector<BitVectorContainer> output;
386 output.resize(size);
387 for (uint64_t i = 0; i < size; i++)
388 {
389 output[i] = BitVectorContainer::load_from_file(ifs);
390 }
391
392 return output;
393 }
394
395 BitVectorContainerIterator begin() const
396 {
397 return this->bits.begin();
398 }
399 BitVectorContainerIterator end() const
400 {
401 return this->bits.end();
402 }
403 };
404 }
405
406}
A container that stores a short sequence of bits. [Unchecked AI's Comment].
Definition bit_deque_container.hpp:14