Files
botw/lib/sead/include/prim/seadLongBitFlag.h
T
Léo Lam 18c60323a9 Switch to subrepos
git subrepo clone https://github.com/open-ead/sead lib/sead

subrepo:
  subdir:   "lib/sead"
  merged:   "1b66e825d"
upstream:
  origin:   "https://github.com/open-ead/sead"
  branch:   "master"
  commit:   "1b66e825d"
git-subrepo:
  version:  "0.4.3"
  origin:   "https://github.com/ingydotnet/git-subrepo"
  commit:   "2f68596"

git subrepo clone (merge) https://github.com/open-ead/nnheaders lib/NintendoSDK

subrepo:
  subdir:   "lib/NintendoSDK"
  merged:   "9ee21399f"
upstream:
  origin:   "https://github.com/open-ead/nnheaders"
  branch:   "master"
  commit:   "9ee21399f"
git-subrepo:
  version:  "0.4.3"
  origin:   "ssh://git@github.com/ingydotnet/git-subrepo"
  commit:   "2f68596"

git subrepo clone https://github.com/open-ead/agl lib/agl

subrepo:
  subdir:   "lib/agl"
  merged:   "7c063271b"
upstream:
  origin:   "https://github.com/open-ead/agl"
  branch:   "master"
  commit:   "7c063271b"
git-subrepo:
  version:  "0.4.3"
  origin:   "ssh://git@github.com/ingydotnet/git-subrepo"
  commit:   "2f68596"

git subrepo clone https://github.com/open-ead/EventFlow lib/EventFlow

subrepo:
  subdir:   "lib/EventFlow"
  merged:   "c35d21b34"
upstream:
  origin:   "https://github.com/open-ead/EventFlow"
  branch:   "master"
  commit:   "c35d21b34"
git-subrepo:
  version:  "0.4.3"
  origin:   "ssh://git@github.com/ingydotnet/git-subrepo"
  commit:   "2f68596"
2022-03-21 21:31:42 +01:00

124 lines
2.6 KiB
C++

#pragma once
#include <array>
#include <basis/seadRawPrint.h>
#include <basis/seadTypes.h>
#include <math/seadMathCalcCommon.h>
namespace sead
{
template <s32 N>
class LongBitFlag
{
public:
using Word = u32;
void makeAllZero() { mStorage.fill(0); }
void makeAllOne() { mStorage.fill(~Word(0)); }
Word& getWord(int bit);
const Word& getWord(int bit) const;
bool isZero() const;
void setBit(int bit);
void resetBit(int bit);
void changeBit(int bit, bool on);
void toggleBit(int bit);
bool isOnBit(int bit) const;
bool isOffBit(int bit) const;
/// Popcount.
int countOnBit() const;
static Word makeMask(int bit) { return 1u << (bit % BitsPerWord); }
protected:
static constexpr s32 BitsPerWord = 8 * sizeof(Word);
static constexpr s32 Shift = log2(BitsPerWord);
static_assert(N % BitsPerWord == 0, "N must be a multiple of the number of bits per word");
std::array<Word, N / BitsPerWord> mStorage{};
};
template <s32 N>
inline typename LongBitFlag<N>::Word& LongBitFlag<N>::getWord(int bit)
{
SEAD_ASSERT_MSG(u32(bit) < u32(N), "range over [0,%d) : %d", N, bit);
return mStorage[bit >> Shift];
}
template <s32 N>
inline const typename LongBitFlag<N>::Word& LongBitFlag<N>::getWord(int bit) const
{
SEAD_ASSERT_MSG(u32(bit) < u32(N), "range over [0,%d) : %d", N, bit);
return mStorage[bit >> Shift];
}
template <s32 N>
inline void LongBitFlag<N>::setBit(int bit)
{
getWord(bit) |= makeMask(bit);
}
template <s32 N>
inline void LongBitFlag<N>::resetBit(int bit)
{
getWord(bit) &= ~makeMask(bit);
}
template <s32 N>
inline void LongBitFlag<N>::changeBit(int bit, bool on)
{
if (on)
setBit(bit);
else
resetBit(bit);
}
template <s32 N>
inline void LongBitFlag<N>::toggleBit(int bit)
{
getWord(bit) ^= makeMask(bit);
}
template <s32 N>
inline bool LongBitFlag<N>::isOnBit(int bit) const
{
return (getWord(bit) & makeMask(bit)) != 0;
}
template <s32 N>
inline bool LongBitFlag<N>::isOffBit(int bit) const
{
return !isOnBit(bit);
}
template <s32 N>
inline bool LongBitFlag<N>::isZero() const
{
for (const u32 word : mStorage)
{
if (word != 0)
return false;
}
return true;
}
template <s32 N>
inline int LongBitFlag<N>::countOnBit() const
{
// This is pretty inefficient, but it appears to be how popcount is implemented
// in Lunchpack's Lp::Sys::ActorSystem::countActiveChildNum.
s32 count = 0;
for (s32 i = 0; i < N; ++i)
{
if (isOnBit(i))
++count;
}
return count;
}
} // namespace sead