diff --git a/include/boost/detail/dynamic_bitset.hpp b/include/boost/detail/dynamic_bitset.hpp index a8612fc..f1695bd 100644 --- a/include/boost/detail/dynamic_bitset.hpp +++ b/include/boost/detail/dynamic_bitset.hpp @@ -1,7 +1,7 @@ -// -------------------------------------------------- +// ----------------------------------------------------------- // -// (C) Copyright Chuck Allison and Jeremy Siek 2001 - 2002. -// (C) Copyright Gennaro Prota 2003 - 2006. +// Copyright (c) 2001-2002 Chuck Allison and Jeremy Siek +// Copyright (c) 2003-2006, 2008 Gennaro Prota // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -9,14 +9,10 @@ // // ----------------------------------------------------------- -// See http://www.boost.org/libs/dynamic_bitset/ for documentation. -// -// $Revision$ $Date$ - $Name$ - #ifndef BOOST_DETAIL_DYNAMIC_BITSET_HPP #define BOOST_DETAIL_DYNAMIC_BITSET_HPP -#include // for std::size_t +#include #include "boost/config.hpp" #include "boost/detail/workaround.hpp" @@ -24,6 +20,7 @@ namespace boost { namespace detail { + namespace dynamic_bitset_impl { // Gives (read-)access to the object representation // of an object of type T (3.9p4). CANNOT be used @@ -46,13 +43,29 @@ namespace boost { // ------- count function implementation -------------- - namespace dynamic_bitset_count_impl { - typedef unsigned char byte_type; - enum mode { access_by_bytes, access_by_blocks }; + // This two entities + // + // enum mode { access_by_bytes, access_by_blocks }; + // template struct mode_to_type {}; + // + // were removed, since the regression logs (as of 24 Aug 2008) show + // that several compilers have troubles with recognizing + // + // const mode m = access_by_bytes + // + // as a constant expression + // + // *We'll use a bool, instead *. + // + template + struct value_to_type + { + }; + const bool access_by_bytes = true; + const bool access_by_blocks = false; - template struct mode_to_type {}; // the table: wrapped in a class template, so // that it is only instantiated if/when needed @@ -87,7 +100,7 @@ namespace boost { template inline std::size_t do_count(Iterator first, std::size_t length, int /*dummy param*/, - mode_to_type* ) + value_to_type* ) { std::size_t num = 0; if (length) @@ -111,7 +124,7 @@ namespace boost { // template inline std::size_t do_count(Iterator first, std::size_t length, ValueType, - mode_to_type*) + value_to_type*) { std::size_t num = 0; while (length){ @@ -129,8 +142,6 @@ namespace boost { return num; } - - } // dynamic_bitset_count_impl // ------------------------------------------------------- @@ -139,7 +150,7 @@ namespace boost { // // size_type(-1) / sizeof(T) // - // from vector<>::max_size. This tries to get out more + // from vector<>::max_size. This tries to get more // meaningful info. // template @@ -158,16 +169,57 @@ namespace boost { // for static_asserts template - struct dynamic_bitset_allowed_block_type { + struct allowed_block_type { enum { value = T(-1) > 0 }; // ensure T has no sign }; template <> - struct dynamic_bitset_allowed_block_type { + struct allowed_block_type { enum { value = false }; }; + template + struct is_numeric { + enum { value = false }; + }; + +# define BOOST_dynamic_bitset_is_numeric(x) \ + template<> \ + struct is_numeric { \ + enum { value = true }; \ + } /**/ + + BOOST_dynamic_bitset_is_numeric(bool); + BOOST_dynamic_bitset_is_numeric(char); + +#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) + BOOST_dynamic_bitset_is_numeric(wchar_t); +#endif + + BOOST_dynamic_bitset_is_numeric(signed char); + BOOST_dynamic_bitset_is_numeric(short int); + BOOST_dynamic_bitset_is_numeric(int); + BOOST_dynamic_bitset_is_numeric(long int); + + BOOST_dynamic_bitset_is_numeric(unsigned char); + BOOST_dynamic_bitset_is_numeric(unsigned short); + BOOST_dynamic_bitset_is_numeric(unsigned int); + BOOST_dynamic_bitset_is_numeric(unsigned long); + +#if defined(BOOST_HAS_LONG_LONG) + BOOST_dynamic_bitset_is_numeric(::boost::long_long_type); + BOOST_dynamic_bitset_is_numeric(::boost::ulong_long_type); +#endif + + // intentionally omitted + //BOOST_dynamic_bitset_is_numeric(float); + //BOOST_dynamic_bitset_is_numeric(double); + //BOOST_dynamic_bitset_is_numeric(long double); + +#undef BOOST_dynamic_bitset_is_numeric + + } // dynamic_bitset_impl } // namespace detail } // namespace boost diff --git a/include/boost/dynamic_bitset/dynamic_bitset.hpp b/include/boost/dynamic_bitset/dynamic_bitset.hpp index d155c4b..98c826f 100644 --- a/include/boost/dynamic_bitset/dynamic_bitset.hpp +++ b/include/boost/dynamic_bitset/dynamic_bitset.hpp @@ -58,7 +58,7 @@ class dynamic_bitset // this class definition to avoid problems with VC++. Similarly, // with the member functions of nested classes. - BOOST_STATIC_ASSERT(detail::dynamic_bitset_allowed_block_type::value); + BOOST_STATIC_ASSERT(detail::dynamic_bitset_impl::allowed_block_type::value); public: typedef Block block_type; @@ -82,7 +82,7 @@ public: // the one and only non-copy ctor reference(block_type & b, block_type pos) :m_block(b), m_mask(block_type(1) << pos) - { assert(pos >= 0 && pos < bits_per_block); } + { assert( pos < bits_per_block); } void operator&(); // left undefined @@ -166,10 +166,39 @@ public: dynamic_bitset(BlockInputIterator first, BlockInputIterator last, const Allocator& alloc = Allocator()) - :m_bits(first, last, alloc), - m_num_bits(m_bits.size() * bits_per_block) - {} + :m_bits(alloc), + m_num_bits(0) + { + using boost::detail::dynamic_bitset_impl::value_to_type; + using boost::detail::dynamic_bitset_impl::is_numeric; + const value_to_type< + is_numeric::value> selector; + + dispatch_init(first, last, selector); + } + + template + void dispatch_init(T num_bits, unsigned long value, + detail::dynamic_bitset_impl::value_to_type) + { + init_from_unsigned_long(static_cast(num_bits), value); + } + + template + void dispatch_init(T first, T last, + detail::dynamic_bitset_impl::value_to_type) + { + init_from_block_range(first, last); + } + + template + void init_from_block_range(BlockIter first, BlockIter last) + { + assert(m_bits.size() == 0); + m_bits.insert(m_bits.end(), first, last); + m_num_bits = m_bits.size() * bits_per_block; + } // copy constructor dynamic_bitset(const dynamic_bitset& b); @@ -350,6 +379,39 @@ private: } + void init_from_unsigned_long(size_type num_bits, + unsigned long value/*, + const Allocator& alloc*/) + { + + assert(m_bits.size() == 0); + + m_bits.resize(calc_num_blocks(num_bits)); + m_num_bits = num_bits; + + typedef unsigned long num_type; + typedef boost::detail::dynamic_bitset_impl + ::shifter shifter; + + //if (num_bits == 0) + // return; + + // zero out all bits at pos >= num_bits, if any; + // note that: num_bits == 0 implies value == 0 + if (num_bits < static_cast(ulong_width)) { + const num_type mask = (num_type(1) << num_bits) - 1; + value &= mask; + } + + typename buffer_type::iterator it = m_bits.begin(); + for( ; value; shifter::left_shift(value), ++it) { + *it = static_cast(value); + } + + } + + + BOOST_DYNAMIC_BITSET_PRIVATE: bool m_unchecked_test(size_type pos) const; @@ -539,28 +601,10 @@ dynamic_bitset::dynamic_bitset(const Allocator& alloc) template dynamic_bitset:: dynamic_bitset(size_type num_bits, unsigned long value, const Allocator& alloc) - : m_bits(calc_num_blocks(num_bits), Block(0), alloc), - m_num_bits(num_bits) + : m_bits(alloc), + m_num_bits(0) { - - typedef unsigned long num_type; - typedef boost::detail::shifter shifter; - - //if (num_bits == 0) - // return; - - // zero out all bits at pos >= num_bits, if any; - // note that: num_bits == 0 implies value == 0 - if (num_bits < static_cast(ulong_width)) { - const num_type mask = (num_type(1) << num_bits) - 1; - value &= mask; - } - - typename buffer_type::iterator it = m_bits.begin(); - for( ; value; shifter::left_shift(value), ++it) { - *it = static_cast(value); - } - + init_from_unsigned_long(num_bits, value); } // copy constructor @@ -957,18 +1001,17 @@ template typename dynamic_bitset::size_type dynamic_bitset::count() const { - using namespace detail::dynamic_bitset_count_impl; + using namespace detail::dynamic_bitset_impl; const bool no_padding = bits_per_block == CHAR_BIT * sizeof(Block); const bool enough_table_width = table_width >= CHAR_BIT; - const mode m = (no_padding && enough_table_width) - ? access_by_bytes - : access_by_blocks; - typedef mode_to_type m_type; + const bool mode = (no_padding && enough_table_width) + ? access_by_bytes + : access_by_blocks; return do_count(m_bits.begin(), num_blocks(), Block(0), - static_cast(0)); + static_cast *>(0)); }