bitmask.h#
#include <sif/structures/bitmask.h>
-
SIF_STRUCTURES_BITMASK_H#
Dense array of bits, packed 64 to a word.
Used where one boolean per grid cell would otherwise cost a byte or more: the finders mark every cell swallowed by an accepted void, and at 1024^3 cells the difference between a bit and a byte is 128 MiB against 1 GiB.
The accessors are
static inlinebecause they sit in the innermost loop of the finders, where a call would cost more than the shift and mask it wraps.
-
struct sif_bitmask_t#
A bitmask for tracking boolean states densely.
Note
The plain set/unset accessors are NOT thread-safe: distinct bits share a 64-bit word, so concurrent read-modify-write silently loses updates. Code that mutates the mask from inside a parallel region must use the _atomic variants.
-
uint64_t *words#
Packed storage, 64 bits per word. Bits past #n_bits are always zero.
-
uint64_t n_bits#
Bits the caller asked for.
-
uint64_t n_words#
Words actually allocated: ceil(n_bits / 64).
-
uint64_t *words#
-
sif_bitmask_t *sif_bitmask_alloc(uint64_t n_bits)#
Allocate a bitmask with every bit clear.
- Parameters:
n_bits – Number of bits. Must be non-zero.
- Returns:
The mask, owned by the caller and released with sif_bitmask_free(). NULL if
n_bitsis 0 or on allocation failure.
-
void sif_bitmask_free(sif_bitmask_t *mask)#
Release a bitmask and its storage.
- Parameters:
mask – Mask to free. NULL is accepted and ignored.
-
void sif_bitmask_clear_all(sif_bitmask_t *mask)#
Clear every bit.
- Parameters:
mask – Mask to clear.
-
uint64_t sif_bitmask_count_set(const sif_bitmask_t *mask)#
Count the set bits.
Parallelized across words with a population count per word, so it costs a pass over the storage rather than over the bits.
- Parameters:
mask – Mask to count.
- Returns:
The number of set bits, or 0 for a NULL or empty mask.
-
static inline uint8_t sif_bitmask_get(const sif_bitmask_t *mask, uint64_t ind)#
Test one bit.
- Parameters:
mask – The mask.
ind – Bit index; must be below sif_bitmask_t::n_bits.
- Returns:
1 if the bit is set, 0 otherwise.
-
static inline void sif_bitmask_set(sif_bitmask_t *mask, uint64_t ind)#
Set one bit. Fast, and NOT thread-safe.
- Parameters:
mask – The mask.
ind – Bit index; must be below sif_bitmask_t::n_bits.
-
static inline void sif_bitmask_unset(sif_bitmask_t *mask, uint64_t ind)#
Clear one bit. Fast, and NOT thread-safe.
- Parameters:
mask – The mask.
ind – Bit index; must be below sif_bitmask_t::n_bits.
-
static inline void sif_bitmask_set_atomic(sif_bitmask_t *mask, uint64_t ind)#
Set one bit. Safe to call concurrently.
- Parameters:
mask – The mask.
ind – Bit index; must be below sif_bitmask_t::n_bits.
Note
The test-before-write is an atomic relaxed load, not a plain read: it skips the expensive RMW when the bit is already set without introducing a data race. Two threads racing to set the same bit is harmless, OR is idempotent.
-
static inline void sif_bitmask_unset_atomic(sif_bitmask_t *mask, uint64_t ind)#
Clear one bit. Safe to call concurrently.
- Parameters:
mask – The mask.
ind – Bit index; must be below sif_bitmask_t::n_bits.
Note
Same relaxed test-before-write as sif_bitmask_set_atomic().