35#ifndef CCSDS124_BITVECTOR_HPP
36#define CCSDS124_BITVECTOR_HPP
60 int clz = __builtin_clz(word);
61 word &= ~(1U << (31U -
static_cast<std::uint32_t
>(clz)));
75 int ctz = __builtin_ctz(word);
93 static constexpr std::size_t
NUM_WORDS = (N + 31) / 32;
96 static constexpr std::size_t
NUM_BYTES = (N + 7) / 8;
107 [[nodiscard]]
constexpr std::size_t
length() const noexcept {
115 [[nodiscard]]
constexpr std::size_t
num_words() const noexcept {
132 [[nodiscard]]
inline int get_bit(std::size_t pos)
const noexcept {
133 if (pos >= N) [[unlikely]]
146 std::size_t word_idx = pos >> 5;
147 std::size_t bit_in_word = 31U - (pos & 31U);
148 return static_cast<int>((data_[word_idx] >> bit_in_word) & 1U);
157 inline void set_bit(std::size_t pos,
int value)
noexcept {
158 if (pos >= N) [[unlikely]]
171 std::size_t word_idx = pos >> 5;
172 std::size_t bit_in_word = 31U - (pos & 31U);
175 data_[word_idx] |= (1U << bit_in_word);
177 data_[word_idx] &= ~(1U << bit_in_word);
195 for (std::size_t i = 0; i <
NUM_WORDS; ++i) {
196 data_[i] = a.data_[i] ^ b.data_[i];
206 for (std::size_t i = 0; i <
NUM_WORDS; ++i) {
207 data_[i] = a.data_[i] | b.data_[i];
217 for (std::size_t i = 0; i <
NUM_WORDS; ++i) {
218 data_[i] = a.data_[i] & b.data_[i];
227 for (std::size_t i = 0; i <
NUM_WORDS; ++i) {
228 data_[i] = ~a.data_[i];
239 for (std::size_t i = 0; i <
NUM_WORDS - 1; ++i) {
240 data_[i] = (a.data_[i] << 1) | (a.data_[i + 1] >> 31);
252 for (std::size_t i = 0; i <
NUM_WORDS; ++i) {
253 std::uint32_t word = a.data_[
NUM_WORDS - 1 - i];
255 word = ((word & 0x55555555U) << 1) | ((word >> 1) & 0x55555555U);
256 word = ((word & 0x33333333U) << 2) | ((word >> 2) & 0x33333333U);
257 word = ((word & 0x0F0F0F0FU) << 4) | ((word >> 4) & 0x0F0F0F0FU);
258 word = __builtin_bswap32(word);
263 constexpr std::size_t extra_bits = (
NUM_WORDS * 32) - N;
264 if constexpr (extra_bits > 0) {
266 for (std::size_t i = 0; i <
NUM_WORDS - 1; ++i) {
267 data_[i] = (data_[i] << extra_bits) | (data_[i + 1] >> (32 - extra_bits));
278 for (std::size_t i = 0; i <
NUM_WORDS; ++i) {
279 data_[i] ^= other.data_[i];
297 for (std::size_t i = 0; i <
NUM_WORDS; ++i) {
298 data_[i] |= other.data_[i];
324 for (std::size_t i = 0; i <
NUM_WORDS; ++i) {
325 data_[i] &= other.data_[i];
333 for (std::size_t i = 0; i <
NUM_WORDS; ++i) {
334 data_[i] = ~data_[i];
344 for (std::size_t i = 0; i <
NUM_WORDS - 1; ++i) {
345 data_[i] = (data_[i] << 1) | (data_[i + 1] >> 31);
364 std::size_t count = 0;
365 for (std::size_t i = 0; i <
NUM_WORDS; ++i) {
366 count +=
static_cast<std::size_t
>(__builtin_popcount(data_[i]));
370 constexpr std::size_t extra_bits = (
NUM_WORDS * 32) - N;
371 if constexpr (extra_bits > 0) {
373 word_t mask = (1U << extra_bits) - 1U;
374 count -=
static_cast<std::size_t
>(__builtin_popcount(last_word & mask));
386 return data_ == other.data_;
395 return data_ != other.data_;
404 void from_bytes(
const std::uint8_t* bytes, std::size_t num_bytes)
noexcept {
408 std::size_t word_idx = 0;
409 int byte_in_word = 4;
412 for (std::size_t i = 0; i < max_bytes; ++i) {
414 word_acc |=
static_cast<word_t>(bytes[i]) << (byte_in_word * 8);
416 if (byte_in_word == 0) {
417 data_[word_idx] = word_acc;
425 if (byte_in_word < 4) {
426 data_[word_idx] = word_acc;
436 void to_bytes(std::uint8_t* bytes, std::size_t num_bytes)
const noexcept {
438 std::size_t byte_idx = 0;
440 for (std::size_t word_idx = 0; word_idx <
NUM_WORDS && byte_idx < max_bytes; ++word_idx) {
441 word_t word = data_[word_idx];
443 for (
int j = 3; j >= 0 && byte_idx < max_bytes; --j) {
444 bytes[byte_idx] =
static_cast<std::uint8_t
>((word >> (j * 8)) & 0xFFU);
467 std::array<word_t, NUM_WORDS> data_;
472 void mask_unused_bits() noexcept {
473 constexpr std::size_t extra_bits = (
NUM_WORDS * 32) - N;
474 if constexpr (extra_bits > 0 &&
NUM_WORDS > 0) {
475 word_t mask = ~((1U << extra_bits) - 1U);
Fixed-length bit vector with compile-time size.
static constexpr std::size_t NUM_WORDS
Number of 32-bit words needed.
void copy_from(const BitVector &src) noexcept
Copy from another BitVector.
void or_with(const BitVector &a, const BitVector &b) noexcept
Compute OR of two vectors (result = a | b).
constexpr std::size_t length() const noexcept
Get the number of bits.
void reverse_of(const BitVector &a) noexcept
Compute bit reversal of a vector.
void xor_of(const BitVector &a, const BitVector &b) noexcept
Compute XOR of two vectors.
int get_bit(std::size_t pos) const noexcept
Get bit value at position.
int get_bit_unchecked(std::size_t pos) const noexcept
Get bit value at position without bounds checking.
void set_bit(std::size_t pos, int value) noexcept
Set bit value at position.
void left_shift_of(const BitVector &a) noexcept
Compute left shift by 1 of a vector.
bool operator!=(const BitVector &other) const noexcept
Compare for inequality.
std::size_t hamming_weight() const noexcept
Count number of set bits (Hamming weight).
void and_of(const BitVector &a, const BitVector &b) noexcept
Compute AND of two vectors.
void xor_with(const BitVector &other) noexcept
XOR in-place with another vector.
bool operator==(const BitVector &other) const noexcept
Compare for equality.
void set_bit_unchecked(std::size_t pos, int value) noexcept
Set bit value at position without bounds checking.
void xor_with(const BitVector &a, const BitVector &b) noexcept
Compute XOR of two vectors (result = a ^ b).
static constexpr std::size_t NUM_BYTES
Number of bytes needed.
void left_shift(const BitVector &src) noexcept
Compute left shift of another vector (result = src << 1).
void left_shift() noexcept
Left shift by 1 in-place.
void or_in_place(const BitVector &other) noexcept
OR in-place with another vector (alias for or_with).
void or_of(const BitVector &a, const BitVector &b) noexcept
Compute OR of two vectors.
void from_bytes(const std::uint8_t *bytes, std::size_t num_bytes) noexcept
Load from byte array (big-endian).
void or_with(const BitVector &other) noexcept
OR in-place with another vector.
const word_t * data() const noexcept
Get raw data pointer (const version).
constexpr BitVector() noexcept
Default constructor - initializes all bits to zero.
constexpr std::size_t num_words() const noexcept
Get the number of 32-bit words.
void to_bytes(std::uint8_t *bytes, std::size_t num_bytes) const noexcept
Store to byte array (big-endian).
void zero() noexcept
Set all bits to zero.
void invert() noexcept
Invert all bits in-place.
word_t * data() noexcept
Get raw data pointer (for advanced use).
void and_with(const BitVector &other) noexcept
AND in-place with another vector.
void not_of(const BitVector &a) noexcept
Compute NOT of a vector.
CCSDS 124.0-B-1 compile-time configuration.
std::uint32_t word_t
32-bit word type for bit vector storage (matches C implementation)
int extract_msb(std::uint32_t &word) noexcept
Extract and clear the most significant set bit from a word.
int extract_lsb(std::uint32_t &word) noexcept
Extract and clear the least significant set bit from a word.