123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- //---------------------------------------------------------------------------//
- // Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@gmail.com>
- //
- // Distributed under the Boost Software License, Version 1.0
- // See accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt
- //
- // See http://boostorg.github.com/compute for more information.
- //---------------------------------------------------------------------------//
- #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 {
- /// \class dynamic_bitset
- /// \brief The dynamic_bitset class contains a resizable bit array.
- ///
- /// For example, to create a dynamic-bitset with space for 1000 bits on the
- /// device:
- /// \code
- /// boost::compute::dynamic_bitset<> bits(1000, queue);
- /// \endcode
- ///
- /// The Boost.Compute \c dynamic_bitset class provides a STL-like API and is
- /// modeled after the \c boost::dynamic_bitset class from Boost.
- ///
- /// \see \ref vector "vector<T>"
- 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));
- /// Creates a new dynamic bitset with storage for \p size bits. Initializes
- /// all bits to zero.
- dynamic_bitset(size_type size, command_queue &queue)
- : m_bits(size / sizeof(block_type), queue.get_context()),
- m_size(size)
- {
- // initialize all bits to zero
- reset(queue);
- }
- /// Creates a new dynamic bitset as a copy of \p other.
- dynamic_bitset(const dynamic_bitset &other)
- : m_bits(other.m_bits),
- m_size(other.m_size)
- {
- }
- /// Copies the data from \p other to \c *this.
- dynamic_bitset& operator=(const dynamic_bitset &other)
- {
- if(this != &other){
- m_bits = other.m_bits;
- m_size = other.m_size;
- }
- return *this;
- }
- /// Destroys the dynamic bitset.
- ~dynamic_bitset()
- {
- }
- /// Returns the size of the dynamic bitset.
- size_type size() const
- {
- return m_size;
- }
- /// Returns the number of blocks to store the bits in the dynamic bitset.
- size_type num_blocks() const
- {
- return m_bits.size();
- }
- /// Returns the maximum possible size for the dynamic bitset.
- size_type max_size() const
- {
- return m_bits.max_size() * bits_per_block;
- }
- /// Returns \c true if the dynamic bitset is empty (i.e. \c size() == \c 0).
- bool empty() const
- {
- return size() == 0;
- }
- /// Returns the number of set bits (i.e. '1') in the bitset.
- 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);
- }
- /// Resizes the bitset to contain \p num_bits. If the new size is greater
- /// than the current size the new bits are set to zero.
- void resize(size_type num_bits, command_queue &queue)
- {
- // resize bits
- const size_type current_block_count = m_bits.size();
- m_bits.resize(num_bits * bits_per_block, queue);
- // fill new block with zeros (if new blocks were added)
- 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
- );
- }
- // store new size
- m_size = num_bits;
- }
- /// Sets the bit at position \p n to \c true.
- void set(size_type n, command_queue &queue)
- {
- set(n, true, queue);
- }
- /// Sets the bit at position \p n to \p value.
- 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;
- // load current block
- block_type block_value;
- copy_n(m_bits.begin() + block, 1, &block_value, queue);
- // update block value
- if(value){
- block_value |= (size_type(1) << bit);
- }
- else {
- block_value &= ~(size_type(1) << bit);
- }
- // store new block
- copy_n(&block_value, 1, m_bits.begin() + block, queue);
- }
- /// Returns \c true if the bit at position \p n is set (i.e. '1').
- 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);
- }
- /// Flips the value of the bit at position \p n.
- void flip(size_type n, command_queue &queue)
- {
- set(n, !test(n, queue), queue);
- }
- /// Returns \c true if any bit in the bitset is set (i.e. '1').
- bool any(command_queue &queue) const
- {
- return any_of(
- m_bits.begin(), m_bits.end(), lambda::_1 != block_type(0), queue
- );
- }
- /// Returns \c true if all of the bits in the bitset are set to zero.
- bool none(command_queue &queue) const
- {
- return !any(queue);
- }
- /// Sets all of the bits in the bitset to zero.
- void reset(command_queue &queue)
- {
- fill(m_bits.begin(), m_bits.end(), block_type(0), queue);
- }
- /// Sets the bit at position \p n to zero.
- void reset(size_type n, command_queue &queue)
- {
- set(n, false, queue);
- }
- /// Empties the bitset (e.g. \c resize(0)).
- void clear()
- {
- m_bits.clear();
- }
- /// Returns the allocator used to allocate storage for the bitset.
- allocator_type get_allocator() const
- {
- return m_bits.get_allocator();
- }
- private:
- container_type m_bits;
- size_type m_size;
- };
- } // end compute namespace
- } // end boost namespace
- #endif // BOOST_COMPUTE_CONTAINER_DYNAMIC_BITSET_HPP
|