CCSDS 124.0-B-1 C 1.0.0
CCSDS 124.0-B-1 Lossless Compression
Loading...
Searching...
No Matches
bitvector.c
Go to the documentation of this file.
1
35#include "ccsds124.h"
36#include <string.h>
37
44int bitvector_init(bitvector_t *bv, size_t num_bits) {
45 int result = CCSDS124_ERROR_INVALID_ARG;
46
47 if (bv != NULL) {
48 if ((num_bits > 0U) && (num_bits <= (size_t)CCSDS124_MAX_PACKET_LENGTH)) {
49 bv->length = num_bits;
50 /* Calculate number of 32-bit words needed */
51 size_t num_bytes = (num_bits + 7U) / 8U;
52 bv->num_words = (num_bytes + 3U) / 4U; /* Ceiling division */
53
54 /* Zero all words */
55 (void)memset(bv->data, 0, bv->num_words * sizeof(uint32_t));
56
57 result = CCSDS124_OK;
58 }
59 }
60
61 return result;
62}
63
64
66 if (bv != NULL) {
67 (void)memset(bv->data, 0, bv->num_words * sizeof(uint32_t));
68 }
69}
70
71
72void bitvector_copy(bitvector_t *dest, const bitvector_t *src) {
73 if ((dest != NULL) && (src != NULL)) {
74 dest->length = src->length;
75 dest->num_words = src->num_words;
76 (void)memcpy(dest->data, src->data, src->num_words * sizeof(uint32_t));
77 }
78}
79
/* End of Initialization Functions */
81
82/* Note: bitvector_get_bit and bitvector_set_bit are now static inline in ccsds124.h */
83
93void bitvector_xor(bitvector_t *result, const bitvector_t *a, const bitvector_t *b) {
94 if ((result != NULL) && (a != NULL) && (b != NULL)) {
95 size_t num_words = a->num_words;
96 if (b->num_words < num_words) {
97 num_words = b->num_words;
98 }
99
100 for (size_t i = 0U; i < num_words; i++) {
101 result->data[i] = a->data[i] ^ b->data[i];
102 }
103
104 result->length = a->length;
105 result->num_words = a->num_words;
106 }
107}
108
109
110void bitvector_or(bitvector_t *result, const bitvector_t *a, const bitvector_t *b) {
111 if ((result != NULL) && (a != NULL) && (b != NULL)) {
112 size_t num_words = a->num_words;
113 if (b->num_words < num_words) {
114 num_words = b->num_words;
115 }
116
117 for (size_t i = 0U; i < num_words; i++) {
118 result->data[i] = a->data[i] | b->data[i];
119 }
120
121 result->length = a->length;
122 result->num_words = a->num_words;
123 }
124}
125
126
127void bitvector_and(bitvector_t *result, const bitvector_t *a, const bitvector_t *b) {
128 if ((result != NULL) && (a != NULL) && (b != NULL)) {
129 size_t num_words = a->num_words;
130 if (b->num_words < num_words) {
131 num_words = b->num_words;
132 }
133
134 for (size_t i = 0U; i < num_words; i++) {
135 result->data[i] = a->data[i] & b->data[i];
136 }
137
138 result->length = a->length;
139 result->num_words = a->num_words;
140 }
141}
142
143
144void bitvector_not(bitvector_t *result, const bitvector_t *a) {
145 if ((result != NULL) && (a != NULL)) {
146 for (size_t i = 0U; i < a->num_words; i++) {
147 result->data[i] = ~a->data[i];
148 }
149
150 /* Mask off unused bits in last word with big-endian packing */
151 if (a->num_words > 0U) {
152 size_t num_bytes = (a->length + 7U) / 8U;
153 size_t bytes_in_last_word = ((num_bytes - 1U) % 4U) + 1U;
154 size_t bits_in_last_byte = a->length - ((num_bytes - 1U) * 8U);
155
156 /* Create mask for valid bits in big-endian word */
157 uint32_t mask = 0U;
158 for (size_t byte = 0U; byte < bytes_in_last_word; byte++) {
159 uint8_t byte_mask;
160 if (byte == (bytes_in_last_word - 1U)) {
161 /* MSB-aligned: valid bits are at the top of the byte */
162 byte_mask = (uint8_t)(0xFFU << (8U - bits_in_last_byte));
163 } else {
164 byte_mask = 0xFFU;
165 }
166 uint32_t shift_amt = (3U - (uint32_t)byte) * 8U;
167 mask |= ((uint32_t)byte_mask) << shift_amt;
168 }
169 result->data[a->num_words - 1U] &= mask;
170 }
171
172 result->length = a->length;
173 result->num_words = a->num_words;
174 }
175}
176
177
179 if ((result != NULL) && (a != NULL)) {
180 result->length = a->length;
181 result->num_words = a->num_words;
182
183 /* MSB-first with big-endian word packing:
184 * Left shift means shift towards MSB (bit 0).
185 * In big-endian packing, MSB is at high bits of first word.
186 * Word-level: shift each word left by 1, carry high bit from next word. */
187 if (a->num_words > 0U) {
188 /* Process words from first (MSB) to last (LSB) */
189 for (size_t i = 0U; i < (a->num_words - 1U); i++) {
190 /* Shift current word left by 1, bring in MSB from next word */
191 result->data[i] = (a->data[i] << 1U) | (a->data[i + 1U] >> 31U);
192 }
193 /* Last word: shift left, LSB becomes 0 */
194 result->data[a->num_words - 1U] = a->data[a->num_words - 1U] << 1U;
195 }
196 }
197}
198
199
201 if ((result != NULL) && (a != NULL)) {
202 bitvector_zero(result);
203 result->length = a->length;
204 result->num_words = a->num_words;
205
206 /* Reverse bit order */
207 for (size_t i = 0U; i < a->length; i++) {
208 int bit = bitvector_get_bit(a, i);
209 bitvector_set_bit(result, (a->length - 1U) - i, bit);
210 }
211 }
212}
213
/* End of Bitwise Operations */
215
223 size_t count = 0U;
224
225 if (bv != NULL) {
226 /* Count '1' bits in each word using popcount intrinsic */
227 for (size_t i = 0U; i < bv->num_words; i++) {
228 count += (size_t)__builtin_popcount(bv->data[i]);
229 }
230
231 /* Adjust for any extra bits in last word */
232 size_t num_bytes = (bv->length + 7U) / 8U;
233 size_t extra_bits = (num_bytes * 8U) - bv->length;
234 if ((extra_bits > 0U) && (bv->num_words > 0U)) {
235 /* Count bits in the unused portion of the last word and subtract */
236 uint32_t last_word = bv->data[bv->num_words - 1U];
237 uint32_t mask = ((1U << (uint32_t)extra_bits) - 1U); /* Mask for the unused LSBs */
238 uint32_t extra_word = last_word & mask;
239 count -= (size_t)__builtin_popcount(extra_word);
240 }
241 }
242
243 return count;
244}
245
246
247int bitvector_equals(const bitvector_t *a, const bitvector_t *b) {
248 int result = 0;
249
250 if ((a != NULL) && (b != NULL)) {
251 if (a->length == b->length) {
252 if (memcmp(a->data, b->data, a->num_words * sizeof(uint32_t)) == 0) {
253 result = 1;
254 }
255 }
256 }
257
258 return result;
259}
260
/* End of Utility Functions */
262
269int bitvector_from_bytes(bitvector_t *bv, const uint8_t *data, size_t num_bytes) {
270 int result = CCSDS124_ERROR_INVALID_ARG;
271
272 if ((bv != NULL) && (data != NULL)) {
273 size_t expected_bytes = (bv->length + 7U) / 8U;
274 if (num_bytes > expected_bytes) {
276 } else {
277 /* Zero the array first */
278 (void)memset(bv->data, 0, bv->num_words * sizeof(uint32_t));
279
280 /* Pack bytes into 32-bit words (big-endian) */
281 int j = 4; /* Counter for bytes within word (4, 3, 2, 1) */
282 uint32_t bytes_to_int = 0U;
283 size_t current_word = 0U;
284
285 for (size_t current_byte = 0U; current_byte < num_bytes; current_byte++) {
286 j--;
287 bytes_to_int |= ((uint32_t)data[current_byte]) << ((unsigned)j * 8U);
288
289 if (j == 0) {
290 /* Word complete - store it */
291 bv->data[current_word] = bytes_to_int;
292 current_word++;
293 bytes_to_int = 0U;
294 j = 4;
295 }
296 }
297
298 /* Handle incomplete final word */
299 if (j < 4) {
300 bv->data[current_word] = bytes_to_int;
301 }
302
303 result = CCSDS124_OK;
304 }
305 }
306
307 return result;
308}
309
310
311int bitvector_to_bytes(const bitvector_t *bv, uint8_t *data, size_t num_bytes) {
312 int result = CCSDS124_ERROR_INVALID_ARG;
313
314 if ((bv != NULL) && (data != NULL)) {
315 size_t expected_bytes = (bv->length + 7U) / 8U;
316 if (num_bytes < expected_bytes) {
318 } else {
319 /* Extract bytes from 32-bit words (big-endian) */
320 size_t byte_index = 0U;
321 for (size_t word_index = 0U; (word_index < bv->num_words) && (byte_index < num_bytes); word_index++) {
322 uint32_t word = bv->data[word_index];
323
324 /* Extract up to 4 bytes from this word */
325 for (int j = 3; (j >= 0) && (byte_index < expected_bytes); j--) {
326 data[byte_index] = (uint8_t)((word >> ((unsigned)j * 8U)) & 0xFFU);
327 byte_index++;
328 }
329 }
330
331 result = CCSDS124_OK;
332 }
333 }
334
335 return result;
336}
337
/* End of Byte Conversion Functions */
CCSDS 124.0-B-1 Compression Library - Public API.
void bitvector_copy(bitvector_t *dest, const bitvector_t *src)
Copy bit vector contents.
Definition bitvector.c:72
int bitvector_from_bytes(bitvector_t *bv, const uint8_t *data, size_t num_bytes)
Load bit vector from byte array.
Definition bitvector.c:269
int bitvector_to_bytes(const bitvector_t *bv, uint8_t *data, size_t num_bytes)
Store bit vector to byte array.
Definition bitvector.c:311
void bitvector_xor(bitvector_t *result, const bitvector_t *a, const bitvector_t *b)
Bitwise XOR operation.
Definition bitvector.c:93
void bitvector_reverse(bitvector_t *result, const bitvector_t *a)
Reverse bit order.
Definition bitvector.c:200
size_t bitvector_hamming_weight(const bitvector_t *bv)
Count number of set bits (Hamming weight).
Definition bitvector.c:222
static void bitvector_set_bit(bitvector_t *bv, size_t pos, int value)
Set bit value at position (inline for performance).
Definition ccsds124.h:188
int bitvector_init(bitvector_t *bv, size_t num_bits)
Initialize a bit vector with specified length.
Definition bitvector.c:44
static int bitvector_get_bit(const bitvector_t *bv, size_t pos)
Get bit value at position (inline for performance).
Definition ccsds124.h:169
int bitvector_equals(const bitvector_t *a, const bitvector_t *b)
Compare two bit vectors for equality.
Definition bitvector.c:247
void bitvector_not(bitvector_t *result, const bitvector_t *a)
Bitwise NOT operation.
Definition bitvector.c:144
void bitvector_zero(bitvector_t *bv)
Set all bits to zero.
Definition bitvector.c:65
void bitvector_left_shift(bitvector_t *result, const bitvector_t *a)
Left shift by one bit.
Definition bitvector.c:178
void bitvector_and(bitvector_t *result, const bitvector_t *a, const bitvector_t *b)
Bitwise AND operation.
Definition bitvector.c:127
void bitvector_or(bitvector_t *result, const bitvector_t *a, const bitvector_t *b)
Bitwise OR operation.
Definition bitvector.c:110
#define CCSDS124_MAX_PACKET_LENGTH
Definition ccsds124.h:66
#define CCSDS124_ERROR_OVERFLOW
Definition ccsds124.h:49
#define CCSDS124_ERROR_INVALID_ARG
Definition ccsds124.h:48
#define CCSDS124_OK
Definition ccsds124.h:47
#define CCSDS124_ERROR_UNDERFLOW
Definition ccsds124.h:50
Fixed-length bit vector structure.
Definition ccsds124.h:133
size_t num_words
Definition ccsds124.h:136
size_t length
Definition ccsds124.h:135
uint32_t data[((CCSDS124_MAX_PACKET_BYTES)+3U)/4U]
Definition ccsds124.h:134