tetl 0.1.0
Embedded Template Library
Loading...
Searching...
No Matches
basic_bitset.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSL-1.0
2// SPDX-FileCopyrightText: Copyright (C) 2024 Tobias Hienzsch
3
4#ifndef TETL_BITSET_BASIC_BITSET_HPP
5#define TETL_BITSET_BASIC_BITSET_HPP
6
7#include <etl/_algorithm/all_of.hpp>
8#include <etl/_algorithm/any_of.hpp>
9#include <etl/_algorithm/fill.hpp>
10#include <etl/_algorithm/min.hpp>
11#include <etl/_algorithm/transform.hpp>
12#include <etl/_array/array.hpp>
13#include <etl/_bit/flip_bit.hpp>
14#include <etl/_bit/popcount.hpp>
15#include <etl/_bit/reset_bit.hpp>
16#include <etl/_bit/set_bit.hpp>
17#include <etl/_bit/test_bit.hpp>
18#include <etl/_concepts/unsigned_integral.hpp>
19#include <etl/_contracts/check.hpp>
20#include <etl/_cstddef/size_t.hpp>
21#include <etl/_functional/plus.hpp>
22#include <etl/_iterator/prev.hpp>
23#include <etl/_limits/numeric_limits.hpp>
24#include <etl/_memory/addressof.hpp>
25#include <etl/_numeric/transform_reduce.hpp>
26
27namespace etl {
28
29/// \headerfile etl/bitset.hpp
30/// \ingroup bitset
31template <etl::size_t Bits, etl::unsigned_integral WordType = etl::size_t>
33 struct reference {
34 constexpr auto operator=(bool x) noexcept -> reference&
35 {
36 *_word = etl::set_bit(*_word, _offset, x);
37 return *this;
38 }
39
40 constexpr auto operator=(reference const& x) noexcept -> reference&
41 {
42 *_word = etl::set_bit(*_word, _offset, static_cast<bool>(x));
43 return *this;
44 }
45
46 [[nodiscard]] constexpr operator bool() const noexcept
47 {
48 return etl::test_bit(*_word, _offset);
49 }
50
51 [[nodiscard]] constexpr auto operator~() const noexcept -> bool
52 {
53 return not static_cast<bool>(*this);
54 }
55
56 constexpr auto flip() noexcept -> reference&
57 {
58 *_word = etl::flip_bit(*_word, _offset);
59 return *this;
60 }
61
62 private:
63 constexpr explicit reference(WordType& word, WordType offset) noexcept
64 : _word{etl::addressof(word)}
65 , _offset{offset}
66 {
67 }
68
69 WordType* _word;
70 WordType _offset;
71
72 friend basic_bitset;
73 };
74
75 /// Default constructor. Constructs a bitset with all bits set to zero.
76 constexpr basic_bitset() = default;
77
78 /// Constructs a bitset, initializing the first (rightmost, least significant)
79 /// M bit positions to the corresponding bit values of val.
80 constexpr basic_bitset(unsigned long long val) noexcept
81 {
82 auto const digits = static_cast<size_t>(etl::numeric_limits<unsigned long long>::digits);
83 auto const m = etl::min(digits, size());
84 for (auto i = etl::size_t(0); i < m; ++i) {
85 unchecked_set(i, etl::test_bit(val, static_cast<unsigned long long>(i)));
86 }
87 }
88
89 /// Returns the number of bits that the bitset holds.
90 [[nodiscard]] constexpr auto size() const noexcept -> etl::size_t
91 {
92 return Bits;
93 }
94
95 /// Returns true if the bit at position \p pos is set.
96 /// \pre `pos < size()`
97 [[nodiscard]] constexpr auto operator[](etl::size_t pos) const -> bool
98 {
99 TETL_PRECONDITION(pos < size());
100 return unchecked_test(pos);
101 }
102
103 /// Returns a reference to the bit at position \p pos
104 /// \pre `pos < size()`
105 [[nodiscard]] constexpr auto operator[](etl::size_t pos) -> reference
106 {
107 TETL_PRECONDITION(pos < size());
108 return reference{_words[word_index(pos)], offset_in_word(pos)};
109 }
110
111 /// Checks if all bits are set to true.
112 [[nodiscard]] constexpr auto all() const noexcept -> bool
113 {
114 auto const allSet = [](auto word) { return word == ones; };
115
116 if constexpr (has_padding) {
117 auto const head = etl::all_of(_words.cbegin(), etl::prev(_words.cend()), allSet);
118 auto const tail = _words[num_words - 1] == padding_mask_inv;
119 return head and tail;
120 } else {
121 return etl::all_of(_words.cbegin(), _words.cend(), allSet);
122 }
123 }
124
125 /// Checks if any bits are set to true.
126 [[nodiscard]] constexpr auto any() const noexcept -> bool
127 {
128 return not none();
129 }
130
131 /// Checks if none of the bits are set to true.
132 [[nodiscard]] constexpr auto none() const noexcept -> bool
133 {
134 return etl::all_of(_words.cbegin(), _words.cend(), [](auto word) { return word == WordType(0); });
135 }
136
137 /// Returns the number of bits that are set to true.
138 [[nodiscard]] constexpr auto count() const noexcept -> etl::size_t
139 {
140 return etl::transform_reduce(_words.cbegin(), _words.cend(), etl::size_t(0), etl::plus(), [](auto word) {
141 return static_cast<etl::size_t>(etl::popcount(word));
142 });
143 }
144
145 /// Returns true if the bit at position \p pos is set.
146 /// \pre `pos < size()`
147 [[nodiscard]] constexpr auto unchecked_test(etl::size_t pos) const -> bool
148 {
149 TETL_PRECONDITION(pos < size());
150 return etl::test_bit(_words[word_index(pos)], offset_in_word(pos));
151 }
152
153 /// Sets all bits to true.
154 constexpr auto set() noexcept -> basic_bitset&
155 {
156 if constexpr (has_padding) {
157 etl::fill(_words.begin(), etl::prev(_words.end()), ones);
158 _words[num_words - 1] = padding_mask_inv;
159 } else {
160 etl::fill(_words.begin(), _words.end(), ones);
161 }
162
163 return *this;
164 }
165
166 /// Set bit at position \p pos to \p value
167 /// \pre `pos < size()`
168 constexpr auto unchecked_set(etl::size_t pos, bool value = true) -> basic_bitset&
169 {
170 TETL_PRECONDITION(pos < size());
171 return transform_bit(pos, [value](auto word, auto bit) { return etl::set_bit(word, bit, value); });
172 }
173
174 /// Sets all bits to false.
175 constexpr auto reset() noexcept -> basic_bitset&
176 {
177 etl::fill(_words.begin(), _words.end(), WordType(0));
178 return *this;
179 }
180
181 /// Sets the bit at position \p pos to false.
182 /// \pre `pos < size()`
183 constexpr auto unchecked_reset(etl::size_t pos) -> basic_bitset&
184 {
185 TETL_PRECONDITION(pos < size());
186 return transform_bit(pos, [](auto word, auto bit) { return etl::reset_bit(word, bit); });
187 }
188
189 /// Flips all bits.
190 constexpr auto flip() noexcept -> basic_bitset&
191 {
192 etl::transform(_words.cbegin(), _words.cend(), _words.begin(), [](auto word) {
193 return static_cast<WordType>(~word);
194 });
195
196 if constexpr (has_padding) {
197 _words[num_words - 1] &= padding_mask_inv;
198 }
199
200 return *this;
201 }
202
203 /// Flip bit at position \p pos
204 /// \pre `pos < size()`
205 constexpr auto unchecked_flip(etl::size_t pos) -> basic_bitset&
206 {
207 TETL_PRECONDITION(pos < size());
208 return transform_bit(pos, [](auto word, auto bit) { return etl::flip_bit(word, bit); });
209 }
210
211 /// Sets the bits to the result of binary AND on corresponding pairs of bits of `*this` and `other`
212 constexpr auto operator&=(basic_bitset const& other) noexcept -> basic_bitset&
213 {
214 etl::transform(_words.begin(), _words.end(), other._words.begin(), _words.begin(), [](auto lhs, auto rhs) {
215 return static_cast<WordType>(lhs & rhs);
216 });
217 return *this;
218 }
219
220 /// Sets the bits to the result of binary OR on corresponding pairs of bits of `*this` and `other`
221 constexpr auto operator|=(basic_bitset const& other) noexcept -> basic_bitset&
222 {
223 etl::transform(_words.begin(), _words.end(), other._words.begin(), _words.begin(), [](auto lhs, auto rhs) {
224 return static_cast<WordType>(lhs | rhs);
225 });
226 return *this;
227 }
228
229 /// Sets the bits to the result of binary XOR on corresponding pairs of bits of `*this` and `other`
230 constexpr auto operator^=(basic_bitset const& other) noexcept -> basic_bitset&
231 {
232 etl::transform(_words.begin(), _words.end(), other._words.begin(), _words.begin(), [](auto lhs, auto rhs) {
233 return static_cast<WordType>(lhs ^ rhs);
234 });
235 return *this;
236 }
237
238 /// Returns true if all of the bits in \p lhs and \p rhs are equal.
239 friend constexpr auto operator==(basic_bitset const& lhs, basic_bitset const& rhs) -> bool = default;
240
241 /// Returns a basic_bitset containing the result of binary AND on corresponding pairs of bits of \p lhs and \p rhs.
242 friend constexpr auto operator&(basic_bitset const& lhs, basic_bitset const& rhs) noexcept -> basic_bitset
243 {
244 return basic_bitset(lhs) &= rhs;
245 }
246
247 /// Returns a basic_bitset containing the result of binary OR on corresponding pairs of bits of \p lhs and \p rhs.
248 friend constexpr auto operator|(basic_bitset const& lhs, basic_bitset const& rhs) noexcept -> basic_bitset
249 {
250 return basic_bitset(lhs) |= rhs;
251 }
252
253 /// Returns a basic_bitset containing the result of binary XOR on corresponding pairs of bits of \p lhs and \p rhs.
254 friend constexpr auto operator^(basic_bitset const& lhs, basic_bitset const& rhs) noexcept -> basic_bitset
255 {
256 return basic_bitset(lhs) ^= rhs;
257 }
258
259private:
260 static constexpr auto ones = etl::numeric_limits<WordType>::max();
261 static constexpr auto bits_per_word = static_cast<size_t>(etl::numeric_limits<WordType>::digits);
262 static constexpr auto num_words = (Bits + bits_per_word - 1) / bits_per_word;
263 static constexpr auto padding = (num_words * bits_per_word) - Bits;
264 static constexpr auto has_padding = padding != 0;
265 static constexpr auto padding_mask = [] {
266 auto mask = WordType{};
267 for (auto i{bits_per_word - padding}; i < bits_per_word; ++i) {
268 mask = etl::set_bit(mask, static_cast<WordType>(i));
269 }
270 return mask;
271 }();
272 static constexpr auto padding_mask_inv = static_cast<WordType>(~padding_mask);
273
274 [[nodiscard]] static constexpr auto word_index(etl::size_t pos) -> etl::size_t
275 {
276 return pos / bits_per_word;
277 }
278
279 [[nodiscard]] static constexpr auto offset_in_word(etl::size_t pos) -> WordType
280 {
281 return static_cast<WordType>(pos & (bits_per_word - etl::size_t(1)));
282 }
283
284 constexpr auto transform_bit(etl::size_t pos, auto op) -> basic_bitset&
285 {
286 auto& word = _words[word_index(pos)];
288 return *this;
289 }
290
291 etl::array<WordType, num_words> _words{};
292};
293
294} // namespace etl
295
296#endif // TETL_BITSET_BASIC_BITSET_HPP
constexpr auto test_bit(UInt word, UInt pos) noexcept -> bool
Test bit at position pos.
Definition test_bit.hpp:20
Definition adjacent_find.hpp:9
A container that encapsulates fixed size arrays.
Definition array.hpp:49
Definition basic_bitset.hpp:33
constexpr auto operator=(bool x) noexcept -> reference &
Definition basic_bitset.hpp:34
constexpr operator bool() const noexcept
Definition basic_bitset.hpp:46
constexpr auto operator~() const noexcept -> bool
Definition basic_bitset.hpp:51
constexpr auto flip() noexcept -> reference &
Definition basic_bitset.hpp:56
constexpr auto operator=(reference const &x) noexcept -> reference &
Definition basic_bitset.hpp:40
Definition basic_bitset.hpp:32
constexpr auto count() const noexcept -> etl::size_t
Returns the number of bits that are set to true.
Definition basic_bitset.hpp:138
constexpr auto none() const noexcept -> bool
Checks if none of the bits are set to true.
Definition basic_bitset.hpp:132
constexpr auto set() noexcept -> basic_bitset &
Sets all bits to true.
Definition basic_bitset.hpp:154
constexpr auto operator^=(basic_bitset const &other) noexcept -> basic_bitset &
Sets the bits to the result of binary XOR on corresponding pairs of bits of *this and other
Definition basic_bitset.hpp:230
constexpr auto any() const noexcept -> bool
Checks if any bits are set to true.
Definition basic_bitset.hpp:126
constexpr auto reset() noexcept -> basic_bitset &
Sets all bits to false.
Definition basic_bitset.hpp:175
constexpr auto operator|=(basic_bitset const &other) noexcept -> basic_bitset &
Sets the bits to the result of binary OR on corresponding pairs of bits of *this and other
Definition basic_bitset.hpp:221
constexpr auto unchecked_reset(etl::size_t pos) -> basic_bitset &
Sets the bit at position pos to false.
Definition basic_bitset.hpp:183
friend constexpr auto operator&(basic_bitset const &lhs, basic_bitset const &rhs) noexcept -> basic_bitset
Returns a basic_bitset containing the result of binary AND on corresponding pairs of bits of lhs and ...
Definition basic_bitset.hpp:242
constexpr auto unchecked_test(etl::size_t pos) const -> bool
Returns true if the bit at position pos is set.
Definition basic_bitset.hpp:147
constexpr auto flip() noexcept -> basic_bitset &
Flips all bits.
Definition basic_bitset.hpp:190
constexpr basic_bitset(unsigned long long val) noexcept
Constructs a bitset, initializing the first (rightmost, least significant) M bit positions to the cor...
Definition basic_bitset.hpp:80
friend constexpr auto operator^(basic_bitset const &lhs, basic_bitset const &rhs) noexcept -> basic_bitset
Returns a basic_bitset containing the result of binary XOR on corresponding pairs of bits of lhs and ...
Definition basic_bitset.hpp:254
constexpr auto operator&=(basic_bitset const &other) noexcept -> basic_bitset &
Sets the bits to the result of binary AND on corresponding pairs of bits of *this and other
Definition basic_bitset.hpp:212
constexpr auto all() const noexcept -> bool
Checks if all bits are set to true.
Definition basic_bitset.hpp:112
constexpr auto unchecked_flip(etl::size_t pos) -> basic_bitset &
Flip bit at position pos.
Definition basic_bitset.hpp:205
constexpr auto unchecked_set(etl::size_t pos, bool value=true) -> basic_bitset &
Set bit at position pos to value.
Definition basic_bitset.hpp:168
friend constexpr auto operator|(basic_bitset const &lhs, basic_bitset const &rhs) noexcept -> basic_bitset
Returns a basic_bitset containing the result of binary OR on corresponding pairs of bits of lhs and r...
Definition basic_bitset.hpp:248
constexpr basic_bitset()=default
Default constructor. Constructs a bitset with all bits set to zero.
friend constexpr auto operator==(basic_bitset const &lhs, basic_bitset const &rhs) -> bool=default
Returns true if all of the bits in lhs and rhs are equal.
constexpr auto operator[](etl::size_t pos) -> reference
Returns a reference to the bit at position pos.
Definition basic_bitset.hpp:105
constexpr auto size() const noexcept -> etl::size_t
Returns the number of bits that the bitset holds.
Definition basic_bitset.hpp:90
constexpr auto operator[](etl::size_t pos) const -> bool
Returns true if the bit at position pos is set.
Definition basic_bitset.hpp:97
static constexpr int digits
Definition numeric_limits.hpp:982
Definition numeric_limits.hpp:18
Function object for performing addition. Effectively calls operator+ on two instances of type T....
Definition plus.hpp:15