#pragma once #include #include #include #include namespace sead { template 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 mStorage{}; }; template inline typename LongBitFlag::Word& LongBitFlag::getWord(int bit) { SEAD_ASSERT_MSG(u32(bit) < u32(N), "range over [0,%d) : %d", N, bit); return mStorage[bit >> Shift]; } template inline const typename LongBitFlag::Word& LongBitFlag::getWord(int bit) const { SEAD_ASSERT_MSG(u32(bit) < u32(N), "range over [0,%d) : %d", N, bit); return mStorage[bit >> Shift]; } template inline void LongBitFlag::setBit(int bit) { getWord(bit) |= makeMask(bit); } template inline void LongBitFlag::resetBit(int bit) { getWord(bit) &= ~makeMask(bit); } template inline void LongBitFlag::changeBit(int bit, bool on) { if (on) setBit(bit); else resetBit(bit); } template inline void LongBitFlag::toggleBit(int bit) { getWord(bit) ^= makeMask(bit); } template inline bool LongBitFlag::isOnBit(int bit) const { return (getWord(bit) & makeMask(bit)) != 0; } template inline bool LongBitFlag::isOffBit(int bit) const { return !isOnBit(bit); } template inline bool LongBitFlag::isZero() const { for (const u32 word : mStorage) { if (word != 0) return false; } return true; } template inline int LongBitFlag::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