z3-z3-4.13.0.src.util.bit_vector.h Maven / Gradle / Ivy
The newest version!
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
bit_vector.h
Abstract:
Simple bitvector implementation.
Author:
Leonardo de Moura (leonardo) 2006-10-03.
Revision History:
--*/
#pragma once
#include
#include "util/debug.h"
#include "util/vector.h"
#include "util/memory_manager.h"
static_assert(sizeof(unsigned) == 4, "unsigned are 4 bytes");
#define BV_DEFAULT_CAPACITY 2
class bit_vector {
protected:
unsigned m_num_bits;
unsigned m_capacity; //!< in words
unsigned * m_data;
static unsigned get_pos_mask(unsigned bit_idx) {
return 1 << (bit_idx % 32);
}
static unsigned num_words(unsigned num_bits) {
// return (num_bits % 32) == 0 ? (num_bits / 32) : ((num_bits / 32) + 1);
return (num_bits + 31) / 32;
}
void expand_to(unsigned new_capacity);
void expand() {
expand_to(m_capacity == 0 ? BV_DEFAULT_CAPACITY : ((m_capacity * 3 + 1) >> 1));
}
unsigned get_bit_word(unsigned bit_idx) const {
SASSERT(bit_idx < size());
return m_data[bit_idx / 32];
}
unsigned & get_bit_word(unsigned bit_idx) {
SASSERT(bit_idx < size());
return m_data[bit_idx / 32];
}
public:
bit_vector():
m_num_bits(0),
m_capacity(0),
m_data(nullptr) {
}
bit_vector(unsigned reserve_num_bits) :
m_num_bits(0),
m_capacity(num_words(reserve_num_bits)),
m_data(alloc_svect(unsigned, m_capacity)) {
memset(m_data, 0, m_capacity * sizeof(unsigned));
}
bit_vector(bit_vector const & source):
m_num_bits(source.m_num_bits),
m_capacity(source.m_capacity),
m_data(nullptr) {
if (source.m_data) {
m_data = alloc_svect(unsigned, m_capacity);
memcpy(m_data, source.m_data, m_capacity * sizeof(unsigned));
}
}
bit_vector(unsigned const * source, int num_bits):
m_num_bits(num_bits),
m_capacity(num_words(num_bits)),
m_data(alloc_svect(unsigned, m_capacity)) {
memcpy(m_data, source, m_capacity * sizeof(unsigned));
}
~bit_vector() {
dealloc_svect(m_data);
}
void reset() {
if (m_data)
memset(m_data, 0, m_capacity * sizeof(unsigned));
m_num_bits = 0;
}
void swap(bit_vector & other) noexcept {
std::swap(m_data, other.m_data);
std::swap(m_num_bits, other.m_num_bits);
std::swap(m_capacity, other.m_capacity);
}
// Increase the size of the bit_vector by k 0-bits.
void shift_right(unsigned k);
void fill0() {
memset(m_data, 0, m_capacity * sizeof(unsigned));
}
unsigned size() const {
return m_num_bits;
}
bool empty() const {
return m_num_bits == 0;
}
unsigned num_words() const {
return num_words(m_num_bits);
}
unsigned get_word(unsigned word_idx) const {
return m_data[word_idx];
}
unsigned get_hash() const;
bool get(unsigned bit_idx) const {
SASSERT(bit_idx < size());
bool r = (get_bit_word(bit_idx) & get_pos_mask(bit_idx)) != 0;
return r;
}
void set(unsigned bit_idx) {
SASSERT(bit_idx < size());
get_bit_word(bit_idx) |= get_pos_mask(bit_idx);
}
void unset(unsigned bit_idx) {
SASSERT(bit_idx < size());
get_bit_word(bit_idx) &= ~get_pos_mask(bit_idx);
}
void set(unsigned bit_idx, bool val) {
SASSERT(bit_idx < size());
int _val = static_cast(val);
get_bit_word(bit_idx) ^= (-_val ^ get_bit_word(bit_idx)) & get_pos_mask(bit_idx);
}
void push_back(bool val) {
unsigned idx = m_num_bits;
m_num_bits++;
if (num_words(m_num_bits) > m_capacity) {
expand();
}
set(idx, val);
}
void pop_back() {
SASSERT(m_num_bits > 0);
m_num_bits--;
}
bool back() const {
SASSERT(!empty());
bool r = get(m_num_bits - 1);
return r;
}
void shrink(unsigned new_size) {
SASSERT(new_size <= m_num_bits);
m_num_bits = new_size;
}
void resize(unsigned new_size, bool val = false);
void reserve(unsigned sz, bool val = false) {
if (sz > size())
resize(sz, val);
}
bool operator==(bit_vector const & other) const;
bool operator!=(bit_vector const & other) const { return !operator==(other); }
bit_vector & operator=(bit_vector const & source) {
m_num_bits = source.m_num_bits;
if (!source.m_data)
return *this;
if (m_capacity < source.m_capacity) {
dealloc_svect(m_data);
m_data = alloc_svect(unsigned, source.m_capacity);
m_capacity = source.m_capacity;
}
memcpy(m_data, source.m_data, source.m_capacity * sizeof(unsigned));
return *this;
}
bit_vector & operator|=(bit_vector const & source);
bit_vector & operator&=(bit_vector const & source);
bit_vector & neg();
void display(std::ostream & out) const;
bool contains(const bit_vector & other) const;
class iterator {
bit_vector const& b;
unsigned m_curr;
public:
iterator(bit_vector const& b, unsigned i) : b(b), m_curr(i) {}
bool operator*(unsigned i) const { return b.get(m_curr); }
bool operator*() const { return b.get(m_curr); }
iterator& operator++() { ++m_curr; return *this; }
iterator operator++(int) { iterator tmp = *this; ++* this; return tmp; }
bool operator==(iterator const& it) const { return m_curr == it.m_curr; }
bool operator!=(iterator const& it) const { return m_curr != it.m_curr; }
};
iterator begin() const { return iterator(*this, 0); }
iterator end() const { return iterator(*this, size()); }
};
inline std::ostream & operator<<(std::ostream & out, bit_vector const & b) {
b.display(out);
return out;
}
/**
\brief Bitvector class with fast reset.
This class should be used if the reset is frequently called.
*/
class fr_bit_vector : private bit_vector {
unsigned_vector m_one_idxs;
public:
void reset();
void fill0() {
bit_vector::fill0();
m_one_idxs.reset();
}
void set(unsigned idx) {
m_one_idxs.push_back(idx);
bit_vector::set(idx);
}
void set(unsigned idx, bool val) {
if (val)
m_one_idxs.push_back(idx);
bit_vector::set(idx, val);
}
void push_back(bool val) {
if (val)
m_one_idxs.push_back(size());
bit_vector::push_back(val);
}
};