CCSDS 124.0-B-1 C 1.0.0
CCSDS 124.0-B-1 Lossless Compression
Loading...
Searching...
No Matches
encode.c
Go to the documentation of this file.
1
27#include "ccsds124.h"
28
40int ccsds124_count_encode(bitbuffer_t *output, uint32_t A) {
41 int result = CCSDS124_ERROR_INVALID_ARG;
42
59 static const uint8_t count_values[34] = {
60 0U, 0U, /* 0: unused, 1: '0' */
61 0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U, /* 2-9 */
62 0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU, /* 10-17 */
63 0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U, /* 18-25 */
64 0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU /* 26-33 */
65 };
66 static const uint8_t count_bits[34] = {
67 0U, 1U, /* 0: unused, 1: 1 bit */
68 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, /* 2-9: 8 bits each */
69 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, /* 10-17 */
70 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, /* 18-25 */
71 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U /* 26-33 */
72 };
73
74 if (output != NULL) {
75 if ((A == 0U) || (A > 65535U)) {
76 /* Invalid range - result already set to INVALID_ARG */
77 } else if (A == 1U) {
78 /* Case 1: A = 1 → '0' (single bit, no lookup overhead) */
79 result = bitbuffer_append_bit(output, 0);
80 } else if (A <= 33U) {
81 /* Fast path: use pre-computed lookup table for A=2-33 */
82 result = bitbuffer_append_value(output,
83 (uint32_t)count_values[A],
84 (size_t)count_bits[A]);
85 } else {
86 /* Case 3: A ≥ 34 → '111' ∥ BIT_E(A-2)
87 * Uses bit-by-bit approach for MISRA-C:2012 compliance. */
88
89 /* Append '111' prefix MSB-first: 1, 1, 1 */
90 result = bitbuffer_append_bit(output, 1);
91 if (result == CCSDS124_OK) {
92 result = bitbuffer_append_bit(output, 1);
93 }
94 if (result == CCSDS124_OK) {
95 result = bitbuffer_append_bit(output, 1);
96 }
97
98 if (result == CCSDS124_OK) {
99 /* Calculate E = 2⌊log₂(A-2)+1⌋ - 6
100 * floor(log2(value)) = highest set bit = 31 - clz(value) */
101 uint32_t value = A - 2U;
102 int highest_bit = 31 - __builtin_clz(value);
103 int E = (2 * (highest_bit + 1)) - 6;
104
105 /* Append BIT_E(A-2) MSB-first - E bits from bit E-1 down to bit 0 */
106 for (int i = E - 1; (i >= 0) && (result == CCSDS124_OK); i--) {
107 uint32_t shifted = value >> (uint32_t)i;
108 uint32_t masked = shifted & 1U;
109 int bit = (int)masked;
110 result = bitbuffer_append_bit(output, bit);
111 }
112 }
113 }
114 }
115
116 return result;
117}
118
/* End of Counter Encoding */
120
135int ccsds124_rle_encode(bitbuffer_t *output, const bitvector_t *input) {
136 int result = CCSDS124_ERROR_INVALID_ARG;
137
138 if ((output != NULL) && (input != NULL)) {
139 /* DeBruijn lookup table for fast LSB finding (matches reference implementation) */
140 static const uint32_t debruijn_lookup[32] = {
141 1U, 2U, 29U, 3U, 30U, 15U, 25U, 4U, 31U, 23U, 21U, 16U,
142 26U, 18U, 5U, 9U, 32U, 28U, 14U, 24U, 22U, 20U, 17U, 8U,
143 27U, 13U, 19U, 7U, 12U, 6U, 11U, 10U
144 };
145
146 result = CCSDS124_OK;
147
148 /* Start from the end of the vector */
149 int old_bit_position = (int)input->length;
150
151 /* Process words in reverse order (from high to low) */
152 for (int word = (int)input->num_words - 1; (word >= 0) && (result == CCSDS124_OK); word--) {
153 uint32_t word_data = input->data[word];
154
155 /* Process all set bits in this word */
156 while ((word_data != 0U) && (result == CCSDS124_OK)) {
157 /* Isolate the LSB: x = change & -change */
158 uint32_t lsb = word_data & (uint32_t)(-(int32_t)word_data);
159
160 /* Find LSB position using DeBruijn sequence */
161 uint32_t debruijn_index = (lsb * 0x077CB531U) >> 27U;
162 int bit_position_in_word = (int)debruijn_lookup[debruijn_index];
163
164 /* Count from the other side (reference line 754) */
165 bit_position_in_word = 32 - bit_position_in_word;
166
167 /* Calculate global bit position (reference line 756) */
168 int new_bit_position = (word * 32) + bit_position_in_word;
169
170 /* Calculate delta (number of zeros + 1) */
171 int delta = old_bit_position - new_bit_position;
172
173 /* Encode the count */
174 result = ccsds124_count_encode(output, (uint32_t)delta);
175
176 /* Update old position for next iteration */
177 old_bit_position = new_bit_position;
178
179 /* Clear the processed bit */
180 word_data ^= lsb;
181 }
182 }
183
184 /* Append terminator '10' MSB-first (bits: 1, 0) */
185 if (result == CCSDS124_OK) {
186 result = bitbuffer_append_bit(output, 1);
187 }
188 if (result == CCSDS124_OK) {
189 result = bitbuffer_append_bit(output, 0);
190 }
191 }
192
193 return result;
194}
195
/* End of Run-Length Encoding */
197
220int ccsds124_bit_extract(bitbuffer_t *output, const bitvector_t *data, const bitvector_t *mask) {
221 int result = CCSDS124_ERROR_INVALID_ARG;
222
223 if ((output != NULL) && (data != NULL) && (mask != NULL)) {
224 if (data->length != mask->length) {
225 /* Length mismatch - result already set to INVALID_ARG */
226 } else {
227 /* DeBruijn lookup for fast LSB finding (same as RLE) */
228 static const uint32_t debruijn_lookup[32] = {
229 1U, 2U, 29U, 3U, 30U, 15U, 25U, 4U, 31U, 23U, 21U, 16U,
230 26U, 18U, 5U, 9U, 32U, 28U, 14U, 24U, 22U, 20U, 17U, 8U,
231 27U, 13U, 19U, 7U, 12U, 6U, 11U, 10U
232 };
233
234 result = CCSDS124_OK;
235
236 /* Process words in REVERSE order (high to low) like RLE.
237 * This gives bits from highest position to lowest, which is
238 * the correct output order for BE (no reversal needed). */
239 for (int word = (int)mask->num_words - 1; (word >= 0) && (result == CCSDS124_OK); word--) {
240 uint32_t mask_word = mask->data[word];
241 uint32_t data_word = data->data[word];
242
243 while ((mask_word != 0U) && (result == CCSDS124_OK)) {
244 /* Isolate LSB */
245 uint32_t lsb = mask_word & (uint32_t)(-(int32_t)mask_word);
246
247 /* Find LSB position using DeBruijn */
248 uint32_t debruijn_index = (lsb * 0x077CB531U) >> 27U;
249 int bit_pos_in_word = 32 - (int)debruijn_lookup[debruijn_index];
250
251 /* Check if this bit is within the valid length */
252 int global_pos = (word * 32) + bit_pos_in_word;
253 if ((size_t)global_pos < data->length) {
254 /* Extract and output data bit directly */
255 int bit = 0;
256 if ((data_word & lsb) != 0U) {
257 bit = 1;
258 }
259 result = bitbuffer_append_bit(output, bit);
260 }
261
262 /* Clear processed bit */
263 mask_word ^= lsb;
264 }
265 }
266 }
267 }
268
269 return result;
270}
271
272
273int ccsds124_bit_extract_forward(bitbuffer_t *output, const bitvector_t *data, const bitvector_t *mask) {
274 int result = CCSDS124_ERROR_INVALID_ARG;
275
276 if ((output != NULL) && (data != NULL) && (mask != NULL)) {
277 if (data->length != mask->length) {
278 /* Length mismatch - result already set to INVALID_ARG */
279 } else {
280 result = CCSDS124_OK;
281
282 /* Process words in FORWARD order (low to high).
283 * Within each word, find MSBs first using clz to get
284 * bits from lowest position to highest. */
285 for (size_t word = 0U; (word < mask->num_words) && (result == CCSDS124_OK); word++) {
286 uint32_t mask_word = mask->data[word];
287 uint32_t data_word = data->data[word];
288
289 while ((mask_word != 0U) && (result == CCSDS124_OK)) {
290 /* Find MSB position using count leading zeros */
291 int clz = __builtin_clz(mask_word);
292 int bit_pos_in_word = clz; /* Physical position from left */
293
294 /* MSB-first: physical position 0 = bit index 0 */
295 size_t global_pos = (word * 32U) + (size_t)bit_pos_in_word;
296
297 if (global_pos < data->length) {
298 /* Extract data bit at this position */
299 uint32_t bit_mask = 1U << (31U - (uint32_t)clz);
300 int bit = 0;
301 if ((data_word & bit_mask) != 0U) {
302 bit = 1;
303 }
304 result = bitbuffer_append_bit(output, bit);
305 }
306
307 /* Clear the MSB we just processed */
308 mask_word &= ~(1U << (31U - (uint32_t)clz));
309 }
310 }
311 }
312 }
313
314 return result;
315}
316
/* End of Bit Extraction */
CCSDS 124.0-B-1 Compression Library - Public API.
int bitbuffer_append_value(bitbuffer_t *bb, uint32_t value, size_t num_bits)
Append multiple bits from a value directly to accumulator.
Definition bitbuffer.c:151
int bitbuffer_append_bit(bitbuffer_t *bb, int bit)
Append a single bit to buffer.
Definition bitbuffer.c:77
int ccsds124_bit_extract_forward(bitbuffer_t *output, const bitvector_t *data, const bitvector_t *mask)
Bit extraction in forward order (LSB to MSB).
Definition encode.c:273
int ccsds124_bit_extract(bitbuffer_t *output, const bitvector_t *data, const bitvector_t *mask)
Bit extraction (CCSDS Section 5.2.4, Equation 11).
Definition encode.c:220
int ccsds124_rle_encode(bitbuffer_t *output, const bitvector_t *input)
Run-length encoding (CCSDS Section 5.2.3, Equation 10).
Definition encode.c:135
int ccsds124_count_encode(bitbuffer_t *output, uint32_t A)
Counter encoding (CCSDS Section 5.2.2, Equation 9).
Definition encode.c:40
#define CCSDS124_ERROR_INVALID_ARG
Definition ccsds124.h:48
#define CCSDS124_OK
Definition ccsds124.h:47
Variable-length bit buffer structure.
Definition ccsds124.h:308
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