dynamic_bitset:
* fixed form of some remaining copyright lines * using namespace detail::dynamic_bitset_impl for *all* implementation details (dynamic_bitset_*count*_impl removed) and consequently shortened some entity names * switched from enum to bools for "enum mode", to help several compilers which show problems with recognizing access_by_bytes and access_by_blocks as constant expressions * minor comment changes * implemented the do-the-right-thing dispatch for constructor from iterator-range, a la standard sequence containers (feature request #2172) * dropped now useless comparison with zero in reference constructor NOTE: updated tests and documentation not committed yet; let's wait for the trunk results first [SVN r48478]
This commit is contained in:
parent
d80a9dbdf8
commit
d09c7d2180
@ -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 <cstddef> // for std::size_t
|
||||
#include <cstddef>
|
||||
#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 <mode> 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 <bool value>
|
||||
struct value_to_type
|
||||
{
|
||||
};
|
||||
const bool access_by_bytes = true;
|
||||
const bool access_by_blocks = false;
|
||||
|
||||
template <mode> 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 <typename Iterator>
|
||||
inline std::size_t do_count(Iterator first, std::size_t length,
|
||||
int /*dummy param*/,
|
||||
mode_to_type<access_by_bytes>* )
|
||||
value_to_type<access_by_bytes>* )
|
||||
{
|
||||
std::size_t num = 0;
|
||||
if (length)
|
||||
@ -111,7 +124,7 @@ namespace boost {
|
||||
//
|
||||
template <typename Iterator, typename ValueType>
|
||||
inline std::size_t do_count(Iterator first, std::size_t length, ValueType,
|
||||
mode_to_type<access_by_blocks>*)
|
||||
value_to_type<access_by_blocks>*)
|
||||
{
|
||||
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 <typename T>
|
||||
@ -158,16 +169,57 @@ namespace boost {
|
||||
|
||||
// for static_asserts
|
||||
template <typename T>
|
||||
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<bool> {
|
||||
struct allowed_block_type<bool> {
|
||||
enum { value = false };
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct is_numeric {
|
||||
enum { value = false };
|
||||
};
|
||||
|
||||
# define BOOST_dynamic_bitset_is_numeric(x) \
|
||||
template<> \
|
||||
struct is_numeric<x> { \
|
||||
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
|
||||
|
@ -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<Block>::value);
|
||||
BOOST_STATIC_ASSERT(detail::dynamic_bitset_impl::allowed_block_type<Block>::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<BlockInputIterator>::value> selector;
|
||||
|
||||
dispatch_init(first, last, selector);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void dispatch_init(T num_bits, unsigned long value,
|
||||
detail::dynamic_bitset_impl::value_to_type<true>)
|
||||
{
|
||||
init_from_unsigned_long(static_cast<size_type>(num_bits), value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void dispatch_init(T first, T last,
|
||||
detail::dynamic_bitset_impl::value_to_type<false>)
|
||||
{
|
||||
init_from_block_range(first, last);
|
||||
}
|
||||
|
||||
template <typename BlockIter>
|
||||
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<num_type, bits_per_block, ulong_width> 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<size_type>(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<block_type>(value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOST_DYNAMIC_BITSET_PRIVATE:
|
||||
|
||||
bool m_unchecked_test(size_type pos) const;
|
||||
@ -539,28 +601,10 @@ dynamic_bitset<Block, Allocator>::dynamic_bitset(const Allocator& alloc)
|
||||
template <typename Block, typename Allocator>
|
||||
dynamic_bitset<Block, Allocator>::
|
||||
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<num_type, bits_per_block, ulong_width> 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<size_type>(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<block_type>(value);
|
||||
}
|
||||
|
||||
init_from_unsigned_long(num_bits, value);
|
||||
}
|
||||
|
||||
// copy constructor
|
||||
@ -957,18 +1001,17 @@ template <typename Block, typename Allocator>
|
||||
typename dynamic_bitset<Block, Allocator>::size_type
|
||||
dynamic_bitset<Block, Allocator>::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> 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<m_type *>(0));
|
||||
static_cast<value_to_type<mode> *>(0));
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user