MT Core (C++)
Core library for replacing C++ standard in project usage
Loading...
Searching...
No Matches
mtcore::Bitset Struct Reference

Represents a bitset with dynamically allocated memory (using an mtcore allocator) Allows operating on an arbitrary number of bits. More...

#include <bitset.hpp>

Collaboration diagram for mtcore::Bitset:

Classes

struct  BitsetAccess
 Helper for accessing a bitset position (including for setting bits) More...
 
struct  SetBitIter
 Simple bit set iterator that uses next() iteration to return the indices of all set bits. More...
 

Public Member Functions

Result< void, AllocationErrorinit (mtcore::Allocator &allocator, const size_t total)
 Initializes a bitset to have a total number of bits All bits will be set to zero.
 
Result< void, BitStrInitErrorinit (mtcore::Allocator &allocator, const Slice< const char > binaryStr)
 Initializes a bitset from a binary string of 1's and 0's.
 
Result< void, BitStrInitErrorinit (mtcore::Allocator &allocator, const size_t total, const Slice< const char > binaryStr)
 Initializes a bitset of a given size from a string Any bits not set by the string will be zero.
 
void deinit (mtcore::Allocator &allocator)
 Deinitialies a bitset.
 
BitsetAccess operator[] (const size_t index)
 Access an individual bit at a specific position.
 
bool operator[] (const size_t index) const
 Access an individual bit at a specific position.
 
size_t size () const
 Gets the size of the bitset.
 
bool at (const size_t pos) const
 Reads a bit at a specific position.
 
Result< Bitset, AllocationErrorclone (mtcore::Allocator &allocator)
 Clones a bitset using a specific allocator.
 
Result< Bitset, AllocationErrorclone (mtcore::Allocator &allocator, const size_t newLen)
 Clones and resizes a bitset using a specific allocator.
 
Result< void, AllocationErrorresize (Allocator &alloc, const size_t newLen, const bool newVal=false)
 
Bitsetset (const size_t pos, const bool val)
 Sets a bit at a position to a specific value.
 
Bitsettoggle (const size_t pos)
 Toggles a bit at a specific position.
 
Optional< size_t > first_set () const
 Returns the position of the first set bit (if one is set) Otherwise, returns a null Optional.
 
size_t pop_count () const
 Counts the number of set bits in the bitset.
 
SetBitIter set_bits () const
 Iterates over the indices of all set bits in the bitset.
 
Bitsetoperator&= (const Bitset &other)
 
Bitsetoperator|= (const Bitset &other)
 
Bitsetoperator^= (const Bitset &other)
 
void set_all (const bool value)
 Sets all bits to a specific value.
 
Bitsetoperator<<= (const size_t amount)
 
Bitsetoperator>>= (const size_t amount)
 

Public Attributes

Slice< u64bits
 
size_t len = 0
 

Detailed Description

Represents a bitset with dynamically allocated memory (using an mtcore allocator) Allows operating on an arbitrary number of bits.

Definition at line 46 of file bitset.hpp.

Member Function Documentation

◆ at()

bool mtcore::Bitset::at ( const size_t pos) const
inlinenodiscard

Reads a bit at a specific position.

Parameters
posBit index to read
Returns
whether it is set or not

Definition at line 179 of file bitset.hpp.

179 {
180 ensure(bits.head, "BITSET NOT INITIALIZED");
181 ensure(pos < len, "OUT OF BOUNDS ACCESS");
182 const auto block = pos / 64;
183 const auto bit = pos % 64;
184 const u64 bitMask = static_cast<u64>(0x1) << bit;
185 return (bits[block] & bitMask) != 0;
186 }
#define ensure(check,...)
Ensures that a check holds true, aborts the program if not true Will print error if the condition is ...
uint64_t u64
Alias for 64-bit unsigned ints.
Slice< u64 > bits
Definition bitset.hpp:47
Here is the caller graph for this function:

◆ clone() [1/2]

Result< Bitset, AllocationError > mtcore::Bitset::clone ( mtcore::Allocator & allocator)
inline

Clones a bitset using a specific allocator.

Parameters
allocatorAllocator to use for cloning
Returns
Bitset on success, or error on failure

Definition at line 193 of file bitset.hpp.

193 {
194 ensure(bits.head, "BITSET NOT INITIALIZED");
195 return clone(allocator, len);
196 }
Result< Bitset, AllocationError > clone(mtcore::Allocator &allocator)
Clones a bitset using a specific allocator.
Definition bitset.hpp:193
Here is the call graph for this function:
Here is the caller graph for this function:

◆ clone() [2/2]

Result< Bitset, AllocationError > mtcore::Bitset::clone ( mtcore::Allocator & allocator,
const size_t newLen )
inline

Clones and resizes a bitset using a specific allocator.

Parameters
allocatorAllocator to use for cloning
newLenNew length for the clone
Returns
Bitset on success, or error on failure

Definition at line 204 of file bitset.hpp.

204 {
205 ensure(bits.head, "BITSET NOT INITIALIZED");
206 Bitset res;
207 auto initRes = res.init(allocator, newLen);
208 if (initRes.is_error()) {
209 return initRes.error();
210 }
211 for (size_t i = 0; i < res.bits.len && i < bits.len; ++i) {
212 res.bits[i] = bits[i];
213 }
214 return res;
215 }
Here is the call graph for this function:

◆ deinit()

void mtcore::Bitset::deinit ( mtcore::Allocator & allocator)
inline

Deinitialies a bitset.

Parameters
allocatorAllocator to use for deinitialization

Definition at line 122 of file bitset.hpp.

122 {
123 if (bits.head != nullptr) {
124 allocator.destroy_many(bits);
125 }
126 len = 0;
127 }
void destroy_many(Slice< T > s)
Destroys objects allocated by this allocator by calling the destructors and freeing memory.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ first_set()

Optional< size_t > mtcore::Bitset::first_set ( ) const
inlinenodiscard

Returns the position of the first set bit (if one is set) Otherwise, returns a null Optional.

Returns
Optional with first set bit position

Definition at line 293 of file bitset.hpp.

293 {
294 ensure(bits.head, "BITSET NOT INITIALIZED");
295 for (size_t i = 0; i < bits.len; ++i) {
296 if (bits[i]) {
297 return 64 * i + std::countr_zero(bits[i]);
298 }
299 }
300 return nullopt;
301 }
constexpr auto nullopt
Placeholder value for an empty Optional.
Definition optional.hpp:409

◆ init() [1/3]

Result< void, AllocationError > mtcore::Bitset::init ( mtcore::Allocator & allocator,
const size_t total )
inlinenodiscard

Initializes a bitset to have a total number of bits All bits will be set to zero.

Parameters
allocatorAllocator to use for memory allocation
totalNumber of bits to use

Definition at line 56 of file bitset.hpp.

56 {
57 ensure(!bits.head, "ALREADY ALLOCATED");
58 this->len = total;
59 const auto sliceLen = total / 64 + (total % 64 ? 1 : 0);
60 ensure(sliceLen > 0, "CANNOT CREATE EMPTY BITSET");
61
62 const auto allocBitsRes = allocator.create_many<u64>(sliceLen);
63 if (allocBitsRes.is_error()) {
64 return allocBitsRes.error();
65 }
66 bits = *allocBitsRes;
67 memset(bits.head, 0, sliceLen * sizeof(u64));
68 return success();
69 }
Success< void > success()
Creates a successful void Result object.
Definition result.hpp:398
Result< Slice< T >, AllocationError > create_many(size_t count=1)
Allocates some block of memory with an allocator with a known type Will call default constructor on t...
Here is the call graph for this function:
Here is the caller graph for this function:

◆ init() [2/3]

Result< void, BitStrInitError > mtcore::Bitset::init ( mtcore::Allocator & allocator,
const size_t total,
const Slice< const char > binaryStr )
inline

Initializes a bitset of a given size from a string Any bits not set by the string will be zero.

Parameters
allocatorAllocator to use for memory allocation
totalNumber of bits to use
binaryStrBinary string to use for initializing bits

Definition at line 88 of file bitset.hpp.

89 {
90 ensure(!bits.head, "ALREADY ALLOCATED");
91 {
92 char cur = '\0';
93 auto iter = binaryStr.iter();
94 while (iter.next().copy_if_present(cur)) {
95 if (cur != '1' && cur != '0') {
97 }
98 }
99 }
100
101 auto initRes = init(allocator, total);
102 if (initRes.is_error()) {
104 }
105
106 char cur = '\0';
107 auto iter = binaryStr.iter();
108 size_t index = 0;
109 while (iter.next().copy_if_present(cur)) {
110 mtdefer { ++index; };
111 if (cur == '1') {
112 set(index, true);
113 }
114 }
115 return success();
116 }
#define mtdefer
Defer statement that will mtdefer execution until the scope is left, at which point the code will run...
Error< Underlying > error(Underlying err)
Creates an error.
Definition result.hpp:425
Bitset & set(const size_t pos, const bool val)
Sets a bit at a position to a specific value.
Definition bitset.hpp:257
Result< void, AllocationError > init(mtcore::Allocator &allocator, const size_t total)
Initializes a bitset to have a total number of bits All bits will be set to zero.
Definition bitset.hpp:56
Here is the call graph for this function:

◆ init() [3/3]

Result< void, BitStrInitError > mtcore::Bitset::init ( mtcore::Allocator & allocator,
const Slice< const char > binaryStr )
inline

Initializes a bitset from a binary string of 1's and 0's.

Parameters
allocatorAllocator to use for memory allocation
binaryStrBinary string to use for initializing bits

Definition at line 76 of file bitset.hpp.

76 {
77 ensure(!bits.head, "ALREADY ALLOCATED");
78 return init(allocator, binaryStr.len, binaryStr);
79 }
Here is the call graph for this function:

◆ operator&=()

Bitset & mtcore::Bitset::operator&= ( const Bitset & other)
inline

Definition at line 351 of file bitset.hpp.

351 {
352 ensure(bits.head, "BITSET NOT INITIALIZED");
353 size_t i = 0;
354 for (; i < other.bits.len && i < bits.len; ++i) {
355 bits[i] &= other.bits[i];
356 }
357 for (; i < bits.len; ++i) {
358 bits[i] = 0;
359 }
360 return *this;
361 }

◆ operator<<=()

Bitset & mtcore::Bitset::operator<<= ( const size_t amount)
inline

Definition at line 398 of file bitset.hpp.

398 {
399 ensure(bits.head, "BITSET NOT INITIALIZED");
400 const auto blockShift = amount / 64;
401 const auto bitShift = amount % 64;
402 if (blockShift > bits.len) {
403 set_all(false);
404 }
405 else {
406 for (size_t i = 0; i < bits.len - blockShift; ++i) {
407 const auto finalIndex = bits.len - i - 1;
408 const auto sourceIndex = bits.len - i - 1 - blockShift;
409 bits[finalIndex] = bits[sourceIndex];
410 }
411 for (size_t i = 0; i < blockShift; ++i) {
412 bits[i] = 0;
413 }
414
415 constexpr u64 fullMask = std::numeric_limits<u64>::max();
416 if (bitShift) {
417 const u64 keepMask = fullMask >> bitShift;
418 const u64 carryMask = ~keepMask;
419
420 u64 carry = 0;
421 for (size_t i = 0; i < bits.len; ++i) {
422 const auto newCarry = (bits[i] & carryMask) >> (64 - bitShift);
423 bits[i] = ((bits[i] & keepMask) << bitShift) | carry;
424 carry = newCarry;
425 }
426 }
427
428 const u64 finalMask = fullMask >> (len % 64);
429 bits[bits.len - 1] &= finalMask;
430 }
431 return *this;
432 }
void set_all(const bool value)
Sets all bits to a specific value.
Definition bitset.hpp:383
Here is the call graph for this function:

◆ operator>>=()

Bitset & mtcore::Bitset::operator>>= ( const size_t amount)
inline

Definition at line 434 of file bitset.hpp.

434 {
435 ensure(bits.head, "BITSET NOT INITIALIZED");
436 const auto blockShift = amount / 64;
437 const auto bitShift = amount % 64;
438 if (blockShift > bits.len) {
439 set_all(false);
440 }
441 else {
442 for (size_t i = 0; i < bits.len - blockShift; ++i) {
443 const auto finalIndex = i;
444 const auto sourceIndex = i + blockShift;
445 bits[finalIndex] = bits[sourceIndex];
446 }
447 for (size_t i = bits.len - blockShift; i < bits.len; ++i) {
448 bits[i] = 0;
449 }
450
451 const u64 fullMask = std::numeric_limits<u64>::max();
452 if (bitShift) {
453 const u64 keepMask = fullMask << bitShift;
454 const u64 carryMask = ~keepMask;
455
456 u64 carry = 0;
457 for (size_t i = 0; i < bits.len; ++i) {
458 const auto newCarry = (bits[i] & carryMask) << (64 - bitShift);
459 bits[i] = ((bits[i] & keepMask) >> bitShift) | carry;
460 carry = newCarry;
461 }
462 }
463
464 const u64 finalMask = fullMask << (len % 64);
465 bits[bits.len - 1] &= finalMask;
466 }
467 return *this;
468 }
Here is the call graph for this function:

◆ operator[]() [1/2]

BitsetAccess mtcore::Bitset::operator[] ( const size_t index)
inlinenodiscard

Access an individual bit at a specific position.

Parameters
indexBit index to access
Returns
Wrapper for reading/setting bit

Definition at line 154 of file bitset.hpp.

154 {
155 ensure(bits.head, "BITSET NOT INITIALIZED");
156 ensure(index < len, "OUT OF BOUNDS ACCESS");
157 return {.pos = index, .bs = *this};
158 }

◆ operator[]() [2/2]

bool mtcore::Bitset::operator[] ( const size_t index) const
inlinenodiscard

Access an individual bit at a specific position.

Parameters
indexBit index to access
Returns
Wrapper for reading/setting bit

Definition at line 165 of file bitset.hpp.

165{ return at(index); }
bool at(const size_t pos) const
Reads a bit at a specific position.
Definition bitset.hpp:179
Here is the call graph for this function:

◆ operator^=()

Bitset & mtcore::Bitset::operator^= ( const Bitset & other)
inline

Definition at line 371 of file bitset.hpp.

371 {
372 ensure(bits.head, "BITSET NOT INITIALIZED");
373 for (size_t i = 0; i < other.bits.len && i < bits.len; ++i) {
374 bits[i] ^= other.bits[i];
375 }
376 return *this;
377 }

◆ operator|=()

Bitset & mtcore::Bitset::operator|= ( const Bitset & other)
inline

Definition at line 363 of file bitset.hpp.

363 {
364 ensure(bits.head, "BITSET NOT INITIALIZED");
365 for (size_t i = 0; i < other.bits.len && i < bits.len; ++i) {
366 bits[i] |= other.bits[i];
367 }
368 return *this;
369 }

◆ pop_count()

size_t mtcore::Bitset::pop_count ( ) const
inlinenodiscard

Counts the number of set bits in the bitset.

Returns
count of set bits

Definition at line 307 of file bitset.hpp.

307 {
308 ensure(bits.head, "BITSET NOT INITIALIZED");
309 size_t count = 0;
310 for (size_t i = 0; i < bits.len; ++i) {
311 count += std::popcount(bits[i]);
312 }
313 return count;
314 }

◆ resize()

Result< void, AllocationError > mtcore::Bitset::resize ( Allocator & alloc,
const size_t newLen,
const bool newVal = false )
inline

Definition at line 217 of file bitset.hpp.

217 {
218 ensure(bits.head, "BITSET NOT INITIALIZED");
219 Bitset res;
220 auto initRes = res.init(alloc, newLen);
221
222 if (initRes.is_error()) {
223 return initRes.error();
224 }
225
226 // by setting all, any new chunks will have the new value set
227 if (newVal) {
228 res.set_all(true);
229 }
230
231 // Copy the old bits over, this will overwrite any existing set bits
232 for (size_t i = 0; i < res.bits.len && i < bits.len; ++i) {
233 res.bits[i] = bits[i];
234 }
235
236 if (newVal) {
237 // For the last segment copied over, just set the new bits individually
238 for (size_t i = (bits.len - 1) * 64; i < newLen && i < bits.len * 64; ++i) {
239 set(i, true);
240 }
241 }
242
243 // Now that we have our copy, do a swap
244 std::swap(bits, res.bits);
245 std::swap(len, res.len);
246
247 // Finally, clean up the old bits
248 res.deinit(alloc);
249 return success();
250 }
Here is the call graph for this function:

◆ set()

Bitset & mtcore::Bitset::set ( const size_t pos,
const bool val )
inline

Sets a bit at a position to a specific value.

Parameters
posBit index to set
valBit value to set to

Definition at line 257 of file bitset.hpp.

257 {
258 ensure(bits.head, "BITSET NOT INITIALIZED");
259 ensure(pos < len, "OUT OF BOUNDS ACCESS");
260 const u64 block = pos / 64;
261 const u64 bit = pos % 64;
262 ensure(bit + block * 64 == pos, 'BAD POSITION DECONSTRUCT');
263 const u64 bitMask = static_cast<u64>(0x1) << bit;
264 if (val) {
265 bits[block] |= bitMask;
266 }
267 else {
268 bits[block] &= ~bitMask;
269 }
270 return *this;
271 }
Here is the caller graph for this function:

◆ set_all()

void mtcore::Bitset::set_all ( const bool value)
inline

Sets all bits to a specific value.

Parameters
valueto set to

Definition at line 383 of file bitset.hpp.

383 {
384 ensure(bits.head, "BITSET NOT INITIALIZED");
385 const u64 mask = value ? std::numeric_limits<u64>::max() : 0;
386
387 // For the first n 64-bit segments, just set them all
388 for (size_t i = 0; i < bits.len - 1; ++i) {
389 bits[i] = mask;
390 }
391
392 // For the last segment, just set what we have allocated
393 for (size_t i = (bits.len - 1) * 64; i < size(); ++i) {
394 set(i, value);
395 }
396 }
size_t size() const
Gets the size of the bitset.
Definition bitset.hpp:172
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_bits()

SetBitIter mtcore::Bitset::set_bits ( ) const
inlinenodiscard

Iterates over the indices of all set bits in the bitset.

Returns
an iterator over all set bits

Definition at line 346 of file bitset.hpp.

346 {
347 ensure(bits.head, "BITSET NOT INITIALIZED");
348 return SetBitIter{*this, bits[0], 0};
349 }
Simple bit set iterator that uses next() iteration to return the indices of all set bits.
Definition bitset.hpp:320

◆ size()

size_t mtcore::Bitset::size ( ) const
inlinenodiscard

Gets the size of the bitset.

Parameters
posBit index to read
Returns
number of bits in bitset (not number of bytes allocated)

Definition at line 172 of file bitset.hpp.

172{ return len; }
Here is the caller graph for this function:

◆ toggle()

Bitset & mtcore::Bitset::toggle ( const size_t pos)
inline

Toggles a bit at a specific position.

Parameters
posBit index to toggle
Returns
a reference to the current bitset

Definition at line 278 of file bitset.hpp.

278 {
279 ensure(bits.head, "BITSET NOT INITIALIZED");
280 ensure(pos < len, "OUT OF BOUNDS ACCESS");
281 const u64 block = pos / 64;
282 const u64 bit = pos % 64;
283 const u64 bitMask = 0x1 << bit;
284 bits[block] ^= bitMask;
285 return *this;
286 }

Member Data Documentation

◆ bits

Slice<u64> mtcore::Bitset::bits

Definition at line 47 of file bitset.hpp.

◆ len

size_t mtcore::Bitset::len = 0

Definition at line 48 of file bitset.hpp.


The documentation for this struct was generated from the following file: