This repository has been archived on 2024-06-13. You can view files and clone it, but cannot push or open issues or pull requests.
2020-08-04 13:13:01 -04:00

1330 lines
40 KiB
C++

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//===========================================================================//
#ifndef BITVEC_H
#define BITVEC_H
#ifdef _WIN32
#pragma once
#endif
#include <limits.h>
#include "tier0/basetypes.h"
#include "tier0/dbg.h"
class CBitVecAccessor {
public:
CBitVecAccessor(uint32 *pDWords, int iBit);
void operator=(int val);
operator uint32();
private:
uint32 *m_pDWords;
int m_iBit;
};
//-----------------------------------------------------------------------------
// Support functions
//-----------------------------------------------------------------------------
#define LOG2_BITS_PER_INT 5
#define BITS_PER_INT 32
#if _WIN32 && !defined(_X360)
#include <intrin.h>
#pragma intrinsic(_BitScanForward)
#endif
inline int FirstBitInWord(unsigned int elem, int offset) {
#if _WIN32
if (!elem) return -1;
#if defined(_X360)
// this implements CountTrailingZeros() / BitScanForward()
unsigned int mask = elem - 1;
unsigned int comp = ~elem;
elem = mask & comp;
return (32 - _CountLeadingZeros(elem)) + offset;
#else
unsigned long out;
_BitScanForward(&out, elem);
return out + offset;
#endif
#else
static unsigned firstBitLUT[256] = {
0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0,
3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0,
3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0,
3, 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0,
3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0,
3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};
unsigned elemByte;
elemByte = (elem & 0xFF);
if (elemByte) return offset + firstBitLUT[elemByte];
elem >>= 8;
offset += 8;
elemByte = (elem & 0xFF);
if (elemByte) return offset + firstBitLUT[elemByte];
elem >>= 8;
offset += 8;
elemByte = (elem & 0xFF);
if (elemByte) return offset + firstBitLUT[elemByte];
elem >>= 8;
offset += 8;
elemByte = (elem & 0xFF);
if (elemByte) return offset + firstBitLUT[elemByte];
return -1;
#endif
}
//-------------------------------------
inline unsigned GetEndMask(int numBits) {
static unsigned bitStringEndMasks[] = {
0xffffffff, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, 0x0000001f,
0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff, 0x0001ffff,
0x0003ffff, 0x0007ffff, 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff, 0x1fffffff,
0x3fffffff, 0x7fffffff,
};
return bitStringEndMasks[numBits % BITS_PER_INT];
}
inline int GetBitForBitnum(int bitNum) {
static int bitsForBitnum[] = {
(1 << 0), (1 << 1), (1 << 2), (1 << 3), (1 << 4), (1 << 5),
(1 << 6), (1 << 7), (1 << 8), (1 << 9), (1 << 10), (1 << 11),
(1 << 12), (1 << 13), (1 << 14), (1 << 15), (1 << 16), (1 << 17),
(1 << 18), (1 << 19), (1 << 20), (1 << 21), (1 << 22), (1 << 23),
(1 << 24), (1 << 25), (1 << 26), (1 << 27), (1 << 28), (1 << 29),
(1 << 30), (1 << 31),
};
return bitsForBitnum[(bitNum) & (BITS_PER_INT - 1)];
}
inline int GetBitForBitnumByte(int bitNum) {
static int bitsForBitnum[] = {
(1 << 0), (1 << 1), (1 << 2), (1 << 3),
(1 << 4), (1 << 5), (1 << 6), (1 << 7),
};
return bitsForBitnum[bitNum & 7];
}
inline int CalcNumIntsForBits(int numBits) {
return (numBits + (BITS_PER_INT - 1)) / BITS_PER_INT;
}
#ifdef _X360
#define BitVec_Bit(bitNum) GetBitForBitnum(bitNum)
#define BitVec_BitInByte(bitNum) GetBitForBitnumByte(bitNum)
#else
#define BitVec_Bit(bitNum) (1 << ((bitNum) & (BITS_PER_INT - 1)))
#define BitVec_BitInByte(bitNum) (1 << ((bitNum)&7))
#endif
#define BitVec_Int(bitNum) ((bitNum) >> LOG2_BITS_PER_INT)
//-----------------------------------------------------------------------------
// template CBitVecT
//
// Defines the operations relevant to any bit array. Simply requires a base
// class that implements GetNumBits(), Base(), GetNumDWords() &
// ValidateOperand()
//
// CVarBitVec and CBitVec<int> are the actual classes generally used
// by clients
//
template <class BASE_OPS>
class CBitVecT : public BASE_OPS {
public:
CBitVecT();
CBitVecT(int numBits); // Must be initialized with the number of bits
void Init(int val = 0);
// Access the bits like an array.
CBitVecAccessor operator[](int i);
// Do NOT override bitwise operators (see note in header)
void And(const CBitVecT &andStr, CBitVecT *out) const;
void Or(const CBitVecT &orStr, CBitVecT *out) const;
void Xor(const CBitVecT &orStr, CBitVecT *out) const;
void Not(CBitVecT *out) const;
void CopyTo(CBitVecT *out) const;
void Copy(const CBitVecT<BASE_OPS> &other, int nBits = -1);
bool Compare(const CBitVecT<BASE_OPS> &other, int nBits = -1) const;
bool IsAllClear(void) const; // Are all bits zero?
bool IsAllSet(void) const; // Are all bits one?
uint32 Get(uint32 bitNum) const;
bool IsBitSet(int bitNum) const;
void Set(int bitNum);
void Set(int bitNum, bool bNewVal);
void Clear(int bitNum);
bool TestAndSet(int bitNum);
void Set(uint32 offset, uint32 mask);
void Clear(uint32 offset, uint32 mask);
uint32 Get(uint32 offset, uint32 mask);
void SetAll(void); // Sets all bits
void ClearAll(void); // Clears all bits
uint32 GetDWord(int i) const;
void SetDWord(int i, uint32 val);
CBitVecT<BASE_OPS> &operator=(const CBitVecT<BASE_OPS> &other) {
other.CopyTo(this);
return *this;
}
bool operator==(const CBitVecT<BASE_OPS> &other) { return Compare(other); }
bool operator!=(const CBitVecT<BASE_OPS> &other) {
return !operator==(other);
}
static void GetOffsetMaskForBit(uint32 bitNum, uint32 *pOffset,
uint32 *pMask) {
*pOffset = BitVec_Int(bitNum);
*pMask = BitVec_Bit(bitNum);
}
};
//-----------------------------------------------------------------------------
// class CVarBitVecBase
//
// Defines the operations necessary for a variable sized bit array
template <typename BITCOUNTTYPE>
class CVarBitVecBase {
public:
bool IsFixedSize() const { return false; }
int GetNumBits(void) const { return m_numBits; }
void Resize(int numBits, bool bClearAll = false); // resizes bit array
int GetNumDWords() const { return m_numInts; }
uint32 *Base() { return m_pInt; }
const uint32 *Base() const { return m_pInt; }
void Attach(uint32 *pBits, int numBits);
bool Detach(uint32 **ppBits, int *pNumBits);
int FindNextSetBit(
int iStartBit) const; // returns -1 if no set bit was found
protected:
CVarBitVecBase();
CVarBitVecBase(int numBits);
CVarBitVecBase(const CVarBitVecBase<BITCOUNTTYPE> &from);
CVarBitVecBase &operator=(const CVarBitVecBase<BITCOUNTTYPE> &from);
~CVarBitVecBase(void);
void ValidateOperand(const CVarBitVecBase<BITCOUNTTYPE> &operand) const {
Assert(GetNumBits() == operand.GetNumBits());
}
unsigned GetEndMask() const { return ::GetEndMask(GetNumBits()); }
private:
BITCOUNTTYPE m_numBits; // Number of bits in the bitstring
BITCOUNTTYPE m_numInts; // Number of ints to needed to store bitstring
uint32
m_iBitStringStorage; // If the bit string fits in one int, it goes here
uint32 *m_pInt; // Array of ints containing the bitstring
void AllocInts(int numInts); // Free the allocated bits
void ReallocInts(int numInts);
void FreeInts(void); // Free the allocated bits
};
//-----------------------------------------------------------------------------
// class CFixedBitVecBase
//
// Defines the operations necessary for a fixed sized bit array.
//
template <int bits>
struct BitCountToEndMask_t {};
template <>
struct BitCountToEndMask_t<0> {
enum { MASK = 0xffffffff };
};
template <>
struct BitCountToEndMask_t<1> {
enum { MASK = 0x00000001 };
};
template <>
struct BitCountToEndMask_t<2> {
enum { MASK = 0x00000003 };
};
template <>
struct BitCountToEndMask_t<3> {
enum { MASK = 0x00000007 };
};
template <>
struct BitCountToEndMask_t<4> {
enum { MASK = 0x0000000f };
};
template <>
struct BitCountToEndMask_t<5> {
enum { MASK = 0x0000001f };
};
template <>
struct BitCountToEndMask_t<6> {
enum { MASK = 0x0000003f };
};
template <>
struct BitCountToEndMask_t<7> {
enum { MASK = 0x0000007f };
};
template <>
struct BitCountToEndMask_t<8> {
enum { MASK = 0x000000ff };
};
template <>
struct BitCountToEndMask_t<9> {
enum { MASK = 0x000001ff };
};
template <>
struct BitCountToEndMask_t<10> {
enum { MASK = 0x000003ff };
};
template <>
struct BitCountToEndMask_t<11> {
enum { MASK = 0x000007ff };
};
template <>
struct BitCountToEndMask_t<12> {
enum { MASK = 0x00000fff };
};
template <>
struct BitCountToEndMask_t<13> {
enum { MASK = 0x00001fff };
};
template <>
struct BitCountToEndMask_t<14> {
enum { MASK = 0x00003fff };
};
template <>
struct BitCountToEndMask_t<15> {
enum { MASK = 0x00007fff };
};
template <>
struct BitCountToEndMask_t<16> {
enum { MASK = 0x0000ffff };
};
template <>
struct BitCountToEndMask_t<17> {
enum { MASK = 0x0001ffff };
};
template <>
struct BitCountToEndMask_t<18> {
enum { MASK = 0x0003ffff };
};
template <>
struct BitCountToEndMask_t<19> {
enum { MASK = 0x0007ffff };
};
template <>
struct BitCountToEndMask_t<20> {
enum { MASK = 0x000fffff };
};
template <>
struct BitCountToEndMask_t<21> {
enum { MASK = 0x001fffff };
};
template <>
struct BitCountToEndMask_t<22> {
enum { MASK = 0x003fffff };
};
template <>
struct BitCountToEndMask_t<23> {
enum { MASK = 0x007fffff };
};
template <>
struct BitCountToEndMask_t<24> {
enum { MASK = 0x00ffffff };
};
template <>
struct BitCountToEndMask_t<25> {
enum { MASK = 0x01ffffff };
};
template <>
struct BitCountToEndMask_t<26> {
enum { MASK = 0x03ffffff };
};
template <>
struct BitCountToEndMask_t<27> {
enum { MASK = 0x07ffffff };
};
template <>
struct BitCountToEndMask_t<28> {
enum { MASK = 0x0fffffff };
};
template <>
struct BitCountToEndMask_t<29> {
enum { MASK = 0x1fffffff };
};
template <>
struct BitCountToEndMask_t<30> {
enum { MASK = 0x3fffffff };
};
template <>
struct BitCountToEndMask_t<31> {
enum { MASK = 0x7fffffff };
};
//-------------------------------------
template <int NUM_BITS>
class CFixedBitVecBase {
public:
bool IsFixedSize() const { return true; }
int GetNumBits(void) const { return NUM_BITS; }
void Resize(int numBits, bool bClearAll = false) {
Assert(numBits == NUM_BITS);
if (bClearAll) Plat_FastMemset(m_Ints, 0, NUM_INTS * sizeof(uint32));
} // for syntatic consistency (for when using templates)
int GetNumDWords() const { return NUM_INTS; }
uint32 *Base() { return m_Ints; }
const uint32 *Base() const { return m_Ints; }
int FindNextSetBit(
int iStartBit) const; // returns -1 if no set bit was found
protected:
CFixedBitVecBase() {}
CFixedBitVecBase(int numBits) {
Assert(numBits == NUM_BITS);
} // doesn't make sense, really. Supported to simplify templates & allow
// easy replacement of variable
void ValidateOperand(const CFixedBitVecBase<NUM_BITS> &operand) const {
} // no need, compiler does so statically
public: // for test code
unsigned GetEndMask() const {
return static_cast<unsigned>(
BitCountToEndMask_t<NUM_BITS % BITS_PER_INT>::MASK);
}
private:
enum { NUM_INTS = (NUM_BITS + (BITS_PER_INT - 1)) / BITS_PER_INT };
uint32 m_Ints[(NUM_BITS + (BITS_PER_INT - 1)) / BITS_PER_INT];
};
//-----------------------------------------------------------------------------
//
// The actual classes used
//
// inheritance instead of typedef to allow forward declarations
class CVarBitVec : public CBitVecT<CVarBitVecBase<unsigned short> > {
public:
CVarBitVec() {}
CVarBitVec(int numBits)
: CBitVecT<CVarBitVecBase<unsigned short> >(numBits) {}
};
class CLargeVarBitVec : public CBitVecT<CVarBitVecBase<int> > {
public:
CLargeVarBitVec() {}
CLargeVarBitVec(int numBits) : CBitVecT<CVarBitVecBase<int> >(numBits) {}
};
//-----------------------------------------------------------------------------
template <int NUM_BITS>
class CBitVec : public CBitVecT<CFixedBitVecBase<NUM_BITS> > {
public:
CBitVec() {}
CBitVec(int numBits) : CBitVecT<CFixedBitVecBase<NUM_BITS> >(numBits) {}
};
//-----------------------------------------------------------------------------
typedef CBitVec<32> CDWordBitVec;
//-----------------------------------------------------------------------------
template <typename BITCOUNTTYPE>
inline CVarBitVecBase<BITCOUNTTYPE>::CVarBitVecBase() {
Plat_FastMemset(this, 0, sizeof(*this));
}
//-----------------------------------------------------------------------------
template <typename BITCOUNTTYPE>
inline CVarBitVecBase<BITCOUNTTYPE>::CVarBitVecBase(int numBits) {
Assert(numBits);
m_numBits = numBits;
// Figure out how many ints are needed
m_numInts = CalcNumIntsForBits(numBits);
m_pInt = NULL;
AllocInts(m_numInts);
}
//-----------------------------------------------------------------------------
template <typename BITCOUNTTYPE>
inline CVarBitVecBase<BITCOUNTTYPE>::CVarBitVecBase(
const CVarBitVecBase<BITCOUNTTYPE> &from) {
if (from.m_numInts) {
m_numBits = from.m_numBits;
m_numInts = from.m_numInts;
m_pInt = NULL;
AllocInts(m_numInts);
memcpy(m_pInt, from.m_pInt, m_numInts * sizeof(int));
} else
memset(this, 0, sizeof(*this));
}
//-----------------------------------------------------------------------------
template <typename BITCOUNTTYPE>
inline CVarBitVecBase<BITCOUNTTYPE> &CVarBitVecBase<BITCOUNTTYPE>::operator=(
const CVarBitVecBase<BITCOUNTTYPE> &from) {
Resize(from.GetNumBits());
if (m_pInt) memcpy(m_pInt, from.m_pInt, m_numInts * sizeof(int));
return (*this);
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
// Input :
// Output :
//-----------------------------------------------------------------------------
template <typename BITCOUNTTYPE>
inline CVarBitVecBase<BITCOUNTTYPE>::~CVarBitVecBase(void) {
FreeInts();
}
//-----------------------------------------------------------------------------
template <typename BITCOUNTTYPE>
inline void CVarBitVecBase<BITCOUNTTYPE>::Attach(uint32 *pBits, int numBits) {
FreeInts();
m_numBits = numBits;
m_numInts = CalcNumIntsForBits(numBits);
if (m_numInts > 1) {
m_pInt = pBits;
} else {
m_iBitStringStorage = *pBits;
m_pInt = &m_iBitStringStorage;
free(pBits);
}
}
//-----------------------------------------------------------------------------
template <typename BITCOUNTTYPE>
inline bool CVarBitVecBase<BITCOUNTTYPE>::Detach(uint32 **ppBits,
int *pNumBits) {
if (!m_numBits) {
return false;
}
*pNumBits = m_numBits;
if (m_numInts > 1) {
*ppBits = m_pInt;
} else {
*ppBits = (uint32 *)malloc(sizeof(uint32));
**ppBits = m_iBitStringStorage;
free(m_pInt);
}
memset(this, 0, sizeof(*this));
return true;
}
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline CBitVecT<BASE_OPS>::CBitVecT() {
// undef this is ints are not 4 bytes
// generate a compile error if sizeof(int) is not 4 (HACK: can't use the
// preprocessor so use the compiler)
COMPILE_TIME_ASSERT(sizeof(int) == 4);
// Initialize bitstring by clearing all bits
ClearAll();
}
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline CBitVecT<BASE_OPS>::CBitVecT(int numBits) : BASE_OPS(numBits) {
// undef this is ints are not 4 bytes
// generate a compile error if sizeof(int) is not 4 (HACK: can't use the
// preprocessor so use the compiler)
COMPILE_TIME_ASSERT(sizeof(int) == 4);
// Initialize bitstring by clearing all bits
ClearAll();
}
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline CBitVecAccessor CBitVecT<BASE_OPS>::operator[](int i) {
Assert(i >= 0 && i < this->GetNumBits());
return CBitVecAccessor(this->Base(), i);
}
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline void CBitVecT<BASE_OPS>::Init(int val) {
if (this->Base())
Plat_FastMemset(this->Base(), (val) ? 0xff : 0,
this->GetNumDWords() * sizeof(int));
}
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline uint32 CBitVecT<BASE_OPS>::Get(uint32 bitNum) const {
Assert(bitNum < (uint32)this->GetNumBits());
const uint32 *pInt = this->Base() + BitVec_Int(bitNum);
return (*pInt & BitVec_Bit(bitNum));
}
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline bool CBitVecT<BASE_OPS>::IsBitSet(int bitNum) const {
Assert(bitNum >= 0 && bitNum < this->GetNumBits());
const uint32 *pInt = this->Base() + BitVec_Int(bitNum);
return ((*pInt & BitVec_Bit(bitNum)) != 0);
}
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline void CBitVecT<BASE_OPS>::Set(int bitNum) {
Assert(bitNum >= 0 && bitNum < this->GetNumBits());
uint32 *pInt = this->Base() + BitVec_Int(bitNum);
*pInt |= BitVec_Bit(bitNum);
}
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline bool CBitVecT<BASE_OPS>::TestAndSet(int bitNum) {
Assert(bitNum >= 0 && bitNum < this->GetNumBits());
uint32 bitVecBit = BitVec_Bit(bitNum);
uint32 *pInt = this->Base() + BitVec_Int(bitNum);
bool bResult = ((*pInt & bitVecBit) != 0);
*pInt |= bitVecBit;
return bResult;
}
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline void CBitVecT<BASE_OPS>::Clear(int bitNum) {
Assert(bitNum >= 0 && bitNum < this->GetNumBits());
uint32 *pInt = this->Base() + BitVec_Int(bitNum);
*pInt &= ~BitVec_Bit(bitNum);
}
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline void CBitVecT<BASE_OPS>::Set(int bitNum, bool bNewVal) {
uint32 *pInt = this->Base() + BitVec_Int(bitNum);
uint32 bitMask = BitVec_Bit(bitNum);
if (bNewVal) {
*pInt |= bitMask;
} else {
*pInt &= ~bitMask;
}
}
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline void CBitVecT<BASE_OPS>::Set(uint32 offset, uint32 mask) {
uint32 *pInt = this->Base() + offset;
*pInt |= mask;
}
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline void CBitVecT<BASE_OPS>::Clear(uint32 offset, uint32 mask) {
uint32 *pInt = this->Base() + offset;
*pInt &= ~mask;
}
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline uint32 CBitVecT<BASE_OPS>::Get(uint32 offset, uint32 mask) {
uint32 *pInt = this->Base() + offset;
return (*pInt & mask);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline void CBitVecT<BASE_OPS>::And(const CBitVecT &addStr,
CBitVecT *out) const {
this->ValidateOperand(addStr);
this->ValidateOperand(*out);
uint32 *pDest = out->Base();
const uint32 *pOperand1 = this->Base();
const uint32 *pOperand2 = addStr.Base();
for (int i = this->GetNumDWords() - 1; i >= 0; --i) {
pDest[i] = pOperand1[i] & pOperand2[i];
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline void CBitVecT<BASE_OPS>::Or(const CBitVecT &orStr, CBitVecT *out) const {
this->ValidateOperand(orStr);
this->ValidateOperand(*out);
uint32 *pDest = out->Base();
const uint32 *pOperand1 = this->Base();
const uint32 *pOperand2 = orStr.Base();
for (int i = this->GetNumDWords() - 1; i >= 0; --i) {
pDest[i] = pOperand1[i] | pOperand2[i];
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline void CBitVecT<BASE_OPS>::Xor(const CBitVecT &xorStr,
CBitVecT *out) const {
uint32 *pDest = out->Base();
const uint32 *pOperand1 = this->Base();
const uint32 *pOperand2 = xorStr.Base();
for (int i = this->GetNumDWords() - 1; i >= 0; --i) {
pDest[i] = pOperand1[i] ^ pOperand2[i];
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline void CBitVecT<BASE_OPS>::Not(CBitVecT *out) const {
this->ValidateOperand(*out);
uint32 *pDest = out->Base();
const uint32 *pOperand = this->Base();
for (int i = this->GetNumDWords() - 1; i >= 0; --i) {
pDest[i] = ~(pOperand[i]);
}
}
//-----------------------------------------------------------------------------
// Purpose: Copy a bit string
// Input :
// Output :
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline void CBitVecT<BASE_OPS>::CopyTo(CBitVecT *out) const {
out->Resize(this->GetNumBits());
this->ValidateOperand(*out);
Assert(out != this);
memcpy(out->Base(), this->Base(), this->GetNumDWords() * sizeof(int));
}
//-----------------------------------------------------------------------------
// Purpose: Are all bits zero?
// Input :
// Output :
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline bool CBitVecT<BASE_OPS>::IsAllClear(void) const {
// Number of available bits may be more than the number
// actually used, so make sure to mask out unused bits
// before testing for zero
(const_cast<CBitVecT *>(this))->Base()[this->GetNumDWords() - 1] &=
CBitVecT<BASE_OPS>::GetEndMask(); // external semantics of const
// retained
for (int i = this->GetNumDWords() - 1; i >= 0; --i) {
if (this->Base()[i] != 0) {
return false;
}
}
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Are all bits set?
// Input :
// Output :
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline bool CBitVecT<BASE_OPS>::IsAllSet(void) const {
// Number of available bits may be more than the number
// actually used, so make sure to mask out unused bits
// before testing for set bits
(const_cast<CBitVecT *>(this))->Base()[this->GetNumDWords() - 1] |=
~CBitVecT<BASE_OPS>::GetEndMask(); // external semantics of const
// retained
for (int i = this->GetNumDWords() - 1; i >= 0; --i) {
if (this->Base()[i] != ~0) {
return false;
}
}
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Sets all bits
// Input :
// Output :
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline void CBitVecT<BASE_OPS>::SetAll(void) {
if (this->Base())
Plat_FastMemset(this->Base(), 0xff, this->GetNumDWords() * sizeof(int));
}
//-----------------------------------------------------------------------------
// Purpose: Clears all bits
// Input :
// Output :
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline void CBitVecT<BASE_OPS>::ClearAll(void) {
if (this->Base())
Plat_FastMemset(this->Base(), 0, this->GetNumDWords() * sizeof(int));
}
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline void CBitVecT<BASE_OPS>::Copy(const CBitVecT<BASE_OPS> &other,
int nBits) {
if (nBits == -1) {
nBits = other.GetNumBits();
}
this->Resize(nBits);
this->ValidateOperand(other);
Assert(&other != this);
memcpy(this->Base(), other.Base(), this->GetNumDWords() * sizeof(uint32));
}
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline bool CBitVecT<BASE_OPS>::Compare(const CBitVecT<BASE_OPS> &other,
int nBits) const {
if (nBits == -1) {
if (other.GetNumBits() != this->GetNumBits()) {
return false;
}
nBits = other.GetNumBits();
}
if (nBits > other.GetNumBits() || nBits > this->GetNumBits()) {
return false;
}
(const_cast<CBitVecT *>(this))->Base()[this->GetNumDWords() - 1] &=
CBitVecT<BASE_OPS>::GetEndMask(); // external semantics of const
// retained
(const_cast<CBitVecT *>(&other))->Base()[this->GetNumDWords() - 1] &=
other.CBitVecT<BASE_OPS>::GetEndMask(); // external semantics of const
// retained
int nBytes = PAD_NUMBER(nBits, 8) >> 3;
return (memcmp(this->Base(), other.Base(), nBytes) == 0);
}
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline uint32 CBitVecT<BASE_OPS>::GetDWord(int i) const {
Assert(i >= 0 && i < this->GetNumDWords());
return this->Base()[i];
}
//-----------------------------------------------------------------------------
template <class BASE_OPS>
inline void CBitVecT<BASE_OPS>::SetDWord(int i, uint32 val) {
Assert(i >= 0 && i < this->GetNumDWords());
this->Base()[i] = val;
}
//-----------------------------------------------------------------------------
inline unsigned GetStartBitMask(int startBit) {
static unsigned int g_StartMask[32] = {
0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8, 0xfffffff0, 0xffffffe0,
0xffffffc0, 0xffffff80, 0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800,
0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000, 0xffff0000, 0xfffe0000,
0xfffc0000, 0xfff80000, 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000,
0xff000000, 0xfe000000, 0xfc000000, 0xf8000000, 0xf0000000, 0xe0000000,
0xc0000000, 0x80000000,
};
return g_StartMask[startBit & 31];
}
template <typename BITCOUNTTYPE>
inline int CVarBitVecBase<BITCOUNTTYPE>::FindNextSetBit(int startBit) const {
if (startBit < GetNumBits()) {
int wordIndex = BitVec_Int(startBit);
unsigned int startMask = GetStartBitMask(startBit);
int lastWord = GetNumDWords() - 1;
// handle non dword lengths
if ((GetNumBits() % BITS_PER_INT) != 0) {
unsigned int elem = Base()[wordIndex];
elem &= startMask;
if (wordIndex == lastWord) {
elem &= (GetEndMask());
// there's a bit remaining in this word
if (elem) return FirstBitInWord(elem, wordIndex << 5);
} else {
// there's a bit remaining in this word
if (elem) return FirstBitInWord(elem, wordIndex << 5);
// iterate the words
for (int i = wordIndex + 1; i < lastWord; i++) {
elem = Base()[i];
if (elem) return FirstBitInWord(elem, i << 5);
}
elem = Base()[lastWord] & GetEndMask();
if (elem) return FirstBitInWord(elem, lastWord << 5);
}
} else {
const uint32 *RESTRICT pCurElem = Base() + wordIndex;
unsigned int elem = *pCurElem;
elem &= startMask;
do {
if (elem) return FirstBitInWord(elem, wordIndex << 5);
++pCurElem;
elem = *pCurElem;
++wordIndex;
} while (wordIndex <= lastWord);
}
}
return -1;
}
template <int NUM_BITS>
inline int CFixedBitVecBase<NUM_BITS>::FindNextSetBit(int startBit) const {
if (startBit < NUM_BITS) {
int wordIndex = BitVec_Int(startBit);
unsigned int startMask = GetStartBitMask(startBit);
// handle non dword lengths
if ((NUM_BITS % BITS_PER_INT) != 0) {
unsigned int elem = Base()[wordIndex];
elem &= startMask;
if (wordIndex == NUM_INTS - 1) {
elem &= (GetEndMask());
// there's a bit remaining in this word
if (elem) return FirstBitInWord(elem, wordIndex << 5);
} else {
// there's a bit remaining in this word
if (elem) return FirstBitInWord(elem, wordIndex << 5);
// iterate the words
for (int i = wordIndex + 1; i < NUM_INTS - 1; i++) {
elem = Base()[i];
if (elem) return FirstBitInWord(elem, i << 5);
}
elem = Base()[NUM_INTS - 1] & GetEndMask();
if (elem) return FirstBitInWord(elem, (NUM_INTS - 1) << 5);
}
} else {
const uint32 *RESTRICT pCurElem = Base() + wordIndex;
unsigned int elem = *pCurElem;
elem &= startMask;
do {
if (elem) return FirstBitInWord(elem, wordIndex << 5);
++pCurElem;
elem = *pCurElem;
++wordIndex;
} while (wordIndex <= NUM_INTS - 1);
}
}
return -1;
}
//-----------------------------------------------------------------------------
// Unrolled loops for some common sizes
template <>
FORCEINLINE_TEMPLATE void CBitVecT<CFixedBitVecBase<256> >::And(
const CBitVecT &addStr, CBitVecT *out) const {
uint32 *pDest = out->Base();
const uint32 *pOperand1 = Base();
const uint32 *pOperand2 = addStr.Base();
pDest[0] = pOperand1[0] & pOperand2[0];
pDest[1] = pOperand1[1] & pOperand2[1];
pDest[2] = pOperand1[2] & pOperand2[2];
pDest[3] = pOperand1[3] & pOperand2[3];
pDest[4] = pOperand1[4] & pOperand2[4];
pDest[5] = pOperand1[5] & pOperand2[5];
pDest[6] = pOperand1[6] & pOperand2[6];
pDest[7] = pOperand1[7] & pOperand2[7];
}
template <>
FORCEINLINE_TEMPLATE bool CBitVecT<CFixedBitVecBase<256> >::IsAllClear(
void) const {
const uint32 *pInts = Base();
return (pInts[0] == 0 && pInts[1] == 0 && pInts[2] == 0 && pInts[3] == 0 &&
pInts[4] == 0 && pInts[5] == 0 && pInts[6] == 0 && pInts[7] == 0);
}
template <>
FORCEINLINE_TEMPLATE void CBitVecT<CFixedBitVecBase<256> >::CopyTo(
CBitVecT *out) const {
uint32 *pDest = out->Base();
const uint32 *pInts = Base();
pDest[0] = pInts[0];
pDest[1] = pInts[1];
pDest[2] = pInts[2];
pDest[3] = pInts[3];
pDest[4] = pInts[4];
pDest[5] = pInts[5];
pDest[6] = pInts[6];
pDest[7] = pInts[7];
}
template <>
FORCEINLINE_TEMPLATE void CBitVecT<CFixedBitVecBase<128> >::And(
const CBitVecT &addStr, CBitVecT *out) const {
uint32 *pDest = out->Base();
const uint32 *pOperand1 = Base();
const uint32 *pOperand2 = addStr.Base();
pDest[0] = pOperand1[0] & pOperand2[0];
pDest[1] = pOperand1[1] & pOperand2[1];
pDest[2] = pOperand1[2] & pOperand2[2];
pDest[3] = pOperand1[3] & pOperand2[3];
}
template <>
FORCEINLINE_TEMPLATE bool CBitVecT<CFixedBitVecBase<128> >::IsAllClear(
void) const {
const uint32 *pInts = Base();
return (pInts[0] == 0 && pInts[1] == 0 && pInts[2] == 0 && pInts[3] == 0);
}
template <>
FORCEINLINE_TEMPLATE void CBitVecT<CFixedBitVecBase<128> >::CopyTo(
CBitVecT *out) const {
uint32 *pDest = out->Base();
const uint32 *pInts = Base();
pDest[0] = pInts[0];
pDest[1] = pInts[1];
pDest[2] = pInts[2];
pDest[3] = pInts[3];
}
template <>
inline void CBitVecT<CFixedBitVecBase<96> >::And(const CBitVecT &addStr,
CBitVecT *out) const {
uint32 *pDest = out->Base();
const uint32 *pOperand1 = Base();
const uint32 *pOperand2 = addStr.Base();
pDest[0] = pOperand1[0] & pOperand2[0];
pDest[1] = pOperand1[1] & pOperand2[1];
pDest[2] = pOperand1[2] & pOperand2[2];
}
template <>
inline bool CBitVecT<CFixedBitVecBase<96> >::IsAllClear(void) const {
const uint32 *pInts = Base();
return (pInts[0] == 0 && pInts[1] == 0 && pInts[2] == 0);
}
template <>
inline void CBitVecT<CFixedBitVecBase<96> >::CopyTo(CBitVecT *out) const {
uint32 *pDest = out->Base();
const uint32 *pInts = Base();
pDest[0] = pInts[0];
pDest[1] = pInts[1];
pDest[2] = pInts[2];
}
template <>
inline void CBitVecT<CFixedBitVecBase<64> >::And(const CBitVecT &addStr,
CBitVecT *out) const {
uint32 *pDest = out->Base();
const uint32 *pOperand1 = Base();
const uint32 *pOperand2 = addStr.Base();
pDest[0] = pOperand1[0] & pOperand2[0];
pDest[1] = pOperand1[1] & pOperand2[1];
}
template <>
inline bool CBitVecT<CFixedBitVecBase<64> >::IsAllClear(void) const {
const uint32 *pInts = Base();
return (pInts[0] == 0 && pInts[1] == 0);
}
template <>
inline void CBitVecT<CFixedBitVecBase<64> >::CopyTo(CBitVecT *out) const {
uint32 *pDest = out->Base();
const uint32 *pInts = Base();
pDest[0] = pInts[0];
pDest[1] = pInts[1];
}
template <>
inline void CBitVecT<CFixedBitVecBase<32> >::And(const CBitVecT &addStr,
CBitVecT *out) const {
uint32 *pDest = out->Base();
const uint32 *pOperand1 = Base();
const uint32 *pOperand2 = addStr.Base();
pDest[0] = pOperand1[0] & pOperand2[0];
}
template <>
inline bool CBitVecT<CFixedBitVecBase<32> >::IsAllClear(void) const {
const uint32 *pInts = Base();
return (pInts[0] == 0);
}
template <>
inline void CBitVecT<CFixedBitVecBase<32> >::CopyTo(CBitVecT *out) const {
uint32 *pDest = out->Base();
const uint32 *pInts = Base();
pDest[0] = pInts[0];
}
//-----------------------------------------------------------------------------
template <>
inline uint32 CBitVecT<CFixedBitVecBase<32> >::Get(uint32 bitNum) const {
return (*Base() & BitVec_Bit(bitNum));
}
//-----------------------------------------------------------------------------
template <>
inline bool CBitVecT<CFixedBitVecBase<32> >::IsBitSet(int bitNum) const {
return ((*Base() & BitVec_Bit(bitNum)) != 0);
}
//-----------------------------------------------------------------------------
template <>
inline void CBitVecT<CFixedBitVecBase<32> >::Set(int bitNum) {
*Base() |= BitVec_Bit(bitNum);
}
//-----------------------------------------------------------------------------
template <>
inline void CBitVecT<CFixedBitVecBase<32> >::Clear(int bitNum) {
*Base() &= ~BitVec_Bit(bitNum);
}
//-----------------------------------------------------------------------------
template <>
inline void CBitVecT<CFixedBitVecBase<32> >::Set(int bitNum, bool bNewVal) {
uint32 bitMask = BitVec_Bit(bitNum);
if (bNewVal) {
*Base() |= bitMask;
} else {
*Base() &= ~bitMask;
}
}
//-----------------------------------------------------------------------------
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose: Resizes the bit string to a new number of bits
// Input : resizeNumBits -
//-----------------------------------------------------------------------------
template <typename BITCOUNTTYPE>
inline void CVarBitVecBase<BITCOUNTTYPE>::Resize(int resizeNumBits,
bool bClearAll) {
Assert(resizeNumBits >= 0 &&
((BITCOUNTTYPE)resizeNumBits == resizeNumBits));
int newIntCount = CalcNumIntsForBits(resizeNumBits);
if (newIntCount != GetNumDWords()) {
if (Base()) {
ReallocInts(newIntCount);
if (!bClearAll && resizeNumBits >= GetNumBits()) {
Base()[GetNumDWords() - 1] &= GetEndMask();
Plat_FastMemset(Base() + GetNumDWords(), 0,
(newIntCount - GetNumDWords()) * sizeof(int));
}
} else {
// Figure out how many ints are needed
AllocInts(newIntCount);
// Initialize bitstring by clearing all bits
bClearAll = true;
}
m_numInts = newIntCount;
} else if (!bClearAll && resizeNumBits >= GetNumBits() && Base()) {
Base()[GetNumDWords() - 1] &= GetEndMask();
}
if (bClearAll && Base()) {
Plat_FastMemset(Base(), 0, newIntCount * sizeof(int));
}
// store the new size and end mask
m_numBits = resizeNumBits;
}
//-----------------------------------------------------------------------------
// Purpose: Allocate the storage for the ints
// Input : numInts -
//-----------------------------------------------------------------------------
template <typename BITCOUNTTYPE>
inline void CVarBitVecBase<BITCOUNTTYPE>::AllocInts(int numInts) {
Assert(!m_pInt);
if (numInts == 0) return;
if (numInts == 1) {
m_pInt = &m_iBitStringStorage;
return;
}
m_pInt = (uint32 *)malloc(numInts * sizeof(int));
}
//-----------------------------------------------------------------------------
// Purpose: Reallocate the storage for the ints
// Input : numInts -
//-----------------------------------------------------------------------------
template <typename BITCOUNTTYPE>
inline void CVarBitVecBase<BITCOUNTTYPE>::ReallocInts(int numInts) {
Assert(Base());
if (numInts == 0) {
FreeInts();
return;
}
if (m_pInt == &m_iBitStringStorage) {
if (numInts != 1) {
m_pInt = ((uint32 *)malloc(numInts * sizeof(int)));
*m_pInt = m_iBitStringStorage;
}
return;
}
if (numInts == 1) {
m_iBitStringStorage = *m_pInt;
free(m_pInt);
m_pInt = &m_iBitStringStorage;
return;
}
m_pInt = (uint32 *)realloc(m_pInt, numInts * sizeof(int));
}
//-----------------------------------------------------------------------------
// Purpose: Free storage allocated with AllocInts
//-----------------------------------------------------------------------------
template <typename BITCOUNTTYPE>
inline void CVarBitVecBase<BITCOUNTTYPE>::FreeInts(void) {
if (m_numInts > 1) {
free(m_pInt);
}
m_pInt = NULL;
}
#include "tier0/memdbgoff.h"
// ------------------------------------------------------------------------ //
// CBitVecAccessor inlines.
// ------------------------------------------------------------------------ //
inline CBitVecAccessor::CBitVecAccessor(uint32 *pDWords, int iBit) {
m_pDWords = pDWords;
m_iBit = iBit;
}
inline void CBitVecAccessor::operator=(int val) {
if (val)
m_pDWords[m_iBit >> 5] |= (1 << (m_iBit & 31));
else
m_pDWords[m_iBit >> 5] &= ~(unsigned long)(1 << (m_iBit & 31));
}
inline CBitVecAccessor::operator uint32() {
return m_pDWords[m_iBit >> 5] & (1 << (m_iBit & 31));
}
//=============================================================================
#endif // BITVEC_H