Friday, January 23, 2015

Simple Bitset

As mentioned yesterday I was going to need to implement a bitset and would post it here when working. Below is the code.

Operators returning copies of a bitset are intentionally left out, the idea being these are expensive operations due to the memory allocations for the bit array. They could easily be implemented using the implemented Copy and Copy Constructor functions though if needed.

*NOTE* A lack of bounds checking in the functions. Could be implemented easily but left out in this v0.1 implementation.

Use any code posted on this blog freely but completely at your own risk, it will work within the parameters I have tested but may contain leaks or other obvious flaws include crashes, endless loops and any other coding issue you care to think of.

#pragma once

class LogicalBitset
{
unsigned int *m_Bits = 0;
int m_NumInts = 0;
int m_NumBits = 0;

public:
LogicalBitset()
{}

LogicalBitset(const LogicalBitset &rOther)
{
Copy(rOther);
}

~LogicalBitset()
{
delete m_Bits;
}

void Init(int iNumBitsNeeded)
{
delete m_Bits;
m_NumInts = (iNumBitsNeeded >> 5) + 1;
m_NumBits = iNumBitsNeeded;
m_Bits = new unsigned int[m_NumInts];
memset(m_Bits, 0, sizeof(m_Bits[0]) * m_NumInts);
}

void Copy(const LogicalBitset &rOther)
{
if (rOther.m_NumInts)
{
Init(rOther.m_NumBits);
for (int i = 0; i < m_NumInts; i++)
{
m_Bits[i] = rOther.m_Bits[i];
}
}
else
{
Reset();
}
}

void Reset()
{
delete m_Bits;
m_Bits = nullptr;
m_NumInts = 0;
m_NumBits = 0;
}

int GetNumBits() const
{
return m_NumBits;
}

void Resize(int neededBits)
{
//Grow only for now
if (neededBits > m_NumBits)
{
int neededInts = (neededBits >> 5) + 1;
if (neededInts > m_NumInts)
{
//Copy old data across to new container
unsigned int *pIntArray = new unsigned int[neededInts];
for (int i = 0; i < m_NumInts; i++)
{
pIntArray[i] = m_Bits[i];
}
delete m_Bits;
pIntArray[m_NumInts] = 0;
m_Bits = pIntArray;
m_NumInts = neededInts;
}
m_NumBits = neededBits;
}
}

void AddBit(bool bValue)
{
int neededBits = m_NumBits+1;
int neededInts = (neededBits >> 5) + 1;
if (neededInts > m_NumInts)
{
//Copy old data across to new container
unsigned int *pIntArray = new unsigned int[neededInts];
for (int i = 0; i < m_NumInts; i++)
{
pIntArray[i] = m_Bits[i];
}
delete m_Bits;
pIntArray[m_NumInts] = 0;
m_Bits = pIntArray;
m_NumInts = neededInts;
}
m_NumBits = neededBits;
SetBit(m_NumBits - 1, bValue);
}

bool IsSet() const
{
return m_NumInts > 0;
}

void SetBit(int iIndex, bool bValue)
{
int iInt = iIndex >> 5;
int iValue = m_Bits[iInt];
int iBit = iIndex & 31;
int iBitMask = 1 << iBit;
m_Bits[iInt] = (iValue & (~iBitMask)) | (bValue ? iBitMask : 0);
}

bool GetBit(int iIndex)
{
int iInt = iIndex >> 5;
int iBit = iIndex & 31;
return (m_Bits[iInt] & (1 << iBit)) != 0;
}

bool operator==(const LogicalBitset &rOther) const
{
if (m_NumInts != rOther.m_NumBits)
return false;

for (int i = 0; i < m_NumInts; i++)
{
if (m_Bits[i] != rOther.m_Bits[i])
return false;
}
return true;
}

void operator=(const LogicalBitset &rOther)
{
Copy(rOther);
}

void Zero()
{
for (int i = 0; i < m_NumInts; i++)
{
m_Bits[i] = 0;
}
}

bool IsNonZero() const
{
for (int i = 0; i < m_NumInts; i++)
{
if (m_Bits[i] != 0)
return true;
}
return false;
}

bool ContainsSomeBits(const LogicalBitset &rOther) const
{
for (int i = 0; i < m_NumInts; i++)
{
if (m_Bits[i] & rOther.m_Bits[i])
return true;
}
return false;
}

bool ContainsAllBits(const LogicalBitset &rOther) const
{
for (int i = 0; i < m_NumInts; i++)
{
const unsigned int iOtherBits = rOther.m_Bits[i];
if ((m_Bits[i] & iOtherBits) != iOtherBits)
return false;
}
return true;
}
};

No comments:

Post a Comment