b-tree-plus-alpha
Loading...
Searching...
No Matches
bit_container.hpp
1#pragma once
2#include "../bp_tree.hpp"
3
4namespace stool
5{
6 namespace bptree
7 {
8
14 {
15 uint64_t bits = 1;
16
17 public:
19 {
20
21 public:
22 uint64_t bits;
23 uint16_t index;
24
25 using iterator_category = std::random_access_iterator_tag;
26 using value_type = bool;
27 using difference_type = std::ptrdiff_t;
28
29 BitContainerIterator() : bits(0), index(UINT16_MAX) {}
30 BitContainerIterator(uint64_t _bits, uint16_t _index) : bits(_bits), index(_index) {}
31
32 bool operator*() const
33 {
34 return stool::LSBByte::get_bit(this->bits, index);
35 }
36 uint64_t get_size() const
37 {
38 return stool::LSBByte::get_code_length(this->bits) - 1;
39 }
40 bool is_end() const
41 {
42 return this->index == UINT16_MAX;
43 }
44
45 BitContainerIterator &operator++()
46 {
47 uint64_t size = this->get_size();
48 if ((uint64_t)(this->index + 1) < size)
49 {
50 this->index++;
51 }
52 else if ((uint64_t)(this->index + 1) == size)
53 {
54 this->index = UINT16_MAX;
55 }
56 else
57 {
58 throw std::invalid_argument("Error: BitDequeIterator::operator++()");
59 }
60
61 return *this;
62 }
63
64 BitContainerIterator operator++(int)
65 {
66 BitContainerIterator temp = *this;
67
68 ++(*this);
69 return temp;
70 }
71
72 BitContainerIterator &operator--()
73 {
74 if (this->index > 1)
75 {
76 this->index--;
77 }
78 else
79 {
80 throw std::invalid_argument("Error: BitDequeIterator::operator--()");
81 }
82
83 return *this;
84 }
85
86 BitContainerIterator operator--(int)
87 {
88 BitContainerIterator temp = *this;
89 --(*this);
90 return temp;
91 }
92
93 BitContainerIterator operator+(difference_type n) const
94 {
95 if ((uint64_t)(this->index + n) < this->get_size())
96 {
97 return BitContainerIterator(this->bits, this->index + n);
98 }
99 else
100 {
101 return BitContainerIterator(this->bits, UINT16_MAX);
102 }
103 }
104
105 BitContainerIterator &operator+=(difference_type n)
106 {
107 if ((uint64_t)(this->index + n) < this->get_size())
108 {
109 this->index += n;
110 }
111 else
112 {
113 this->index = UINT16_MAX;
114 }
115 return *this;
116 }
117
118 BitContainerIterator operator-(difference_type n) const
119 {
120 if (this->index - n >= 0)
121 {
122 return BitContainerIterator(this->bits, this->index - n);
123 }
124 else
125 {
126 throw std::invalid_argument("Error: BitContainerIterator::operator-()");
127 }
128 }
129
130 BitContainerIterator &operator-=(difference_type n)
131 {
132 if (this->index < n)
133 {
134 throw std::invalid_argument("Error: BitDequeIterator::operator-()");
135 }
136 this->index -= n;
137 return *this;
138 }
139
140 uint64_t read_64bit_MSB_string() const
141 {
142 uint64_t size = this->get_size();
143 if (this->index == size)
144 {
145 throw std::invalid_argument("Error: BitContainerIterator::read_64_bit_string()");
146 }
147 else if (size == 0)
148 {
149 return 0;
150 }
151 else
152 {
153 uint64_t p = size - this->index;
154 uint64_t return_bits = 0;
155
156
157 for(uint64_t x = 0; x < p; x++){
158 uint64_t y = x + this->index;
159 if(stool::LSBByte::get_bit(this->bits, y)){
160 return_bits = return_bits | (1ULL << (63-x));
161 }
162 }
163
164 return return_bits;
165 }
166 }
167
168
169 difference_type operator-(const BitContainerIterator &other) const
170 {
171 return (int16_t)this->index - (int16_t)other.index;
172 }
173
177 bool operator==(const BitContainerIterator &other) const { return this->index == other.index; }
178
182 bool operator!=(const BitContainerIterator &other) const { return this->index != other.index; }
183
187 bool operator<(const BitContainerIterator &other) const { return this->index < other.index; }
188
192 bool operator>(const BitContainerIterator &other) const { return this->index > other.index; }
193
197 bool operator<=(const BitContainerIterator &other) const { return this->index <= other.index; }
198
202 bool operator>=(const BitContainerIterator &other) const { return this->index >= other.index; }
203 };
204
206 {
207 }
208 BitContainer(std::vector<uint64_t> &_items)
209 {
210 for (uint64_t x : _items)
211 {
212 this->push_back(x);
213 }
214 }
215 BitContainer(std::vector<bool> &_items)
216 {
217 for (uint64_t i = 0; i < _items.size(); i++)
218 {
219 this->push_back(_items[i]);
220 }
221 }
222
223 void swap(BitContainer &item)
224 {
225 std::swap(this->bits, item.bits);
226 }
227 uint64_t size() const
228 {
229 return stool::LSBByte::get_code_length(this->bits) - 1;
230 }
231 uint64_t size_in_bytes(bool only_extra_bytes) const
232 {
233 if (only_extra_bytes)
234 {
235 return 0;
236 }
237 else
238 {
239 return sizeof(uint64_t);
240 }
241 }
242 uint64_t unused_size_in_bytes() const
243 {
244 return 0;
245 }
246
247 uint64_t at(uint64_t pos) const
248 {
249 return stool::LSBByte::get_bit(this->bits, pos);
250 }
251 void print() const
252 {
253 throw std::runtime_error("Error: BitContainer");
254 }
255
256 void clear()
257 {
258 this->bits = 1;
259 }
260 static std::string name()
261 {
262 return "Bits";
263 }
264 uint64_t psum(uint64_t i) const noexcept
265 {
266 uint64_t x = (this->bits << (63 - i));
267 return __builtin_popcountll(x);
268 }
269 uint64_t psum() const noexcept
270 {
271 return __builtin_popcountll(this->bits) - 1;
272 }
273 int64_t search(uint64_t x) const noexcept
274 {
275 if (x == 0)
276 {
277 return 0;
278 }
279 else
280 {
281 uint64_t count = this->psum();
282 if (x <= count)
283 {
284 return stool::LSBByte::select1(this->bits, x - 1);
285 }
286 else
287 {
288 return -1;
289 }
290 }
291 }
292
293 std::string to_string() const
294 {
295 std::string s;
296 for (uint64_t i = 0; i < this->size(); i++)
297 {
298 if (this->at(i) >= 1)
299 {
300 s.push_back('1');
301 }
302 else
303 {
304 s.push_back('0');
305 }
306 }
307
308 return s;
309 }
310 std::vector<uint64_t> to_packed_vector() const
311 {
312 std::vector<uint64_t> r;
313 for (uint64_t i = 0; i < this->size(); i++)
314 {
315 r.push_back(this->at(i));
316 }
317 return r;
318 }
319 uint64_t to_uint64() const
320 {
321 return stool::LSBByte::write_bit(this->bits, this->size(), false);
322 }
323
324 template <typename VEC>
325 void to_values(VEC &output_vec) const
326 {
327 output_vec.clear();
328 output_vec.resize(this->size());
329 for (uint64_t i = 0; i < this->size(); i++)
330 {
331 output_vec[i] = this->at(i);
332 }
333 }
334
335 void insert(uint64_t pos, uint64_t value)
336 {
337 assert(this->size() + 1 < 64);
338 this->bits = stool::LSBByte::insert_bit(this->bits, pos, value >= 1);
339 }
340 void remove(uint64_t pos)
341 {
342 assert(this->size() > 0);
343 this->bits = stool::LSBByte::remove_bit(this->bits, pos);
344 }
345 void push_front(std::vector<uint64_t> &new_items)
346 {
347 assert(this->size() + new_items.size() < 64);
348
349 for (int64_t i = new_items.size() - 1; i >= 0; i--)
350 {
351 this->push_front(new_items[i]);
352 }
353 }
354 void push_front(uint64_t new_item)
355 {
356 assert(this->size() + 1 < 64);
357 this->bits = (this->bits << 1) | (new_item >= 1 ? 1 : 0);
358 }
359
360 void push_back(std::vector<uint64_t> &new_items)
361 {
362 assert(this->size() + 1 < 64);
363 assert(this->size() + new_items.size() < 64);
364
365 for (uint64_t v : new_items)
366 {
367 this->push_back(v);
368 }
369 }
370 void verify() const{
371
372 }
373 void push_back(uint64_t value)
374 {
375 assert(this->size() + 1 < 64);
376 this->bits = stool::LSBByte::insert_bit(this->bits, this->size(), value >= 1);
377 }
378 void pop_front()
379 {
380 assert(this->size() > 0);
381 this->bits = this->bits >> 1;
382 }
383 std::vector<uint64_t> pop_front(uint64_t len)
384 {
385 assert(len <= this->size());
386 std::vector<uint64_t> r;
387 for (uint64_t i = 0; i < len; i++)
388 {
389 r.push_back(this->at(0));
390 this->pop_front();
391 }
392 return r;
393 }
394 void pop_back()
395 {
396 assert(this->size() > 0);
397 this->remove(this->size() - 1);
398 }
399
400 std::vector<uint64_t> pop_back(uint64_t len)
401 {
402 assert(len <= this->size());
403 std::vector<uint64_t> r;
404 r.resize(len);
405
406 for (uint64_t i = 0; i < len; i++)
407 {
408 r[len - i - 1] = this->at(this->size() - 1);
409 this->pop_back();
410 }
411 return r;
412 }
413
414 uint64_t reverse_psum(uint64_t i) const
415 {
416 if (i == this->size() - 1)
417 {
418 return this->psum();
419 }
420 else
421 {
422 uint64_t len1 = i + 1;
423 uint64_t idx = this->size() - len1;
424 return this->psum() - this->psum(idx - 1);
425 }
426 }
427
428 uint64_t psum(uint64_t i, uint64_t j) const
429 {
430 if (i == j)
431 {
432 return this->at(i);
433 }
434 else
435 {
436 throw std::runtime_error("No implementation");
437 }
438 }
439
440 void increment(uint64_t i, int64_t delta)
441 {
442 if (delta >= 1)
443 {
444 this->bits = stool::LSBByte::write_bit(this->bits, i, true);
445 }
446 else if (delta <= -1)
447 {
448 this->bits = stool::LSBByte::write_bit(this->bits, i, false);
449 }
450 }
451
452 BitContainerIterator begin() const
453 {
454 if (this->size() == 0)
455 {
456 return BitContainerIterator(this->bits, UINT16_MAX);
457 }
458 else
459 {
460 return BitContainerIterator(this->bits, 0);
461 }
462 }
463
464 BitContainerIterator end() const
465 {
466 return BitContainerIterator(this->bits, UINT16_MAX);
467 }
468
469 int64_t one_based_rank1(uint64_t i) const
470 {
471 if (i == 0)
472 {
473 return 0;
474 }
475 else
476 {
477 return this->psum(i - 1);
478 }
479 }
480
481 int64_t one_based_rank0(uint64_t i) const
482 {
483 return i - this->one_based_rank1(i);
484 }
485 int64_t one_based_rank(uint64_t i, bool b) const
486 {
487 return b ? this->one_based_rank1(i) : this->one_based_rank0(i);
488 }
489
490 int64_t select(uint64_t i, bool b) const
491 {
492 return b ? this->select1(i) : this->select0(i);
493 }
494
495 int64_t select1(uint64_t i) const
496 {
497 return this->search(i + 1);
498 }
499 int64_t select0(uint64_t i) const
500 {
501 return stool::LSBByte::select0(this->bits, i);
502 }
503
504 void to_data(std::vector<uint8_t> &output) const
505 {
506 output.push_back(this->bits);
507 }
508 /*
509 void load_from_data(std::vector<uint64_t> &output){
510
511 }
512 */
513
514 static uint64_t get_byte_size(const std::vector<BitContainer> &items)
515 {
516 return sizeof(uint64_t) + (items.size() * sizeof(BitContainer));
517 }
518 static void store_to_bytes(const std::vector<BitContainer> &items, std::vector<uint8_t> &output, uint64_t &pos)
519 {
520 uint64_t size = get_byte_size(items);
521 if (pos + size > output.size())
522 {
523 output.resize(pos + size);
524 }
525
526 uint64_t items_size = items.size();
527 std::memcpy(output.data() + pos, &items_size, sizeof(uint64_t));
528 pos += sizeof(uint64_t);
529
530 std::memcpy(output.data() + pos, items.data(), items_size * sizeof(BitContainer));
531 pos += size * sizeof(BitContainer);
532 }
533 static void store_to_file(const std::vector<BitContainer> &items, std::ofstream &os)
534 {
535 uint64_t items_size = items.size();
536 os.write(reinterpret_cast<const char *>(&items_size), sizeof(uint64_t));
537 os.write(reinterpret_cast<const char *>(items.data()), items.size() * sizeof(BitContainer));
538 }
539
540 static std::vector<BitContainer> load_vector_from_bytes(const std::vector<uint8_t> &data, uint64_t &pos)
541 {
542 uint64_t size = 0;
543 std::memcpy(&size, data.data() + pos, sizeof(uint64_t));
544 pos += sizeof(uint64_t);
545
546 std::vector<BitContainer> output;
547 output.resize(size);
548 std::memcpy(output.data(), data.data() + pos, size * sizeof(BitContainer));
549 pos += size * sizeof(BitContainer);
550 return output;
551 }
552 static std::vector<BitContainer> load_vector_from_file(std::ifstream &ifs)
553 {
554 uint64_t size = 0;
555 ifs.read(reinterpret_cast<char *>(&size), sizeof(uint64_t));
556
557 std::vector<BitContainer> output;
558 output.resize(size);
559
560 ifs.read(reinterpret_cast<char *>(output.data()), size * sizeof(BitContainer));
561
562 return output;
563 }
564 void sort_leaf_containers()
565 {
566 }
567 };
568 }
569
570}
bool operator<=(const BitContainerIterator &other) const
Less than or equal comparison.
Definition bit_container.hpp:197
bool operator>=(const BitContainerIterator &other) const
Greater than or equal comparison.
Definition bit_container.hpp:202
bool operator>(const BitContainerIterator &other) const
Greater than comparison.
Definition bit_container.hpp:192
bool operator==(const BitContainerIterator &other) const
Equality comparison.
Definition bit_container.hpp:177
bool operator!=(const BitContainerIterator &other) const
Inequality comparison.
Definition bit_container.hpp:182
bool operator<(const BitContainerIterator &other) const
Less than comparison.
Definition bit_container.hpp:187
A container that stores a short sequence of bits. [Unchecked AI's Comment].
Definition bit_container.hpp:14