]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/boost/dynamic_bitset/dynamic_bitset.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / dynamic_bitset / dynamic_bitset.hpp
index 83fcb61a1ee9c31e7d2f869715045bd48b289aeb..f224051b3b5b8d7780a8ab0a7b5e59e450f9e6f9 100644 (file)
@@ -5,8 +5,10 @@
 //             Copyright (c) 2014 Ahmed Charles
 //
 // Copyright (c) 2014 Glen Joseph Fernandes
-// glenfe at live dot com
+// (glenjofe@gmail.com)
+//
 // Copyright (c) 2014 Riccardo Marcangelo
+//             Copyright (c) 2018 Evgeny Shulgin
 //
 // Distributed under the Boost Software License, Version 1.0.
 //    (See accompanying file LICENSE_1_0.txt or copy at
 #endif
 
 #include "boost/dynamic_bitset_fwd.hpp"
-#include "boost/detail/dynamic_bitset.hpp"
+#include "boost/dynamic_bitset/detail/dynamic_bitset.hpp"
+#include "boost/dynamic_bitset/detail/lowest_bit.hpp"
 #include "boost/detail/iterator.hpp" // used to implement append(Iter, Iter)
 #include "boost/move/move.hpp"
 #include "boost/limits.hpp"
-#include "boost/pending/lowest_bit.hpp"
 #include "boost/static_assert.hpp"
 #include "boost/utility/addressof.hpp"
 #include "boost/detail/no_exceptions_support.hpp"
 #include "boost/throw_exception.hpp"
+#include "boost/functional/hash/hash.hpp"
 
 
 namespace boost {
@@ -125,8 +128,10 @@ public:
     typedef bool const_reference;
 
     // constructors, etc.
+    dynamic_bitset() : m_num_bits(0) {}
+
     explicit
-    dynamic_bitset(const Allocator& alloc = Allocator());
+    dynamic_bitset(const Allocator& alloc);
 
     explicit
     dynamic_bitset(size_type num_bits, unsigned long value = 0,
@@ -279,10 +284,13 @@ public:
     dynamic_bitset operator>>(size_type n) const;
 
     // basic bit operations
+    dynamic_bitset& set(size_type n, size_type len, bool val /* = true */); // default would make it ambiguous
     dynamic_bitset& set(size_type n, bool val = true);
     dynamic_bitset& set();
+    dynamic_bitset& reset(size_type n, size_type len);
     dynamic_bitset& reset(size_type n);
     dynamic_bitset& reset();
+    dynamic_bitset& flip(size_type n, size_type len);
     dynamic_bitset& flip(size_type n);
     dynamic_bitset& flip();
     bool test(size_type n) const;
@@ -349,7 +357,8 @@ public:
     template <typename B, typename A, typename stringT>
     friend void to_string_helper(const dynamic_bitset<B, A> & b, stringT & s, bool dump_all);
 
-
+    template <typename B, typename A>
+    friend std::size_t hash_value(const dynamic_bitset<B, A>& a);
 #endif
 
 public:
@@ -360,6 +369,9 @@ public:
 private:
     BOOST_STATIC_CONSTANT(block_width_type, ulong_width = std::numeric_limits<unsigned long>::digits);
 
+    dynamic_bitset& range_operation(size_type pos, size_type len,
+        Block (*partial_block_operation)(Block, size_type, size_type),
+        Block (*full_block_operation)(Block));
     void m_zero_unused_bits();
     bool m_check_invariants() const;
 
@@ -369,6 +381,51 @@ private:
     static size_type block_index(size_type pos) BOOST_NOEXCEPT { return pos / bits_per_block; }
     static block_width_type bit_index(size_type pos) BOOST_NOEXCEPT { return static_cast<block_width_type>(pos % bits_per_block); }
     static Block bit_mask(size_type pos) BOOST_NOEXCEPT { return Block(1) << bit_index(pos); }
+    static Block bit_mask(size_type first, size_type last) BOOST_NOEXCEPT
+    {
+        Block res = (last == bits_per_block - 1)
+            ? static_cast<Block>(~0)
+            : ((Block(1) << (last + 1)) - 1);
+        res ^= (Block(1) << first) - 1;
+        return res;
+    }
+    static Block set_block_bits(Block block, size_type first,
+        size_type last, bool val) BOOST_NOEXCEPT
+    {
+        if (val)
+            return block | bit_mask(first, last);
+        else
+            return block & static_cast<Block>(~bit_mask(first, last));
+    }
+
+    // Functions for operations on ranges
+    inline static Block set_block_partial(Block block, size_type first,
+        size_type last) BOOST_NOEXCEPT
+    {
+        return set_block_bits(block, first, last, true);
+    }
+    inline static Block set_block_full(Block) BOOST_NOEXCEPT
+    {
+        return static_cast<Block>(~0);
+    }
+    inline static Block reset_block_partial(Block block, size_type first,
+        size_type last) BOOST_NOEXCEPT
+    {
+        return set_block_bits(block, first, last, false);
+    }
+    inline static Block reset_block_full(Block) BOOST_NOEXCEPT
+    {
+        return 0;
+    }
+    inline static Block flip_block_partial(Block block, size_type first,
+        size_type last) BOOST_NOEXCEPT
+    {
+        return block ^ bit_mask(first, last);
+    }
+    inline static Block flip_block_full(Block block) BOOST_NOEXCEPT
+    {
+        return ~block;
+    }
 
     template <typename CharT, typename Traits, typename Alloc>
     void init_from_string(const std::basic_string<CharT, Traits, Alloc>& s,
@@ -959,6 +1016,17 @@ dynamic_bitset<Block, Allocator>::operator>>(size_type n) const
 //-----------------------------------------------------------------------------
 // basic bit operations
 
+template <typename Block, typename Allocator>
+dynamic_bitset<Block, Allocator>&
+dynamic_bitset<Block, Allocator>::set(size_type pos,
+        size_type len, bool val)
+{
+    if (val)
+        return range_operation(pos, len, set_block_partial, set_block_full);
+    else
+        return range_operation(pos, len, reset_block_partial, reset_block_full);
+}
+
 template <typename Block, typename Allocator>
 dynamic_bitset<Block, Allocator>&
 dynamic_bitset<Block, Allocator>::set(size_type pos, bool val)
@@ -982,6 +1050,13 @@ dynamic_bitset<Block, Allocator>::set()
   return *this;
 }
 
+template <typename Block, typename Allocator>
+inline dynamic_bitset<Block, Allocator>&
+dynamic_bitset<Block, Allocator>::reset(size_type pos, size_type len)
+{
+    return range_operation(pos, len, reset_block_partial, reset_block_full);
+}
+
 template <typename Block, typename Allocator>
 dynamic_bitset<Block, Allocator>&
 dynamic_bitset<Block, Allocator>::reset(size_type pos)
@@ -1006,6 +1081,13 @@ dynamic_bitset<Block, Allocator>::reset()
   return *this;
 }
 
+template <typename Block, typename Allocator>
+dynamic_bitset<Block, Allocator>&
+dynamic_bitset<Block, Allocator>::flip(size_type pos, size_type len)
+{
+    return range_operation(pos, len, flip_block_partial, flip_block_full);
+}
+
 template <typename Block, typename Allocator>
 dynamic_bitset<Block, Allocator>&
 dynamic_bitset<Block, Allocator>::flip(size_type pos)
@@ -1125,7 +1207,17 @@ dynamic_bitset<Block, Allocator>::count() const BOOST_NOEXCEPT
 
     enum { enough_table_width = table_width >= CHAR_BIT };
 
-    enum { mode = (no_padding && enough_table_width)
+#if ((defined(BOOST_MSVC) && (BOOST_MSVC >= 1600)) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64))
+    // Windows popcount is effective starting from the unsigned short type
+    enum { uneffective_popcount = sizeof(Block) < sizeof(unsigned short) };
+#elif defined(BOOST_GCC) || defined(__clang__) || (defined(BOOST_INTEL) && defined(__GNUC__))
+    // GCC popcount is effective starting from the unsigned int type
+    enum { uneffective_popcount = sizeof(Block) < sizeof(unsigned int) };
+#else
+    enum { uneffective_popcount = true };
+#endif
+
+    enum { mode = (no_padding && enough_table_width && uneffective_popcount)
                           ? access_by_bytes
                           : access_by_blocks };
 
@@ -1346,7 +1438,6 @@ bool dynamic_bitset<Block, Allocator>::intersects(const dynamic_bitset & b) cons
 // --------------------------------
 // lookup
 
-
 // look for the first bit "on", starting
 // from the block with index first_block
 //
@@ -1363,8 +1454,7 @@ dynamic_bitset<Block, Allocator>::m_do_find_from(size_type first_block) const
     if (i >= num_blocks())
         return npos; // not found
 
-    return i * bits_per_block + static_cast<size_type>(boost::lowest_bit(m_bits[i]));
-
+    return i * bits_per_block + static_cast<size_type>(detail::lowest_bit(m_bits[i]));
 }
 
 
@@ -1394,7 +1484,7 @@ dynamic_bitset<Block, Allocator>::find_next(size_type pos) const
     const Block fore = m_bits[blk] >> ind;
 
     return fore?
-        pos + static_cast<size_type>(lowest_bit(fore))
+        pos + static_cast<size_type>(detail::lowest_bit(fore))
         :
         m_do_find_from(blk + 1);
 
@@ -1536,6 +1626,17 @@ inline bool operator>=(const dynamic_bitset<Block, Allocator>& a,
     return !(a < b);
 }
 
+//-----------------------------------------------------------------------------
+// hash operations
+
+template <typename Block, typename Allocator>
+inline std::size_t hash_value(const dynamic_bitset<Block, Allocator>& a)
+{
+    std::size_t res = hash_value(a.m_num_bits);
+    boost::hash_combine(res, a.m_bits);
+    return res;
+}
+
 //-----------------------------------------------------------------------------
 // stream operations
 
@@ -1925,6 +2026,63 @@ inline const Block& dynamic_bitset<Block, Allocator>::m_highest_block() const
     return m_bits.back();
 }
 
+template <typename Block, typename Allocator>
+dynamic_bitset<Block, Allocator>& dynamic_bitset<Block, Allocator>::range_operation(
+    size_type pos, size_type len,
+    Block (*partial_block_operation)(Block, size_type, size_type),
+    Block (*full_block_operation)(Block))
+{
+    assert(pos + len <= m_num_bits);
+
+    // Do nothing in case of zero length
+    if (!len)
+        return *this;
+
+    // Use an additional asserts in order to detect size_type overflow
+    // For example: pos = 10, len = size_type_limit - 2, pos + len = 7
+    // In case of overflow, 'pos + len' is always smaller than 'len'
+    assert(pos + len >= len);
+
+    // Start and end blocks of the [pos; pos + len - 1] sequence
+    const size_type first_block = block_index(pos);
+    const size_type last_block = block_index(pos + len - 1);
+
+    const size_type first_bit_index = bit_index(pos);
+    const size_type last_bit_index = bit_index(pos + len - 1);
+
+    if (first_block == last_block) {
+        // Filling only a sub-block of a block
+        m_bits[first_block] = partial_block_operation(m_bits[first_block],
+            first_bit_index, last_bit_index);
+    } else {
+        // Check if the corner blocks won't be fully filled with 'val'
+        const size_type first_block_shift = bit_index(pos) ? 1 : 0;
+        const size_type last_block_shift = (bit_index(pos + len - 1)
+            == bits_per_block - 1) ? 0 : 1;
+
+        // Blocks that will be filled with ~0 or 0 at once
+        const size_type first_full_block = first_block + first_block_shift;
+        const size_type last_full_block = last_block - last_block_shift;
+
+        for (size_type i = first_full_block; i <= last_full_block; ++i) {
+            m_bits[i] = full_block_operation(m_bits[i]);
+        }
+
+        // Fill the first block from the 'first' bit index to the end
+        if (first_block_shift) {
+            m_bits[first_block] = partial_block_operation(m_bits[first_block],
+                first_bit_index, bits_per_block - 1);
+        }
+
+        // Fill the last block from the start to the 'last' bit index
+        if (last_block_shift) {
+            m_bits[last_block] = partial_block_operation(m_bits[last_block],
+                0, last_bit_index);
+        }
+    }
+
+    return *this;
+}
 
 // If size() is not a multiple of bits_per_block
 // then not all the bits in the last block are used.
@@ -1963,8 +2121,26 @@ bool dynamic_bitset<Block, Allocator>::m_check_invariants() const
 
 } // namespace boost
 
-
 #undef BOOST_BITSET_CHAR
 
+// std::hash support
+#if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) && !defined(BOOST_DYNAMIC_BITSET_NO_STD_HASH)
+#include <functional>
+namespace std
+{
+    template<typename Block, typename Allocator>
+    struct hash< boost::dynamic_bitset<Block, Allocator> >
+    {
+        typedef boost::dynamic_bitset<Block, Allocator> argument_type;
+        typedef std::size_t result_type;
+        result_type operator()(const argument_type& a) const BOOST_NOEXCEPT
+        {
+            boost::hash<argument_type> hasher;
+            return hasher(a);
+        }
+    };
+}
+#endif
+
 #endif // include guard