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
3#ifndef TETL_BITSET_BASIC_BITSET_HPP
4#define TETL_BITSET_BASIC_BITSET_HPP
5
11#include <etl/_array/array.hpp>
12#include <etl/_bit/flip_bit.hpp>
13#include <etl/_bit/popcount.hpp>
15#include <etl/_bit/set_bit.hpp>
16#include <etl/_bit/test_bit.hpp>
25
26namespace etl {
27
30template <etl::size_t Bits, etl::unsigned_integral WordType = etl::size_t>
32
33 struct reference {
34
35 constexpr auto operator=(bool x) noexcept -> reference&
36 {
37 *_word = etl::set_bit(*_word, _offset, x);
38 return *this;
39 }
40
41 constexpr auto operator=(reference const& x) noexcept -> reference&
42 {
43 *_word = etl::set_bit(*_word, _offset, static_cast<bool>(x));
44 return *this;
45 }
46
47 [[nodiscard]] constexpr operator bool() const noexcept { return etl::test_bit(*_word, _offset); }
48
49 [[nodiscard]] constexpr auto operator~() const noexcept -> bool { return not static_cast<bool>(*this); }
50
51 constexpr auto flip() noexcept -> reference&
52 {
53 *_word = etl::flip_bit(*_word, _offset);
54 return *this;
55 }
56
57 private:
58 constexpr explicit reference(WordType& word, WordType offset) noexcept
59 : _word{etl::addressof(word)}
60 , _offset{offset}
61 {
62 }
63
64 WordType* _word;
65 WordType _offset;
66
67 friend basic_bitset;
68 };
69
71 constexpr basic_bitset() = default;
72
75 constexpr basic_bitset(unsigned long long val) noexcept
76 {
77 auto const digits = static_cast<size_t>(etl::numeric_limits<unsigned long long>::digits);
78 auto const m = etl::min(digits, size());
79 for (auto i = etl::size_t(0); i < m; ++i) {
80 unchecked_set(i, etl::test_bit(val, static_cast<unsigned long long>(i)));
81 }
82 }
83
85 [[nodiscard]] constexpr auto size() const noexcept -> etl::size_t { return Bits; }
86
89 [[nodiscard]] constexpr auto operator[](etl::size_t pos) const -> bool
90 {
91 TETL_PRECONDITION(pos < size());
92 return unchecked_test(pos);
93 }
94
97 [[nodiscard]] constexpr auto operator[](etl::size_t pos) -> reference
98 {
99 TETL_PRECONDITION(pos < size());
100 return reference{_words[word_index(pos)], offset_in_word(pos)};
101 }
102
104 [[nodiscard]] constexpr auto all() const noexcept -> bool
105 {
106 auto const allSet = [](auto word) { return word == ones; };
107
108 if constexpr (has_padding) {
109 auto const head = etl::all_of(_words.cbegin(), etl::prev(_words.cend()), allSet);
110 auto const tail = _words[num_words - 1] == padding_mask_inv;
111 return head and tail;
112 } else {
113 return etl::all_of(_words.cbegin(), _words.cend(), allSet);
114 }
115 }
116
118 [[nodiscard]] constexpr auto any() const noexcept -> bool { return not none(); }
119
121 [[nodiscard]] constexpr auto none() const noexcept -> bool
122 {
123 return etl::all_of(_words.cbegin(), _words.cend(), [](auto word) { return word == WordType(0); });
124 }
125
127 [[nodiscard]] constexpr auto count() const noexcept -> etl::size_t
128 {
129 return etl::transform_reduce(_words.cbegin(), _words.cend(), etl::size_t(0), etl::plus(), [](auto word) {
130 return static_cast<etl::size_t>(etl::popcount(word));
131 });
132 }
133
136 [[nodiscard]] constexpr auto unchecked_test(etl::size_t pos) const -> bool
137 {
138 TETL_PRECONDITION(pos < size());
139 return etl::test_bit(_words[word_index(pos)], offset_in_word(pos));
140 }
141
143 constexpr auto set() noexcept -> basic_bitset&
144 {
145 if constexpr (has_padding) {
146 etl::fill(_words.begin(), etl::prev(_words.end()), ones);
147 _words[num_words - 1] = padding_mask_inv;
148 } else {
149 etl::fill(_words.begin(), _words.end(), ones);
150 }
151
152 return *this;
153 }
154
157 constexpr auto unchecked_set(etl::size_t pos, bool value = true) -> basic_bitset&
158 {
159 TETL_PRECONDITION(pos < size());
160 return transform_bit(pos, [value](auto word, auto bit) { return etl::set_bit(word, bit, value); });
161 }
162
164 constexpr auto reset() noexcept -> basic_bitset&
165 {
166 etl::fill(_words.begin(), _words.end(), WordType(0));
167 return *this;
168 }
169
173 {
174 TETL_PRECONDITION(pos < size());
175 return transform_bit(pos, [](auto word, auto bit) { return etl::reset_bit(word, bit); });
176 }
177
179 constexpr auto flip() noexcept -> basic_bitset&
180 {
181 etl::transform(_words.cbegin(), _words.cend(), _words.begin(), [](auto word) {
182 return static_cast<WordType>(~word);
183 });
184
185 if constexpr (has_padding) {
186 _words[num_words - 1] &= padding_mask_inv;
187 }
188
189 return *this;
190 }
191
195 {
196 TETL_PRECONDITION(pos < size());
197 return transform_bit(pos, [](auto word, auto bit) { return etl::flip_bit(word, bit); });
198 }
199
201 constexpr auto operator&=(basic_bitset const& other) noexcept -> basic_bitset&
202 {
203 etl::transform(_words.begin(), _words.end(), other._words.begin(), _words.begin(), [](auto lhs, auto rhs) {
204 return static_cast<WordType>(lhs & rhs);
205 });
206 return *this;
207 }
208
210 constexpr auto operator|=(basic_bitset const& other) noexcept -> basic_bitset&
211 {
212 etl::transform(_words.begin(), _words.end(), other._words.begin(), _words.begin(), [](auto lhs, auto rhs) {
213 return static_cast<WordType>(lhs | rhs);
214 });
215 return *this;
216 }
217
219 constexpr auto operator^=(basic_bitset const& other) noexcept -> basic_bitset&
220 {
221 etl::transform(_words.begin(), _words.end(), other._words.begin(), _words.begin(), [](auto lhs, auto rhs) {
222 return static_cast<WordType>(lhs ^ rhs);
223 });
224 return *this;
225 }
226
228 friend constexpr auto operator==(basic_bitset const& lhs, basic_bitset const& rhs) -> bool = default;
229
231 friend constexpr auto operator&(basic_bitset const& lhs, basic_bitset const& rhs) noexcept -> basic_bitset
232 {
233 return basic_bitset(lhs) &= rhs;
234 }
235
237 friend constexpr auto operator|(basic_bitset const& lhs, basic_bitset const& rhs) noexcept -> basic_bitset
238 {
239 return basic_bitset(lhs) |= rhs;
240 }
241
243 friend constexpr auto operator^(basic_bitset const& lhs, basic_bitset const& rhs) noexcept -> basic_bitset
244 {
245 return basic_bitset(lhs) ^= rhs;
246 }
247
248private:
249 static constexpr auto ones = etl::numeric_limits<WordType>::max();
250 static constexpr auto bits_per_word = static_cast<size_t>(etl::numeric_limits<WordType>::digits);
251 static constexpr auto num_words = (Bits + bits_per_word - 1) / bits_per_word;
252 static constexpr auto padding = num_words * bits_per_word - Bits;
253 static constexpr auto has_padding = padding != 0;
254 static constexpr auto padding_mask = [] {
255 auto mask = WordType{};
256 for (auto i{bits_per_word - padding}; i < bits_per_word; ++i) {
257 mask = etl::set_bit(mask, static_cast<WordType>(i));
258 }
259 return mask;
260 }();
261 static constexpr auto padding_mask_inv = static_cast<WordType>(~padding_mask);
262
263 [[nodiscard]] static constexpr auto word_index(etl::size_t pos) -> etl::size_t { return pos / bits_per_word; }
264
265 [[nodiscard]] static constexpr auto offset_in_word(etl::size_t pos) -> WordType
266 {
267 return static_cast<WordType>(pos & (bits_per_word - etl::size_t(1)));
268 }
269
270 constexpr auto transform_bit(etl::size_t pos, auto op) -> basic_bitset&
271 {
272 auto& word = _words[word_index(pos)];
273 word = op(word, offset_in_word(pos));
274 return *this;
275 }
276
277 etl::array<WordType, num_words> _words{};
278};
279
280} // namespace etl
281
282#endif // TETL_BITSET_BASIC_BITSET_HPP
#define TETL_PRECONDITION(...)
Definition check.hpp:16
constexpr auto all_of(InputIt first, InputIt last, Predicate p) -> bool
Checks if unary predicate p returns true for all elements in the range [first, last).
Definition all_of.hpp:15
constexpr auto transform(InputIt first, InputIt last, OutputIt dest, UnaryOp op) -> OutputIt
Applies the given function to a range and stores the result in another range, beginning at dest....
Definition transform.hpp:24
constexpr auto min(Type const &a, Type const &b, Compare comp) noexcept -> Type const &
Returns the smaller of a and b, using a compare function.
Definition min.hpp:13
constexpr auto fill(ForwardIt first, ForwardIt last, T const &value) -> void
Assigns the given value to the elements in the range [first, last).
Definition fill.hpp:11
constexpr auto set_bit(UInt word, UInt pos) noexcept -> UInt
Set bit at position pos.
Definition set_bit.hpp:19
constexpr auto reset_bit(UInt word, UInt pos) noexcept -> UInt
Reset bit at position pos.
Definition reset_bit.hpp:19
constexpr auto flip_bit(UInt word, UInt pos) noexcept -> UInt
Flip bit at position pos.
Definition flip_bit.hpp:19
constexpr auto test_bit(UInt word, UInt pos) noexcept -> bool
Test bit at position pos.
Definition test_bit.hpp:19
constexpr auto prev(BidirIt it, typename iterator_traits< BidirIt >::difference_type n=1) -> BidirIt
Return the nth predecessor of iterator it.
Definition prev.hpp:14
constexpr auto transform_reduce(InputIt1 first1, InputIt1 last1, InputIt2 first2, T init, BinaryReductionOp reduce, BinaryTransformOp transform) -> T
https://en.cppreference.com/w/cpp/algorithm/transform_reduce
Definition transform_reduce.hpp:13
Definition adjacent_find.hpp:8
constexpr auto addressof(T &arg) noexcept -> T *
Obtains the actual address of the object or function arg, even in presence of overloaded operator&.
Definition addressof.hpp:15
TETL_BUILTIN_SIZET size_t
etl::size_t is the unsigned integer type of the result of the sizeof operator.
Definition size_t.hpp:14
Definition basic_bitset.hpp:33
constexpr auto operator=(bool x) noexcept -> reference &
Definition basic_bitset.hpp:35
constexpr auto operator~() const noexcept -> bool
Definition basic_bitset.hpp:49
constexpr auto flip() noexcept -> reference &
Definition basic_bitset.hpp:51
constexpr auto operator=(reference const &x) noexcept -> reference &
Definition basic_bitset.hpp:41
constexpr auto count() const noexcept -> etl::size_t
Returns the number of bits that are set to true.
Definition basic_bitset.hpp:127
constexpr auto none() const noexcept -> bool
Checks if none of the bits are set to true.
Definition basic_bitset.hpp:121
constexpr auto set() noexcept -> basic_bitset &
Sets all bits to true.
Definition basic_bitset.hpp:143
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:219
constexpr auto any() const noexcept -> bool
Checks if any bits are set to true.
Definition basic_bitset.hpp:118
constexpr auto reset() noexcept -> basic_bitset &
Sets all bits to false.
Definition basic_bitset.hpp:164
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:210
constexpr auto unchecked_reset(etl::size_t pos) -> basic_bitset &
Sets the bit at position pos to false.
Definition basic_bitset.hpp:172
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:231
constexpr auto unchecked_test(etl::size_t pos) const -> bool
Returns true if the bit at position pos is set.
Definition basic_bitset.hpp:136
constexpr auto flip() noexcept -> basic_bitset &
Flips all bits.
Definition basic_bitset.hpp:179
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:75
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:243
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:201
constexpr auto all() const noexcept -> bool
Checks if all bits are set to true.
Definition basic_bitset.hpp:104
constexpr auto unchecked_flip(etl::size_t pos) -> basic_bitset &
Flip bit at position pos.
Definition basic_bitset.hpp:194
constexpr auto unchecked_set(etl::size_t pos, bool value=true) -> basic_bitset &
Set bit at position pos to value.
Definition basic_bitset.hpp:157
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:237
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:97
constexpr auto size() const noexcept -> etl::size_t
Returns the number of bits that the bitset holds.
Definition basic_bitset.hpp:85
constexpr auto operator[](etl::size_t pos) const -> bool
Returns true if the bit at position pos is set.
Definition basic_bitset.hpp:89
static constexpr int digits
Definition numeric_limits.hpp:24
static constexpr auto max() noexcept
Definition numeric_limits.hpp:21
Function object for performing addition. Effectively calls operator+ on two instances of type T....
Definition plus.hpp:14