mirror of
https://github.com/TombEngine/TombEngine.git
synced 2025-04-28 15:57:59 +03:00
Optimise BitField class (#1511)
* Optimise BitField class * DebugBuild -> DEBUG_BUILD * Fix merge error
This commit is contained in:
parent
48902b00a9
commit
903fdf288f
8 changed files with 350 additions and 142 deletions
|
@ -368,7 +368,6 @@
|
|||
</dt>
|
||||
<dd>
|
||||
Get a copy of this Vec2 translated in the direction of the input rotation in degrees by the input distance.
|
||||
Get the translated Vec2 according to the input Rotation and distance.
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -363,7 +363,6 @@
|
|||
</dt>
|
||||
<dd>
|
||||
Get a copy of this Vec3 translated in the direction of the input Rotation object by the input distance.
|
||||
Get the translated Vec3 according to the input Rotation and distance.
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace TEN::Debug
|
|||
if (prevString == msg && !allowSpam)
|
||||
return;
|
||||
|
||||
if constexpr (!DebugBuild)
|
||||
if constexpr (!DEBUG_BUILD)
|
||||
{
|
||||
if (config == LogConfig::Debug)
|
||||
return;
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
namespace TEN::Debug
|
||||
{
|
||||
#if _DEBUG
|
||||
constexpr bool DebugBuild = true;
|
||||
constexpr auto DEBUG_BUILD = true;
|
||||
#else
|
||||
constexpr bool DebugBuild = false;
|
||||
constexpr auto DEBUG_BUILD = false;
|
||||
#endif
|
||||
|
||||
enum class LogLevel
|
||||
|
@ -41,7 +41,7 @@ namespace TEN::Debug
|
|||
|
||||
inline void TENAssert(const bool& cond, const std::string& msg)
|
||||
{
|
||||
if constexpr (DebugBuild)
|
||||
if constexpr (DEBUG_BUILD)
|
||||
{
|
||||
if (!cond)
|
||||
{
|
||||
|
|
|
@ -550,7 +550,7 @@ namespace TEN::Renderer
|
|||
D3D_FEATURE_LEVEL featureLevel;
|
||||
HRESULT res;
|
||||
|
||||
if constexpr (DebugBuild)
|
||||
if constexpr (DEBUG_BUILD)
|
||||
{
|
||||
res = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_DEBUG,
|
||||
levels, 1, D3D11_SDK_VERSION, &_device, &featureLevel, &_context);
|
||||
|
|
|
@ -228,7 +228,7 @@ namespace TEN::Renderer::Utils
|
|||
|
||||
// Set up compilation flags according to build configuration.
|
||||
unsigned int flags = D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_PACK_MATRIX_ROW_MAJOR;
|
||||
if constexpr (DebugBuild)
|
||||
if constexpr (DEBUG_BUILD)
|
||||
{
|
||||
flags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
|
||||
}
|
||||
|
|
|
@ -4,71 +4,104 @@
|
|||
namespace TEN::Utils
|
||||
{
|
||||
const BitField BitField::Empty = BitField(0);
|
||||
const BitField BitField::Default = BitField(SIZE_DEFAULT);
|
||||
const BitField BitField::Default = BitField(DEFAULT_SIZE);
|
||||
|
||||
BitField::BitField()
|
||||
{
|
||||
_bits.resize(SIZE_DEFAULT);
|
||||
_chunks.resize((DEFAULT_SIZE + (CHUNK_SIZE - 1)) / CHUNK_SIZE);
|
||||
_size = DEFAULT_SIZE;
|
||||
}
|
||||
|
||||
BitField::BitField(unsigned int size)
|
||||
{
|
||||
// NOTE: Bits initialize as unset.
|
||||
size = std::min<unsigned int>(size, SIZE_DEFAULT);
|
||||
_bits.resize(size);
|
||||
_chunks.resize((size + (CHUNK_SIZE - 1)) / CHUNK_SIZE);
|
||||
_size = size;
|
||||
}
|
||||
|
||||
BitField::BitField(unsigned int size, unsigned int packedBits)
|
||||
BitField::BitField(const std::initializer_list<bool>& bits)
|
||||
{
|
||||
size = std::min<unsigned int>(size, SIZE_DEFAULT);
|
||||
_bits.reserve(size);
|
||||
_chunks.resize((bits.size() + (CHUNK_SIZE - 1)) / CHUNK_SIZE);
|
||||
_size = (unsigned int)bits.size();
|
||||
|
||||
for (unsigned int i = 0; i < size; i++)
|
||||
unsigned int bitID = 0;
|
||||
for (auto it = bits.begin(); it != bits.end(); it++, bitID++)
|
||||
{
|
||||
unsigned int bit = unsigned int(1 << i);
|
||||
_bits.push_back((packedBits & bit) == bit);
|
||||
unsigned int localBitID = bitID % CHUNK_SIZE;
|
||||
unsigned int chunkID = bitID / CHUNK_SIZE;
|
||||
|
||||
bool bit = *it;
|
||||
if (bit)
|
||||
_chunks[chunkID] |= (ChunkType)1 << localBitID;
|
||||
}
|
||||
}
|
||||
|
||||
BitField::BitField(const std::vector<ChunkType>& bitChunks, unsigned int size)
|
||||
{
|
||||
_chunks = bitChunks;
|
||||
_size = std::min(size, (unsigned int)bitChunks.size() * CHUNK_SIZE);
|
||||
}
|
||||
|
||||
BitField::BitField(const std::string& bitString)
|
||||
{
|
||||
_bits.reserve(bitString.size());
|
||||
_chunks.resize((bitString.size() + (CHUNK_SIZE - 1)) / CHUNK_SIZE);
|
||||
_size = (unsigned int)bitString.size();
|
||||
|
||||
for (const char& bit : bitString)
|
||||
_bits.push_back(bit == '1');
|
||||
unsigned int bitID = 0;
|
||||
for (char bit : bitString)
|
||||
{
|
||||
unsigned int i = bitID % CHUNK_SIZE;
|
||||
unsigned int chunkID = bitID / CHUNK_SIZE;
|
||||
|
||||
if (bit == '1')
|
||||
_chunks[chunkID] |= (ChunkType)1 << i;
|
||||
|
||||
bitID++;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int BitField::GetSize() const
|
||||
{
|
||||
return (unsigned int)_bits.size();
|
||||
return _size;
|
||||
}
|
||||
|
||||
unsigned int BitField::GetCount() const
|
||||
{
|
||||
unsigned int count = 0;
|
||||
for (const bool& bit : _bits)
|
||||
for (auto chunk : _chunks)
|
||||
{
|
||||
if (bit)
|
||||
count++;
|
||||
for (unsigned int localBitID = 0; localBitID < CHUNK_SIZE; localBitID++)
|
||||
{
|
||||
bool bit = bool(chunk & ((ChunkType)1 << localBitID));
|
||||
if (bit)
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void BitField::Set(const std::vector<unsigned int>& indices)
|
||||
const std::vector<BitField::ChunkType>& BitField::GetChunks() const
|
||||
{
|
||||
for (const unsigned int& index : indices)
|
||||
{
|
||||
if (!IsIndexCorrect(index))
|
||||
continue;
|
||||
|
||||
_bits[index] = true;
|
||||
}
|
||||
return _chunks;
|
||||
}
|
||||
|
||||
void BitField::Set(unsigned int index)
|
||||
void BitField::Set(unsigned int bitID)
|
||||
{
|
||||
Set(std::vector<unsigned int>{ index });
|
||||
if constexpr (DEBUG_BUILD)
|
||||
{
|
||||
if (!IsBitIDCorrect(bitID))
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int localBitId = bitID % CHUNK_SIZE;
|
||||
unsigned int chunkID = bitID / CHUNK_SIZE;
|
||||
_chunks[chunkID] |= (ChunkType)1 << localBitId;
|
||||
}
|
||||
|
||||
void BitField::Set(const std::vector<unsigned int>& bitIds)
|
||||
{
|
||||
for (unsigned int bitID : bitIds)
|
||||
Set(bitID);
|
||||
}
|
||||
|
||||
void BitField::SetAll()
|
||||
|
@ -76,85 +109,113 @@ namespace TEN::Utils
|
|||
Fill(true);
|
||||
}
|
||||
|
||||
void BitField::Clear(const std::vector<unsigned int>& indices)
|
||||
void BitField::Clear(unsigned int bitID)
|
||||
{
|
||||
for (const unsigned int& index : indices)
|
||||
if constexpr (DEBUG_BUILD)
|
||||
{
|
||||
if (!IsIndexCorrect(index))
|
||||
continue;
|
||||
|
||||
_bits[index] = false;
|
||||
if (!IsBitIDCorrect(bitID))
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int localBitID = bitID % CHUNK_SIZE;
|
||||
unsigned int chunkID = bitID / CHUNK_SIZE;
|
||||
_chunks[chunkID] &= ~((ChunkType)1 << localBitID);
|
||||
}
|
||||
|
||||
void BitField::Clear(unsigned int index)
|
||||
|
||||
void BitField::Clear(const std::vector<unsigned int>& bitIds)
|
||||
{
|
||||
Clear(std::vector<unsigned int>{ index });
|
||||
for (unsigned int bitID : bitIds)
|
||||
Clear(bitID);
|
||||
}
|
||||
|
||||
void BitField::ClearAll()
|
||||
{
|
||||
Fill(false);
|
||||
}
|
||||
|
||||
void BitField::Flip(const std::vector<unsigned int>& indices)
|
||||
{
|
||||
for (const unsigned int& index : indices)
|
||||
{
|
||||
if (!IsIndexCorrect(index))
|
||||
continue;
|
||||
|
||||
_bits[index].flip();
|
||||
}
|
||||
}
|
||||
|
||||
void BitField::Flip(unsigned int index)
|
||||
void BitField::Flip(unsigned int bitID)
|
||||
{
|
||||
Flip(std::vector<unsigned int>{ index });
|
||||
if constexpr (DEBUG_BUILD)
|
||||
{
|
||||
if (!IsBitIDCorrect(bitID))
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int localBitID = bitID % CHUNK_SIZE;
|
||||
unsigned int chunkID = bitID / CHUNK_SIZE;
|
||||
_chunks[chunkID] ^= (ChunkType)1 << localBitID;
|
||||
}
|
||||
|
||||
void BitField::Flip(const std::vector<unsigned int>& bitIds)
|
||||
{
|
||||
for (unsigned int bitID : bitIds)
|
||||
Flip(bitID);
|
||||
}
|
||||
|
||||
void BitField::FlipAll()
|
||||
{
|
||||
_bits.flip();
|
||||
for (unsigned int chunkID = 0; chunkID < _chunks.size(); chunkID++)
|
||||
_chunks[chunkID] = ~_chunks[chunkID];
|
||||
|
||||
unsigned int endBitCount = _size % CHUNK_SIZE;
|
||||
if (endBitCount > 0)
|
||||
{
|
||||
for (unsigned int localBitID = endBitCount; localBitID < CHUNK_SIZE; localBitID++)
|
||||
_chunks.back() &= ~((ChunkType)1 << localBitID);
|
||||
}
|
||||
}
|
||||
|
||||
bool BitField::Test(const std::vector<unsigned int>& indices, bool testAny) const
|
||||
bool BitField::IsEmpty() const
|
||||
{
|
||||
for (const unsigned int& index : indices)
|
||||
{
|
||||
if (!IsIndexCorrect(index))
|
||||
continue;
|
||||
if (_chunks.empty())
|
||||
return true;
|
||||
|
||||
// Test if any bits at input indices are set.
|
||||
for (auto chunk : _chunks)
|
||||
{
|
||||
if (chunk != (ChunkType)0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BitField::Test(unsigned int bitID) const
|
||||
{
|
||||
if constexpr (DEBUG_BUILD)
|
||||
{
|
||||
if (!IsBitIDCorrect(bitID))
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int localBitID = bitID % CHUNK_SIZE;
|
||||
unsigned int chunkID = bitID / CHUNK_SIZE;
|
||||
return bool(_chunks[chunkID] & ((ChunkType)1 << localBitID));
|
||||
}
|
||||
|
||||
bool BitField::Test(const std::vector<unsigned int>& bitIds, bool testAny) const
|
||||
{
|
||||
for (unsigned int bitID : bitIds)
|
||||
{
|
||||
if (testAny)
|
||||
{
|
||||
if (_bits[index])
|
||||
if (Test(bitID))
|
||||
return true;
|
||||
}
|
||||
// Test if any bits at input indices are set.
|
||||
else
|
||||
else // Test all.
|
||||
{
|
||||
if (!_bits[index])
|
||||
if (!Test(bitID))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return (testAny ? false : true);
|
||||
}
|
||||
|
||||
bool BitField::Test(unsigned int index) const
|
||||
{
|
||||
if (!IsIndexCorrect(index))
|
||||
return false;
|
||||
|
||||
return _bits[index];
|
||||
return !testAny;
|
||||
}
|
||||
|
||||
bool BitField::TestAny() const
|
||||
{
|
||||
for (const bool& bit : _bits)
|
||||
for (auto chunk : _chunks)
|
||||
{
|
||||
if (bit)
|
||||
if (chunk != 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -163,50 +224,174 @@ namespace TEN::Utils
|
|||
|
||||
bool BitField::TestAll() const
|
||||
{
|
||||
for (const bool& bit : _bits)
|
||||
for (unsigned int chunkID = 0; chunkID < (_chunks.size() - 1); chunkID++)
|
||||
{
|
||||
if (!bit)
|
||||
if (_chunks[chunkID] != (ChunkType)~0)
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int endBitCount = _size % CHUNK_SIZE;
|
||||
if (endBitCount > 0)
|
||||
{
|
||||
auto validMask = ((ChunkType)1 << endBitCount) - 1;
|
||||
if ((_chunks.back() & validMask) != validMask)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int BitField::ToPackedBits() const
|
||||
void BitField::Resize(unsigned int size)
|
||||
{
|
||||
unsigned int packedBits = 0;
|
||||
for (unsigned int i = 0; i < _bits.size(); i++)
|
||||
{
|
||||
if (_bits[i])
|
||||
{
|
||||
unsigned int bit = unsigned int(1 << i);
|
||||
packedBits |= bit;
|
||||
}
|
||||
}
|
||||
_chunks.resize((size + (CHUNK_SIZE - 1)) / CHUNK_SIZE);
|
||||
_size = size;
|
||||
|
||||
return packedBits;
|
||||
unsigned int endBitCount = size % CHUNK_SIZE;
|
||||
if (endBitCount > 0)
|
||||
{
|
||||
for (unsigned int localBitID = endBitCount; localBitID < CHUNK_SIZE; localBitID++)
|
||||
_chunks.back() &= ~((ChunkType)1 << localBitID);
|
||||
}
|
||||
}
|
||||
|
||||
std::string BitField::ToString() const
|
||||
{
|
||||
auto bitString = std::string();
|
||||
for (const bool& bit : _bits)
|
||||
bitString += bit ? '1' : '0';
|
||||
bitString.reserve(_size);
|
||||
|
||||
for (unsigned int chunkID = 0; chunkID < _chunks.size(); chunkID++)
|
||||
{
|
||||
for (unsigned int localBitID = 0; localBitID < CHUNK_SIZE; localBitID++)
|
||||
{
|
||||
if (((chunkID * CHUNK_SIZE) + localBitID) >= _size)
|
||||
break;
|
||||
|
||||
bool bit = _chunks[chunkID] & ((ChunkType)1 << localBitID);
|
||||
bitString += bit ? '1' : '0';
|
||||
}
|
||||
}
|
||||
|
||||
return bitString;
|
||||
}
|
||||
|
||||
bool BitField::operator ==(unsigned int packedBits) const
|
||||
BitField::ChunkType BitField::ToPackedBits() const
|
||||
{
|
||||
for (unsigned int i = 0; i < _bits.size(); i++)
|
||||
if (_chunks.empty())
|
||||
return 0;
|
||||
|
||||
return _chunks.front();
|
||||
}
|
||||
|
||||
bool BitField::operator ==(const BitField& bitField) const
|
||||
{
|
||||
if (_size != bitField.GetSize())
|
||||
return false;
|
||||
|
||||
for (unsigned int chunkID = 0; chunkID < _chunks.size(); chunkID++)
|
||||
{
|
||||
unsigned int bit = unsigned int(1 << i);
|
||||
if (_bits[i] != ((packedBits & bit) == bit))
|
||||
if (_chunks[chunkID] != bitField.GetChunks()[chunkID])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BitField::operator !=(const BitField& bitField) const
|
||||
{
|
||||
return !(*this == bitField);
|
||||
}
|
||||
|
||||
BitField& BitField::operator &=(const BitField& bitField)
|
||||
{
|
||||
for (unsigned int chunkID = 0; chunkID < std::min(_chunks.size(), bitField.GetChunks().size()); chunkID++)
|
||||
_chunks[chunkID] &= bitField.GetChunks()[chunkID];
|
||||
|
||||
_chunks.resize(std::min((unsigned int)_chunks.size(), bitField.GetSize()));
|
||||
_size = std::min(_size, bitField.GetSize());
|
||||
return *this;
|
||||
}
|
||||
|
||||
BitField& BitField::operator |=(const BitField& bitField)
|
||||
{
|
||||
_chunks.resize(std::max(_chunks.size(), bitField.GetChunks().size()));
|
||||
_size = std::max(_size, bitField.GetSize());
|
||||
|
||||
for (unsigned int chunkID = 0; chunkID < bitField.GetChunks().size(); chunkID++)
|
||||
_chunks[chunkID] |= bitField.GetChunks()[chunkID];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BitField& BitField::operator ^=(const BitField& bitField)
|
||||
{
|
||||
_chunks.resize(std::max(_chunks.size(), bitField.GetChunks().size()));
|
||||
_size = std::max(_size, bitField.GetSize());
|
||||
|
||||
for (unsigned int chunkID = 0; chunkID < std::min(_chunks.size(), bitField.GetChunks().size()); chunkID++)
|
||||
_chunks[chunkID] ^= bitField.GetChunks()[chunkID];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BitField BitField::operator &(const BitField& bitField) const
|
||||
{
|
||||
auto chunks = std::vector<ChunkType>(std::min(_chunks.size(), bitField.GetChunks().size()));
|
||||
for (unsigned int chunkID = 0; chunkID < chunks.size(); chunkID++)
|
||||
chunks[chunkID] = _chunks[chunkID] & bitField.GetChunks()[chunkID];
|
||||
|
||||
return BitField(chunks, std::min(_size, bitField.GetSize()));
|
||||
}
|
||||
|
||||
BitField BitField::operator |(const BitField& bitField) const
|
||||
{
|
||||
auto chunks = std::vector<ChunkType>(std::max(_chunks.size(), bitField.GetChunks().size()));
|
||||
|
||||
for (unsigned int chunkID = 0; chunkID < _chunks.size(); chunkID++)
|
||||
chunks[chunkID] |= _chunks[chunkID];
|
||||
|
||||
for (unsigned int chunkID = 0; chunkID < bitField.GetChunks().size(); chunkID++)
|
||||
chunks[chunkID] |= bitField.GetChunks()[chunkID];
|
||||
|
||||
return BitField(chunks, std::max(_size, bitField.GetSize()));
|
||||
}
|
||||
|
||||
BitField BitField::operator ^(const BitField& bitField) const
|
||||
{
|
||||
auto chunks = std::vector<ChunkType>(std::max(_chunks.size(), bitField.GetChunks().size()));
|
||||
|
||||
for (unsigned int chunkID = 0; chunkID < chunks.size(); chunkID++)
|
||||
{
|
||||
if (chunkID < _chunks.size() && chunkID < bitField.GetChunks().size())
|
||||
{
|
||||
chunks[chunkID] = _chunks[chunkID] ^ bitField.GetChunks()[chunkID];
|
||||
}
|
||||
else if (chunkID < _chunks.size())
|
||||
{
|
||||
chunks[chunkID] = _chunks[chunkID];
|
||||
}
|
||||
else if (chunkID < bitField.GetChunks().size())
|
||||
{
|
||||
chunks[chunkID] = bitField.GetChunks()[chunkID];
|
||||
}
|
||||
}
|
||||
|
||||
return BitField(chunks, std::max(_size, bitField.GetSize()));
|
||||
}
|
||||
|
||||
BitField BitField::operator ~() const
|
||||
{
|
||||
auto newBitField = *this;
|
||||
newBitField.FlipAll();
|
||||
return newBitField;
|
||||
}
|
||||
|
||||
bool BitField::operator ==(unsigned int packedBits) const
|
||||
{
|
||||
if (_chunks.empty())
|
||||
return (packedBits == 0);
|
||||
|
||||
return (_chunks.front() == packedBits);
|
||||
}
|
||||
|
||||
bool BitField::operator !=(unsigned int packedBits) const
|
||||
{
|
||||
|
@ -215,59 +400,60 @@ namespace TEN::Utils
|
|||
|
||||
BitField& BitField::operator =(unsigned int packedBits)
|
||||
{
|
||||
for (unsigned int i = 0; i < _bits.size(); i++)
|
||||
{
|
||||
unsigned int bit = unsigned int(1 << i);
|
||||
_bits[i] = ((packedBits & bit) == bit);
|
||||
}
|
||||
_chunks.resize(1);
|
||||
_chunks.front() = packedBits;
|
||||
_size = DEFAULT_SIZE;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BitField& BitField::operator &=(unsigned int packedBits)
|
||||
{
|
||||
for (unsigned int i = 0; i < _bits.size(); i++)
|
||||
{
|
||||
unsigned int bit = unsigned int(1 << i);
|
||||
_bits[i] = (_bits[i] && (packedBits & bit) == bit);
|
||||
}
|
||||
_chunks.resize(1);
|
||||
_chunks.front() &= packedBits;
|
||||
_size = DEFAULT_SIZE;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BitField& BitField::operator |=(unsigned int packedBits)
|
||||
{
|
||||
for (unsigned int i = 0; i < _bits.size(); i++)
|
||||
{
|
||||
if (_bits[i])
|
||||
continue;
|
||||
|
||||
unsigned int bit = unsigned int(1 << i);
|
||||
if ((packedBits & bit) == bit)
|
||||
_bits[i] = true;
|
||||
}
|
||||
_chunks.resize(1);
|
||||
_chunks.front() |= packedBits;
|
||||
_size = DEFAULT_SIZE;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
unsigned int BitField::operator &(unsigned int packedBits) const
|
||||
{
|
||||
return (ToPackedBits() & packedBits);
|
||||
if (_chunks.empty())
|
||||
return 0;
|
||||
|
||||
return (_chunks.front() & packedBits);
|
||||
}
|
||||
|
||||
unsigned int BitField::operator |(unsigned int packedBits) const
|
||||
{
|
||||
return (ToPackedBits() | packedBits);
|
||||
if (_chunks.empty())
|
||||
return packedBits;
|
||||
|
||||
return (_chunks.front() | packedBits);
|
||||
}
|
||||
|
||||
void BitField::Fill(bool value)
|
||||
{
|
||||
std::fill(_bits.begin(), _bits.end(), value);
|
||||
auto fillChunk = value ? ~(ChunkType)0 : (ChunkType)0;
|
||||
std::fill(_chunks.begin(), _chunks.end(), fillChunk);
|
||||
|
||||
unsigned int endBitCount = _size % CHUNK_SIZE;
|
||||
if (endBitCount > 0 && value)
|
||||
_chunks.back() &= ((ChunkType)1 << endBitCount) - 1;
|
||||
}
|
||||
|
||||
bool BitField::IsIndexCorrect(unsigned int index) const
|
||||
bool BitField::IsBitIDCorrect(unsigned int bitID) const
|
||||
{
|
||||
if (index >= _bits.size())
|
||||
if (bitID >= _size)
|
||||
{
|
||||
TENLog(std::string("BitField attempted to access bit at invalid index."), LogLevel::Warning);
|
||||
return false;
|
||||
|
|
|
@ -2,18 +2,22 @@
|
|||
|
||||
namespace TEN::Utils
|
||||
{
|
||||
// TODO: When all conversions are complete, remove the size cap and use unsigned long long for packedBits input.
|
||||
|
||||
class BitField
|
||||
{
|
||||
private:
|
||||
// Aliases
|
||||
|
||||
using ChunkType = unsigned int;
|
||||
|
||||
// Constants
|
||||
|
||||
static constexpr auto SIZE_DEFAULT = 32;
|
||||
static constexpr auto DEFAULT_SIZE = 32;
|
||||
static constexpr auto CHUNK_SIZE = std::numeric_limits<ChunkType>::digits;
|
||||
|
||||
// Fields
|
||||
|
||||
std::vector<bool> _bits = {};
|
||||
unsigned int _size = 0;
|
||||
std::vector<ChunkType> _chunks = {};
|
||||
|
||||
public:
|
||||
// Presets
|
||||
|
@ -25,40 +29,60 @@ namespace TEN::Utils
|
|||
|
||||
BitField();
|
||||
BitField(unsigned int size);
|
||||
BitField(unsigned int size, unsigned int packedBits);
|
||||
BitField(const std::initializer_list<bool>& bits);
|
||||
BitField(const std::vector<ChunkType>& bitChunks, unsigned int size);
|
||||
BitField(const std::string& bitString);
|
||||
|
||||
// Getters
|
||||
|
||||
unsigned int GetSize() const;
|
||||
unsigned int GetCount() const;
|
||||
unsigned int GetSize() const;
|
||||
unsigned int GetCount() const;
|
||||
const std::vector<ChunkType>& GetChunks() const;
|
||||
|
||||
// Setters
|
||||
|
||||
void Set(const std::vector<unsigned int>& indices);
|
||||
void Set(unsigned int index);
|
||||
void Set(unsigned int bitID);
|
||||
void Set(const std::vector<unsigned int>& bitIds);
|
||||
void SetAll();
|
||||
void Clear(const std::vector<unsigned int>& indices);
|
||||
void Clear(unsigned int index);
|
||||
void Clear(unsigned int bitID);
|
||||
void Clear(const std::vector<unsigned int>& bitIds);
|
||||
void ClearAll();
|
||||
void Flip(const std::vector<unsigned int>& indices);
|
||||
void Flip(unsigned int index);
|
||||
void Flip(unsigned int bitID);
|
||||
void Flip(const std::vector<unsigned int>& bitIds);
|
||||
void FlipAll();
|
||||
|
||||
// Inquirers
|
||||
|
||||
bool Test(const std::vector<unsigned int>& indices, bool testAny = true) const;
|
||||
bool Test(unsigned int index) const;
|
||||
bool IsEmpty() const;
|
||||
|
||||
bool Test(const std::vector<unsigned int>& bitIds, bool testAny = true) const;
|
||||
bool Test(unsigned int bitID) const;
|
||||
bool TestAny() const;
|
||||
bool TestAll() const;
|
||||
|
||||
// Utilities
|
||||
|
||||
void Resize(unsigned int size);
|
||||
|
||||
// Converters
|
||||
|
||||
unsigned int ToPackedBits() const;
|
||||
std::string ToString() const;
|
||||
std::string ToString() const;
|
||||
ChunkType ToPackedBits() const; // For compatibility.
|
||||
|
||||
// Operators
|
||||
// NOTE: packedBits will not be assessed in full if the size of the given BitField object is less than SIZE_DEFAULT.
|
||||
|
||||
bool operator ==(const BitField& bitField) const;
|
||||
bool operator !=(const BitField& bitField) const;
|
||||
BitField& operator =(const BitField& bitField) = default;
|
||||
BitField& operator &=(const BitField& bitField);
|
||||
BitField& operator |=(const BitField& bitField);
|
||||
BitField& operator ^=(const BitField& bitField);
|
||||
BitField operator &(const BitField& bitField) const;
|
||||
BitField operator |(const BitField& bitField) const;
|
||||
BitField operator ^(const BitField& bitField) const;
|
||||
BitField operator ~() const;
|
||||
|
||||
// Compatibility operators
|
||||
|
||||
bool operator ==(unsigned int packedBits) const;
|
||||
bool operator !=(unsigned int packedBits) const;
|
||||
|
@ -72,6 +96,6 @@ namespace TEN::Utils
|
|||
// Helpers
|
||||
|
||||
void Fill(bool value);
|
||||
bool IsIndexCorrect(unsigned int index) const;
|
||||
bool IsBitIDCorrect(unsigned int bitID) const;
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue