#ifndef BOOST_COMPUTE_CONTAINER_DYNAMIC_BITSET_HPP
#define BOOST_COMPUTE_CONTAINER_DYNAMIC_BITSET_HPP
#include <boost/compute/lambda.hpp>
#include <boost/compute/algorithm/any_of.hpp>
#include <boost/compute/algorithm/fill.hpp>
#include <boost/compute/algorithm/transform_reduce.hpp>
#include <boost/compute/container/vector.hpp>
#include <boost/compute/functional/integer.hpp>
#include <boost/compute/types/fundamental.hpp>
namespace boost {
namespace compute {
template<class Block = ulong_, class Alloc = buffer_allocator<Block> >
class dynamic_bitset
{
public:
typedef Block block_type;
typedef Alloc allocator_type;
typedef vector<Block, Alloc> container_type;
typedef typename container_type::size_type size_type;
BOOST_STATIC_CONSTANT(size_type, bits_per_block = sizeof(block_type) * CHAR_BIT);
BOOST_STATIC_CONSTANT(size_type, npos = static_cast<size_type>(-1));
dynamic_bitset(size_type size, command_queue &queue)
: m_bits(size / sizeof(block_type), queue.get_context()),
m_size(size)
{
reset(queue);
}
dynamic_bitset(const dynamic_bitset &other)
: m_bits(other.m_bits),
m_size(other.m_size)
{
}
dynamic_bitset& operator=(const dynamic_bitset &other)
{
if(this != &other){
m_bits = other.m_bits;
m_size = other.m_size;
}
return *this;
}
~dynamic_bitset()
{
}
size_type size() const
{
return m_size;
}
size_type num_blocks() const
{
return m_bits.size();
}
size_type max_size() const
{
return m_bits.max_size() * bits_per_block;
}
bool empty() const
{
return size() == 0;
}
size_type count(command_queue &queue) const
{
ulong_ count = 0;
transform_reduce(
m_bits.begin(),
m_bits.end(),
&count,
popcount<block_type>(),
plus<ulong_>(),
queue
);
return static_cast<size_type>(count);
}
void resize(size_type num_bits, command_queue &queue)
{
const size_type current_block_count = m_bits.size();
m_bits.resize(num_bits * bits_per_block, queue);
const size_type new_block_count = m_bits.size();
if(new_block_count > current_block_count){
fill_n(
m_bits.begin() + current_block_count,
new_block_count - current_block_count,
block_type(0),
queue
);
}
m_size = num_bits;
}
void set(size_type n, command_queue &queue)
{
set(n, true, queue);
}
void set(size_type n, bool value, command_queue &queue)
{
const size_type bit = n % bits_per_block;
const size_type block = n / bits_per_block;
block_type block_value;
copy_n(m_bits.begin() + block, 1, &block_value, queue);
if(value){
block_value |= (size_type(1) << bit);
}
else {
block_value &= ~(size_type(1) << bit);
}
copy_n(&block_value, 1, m_bits.begin() + block, queue);
}
bool test(size_type n, command_queue &queue)
{
const size_type bit = n % (sizeof(block_type) * CHAR_BIT);
const size_type block = n / (sizeof(block_type) * CHAR_BIT);
block_type block_value;
copy_n(m_bits.begin() + block, 1, &block_value, queue);
return block_value & (size_type(1) << bit);
}
void flip(size_type n, command_queue &queue)
{
set(n, !test(n, queue), queue);
}
bool any(command_queue &queue) const
{
return any_of(
m_bits.begin(), m_bits.end(), lambda::_1 != block_type(0), queue
);
}
bool none(command_queue &queue) const
{
return !any(queue);
}
void reset(command_queue &queue)
{
fill(m_bits.begin(), m_bits.end(), block_type(0), queue);
}
void reset(size_type n, command_queue &queue)
{
set(n, false, queue);
}
void clear()
{
m_bits.clear();
}
allocator_type get_allocator() const
{
return m_bits.get_allocator();
}
private:
container_type m_bits;
size_type m_size;
};
} }
#endif