/*++ Copyright (c) 2006 Microsoft Corporation Module Name: bitvector.cpp Abstract: Simple bitvector implementation Author: Leonardo de Moura (leonardo) 2006-10-03. Revision History: --*/ #include"bit_vector.h" #include"trace.h" #define DEFAULT_CAPACITY 2 void bit_vector::expand_to(unsigned new_capacity) { unsigned * new_data = alloc_svect(unsigned, new_capacity); memset(new_data, 0, new_capacity * sizeof(unsigned)); if (m_capacity > 0) { memcpy(new_data, m_data, m_capacity * sizeof(unsigned)); dealloc_svect(m_data); } m_data = new_data; m_capacity = new_capacity; } void bit_vector::resize(unsigned new_size, bool val) { if (new_size <= m_num_bits) { m_num_bits = new_size; return; } TRACE("bit_vector", tout << "expanding: " << new_size << " capacity: " << m_capacity << " num words: " << num_words(new_size) << "\n";); if (num_words(new_size) > m_capacity) { expand_to((num_words(new_size) * 3 + 1) >> 1); } unsigned bwidx = m_num_bits/32; unsigned ewidx = num_words(new_size); unsigned * begin = m_data + bwidx; unsigned pos = m_num_bits % 32; unsigned mask = (1 << pos) - 1; int cval; if (val) { *begin |= ~mask; cval = ~0; } else { *begin &= mask; cval = 0; } TRACE("bit_vector", tout << "num_bits: " << m_num_bits << "\n"; tout << "bwidx: " << bwidx << "\n"; tout << "ewidx: " << ewidx << "\n"; tout << "pos: " << pos << "\n"; tout << "mask: " << std::hex << mask << "\n" << std::dec; tout << "cval: " << cval << "\n";); if (bwidx < ewidx) { memset(begin + 1, cval, (ewidx - bwidx - 1) * sizeof(unsigned)); } m_num_bits = new_size; } void bit_vector::shift_right(unsigned k) { if (k == 0) return; unsigned new_num_bits = m_num_bits + k; unsigned old_num_words = num_words(m_num_bits); unsigned new_num_words = num_words(new_num_bits); resize(m_num_bits + k, false); unsigned bit_shift = k % (8 * sizeof(unsigned)); unsigned word_shift = k / (8 * sizeof(unsigned)); if (word_shift > 0) { unsigned j = old_num_words; unsigned i = old_num_words + word_shift; while (j > 0) { --j; --i; m_data[i] = m_data[j]; } while (i > 0) { --i; m_data[i] = 0; } } if (bit_shift > 0) { DEBUG_CODE({ for (unsigned i = 0; i < word_shift; i++) { SASSERT(m_data[i] == 0); } }); unsigned comp_shift = (8 * sizeof(unsigned)) - bit_shift; unsigned prev = 0; for (unsigned i = word_shift; i < new_num_words; i++) { unsigned new_prev = (m_data[i] >> comp_shift); m_data[i] <<= bit_shift; m_data[i] |= prev; prev = new_prev; } } } bool bit_vector::operator==(bit_vector const & source) { if (m_num_bits != source.m_num_bits) return false; unsigned n = num_words(); if (n == 0) return true; unsigned i; for (i = 0; i < n - 1; i++) { if (m_data[i] != source.m_data[i]) return false; } unsigned bit_rest = source.m_num_bits % 32; unsigned mask = (1 << bit_rest) - 1; return (m_data[i] & mask) == (source.m_data[i] & mask); } bit_vector & bit_vector::operator|=(bit_vector const & source) { if (size() < source.size()) resize(source.size(), false); unsigned n1 = num_words(); unsigned n2 = source.num_words(); SASSERT(n2 <= n1); unsigned bit_rest = source.m_num_bits % 32; if (bit_rest == 0) { unsigned i = 0; for (i = 0; i < n2; i++) m_data[i] |= source.m_data[i]; } else { unsigned i = 0; for (i = 0; i < n2 - 1; i++) m_data[i] |= source.m_data[i]; unsigned mask = (1 << bit_rest) - 1; m_data[i] |= source.m_data[i] & mask; } return *this; } bit_vector & bit_vector::operator&=(bit_vector const & source) { unsigned n1 = num_words(); unsigned n2 = source.num_words(); if (n1 == 0) return *this; if (n2 > n1) { for (unsigned i = 0; i < n1; i++) m_data[i] &= source.m_data[i]; } else { SASSERT(n2 <= n1); unsigned bit_rest = source.m_num_bits % 32; unsigned i = 0; if (bit_rest == 0) { for (i = 0; i < n2; i++) m_data[i] &= source.m_data[i]; } else { for (i = 0; i < n2 - 1; i++) m_data[i] &= source.m_data[i]; unsigned mask = (1 << bit_rest) - 1; m_data[i] &= (source.m_data[i] & mask); } for (i = n2; i < n1; i++) m_data[i] = 0; } return *this; } void bit_vector::display(std::ostream & out) const { #if 1 unsigned i = m_num_bits; while (i > 0) { --i; if (get(i)) out << "1"; else out << "0"; } #else for (unsigned i = 0; i < m_num_bits; i++) { if (get(i)) out << "1"; else out << "0"; if ((i + 1) % 32 == 0) out << "\n"; } #endif } void fr_bit_vector::reset() { unsigned sz = size(); vector::const_iterator it = m_one_idxs.begin(); vector::const_iterator end = m_one_idxs.end(); for (; it != end; ++it) { unsigned idx = *it; if (idx < sz) unset(idx); } m_one_idxs.reset(); }