bit_set.h 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <array>
  5. #include <bit>
  6. #include "common/alignment.h"
  7. #include "common/bit_util.h"
  8. #include "common/common_types.h"
  9. namespace Common {
  10. namespace impl {
  11. template <typename Storage, size_t N>
  12. class BitSet {
  13. public:
  14. constexpr BitSet() = default;
  15. constexpr void SetBit(size_t i) {
  16. this->words[i / FlagsPerWord] |= GetBitMask(i % FlagsPerWord);
  17. }
  18. constexpr void ClearBit(size_t i) {
  19. this->words[i / FlagsPerWord] &= ~GetBitMask(i % FlagsPerWord);
  20. }
  21. constexpr size_t CountLeadingZero() const {
  22. for (size_t i = 0; i < NumWords; i++) {
  23. if (this->words[i]) {
  24. return FlagsPerWord * i + CountLeadingZeroImpl(this->words[i]);
  25. }
  26. }
  27. return FlagsPerWord * NumWords;
  28. }
  29. constexpr size_t GetNextSet(size_t n) const {
  30. for (size_t i = (n + 1) / FlagsPerWord; i < NumWords; i++) {
  31. Storage word = this->words[i];
  32. if (!IsAligned(n + 1, FlagsPerWord)) {
  33. word &= GetBitMask(n % FlagsPerWord) - 1;
  34. }
  35. if (word) {
  36. return FlagsPerWord * i + CountLeadingZeroImpl(word);
  37. }
  38. }
  39. return FlagsPerWord * NumWords;
  40. }
  41. private:
  42. static_assert(std::is_unsigned_v<Storage>);
  43. static_assert(sizeof(Storage) <= sizeof(u64));
  44. static constexpr size_t FlagsPerWord = BitSize<Storage>();
  45. static constexpr size_t NumWords = AlignUp(N, FlagsPerWord) / FlagsPerWord;
  46. static constexpr auto CountLeadingZeroImpl(Storage word) {
  47. return std::countl_zero(static_cast<unsigned long long>(word)) -
  48. (BitSize<unsigned long long>() - FlagsPerWord);
  49. }
  50. static constexpr Storage GetBitMask(size_t bit) {
  51. return Storage(1) << (FlagsPerWord - 1 - bit);
  52. }
  53. std::array<Storage, NumWords> words{};
  54. };
  55. } // namespace impl
  56. template <size_t N>
  57. using BitSet8 = impl::BitSet<u8, N>;
  58. template <size_t N>
  59. using BitSet16 = impl::BitSet<u16, N>;
  60. template <size_t N>
  61. using BitSet32 = impl::BitSet<u32, N>;
  62. template <size_t N>
  63. using BitSet64 = impl::BitSet<u64, N>;
  64. } // namespace Common