|
|
|
|
@@ -6,17 +6,31 @@
|
|
|
|
|
// implied warranty, and with no claim as to its suitability for any
|
|
|
|
|
// purpose.
|
|
|
|
|
|
|
|
|
|
// With optimizations by Gennaro Prota.
|
|
|
|
|
// With optimizations, bug fixes, and improvements by Gennaro Prota.
|
|
|
|
|
|
|
|
|
|
// -------------------------------------
|
|
|
|
|
// CHANGE LOG:
|
|
|
|
|
//
|
|
|
|
|
// - corrected workaround for Dinkum lib's allocate() [GP]
|
|
|
|
|
// - changed macro test for old iostreams [GP]
|
|
|
|
|
// - removed #include <vector> for now. [JGS]
|
|
|
|
|
// - Added __GNUC__ to compilers that cannot handle the constructor from basic_string. [JGS]
|
|
|
|
|
// - corrected to_block_range [GP]
|
|
|
|
|
// - corrected from_block_range [GP]
|
|
|
|
|
// - Removed __GNUC__ from compilers that cannot handle the constructor
|
|
|
|
|
// from basic_string and added the workaround suggested by GP. [JGS]
|
|
|
|
|
// - Removed __BORLANDC__ from the #if around the basic_string
|
|
|
|
|
// constructor. Luckily the fix by GP for g++ also fixes Borland. [JGS]
|
|
|
|
|
|
|
|
|
|
#ifndef BOOST_DYNAMIC_BITSET_HPP
|
|
|
|
|
#define BOOST_DYNAMIC_BITSET_HPP
|
|
|
|
|
|
|
|
|
|
#include <boost/config.hpp>
|
|
|
|
|
#include <cassert>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <iosfwd>
|
|
|
|
|
#include <cstring> // for memset, memcpy, memcmp, etc.
|
|
|
|
|
#include <stdexcept> // for std::domain_error
|
|
|
|
|
#include <stdexcept> // for std::overflow_error
|
|
|
|
|
#include <algorithm> // for std::swap, std::min, std::copy, std::fill
|
|
|
|
|
|
|
|
|
|
#if defined(__GNUC__) && !defined(__SGI_STL_PORT)
|
|
|
|
|
@@ -25,12 +39,10 @@
|
|
|
|
|
#include <cctype> // for isspace
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
#include "boost/dynamic_bitset_fwd.hpp" //G.P.S.
|
|
|
|
|
#include "boost/detail/dynamic_bitset.hpp"
|
|
|
|
|
|
|
|
|
|
#ifdef __GNUC__ // this isn't right... what's the right way to detect?
|
|
|
|
|
#if defined (__STL_CONFIG_H) && !defined (__STL_USE_NEW_IOSTREAMS)
|
|
|
|
|
#define BOOST_OLD_IOSTREAMS
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
@@ -164,7 +176,7 @@ public:
|
|
|
|
|
const Allocator& alloc = Allocator());
|
|
|
|
|
|
|
|
|
|
// from string
|
|
|
|
|
#if defined(BOOST_OLD_IOSTREAMS) || defined(__BORLANDC__)
|
|
|
|
|
#if defined(BOOST_OLD_IOSTREAMS)
|
|
|
|
|
explicit
|
|
|
|
|
dynamic_bitset(const std::string& s,
|
|
|
|
|
std::string::size_type pos = 0,
|
|
|
|
|
@@ -173,12 +185,14 @@ public:
|
|
|
|
|
: detail::dynamic_bitset_base<Block, Allocator>
|
|
|
|
|
(std::min(n, s.size() - pos), alloc)
|
|
|
|
|
#else
|
|
|
|
|
// The parenthesis around std::basic_string<CharT, Traits, Alloc>::npos
|
|
|
|
|
// in the code below are to avoid a g++ 3.2 bug and a Borland bug. -JGS
|
|
|
|
|
template <typename CharT, typename Traits, typename Alloc>
|
|
|
|
|
explicit
|
|
|
|
|
dynamic_bitset(const std::basic_string<CharT, Traits, Alloc>& s,
|
|
|
|
|
typename std::basic_string<CharT, Traits, Alloc>::size_type pos = 0,
|
|
|
|
|
typename std::basic_string<CharT, Traits, Alloc>::size_type n
|
|
|
|
|
= std::basic_string<CharT, Traits, Alloc>::npos,
|
|
|
|
|
= (std::basic_string<CharT, Traits, Alloc>::npos),
|
|
|
|
|
const Allocator& alloc = Allocator())
|
|
|
|
|
: detail::dynamic_bitset_base<Block, Allocator>
|
|
|
|
|
(std::min(n, s.size() - pos), alloc)
|
|
|
|
|
@@ -301,10 +315,13 @@ public:
|
|
|
|
|
friend void to_block_range(const dynamic_bitset<B, A>& b,
|
|
|
|
|
BlockOutputIterator result);
|
|
|
|
|
|
|
|
|
|
template <typename BlockIterator, typename B, typename A>
|
|
|
|
|
friend void from_block_range(BlockIterator first, BlockIterator last,
|
|
|
|
|
dynamic_bitset<B, A>& result);
|
|
|
|
|
|
|
|
|
|
template <typename B, typename A, typename CharT, typename Alloc>
|
|
|
|
|
friend void dump_to_string(const dynamic_bitset<B, A>& b,
|
|
|
|
|
std::basic_string<CharT, Alloc>& s);
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
@@ -336,14 +353,6 @@ public:
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename BlockIterator>
|
|
|
|
|
void from_block_range(BlockIterator first, BlockIterator last)
|
|
|
|
|
{
|
|
|
|
|
// PRE: distance(first, last) == size() / bits_per_block
|
|
|
|
|
for (size_type i = 0; first != last; ++first, ++i)
|
|
|
|
|
this->m_bits[i] = *first;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Global Functions:
|
|
|
|
|
@@ -417,7 +426,10 @@ void
|
|
|
|
|
to_block_range(const dynamic_bitset<Block, Allocator>& b,
|
|
|
|
|
BlockOutputIterator result);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename BlockIterator, typename B, typename A>
|
|
|
|
|
inline void
|
|
|
|
|
from_block_range(BlockIterator first, BlockIterator last,
|
|
|
|
|
dynamic_bitset<B, A>& result);
|
|
|
|
|
|
|
|
|
|
//=============================================================================
|
|
|
|
|
// dynamic_bitset implementation
|
|
|
|
|
@@ -497,11 +509,7 @@ resize(size_type num_bits, bool value)
|
|
|
|
|
if (num_bits == size())
|
|
|
|
|
return;
|
|
|
|
|
size_type new_nblocks = this->calc_num_blocks(num_bits);
|
|
|
|
|
#if (defined(_MSC_VER) && (_MSC_VER <= 1300)) || !defined(_CPPLIB_VER) || (_CPPLIB_VER < 306) // Dinkumware for VC6/7
|
|
|
|
|
Block* d = this->m_alloc.allocate(new_nblocks, 0);
|
|
|
|
|
#else
|
|
|
|
|
Block* d = this->m_alloc.allocate(new_nblocks);
|
|
|
|
|
#endif
|
|
|
|
|
Block* d = this->m_alloc.allocate(new_nblocks, static_cast<void const *>(0));
|
|
|
|
|
if (num_bits < size()) { // shrink
|
|
|
|
|
std::copy(this->m_bits, this->m_bits + new_nblocks, d);
|
|
|
|
|
std::swap(d, this->m_bits);
|
|
|
|
|
@@ -659,7 +667,7 @@ dynamic_bitset<Block, Allocator>::operator<<=(size_type n)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// div blocks are zero filled at the less significant end
|
|
|
|
|
std::fill(m_bits, m_bits+div, static_cast<block_type>(0));
|
|
|
|
|
std::fill(this->m_bits, this->m_bits+div, static_cast<block_type>(0));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
@@ -726,18 +734,18 @@ dynamic_bitset<B, A> & dynamic_bitset<B, A>::operator>>=(size_type n) {
|
|
|
|
|
block_type const ls = bits_per_block - r;
|
|
|
|
|
|
|
|
|
|
for (size_type i = div; i < last; ++i) {
|
|
|
|
|
m_bits[i-div] = (m_bits[i] >> r) | (m_bits[i+1] << ls);
|
|
|
|
|
this->m_bits[i-div] = (this->m_bits[i] >> r) | (this->m_bits[i+1] << ls);
|
|
|
|
|
}
|
|
|
|
|
// r bits go to zero
|
|
|
|
|
m_bits[last-div] = m_bits[last] >> r;
|
|
|
|
|
this->m_bits[last-div] = this->m_bits[last] >> r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else {
|
|
|
|
|
for (size_type i = div; i <= last; ++i) {
|
|
|
|
|
m_bits[i-div] = m_bits[i];
|
|
|
|
|
this->m_bits[i-div] = this->m_bits[i];
|
|
|
|
|
}
|
|
|
|
|
// note the '<=': the last iteration 'absorbs'
|
|
|
|
|
// m_bits[last-div] = m_bits[last] >> 0;
|
|
|
|
|
// this->m_bits[last-div] = this->m_bits[last] >> 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -921,7 +929,7 @@ dynamic_bitset<Block, Allocator>::count() const
|
|
|
|
|
using detail::byte_t;
|
|
|
|
|
|
|
|
|
|
const byte_t * p = reinterpret_cast<const byte_t*>(this->m_bits);
|
|
|
|
|
const byte_t * past_end = p + m_num_blocks * sizeof(Block);
|
|
|
|
|
const byte_t * past_end = p + this->m_num_blocks * sizeof(Block);
|
|
|
|
|
|
|
|
|
|
size_type num = 0;
|
|
|
|
|
unsigned int const max_bit = detail::count<>::max_bit;
|
|
|
|
|
@@ -979,7 +987,7 @@ dump_to_string(const dynamic_bitset<B, A>& b,
|
|
|
|
|
std::size_t const len = b.m_num_blocks * (dynamic_bitset<B, A>::bits_per_block);
|
|
|
|
|
s.assign(len, '0');
|
|
|
|
|
for (std::size_t i = 0; i != len; ++i)
|
|
|
|
|
if (b.test_(i))
|
|
|
|
|
if (b[i])// could use test_ here, but we have friend issues.-JGS
|
|
|
|
|
s[len - 1 - i] = '1';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -988,10 +996,17 @@ void
|
|
|
|
|
to_block_range(const dynamic_bitset<Block, Allocator>& b,
|
|
|
|
|
BlockOutputIterator result)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
//std::copy(m.m_bits, m.m_num_bits, result);
|
|
|
|
|
//[gps] Did you mean this?
|
|
|
|
|
std::copy (b.m_bits, b.m_bits + b.m_num_bits, result);
|
|
|
|
|
assert(b.size() != 0 || b.num_blocks() == 0);
|
|
|
|
|
std::copy (b.m_bits, b.m_bits + b.m_num_blocks, result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename Block, typename Allocator>
|
|
|
|
|
@@ -1342,13 +1357,7 @@ template <typename Block, typename Allocator>
|
|
|
|
|
inline void dynamic_bitset<Block, Allocator>::
|
|
|
|
|
set_block_(size_type blocknum, Block value)
|
|
|
|
|
{
|
|
|
|
|
/*for (std::size_t i = 0; i < bits_per_block; ++i, value >>= 1)
|
|
|
|
|
if (value & 0x1) {
|
|
|
|
|
size_type bit = blocknum * bits_per_block + i;
|
|
|
|
|
set_(bit);
|
|
|
|
|
}*/
|
|
|
|
|
// [gps]
|
|
|
|
|
m_bits[blocknum] = value;
|
|
|
|
|
this->m_bits[blocknum] = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename Block, typename Allocator>
|
|
|
|
|
@@ -1383,13 +1392,13 @@ bool dynamic_bitset<Block, Allocator>::set_(size_type n, bool value)
|
|
|
|
|
template <typename Block, typename Allocator>
|
|
|
|
|
inline void dynamic_bitset<Block, Allocator>::m_zero_unused_bits()
|
|
|
|
|
{
|
|
|
|
|
assert (m_num_blocks == this->calc_num_blocks(m_num_bits));
|
|
|
|
|
assert (this->m_num_blocks == this->calc_num_blocks(this->m_num_bits));
|
|
|
|
|
|
|
|
|
|
// if != 0 this is the number of bits used in the last block
|
|
|
|
|
const size_type used_bits = m_num_bits % bits_per_block;
|
|
|
|
|
const size_type used_bits = this->m_num_bits % bits_per_block;
|
|
|
|
|
|
|
|
|
|
if (used_bits != 0)
|
|
|
|
|
m_bits[m_num_blocks - 1] &= ~(~static_cast<Block>(0) << used_bits);
|
|
|
|
|
this->m_bits[this->m_num_blocks - 1] &= ~(~static_cast<Block>(0) << used_bits);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|