📄 dynamic_bitset.hpp
字号:
template <typename Block, typename Allocator>
bool operator>=(const dynamic_bitset<Block, Allocator>& a,
const dynamic_bitset<Block, Allocator>& b);
// stream operators
#ifdef BOOST_OLD_IOSTREAMS
template <typename Block, typename Allocator>
std::ostream& operator<<(std::ostream& os,
const dynamic_bitset<Block, Allocator>& b);
template <typename Block, typename Allocator>
std::istream& operator>>(std::istream& is, dynamic_bitset<Block,Allocator>& b);
#else
// NOTE: Digital Mars wants the same template parameter names
// here and in the definition! [last tested: 8.48.10]
//
template <typename Ch, typename Tr, typename Block, typename Alloc>
std::basic_ostream<Ch, Tr>&
operator<<(std::basic_ostream<Ch, Tr>& os,
const dynamic_bitset<Block, Alloc>& b);
template <typename Ch, typename Tr, typename Block, typename Alloc>
std::basic_istream<Ch, Tr>&
operator>>(std::basic_istream<Ch, Tr>& is,
dynamic_bitset<Block, Alloc>& b);
#endif
// bitset operations
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>
operator&(const dynamic_bitset<Block, Allocator>& b1,
const dynamic_bitset<Block, Allocator>& b2);
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>
operator|(const dynamic_bitset<Block, Allocator>& b1,
const dynamic_bitset<Block, Allocator>& b2);
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>
operator^(const dynamic_bitset<Block, Allocator>& b1,
const dynamic_bitset<Block, Allocator>& b2);
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>
operator-(const dynamic_bitset<Block, Allocator>& b1,
const dynamic_bitset<Block, Allocator>& b2);
// namespace scope swap
template<typename Block, typename Allocator>
void swap(dynamic_bitset<Block, Allocator>& b1,
dynamic_bitset<Block, Allocator>& b2);
template <typename Block, typename Allocator, typename stringT>
void
to_string(const dynamic_bitset<Block, Allocator>& b, stringT & s); // gps
template <typename Block, typename Allocator, typename BlockOutputIterator>
void
to_block_range(const dynamic_bitset<Block, Allocator>& b,
BlockOutputIterator result);
// gps - check docs with Jeremy
//
template <typename BlockIterator, typename B, typename A>
inline void
from_block_range(BlockIterator first, BlockIterator last,
dynamic_bitset<B, A>& result)
{
// PRE: distance(first, last) <= numblocks()
std::copy (first, last, result.m_bits.begin()); //[gps]
}
//=============================================================================
// dynamic_bitset implementation
//-----------------------------------------------------------------------------
// constructors, etc.
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>::dynamic_bitset(const Allocator& alloc)
: m_bits(alloc), m_num_bits(0)
{
}
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>::
dynamic_bitset(size_type num_bits, unsigned long value, const Allocator& alloc)
: m_bits(calc_num_blocks(num_bits), Block(0), alloc),
m_num_bits(num_bits)
{
if (num_bits == 0)
return;
typedef unsigned long num_type;
// cut off all bits in value that have pos >= num_bits, if any
if (num_bits < static_cast<size_type>(ulong_width)) {
const num_type mask = (num_type(1) << num_bits) - 1;
value &= mask;
}
if (bits_per_block >= ulong_width) {
m_bits[0] = static_cast<block_type>(value);
}
else {
for(size_type i = 0; value != 0; ++i) {
m_bits[i] = static_cast<block_type>(value);
value >>= BOOST_DYNAMIC_BITSET_WRAP_CONSTANT(bits_per_block);
}
}
}
// copy constructor
template <typename Block, typename Allocator>
inline dynamic_bitset<Block, Allocator>::
dynamic_bitset(const dynamic_bitset& b)
: m_bits(b.m_bits), m_num_bits(b.m_num_bits) // [gps]
{
}
template <typename Block, typename Allocator>
inline dynamic_bitset<Block, Allocator>::
~dynamic_bitset()
{
assert(m_check_invariants());
}
template <typename Block, typename Allocator>
inline void dynamic_bitset<Block, Allocator>::
swap(dynamic_bitset<Block, Allocator>& b) // no throw
{
std::swap(m_bits, b.m_bits);
std::swap(m_num_bits, b.m_num_bits);
}
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>& dynamic_bitset<Block, Allocator>::
operator=(const dynamic_bitset<Block, Allocator>& b)
{
#if 0 // gps
dynamic_bitset<Block, Allocator> tmp(b);
this->swap(tmp);
return *this;
#else
m_bits = b.m_bits;
m_num_bits = b.m_num_bits;
return *this;
#endif
}
template <typename Block, typename Allocator>
inline typename dynamic_bitset<Block, Allocator>::allocator_type
dynamic_bitset<Block, Allocator>::get_allocator() const
{
return m_bits.get_allocator();
}
//-----------------------------------------------------------------------------
// size changing operations
template <typename Block, typename Allocator>
void dynamic_bitset<Block, Allocator>::
resize(size_type num_bits, bool value) // strong guarantee
{
const size_type old_num_blocks = num_blocks();
const size_type required_blocks = calc_num_blocks(num_bits);
const block_type v = value? ~Block(0) : Block(0);
if (required_blocks != old_num_blocks) {
m_bits.resize(required_blocks, v); // s.g. (copy) [gps]
}
// At this point:
//
// - if the buffer was shrunk, there's nothing to do, except
// a call to m_zero_unused_bits()
//
// - if it it is enlarged, all the (used) bits in the new blocks have
// the correct value, but we should also take care of the bits,
// if any, that were 'unused bits' before enlarging: if value == true,
// they must be set.
if (value && (num_bits > m_num_bits)) {
const size_type extra_bits = count_extra_bits(); // gps
if (extra_bits) {
assert(old_num_blocks >= 1 && old_num_blocks <= m_bits.size());
// Set them.
m_bits[old_num_blocks - 1] |= (v << extra_bits); // gps
}
}
m_num_bits = num_bits;
m_zero_unused_bits();
}
template <typename Block, typename Allocator>
void dynamic_bitset<Block, Allocator>::
clear() // no throw
{
m_bits.clear();
m_num_bits = 0;
}
template <typename Block, typename Allocator>
void dynamic_bitset<Block, Allocator>::
push_back(bool bit)
{
resize(size() + 1);
set(size() - 1, bit);
}
template <typename Block, typename Allocator>
void dynamic_bitset<Block, Allocator>::
append(Block value) // strong guarantee
{
// G.P.S. to be reviewed...
const block_width_type r = count_extra_bits();
if (r == 0) {
// the buffer is empty, or all blocks are filled
m_bits.push_back(value);
}
else {
m_bits.push_back(value >> (bits_per_block - r));
m_bits[m_bits.size() - 2] |= (value << r); // m_bits.size() >= 2
}
m_num_bits += bits_per_block;
assert(m_check_invariants());
}
//-----------------------------------------------------------------------------
// bitset operations
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>&
dynamic_bitset<Block, Allocator>::operator&=(const dynamic_bitset& rhs)
{
assert(size() == rhs.size());
for (size_type i = 0; i < num_blocks(); ++i)
m_bits[i] &= rhs.m_bits[i];
return *this;
}
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>&
dynamic_bitset<Block, Allocator>::operator|=(const dynamic_bitset& rhs)
{
assert(size() == rhs.size());
for (size_type i = 0; i < num_blocks(); ++i)
m_bits[i] |= rhs.m_bits[i];
//m_zero_unused_bits();
return *this;
}
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>&
dynamic_bitset<Block, Allocator>::operator^=(const dynamic_bitset& rhs)
{
assert(size() == rhs.size());
for (size_type i = 0; i < this->num_blocks(); ++i)
m_bits[i] ^= rhs.m_bits[i];
//m_zero_unused_bits();
return *this;
}
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>&
dynamic_bitset<Block, Allocator>::operator-=(const dynamic_bitset& rhs)
{
assert(size() == rhs.size());
for (size_type i = 0; i < num_blocks(); ++i)
m_bits[i] &= ~rhs.m_bits[i];
//m_zero_unused_bits();
return *this;
}
//
// NOTE:
// Note that the 'if (r != 0)' is crucial to avoid undefined
// behavior when the left hand operand of >> isn't promoted to a
// wider type (because rs would be too large).
//
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>&
dynamic_bitset<Block, Allocator>::operator<<=(size_type n)
{
if (n >= m_num_bits)
return reset();
//else
if (n > 0) {
size_type const last = num_blocks() - 1; // num_blocks() is >= 1
size_type const div = n / bits_per_block; // div is <= last
block_width_type const r = bit_index(n);
block_type * const b = &m_bits[0];
if (r != 0) {
block_width_type const rs = bits_per_block - r;
for (size_type i = last-div; i>0; --i) {
b[i+div] = (b[i] << r) | (b[i-1] >> rs);
}
b[div] = b[0] << r;
}
else {
for (size_type i = last-div; i>0; --i) {
b[i+div] = b[i];
}
b[div] = b[0];
}
// zero out div blocks at the less significant end
std::fill_n(b, div, static_cast<block_type>(0));
// zero out any 1 bit that flowed into the unused part
m_zero_unused_bits(); // thanks to Lester Gong
}
return *this;
}
//
// NOTE:
// see the comments to operator <<=
//
template <typename B, typename A>
dynamic_bitset<B, A> & dynamic_bitset<B, A>::operator>>=(size_type n) {
if (n >= m_num_bits) {
return reset();
}
//else
if (n>0) {
size_type const last = num_blocks() - 1; // num_blocks() is >= 1
size_type const div = n / bits_per_block; // div is <= last
block_width_type const r = bit_index(n);
block_type * const b = &m_bits[0];
if (r != 0) {
block_width_type const ls = bits_per_block - r;
for (size_type i = div; i < last; ++i) {
b[i-div] = (b[i] >> r) | (b[i+1] << ls);
}
// r bits go to zero
b[last-div] = b[last] >> r;
}
else {
for (size_type i = div; i <= last; ++i) {
b[i-div] = b[i];
}
// note the '<=': the last iteration 'absorbs'
// b[last-div] = b[last] >> 0;
}
// div blocks are zero filled at the most significant end
std::fill_n(b + (num_blocks()-div), div, static_cast<block_type>(0));
}
return *this;
}
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>
dynamic_bitset<Block, Allocator>::operator<<(size_type n) const
{
dynamic_bitset r(*this);
return r <<= n;
}
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>
dynamic_bitset<Block, Allocator>::operator>>(size_type n) const
{
dynamic_bitset r(*this);
return r >>= n;
}
//-----------------------------------------------------------------------------
// basic bit operations
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>&
dynamic_bitset<Block, Allocator>::set(size_type pos, bool val)
{
// [gps]
//
// Below we have no set(size_type) function to call when
// value == true; instead of using a helper, I think
// overloading set (rather than giving it a default bool
// argument) would be more elegant.
assert(pos < m_num_bits);
if (val)
m_bits[block_index(pos)] |= bit_mask(pos);
else
reset(pos);
return *this;
}
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>&
dynamic_bitset<Block, Allocator>::set()
{
std::fill(m_bits.begin(), m_bits.end(), ~Block(0));
m_zero_unused_bits();
return *this;
}
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>&
dynamic_bitset<Block, Allocator>::reset(size_type pos)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -