#ifndef __BITARRAY_AMV
#define __BITARRAY_AMV
#include <limits>
#include <iostream>
#include "algorithm.h"
#include "amvdefs.h"
namespace amv {
const int nBits=std::numeric_limits<unsigned int>::digits;
const unsigned int maxBit=(1<<(nBits-1));
const unsigned int minBit=1;
const unsigned int maxVal=std::numeric_limits<unsigned int>::max();
class bitarray {
int m_size;
int nBlocks;
unsigned int *pBlocks;
class bit {
unsigned int * const pBlock;
int nBit;
public:
bit(unsigned int *pBlocks, int subscript);
bool operator=(bool value);
operator bool() const;
};
public:
bitarray(int size);
bitarray(const bitarray &b);
~bitarray();
bitarray &operator=(bool val);
bool operator[](int subscript) const;
bit operator[](int subscript);
int bytes() const;
int size() const;
void resize(int size);
int count(bool val);
int find(bool val);
friend ostream &operator<<(ostream &os, const bitarray &b);
};
inline bitarray::bit::bit(unsigned int *pBlocks, int subscript):
pBlock(pBlocks+subscript/nBits),
nBit(subscript%nBits)
{
}
inline bool bitarray::bit::operator=(bool value)
{
if(value)
*pBlock|=maxBit>>nBit;
else
*pBlock&=~(maxBit>>nBit);
return value;
}
inline bitarray::bit::operator bool() const
{
return (*pBlock & (maxBit>>nBit)) ? true : false;
}
inline bitarray::bitarray(int size): m_size(size),
nBlocks(m_size%nBits ? m_size/nBits+1 : m_size/nBits),
pBlocks(new unsigned int[nBlocks])
{
unsigned int *pTemp=pBlocks, *pEnd=pBlocks+nBlocks;
while(pTemp!=pEnd)
{
*pTemp=0;
++pTemp;
}
}
inline bitarray::bitarray(const bitarray &b): m_size(b.m_size),
nBlocks(b.nBlocks),
pBlocks(new unsigned int[nBlocks])
{
copy(b.pBlocks,b.pBlocks+b.nBlocks,pBlocks);
}
inline bitarray::~bitarray()
{
delete [] pBlocks;
}
inline bitarray &bitarray::operator=(bool val)
{
unsigned int *pBegin=pBlocks, *pEnd=pBlocks+nBlocks;
if(val)
{
while(pBegin!=pEnd)
{
*pBegin=maxVal;
++pBegin;
}
}
else
{
while(pBegin!=pEnd)
{
*pBegin=0;
++pBegin;
}
}
return *this;
}
inline bool bitarray::operator[](int subscript) const
{
return (*(pBlocks+subscript/nBits) & (maxBit>>(subscript%nBits)));
}
inline bitarray::bit bitarray::operator[](int subscript)
{
return bit(pBlocks,subscript);
}
inline int bitarray::bytes() const
{
return (nBlocks*sizeof(unsigned int));
}
inline int bitarray::size() const
{
return m_size;
}
inline void bitarray::resize(int size)
{
this->~bitarray();
int nBlocks1=size%nBits ? size/nBits+1 : size/nBits;
unsigned int *pBlocks1=new unsigned int[nBlocks1];
copy(pBlocks,pBlocks+nBlocks,pBlocks1);
unsigned int *pTemp=pBlocks, *pEnd=pBlocks+nBlocks;
while(pTemp!=pEnd)
{
*pTemp=0;
++pTemp;
}
}
inline int bitarray::count(bool val)
{
int n=0;
for(int i=0; i<m_size; ++i)
if(bit(pBlocks,i)==val)
++n;
return n;
}
inline int bitarray::find(bool val)
{
int subscript=-1;
for(int i=0; i<m_size; ++i)
if(bit(pBlocks,i)==val)
{
subscript=i;
break;
}
return subscript;
}
ostream &operator<<(ostream &os, const bitarray &b)
{
for(int i=0; i<b.m_size; ++i)
os<<int(b[i]);
return os;
}
}
#endif