Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:58

0001 //---------------------------------------------------------------------------//
0002 // Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@gmail.com>
0003 //
0004 // Distributed under the Boost Software License, Version 1.0
0005 // See accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt
0007 //
0008 // See http://boostorg.github.com/compute for more information.
0009 //---------------------------------------------------------------------------//
0010 
0011 #ifndef BOOST_COMPUTE_CONTAINER_DYNAMIC_BITSET_HPP
0012 #define BOOST_COMPUTE_CONTAINER_DYNAMIC_BITSET_HPP
0013 
0014 #include <boost/compute/lambda.hpp>
0015 #include <boost/compute/algorithm/any_of.hpp>
0016 #include <boost/compute/algorithm/fill.hpp>
0017 #include <boost/compute/algorithm/transform_reduce.hpp>
0018 #include <boost/compute/container/vector.hpp>
0019 #include <boost/compute/functional/integer.hpp>
0020 #include <boost/compute/types/fundamental.hpp>
0021 
0022 namespace boost {
0023 namespace compute {
0024 
0025 /// \class dynamic_bitset
0026 /// \brief The dynamic_bitset class contains a resizable bit array.
0027 ///
0028 /// For example, to create a dynamic-bitset with space for 1000 bits on the
0029 /// device:
0030 /// \code
0031 /// boost::compute::dynamic_bitset<> bits(1000, queue);
0032 /// \endcode
0033 ///
0034 /// The Boost.Compute \c dynamic_bitset class provides a STL-like API and is
0035 /// modeled after the \c boost::dynamic_bitset class from Boost.
0036 ///
0037 /// \see \ref vector "vector<T>"
0038 template<class Block = ulong_, class Alloc = buffer_allocator<Block> >
0039 class dynamic_bitset
0040 {
0041 public:
0042     typedef Block block_type;
0043     typedef Alloc allocator_type;
0044     typedef vector<Block, Alloc> container_type;
0045     typedef typename container_type::size_type size_type;
0046 
0047     BOOST_STATIC_CONSTANT(size_type, bits_per_block = sizeof(block_type) * CHAR_BIT);
0048     BOOST_STATIC_CONSTANT(size_type, npos = static_cast<size_type>(-1));
0049 
0050     /// Creates a new dynamic bitset with storage for \p size bits. Initializes
0051     /// all bits to zero.
0052     dynamic_bitset(size_type size, command_queue &queue)
0053         : m_bits(size / sizeof(block_type), queue.get_context()),
0054           m_size(size)
0055     {
0056         // initialize all bits to zero
0057         reset(queue);
0058     }
0059 
0060     /// Creates a new dynamic bitset as a copy of \p other.
0061     dynamic_bitset(const dynamic_bitset &other)
0062         : m_bits(other.m_bits),
0063           m_size(other.m_size)
0064     {
0065     }
0066 
0067     /// Copies the data from \p other to \c *this.
0068     dynamic_bitset& operator=(const dynamic_bitset &other)
0069     {
0070         if(this != &other){
0071             m_bits = other.m_bits;
0072             m_size = other.m_size;
0073         }
0074 
0075         return *this;
0076     }
0077 
0078     /// Destroys the dynamic bitset.
0079     ~dynamic_bitset()
0080     {
0081     }
0082 
0083     /// Returns the size of the dynamic bitset.
0084     size_type size() const
0085     {
0086         return m_size;
0087     }
0088 
0089     /// Returns the number of blocks to store the bits in the dynamic bitset.
0090     size_type num_blocks() const
0091     {
0092         return m_bits.size();
0093     }
0094 
0095     /// Returns the maximum possible size for the dynamic bitset.
0096     size_type max_size() const
0097     {
0098         return m_bits.max_size() * bits_per_block;
0099     }
0100 
0101     /// Returns \c true if the dynamic bitset is empty (i.e. \c size() == \c 0).
0102     bool empty() const
0103     {
0104         return size() == 0;
0105     }
0106 
0107     /// Returns the number of set bits (i.e. '1') in the bitset.
0108     size_type count(command_queue &queue) const
0109     {
0110         ulong_ count = 0;
0111         transform_reduce(
0112             m_bits.begin(),
0113             m_bits.end(),
0114             &count,
0115             popcount<block_type>(),
0116             plus<ulong_>(),
0117             queue
0118         );
0119         return static_cast<size_type>(count);
0120     }
0121 
0122     /// Resizes the bitset to contain \p num_bits. If the new size is greater
0123     /// than the current size the new bits are set to zero.
0124     void resize(size_type num_bits, command_queue &queue)
0125     {
0126         // resize bits
0127         const size_type current_block_count = m_bits.size();
0128         m_bits.resize(num_bits * bits_per_block, queue);
0129 
0130         // fill new block with zeros (if new blocks were added)
0131         const size_type new_block_count = m_bits.size();
0132         if(new_block_count > current_block_count){
0133             fill_n(
0134                 m_bits.begin() + current_block_count,
0135                 new_block_count - current_block_count,
0136                 block_type(0),
0137                 queue
0138             );
0139         }
0140 
0141         // store new size
0142         m_size = num_bits;
0143     }
0144 
0145     /// Sets the bit at position \p n to \c true.
0146     void set(size_type n, command_queue &queue)
0147     {
0148         set(n, true, queue);
0149     }
0150 
0151     /// Sets the bit at position \p n to \p value.
0152     void set(size_type n, bool value, command_queue &queue)
0153     {
0154         const size_type bit = n % bits_per_block;
0155         const size_type block = n / bits_per_block;
0156 
0157         // load current block
0158         block_type block_value;
0159         copy_n(m_bits.begin() + block, 1, &block_value, queue);
0160 
0161         // update block value
0162         if(value){
0163             block_value |= (size_type(1) << bit);
0164         }
0165         else {
0166             block_value &= ~(size_type(1) << bit);
0167         }
0168 
0169         // store new block
0170         copy_n(&block_value, 1, m_bits.begin() + block, queue);
0171     }
0172 
0173     /// Returns \c true if the bit at position \p n is set (i.e. '1').
0174     bool test(size_type n, command_queue &queue)
0175     {
0176         const size_type bit = n % (sizeof(block_type) * CHAR_BIT);
0177         const size_type block = n / (sizeof(block_type) * CHAR_BIT);
0178 
0179         block_type block_value;
0180         copy_n(m_bits.begin() + block, 1, &block_value, queue);
0181 
0182         return block_value & (size_type(1) << bit);
0183     }
0184 
0185     /// Flips the value of the bit at position \p n.
0186     void flip(size_type n, command_queue &queue)
0187     {
0188         set(n, !test(n, queue), queue);
0189     }
0190 
0191     /// Returns \c true if any bit in the bitset is set (i.e. '1').
0192     bool any(command_queue &queue) const
0193     {
0194         return any_of(
0195             m_bits.begin(), m_bits.end(), lambda::_1 != block_type(0), queue
0196         );
0197     }
0198 
0199     /// Returns \c true if all of the bits in the bitset are set to zero.
0200     bool none(command_queue &queue) const
0201     {
0202         return !any(queue);
0203     }
0204 
0205     /// Sets all of the bits in the bitset to zero.
0206     void reset(command_queue &queue)
0207     {
0208         fill(m_bits.begin(), m_bits.end(), block_type(0), queue);
0209     }
0210 
0211     /// Sets the bit at position \p n to zero.
0212     void reset(size_type n, command_queue &queue)
0213     {
0214         set(n, false, queue);
0215     }
0216 
0217     /// Empties the bitset (e.g. \c resize(0)).
0218     void clear()
0219     {
0220         m_bits.clear();
0221     }
0222 
0223     /// Returns the allocator used to allocate storage for the bitset.
0224     allocator_type get_allocator() const
0225     {
0226         return m_bits.get_allocator();
0227     }
0228 
0229 private:
0230     container_type m_bits;
0231     size_type m_size;
0232 };
0233 
0234 } // end compute namespace
0235 } // end boost namespace
0236 
0237 #endif // BOOST_COMPUTE_CONTAINER_DYNAMIC_BITSET_HPP