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