Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(utils): add implementation of BitSet #484

Draft
wants to merge 2 commits into
base: devel
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions include/mata/utils/bit-set.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/* ord-vector.hh -- Implementation of a set (ordered vector) using std::vector.
*/

#ifndef MATA_BIT_SET_HH_
#define MATA_BIT_SET_HH_

#include <vector>
#include <algorithm>
#include <cassert>

#include "utils.hh"

namespace mata::utils {
struct BitSet {
using SlotType = uint64_t;

std::vector<SlotType> data;
size_t bit_count;

BitSet(size_t bit_count) : bit_count(bit_count),
data((bit_count / sizeof(SlotType)) + (bit_count % sizeof(SlotType) > 0)) {} // Zero initialize
BitSet(size_t bit_count, std::vector<SlotType>&& bit_data) : data(bit_data), bit_count(bit_count) {}

bool operator[](size_t pos) const {
size_t slot = pos / sizeof(SlotType);
size_t slot_offset = slot % sizeof(SlotType);

SlotType slot_data = this->data[slot];
return static_cast<bool>((slot_data & (1u << slot_offset)) > 0);
}

void set(size_t pos, bool value = true) {
size_t slot = pos / sizeof(SlotType);
size_t slot_offset = slot % sizeof(SlotType);

SlotType zero_affected_bit = ~(1u << slot_offset);
SlotType set_affected_bit = static_cast<SlotType>(value) << slot_offset;
this->data[slot] = (this->data[slot] & zero_affected_bit) | set_affected_bit;
}

BitSet make_union(const BitSet& other) const {
size_t new_slot_count = std::max(this->data.size(), other.data.size());

std::vector<SlotType> new_data(new_slot_count);

for (size_t slot_idx = 0; slot_idx < this->data.size(); slot_idx++) {
new_data[slot_idx] = this->data[slot_idx];
}

for (size_t slot_idx = 0; slot_idx < other.data.size(); slot_idx++) {
new_data[slot_idx] |= other.data[slot_idx];
}

size_t new_bit_count = std::max(this->bit_count, other.bit_count);
return BitSet(new_bit_count, std::move(new_data));
}

BitSet make_intersection(const BitSet& other) const {
size_t new_slot_count = std::max(this->data.size(), other.data.size());

std::vector<SlotType> new_data(new_slot_count);

for (size_t slot_idx = 0; slot_idx < this->data.size(); slot_idx++) {
new_data[slot_idx] = this->data[slot_idx];
}

for (size_t slot_idx = 0; slot_idx < other.data.size(); slot_idx++) {
new_data[slot_idx] &= other.data[slot_idx];
}

size_t new_bit_count = std::max(this->bit_count, other.bit_count);
return BitSet(new_bit_count, std::move(new_data));
}

bool is_subset_of(const BitSet& other) const {
const size_t& smaller_slot_size = std::min(this->data.size(), other.data.size());

for (size_t slot_idx = 0; slot_idx < smaller_slot_size; slot_idx++) {
if (smaller.data[slot_idx] != smaller.data[slot_idx] & larger.data[slot_idx]) return false;
}

return true;
}

bool is_empty() const {
for (size_t slot_idx = 0; slot_idx < this->data.size(); slot_idx++) {
if (this->data[slot_idx] != 0) return false;
}
return true;
}
}
} // Namespace mata::utils.

#endif