summaryrefslogtreecommitdiff
path: root/src/common/bit_set.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/bit_set.h')
-rw-r--r--src/common/bit_set.h99
1 files changed, 99 insertions, 0 deletions
diff --git a/src/common/bit_set.h b/src/common/bit_set.h
new file mode 100644
index 000000000..9235ad412
--- /dev/null
+++ b/src/common/bit_set.h
@@ -0,0 +1,99 @@
1/*
2 * Copyright (c) 2018-2020 Atmosphère-NX
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#pragma once
18
19#include <array>
20#include <bit>
21
22#include "common/alignment.h"
23#include "common/bit_util.h"
24#include "common/common_types.h"
25
26namespace Common {
27
28namespace impl {
29
30template <typename Storage, size_t N>
31class BitSet {
32
33public:
34 constexpr BitSet() = default;
35
36 constexpr void SetBit(size_t i) {
37 this->words[i / FlagsPerWord] |= GetBitMask(i % FlagsPerWord);
38 }
39
40 constexpr void ClearBit(size_t i) {
41 this->words[i / FlagsPerWord] &= ~GetBitMask(i % FlagsPerWord);
42 }
43
44 constexpr size_t CountLeadingZero() const {
45 for (size_t i = 0; i < NumWords; i++) {
46 if (this->words[i]) {
47 return FlagsPerWord * i + CountLeadingZeroImpl(this->words[i]);
48 }
49 }
50 return FlagsPerWord * NumWords;
51 }
52
53 constexpr size_t GetNextSet(size_t n) const {
54 for (size_t i = (n + 1) / FlagsPerWord; i < NumWords; i++) {
55 Storage word = this->words[i];
56 if (!IsAligned(n + 1, FlagsPerWord)) {
57 word &= GetBitMask(n % FlagsPerWord) - 1;
58 }
59 if (word) {
60 return FlagsPerWord * i + CountLeadingZeroImpl(word);
61 }
62 }
63 return FlagsPerWord * NumWords;
64 }
65
66private:
67 static_assert(std::is_unsigned_v<Storage>);
68 static_assert(sizeof(Storage) <= sizeof(u64));
69
70 static constexpr size_t FlagsPerWord = BitSize<Storage>();
71 static constexpr size_t NumWords = AlignUp(N, FlagsPerWord) / FlagsPerWord;
72
73 static constexpr auto CountLeadingZeroImpl(Storage word) {
74 return std::countl_zero(static_cast<unsigned long long>(word)) -
75 (BitSize<unsigned long long>() - FlagsPerWord);
76 }
77
78 static constexpr Storage GetBitMask(size_t bit) {
79 return Storage(1) << (FlagsPerWord - 1 - bit);
80 }
81
82 std::array<Storage, NumWords> words{};
83};
84
85} // namespace impl
86
87template <size_t N>
88using BitSet8 = impl::BitSet<u8, N>;
89
90template <size_t N>
91using BitSet16 = impl::BitSet<u16, N>;
92
93template <size_t N>
94using BitSet32 = impl::BitSet<u32, N>;
95
96template <size_t N>
97using BitSet64 = impl::BitSet<u64, N>;
98
99} // namespace Common