Skip to content
Snippets Groups Projects
Commit f0f86a7e authored by Christian Engwer's avatar Christian Engwer
Browse files

patch as proposed in FS#453, add an stl interface to BlockBitField

[[Imported from SVN: r5346]]
parent 1dc7139c
No related branches found
No related tags found
No related merge requests found
......@@ -11,43 +11,119 @@
#include <bitset>
#include <iostream>
#include <dune/common/genericiterator.hh>
#include <dune/common/exceptions.hh>
namespace Dune {
template <int block_size, class Allocator=std::allocator<bool> > class BlockBitField;
template <int block_size, class Alloc> class BlockBitField;
template <int block_size>
class BlockBitFieldReference
template <int block_size, class Alloc>
class BlockBitFieldConstReference
{
protected:
BlockBitFieldReference(BlockBitField<block_size>& blockBitField, int block_number) :
typedef Dune::BlockBitField<block_size, Alloc> BlockBitField;
friend class Dune::BlockBitField<block_size, Alloc>;
BlockBitFieldConstReference(const BlockBitField& blockBitField, int block_number) :
blockBitField(blockBitField),
block_number(block_number)
{};
typedef typename BlockBitField<block_size>::BlocklessBaseClass BlockLess;
public:
typedef std::vector<bool>::reference BitReference;
typedef std::bitset<block_size> bitset;
BlockBitFieldReference<block_size>& operator=(bool b)
// bitset interface typedefs
typedef typename std::vector<bool, Alloc>::const_reference reference;
typedef typename std::vector<bool, Alloc>::const_reference const_reference;
typedef size_t size_type;
//! Returns a copy of *this shifted left by n bits.
bitset operator<<(size_type n) const
{
for(int i=0; i<block_size; ++i)
blockBitField.BlockLess::operator[](block_number*block_size+i) = b;
bitset b = *this;
b <<= n;
return b;
}
return (*this);
//! Returns a copy of *this shifted right by n bits.
bitset operator>>(size_type n) const
{
bitset b = *this;
b >>= n;
return b;
}
//! Returns a copy of *this with all of its bits flipped.
bitset operator~() const
{
bitset b = *this;
b.flip();
return b;
}
//! Returns block_size.
size_type size() const
{
return block_size;
}
//! Returns the number of bits that are set.
size_type count() const
{
size_type n = 0;
for(size_type i=0; i<block_size; ++i)
n += getBit(i);
return n;
}
//! Returns true if any bits are set.
bool any() const
{
return nSetBits();
}
//! Returns true if no bits are set.
bool none() const
{
return ! any();
}
//! Returns true if bit n is set.
bool test(size_type n) const
{
return getBit(n);
}
BitReference operator[](int i)
const_reference operator[](size_type i) const
{
return blockBitField.BlockLess::operator[](block_number*block_size+i);
return getBit(i);
}
const BitReference operator[](int i) const
//! Returns the total number of set bits
size_type nSetBits() const
{
return blockBitField.BlockLess::operator[](block_number*block_size+i);
return count();
}
friend std::ostream& operator<< (std::ostream& s, const BlockBitFieldReference<block_size>& v)
//! cast to bitset
operator bitset() const
{
return blockBitField.getLocalBits(block_number);
}
/*!
missing operators:
- bool operator==(const bitset&) const
- bool operator==(const BlockBitFieldReferenceBase&) const
- bool operator!=(const bitset&) const
- bool operator!=(const BlockBitFieldReferenceBase&) const
- unsigned long to_ulong() const
*/
friend std::ostream& operator<< (std::ostream& s, const BlockBitFieldConstReference& v)
{
s << "(";
for(int i=0; i<block_size; ++i)
......@@ -56,28 +132,203 @@ namespace Dune {
return s;
}
private:
BlockBitField<block_size>& blockBitField;
protected:
const BlockBitField& blockBitField;
int block_number;
friend class BlockBitField<block_size>;
const_reference getBit(size_type i) const
{
return blockBitField.getBit(block_number,i);
}
};
template <int block_size, class Alloc>
class BlockBitFieldReference : public BlockBitFieldConstReference<block_size,Alloc>
{
protected:
typedef Dune::BlockBitField<block_size, Alloc> BlockBitField;
friend class Dune::BlockBitField<block_size, Alloc>;
typedef Dune::BlockBitFieldConstReference<block_size,Alloc> BlockBitFieldConstReference;
BlockBitFieldReference(BlockBitField& blockBitField, int block_number) :
BlockBitFieldConstReference(blockBitField, block_number),
blockBitField(blockBitField)
{};
public:
typedef std::bitset<block_size> bitset;
// bitset interface typedefs
typedef typename std::vector<bool, Alloc>::reference reference;
typedef typename std::vector<bool, Alloc>::const_reference const_reference;
typedef size_t size_type;
BlockBitFieldReference& operator=(bool b)
{
for(int i=0; i<block_size; ++i)
getBit(i) = b;
return (*this);
}
BlockBitFieldReference& operator=(const bitset & b)
{
for(int i=0; i<block_size; ++i)
getBit(i) = b[i];
return (*this);
}
BlockBitFieldReference& operator=(const BlockBitFieldConstReference & b)
{
for(int i=0; i<block_size; ++i)
getBit(i) = b[i];
/** \brief A dynamic array of blocks of booleans
*
return (*this);
}
//! Bitwise and.
BlockBitFieldReference& operator&=(const BlockBitFieldConstReference& x)
{
for (size_type i=0; i<block_size; i++)
set(i, getBit(i) & x.getBit(i));
return *this;
}
//! Bitwise inclusive or.
BlockBitFieldReference& operator|=(const BlockBitFieldConstReference& x)
{
for (size_type i=0; i<block_size; i++)
set(i, getBit(i) | x.getBit(i));
return *this;
}
//! Bitwise exclusive or.
BlockBitFieldReference& operator^=(const BlockBitFieldConstReference& x)
{
for (size_type i=0; i<block_size; i++)
set(i, getBit(i) ^ x.getBit(i));
return *this;
}
//! Left shift.
BlockBitFieldReference& operator<<=(size_type n)
{
for (size_type i=0; i<block_size-n; i++)
set(i, getBit(i+n));
return *this;
}
//! Right shift.
BlockBitFieldReference& operator>>=(size_type n)
{
for (size_type i=0; i<block_size-n; i++)
set(i+n, getBit(i));
return *this;
}
// Sets every bit.
BlockBitFieldReference& set()
{
for (size_type i=0; i<block_size; i++)
set(i);
return *this;
}
//! Flips the value of every bit.
BlockBitFieldReference& flip()
{
for (size_type i=0; i<block_size; i++)
flip(i);
return *this;
}
//! Clears every bit.
BlockBitFieldReference& reset()
{}
//! Sets bit n if val is nonzero, and clears bit n if val is zero.
BlockBitFieldReference& set(size_type n, int val = 1)
{
getBit(n) = val;
return *this;
}
//! Clears bit n.
BlockBitFieldReference& reset(size_type n)
{
set(n, false);
return *this;
}
//! Flips bit n.
BlockBitFieldReference& flip(size_type n)
{
bool val = ! getBit(n);
set(n, val);
return *this;
}
reference operator[](size_type i)
{
return getBit(i);
}
protected:
BlockBitField& blockBitField;
reference getBit(size_type i)
{
return blockBitField.getBit(this->block_number,i);
}
};
/**
\brief A dynamic array of blocks of booleans
*/
template <int block_size, class Allocator>
template <int block_size, class Allocator=std::allocator<bool> >
class BlockBitField : private std::vector<bool, Allocator>
{
protected:
/** \brief The implementation class: an unblocked bitfield */
typedef std::vector<bool> BlocklessBaseClass;
typedef std::vector<bool, Allocator> BlocklessBaseClass;
public:
typedef std::bitset<block_size> LocalBits;
//! container interface typedefs
//! {
typedef std::bitset<block_size> value_type;
typedef BlockBitFieldReference<block_size,Allocator> reference;
typedef BlockBitFieldConstReference<block_size,Allocator> const_reference;
typedef typename std::vector<bool, Allocator>::size_type size_type;
//! }
//! iterators
//! {
typedef Dune::GenericIterator<BlockBitField<block_size,Allocator>, value_type, reference> iterator;
typedef Dune::GenericIterator<const BlockBitField<block_size,Allocator>, const value_type, const reference> const_iterator;
//! }
//! Returns a iterator pointing to the beginning of the vector.
iterator begin(){
return iterator(*this, 0);
}
//! Returns a const_iterator pointing to the beginning of the vector.
const_iterator begin() const {
return const_iterator(*this, 0);
}
//! Returns an iterator pointing to the end of the vector.
iterator end(){
return iterator(*this, 100);
}
//! Returns a const_iterator pointing to the end of the vector.
const_iterator end() const {
return const_iterator(*this, 100);
}
//! Default constructor
BlockBitField() :
......@@ -104,10 +355,16 @@ namespace Dune {
BlocklessBaseClass(n*block_size,v)
{}
//! Erases all of the elements.
void clear()
{
BlocklessBaseClass::clear();
}
//! Resize field
void resize(int n)
void resize(int n, bool v = bool())
{
BlocklessBaseClass::resize(n*block_size);
BlocklessBaseClass::resize(n*block_size, v);
}
/** \brief Return the number of blocks */
......@@ -127,34 +384,34 @@ namespace Dune {
}
/** \brief Return reference to i-th block */
BlockBitFieldReference<block_size> operator[](int i)
reference operator[](int i)
{
return BlockBitFieldReference<block_size>(*this, i);
return reference(*this, i);
}
/** \brief Return const reference to i-th block */
const BlockBitFieldReference<block_size> operator[](int i) const
const_reference operator[](int i) const
{
return BlockBitFieldReference<block_size>(const_cast<BlockBitField<block_size>& >(*this), i);
return const_reference(*this, i);
}
/** \brief Return reference to last block */
BlockBitFieldReference<block_size> back()
reference back()
{
return BlockBitFieldReference<block_size>(*this, size()-1);
return reference(*this, size()-1);
}
/** \brief Return const reference to last block */
const BlockBitFieldReference<block_size> back() const
const_reference back() const
{
return BlockBitFieldReference<block_size>(const_cast<BlockBitField<block_size>& >(*this), size()-1);
return const_reference(*this, size()-1);
}
//! Returns the total number of set bits
int nSetBits() const
size_type nSetBits() const
{
int n = 0;
for(int i=0; i<BlocklessBaseClass::size(); ++i)
size_type n = 0;
for(size_type i=0; i<BlocklessBaseClass::size(); ++i)
n += BlocklessBaseClass::operator[](i);
return n;
}
......@@ -162,25 +419,25 @@ namespace Dune {
//! Returns the number of set bits for given component
int nSetBits(int j) const
{
int n = 0;
int blocks = size();
for(int i=0; i<blocks; ++i)
n += (BlocklessBaseClass::operator[](i*block_size+j)) ? 1 : 0;
size_type n = 0;
size_type blocks = size();
for(size_type i=0; i<blocks; ++i)
n += getBit(i,j);
return n;
}
/** \brief Return i-th block by value */
LocalBits getLocalBits(int i) const
value_type getLocalBits(int i) const
{
LocalBits bits;
value_type bits;
for(int j=0; j<block_size; ++j)
bits.set(j, BlocklessBaseClass::operator[](i*block_size+j));
bits.set(j, getBit(i,j));
return bits;
}
//! Send bitfield to an output stream
friend std::ostream& operator<< (std::ostream& s, const BlockBitField<block_size>& v)
friend std::ostream& operator<< (std::ostream& s, const BlockBitField& v)
{
for (size_t i=0; i<v.size(); i++)
s << v[i] << " ";
......@@ -189,7 +446,18 @@ namespace Dune {
return s;
}
friend class BlockBitFieldReference<block_size>;
private:
typename std::vector<bool>::reference getBit(size_type i, size_type j) {
return BlocklessBaseClass::operator[](i*block_size+j);
}
typename std::vector<bool>::const_reference getBit(size_type i, size_type j) const {
return BlocklessBaseClass::operator[](i*block_size+j);
}
friend class BlockBitFieldReference<block_size,Allocator>;
friend class BlockBitFieldConstReference<block_size,Allocator>;
};
} // namespace Dune
......
......@@ -42,3 +42,4 @@ testfassign4
smallobject
conversiontest
nullptr-test
blockbitfieldtest
......@@ -10,7 +10,7 @@ TESTPROGS = parsetest test-stack arraylisttest smartpointertest \
testfassign4 \
testfassign_fail1 testfassign_fail2 testfassign_fail3 \
testfassign_fail4 testfassign_fail5 testfassign_fail6 \
conversiontest
conversiontest blockbitfieldtest
# which tests to run
COMPILE_XFAIL=$(DUNE_COMMON_ROOT)/bin/xfail-compile-tests
......@@ -41,6 +41,8 @@ AM_LDFLAGS = $(LOCAL_LIBS)
# define the programs
smallobject_SOURCES = smallobject.cc
blockbitfieldtest_SOURCES = blockbitfieldtest.cc
nullptr_test_SOURCES = nullptr-test.cc nullptr-test2.cc
nullptr_test_fail_SOURCES = nullptr-test.cc
nullptr_test_fail_CPPFLAGS = -DFAIL
......
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#include <config.h>
#ifdef __GNUC__
#include <ext/malloc_allocator.h>
#endif
#include <dune/common/blockbitfield.hh>
template<int block_size, class Alloc>
void doTest() {
typedef Dune::BlockBitField<block_size, Alloc> BBF;
typedef typename BBF::value_type bitset;
typedef typename BBF::reference reference;
BBF bbf(10,true);
bitset x = bbf[3];
reference y = bbf[4];
y[2] = true;
y = x;
x = y;
const BBF & cbbf = bbf;
y = cbbf[1];
x = cbbf[1];
}
int main()
{
doTest<4, std::allocator<bool> >();
#ifdef __GNUC__
doTest<4, __gnu_cxx::malloc_allocator<bool> >();
#endif
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment