blob: 94f60eb3e178dc946d118e50ceebfa94cfe5e0ca [file] [log] [blame]
Neels Hofmeyr17518fe2017-06-20 04:35:06 +02001/*! \file bitcomp.c
2 * Osmocom bit compression routines */
3/*
4 * (C) 2016 sysmocom s.f.m.c. GmbH by Max Suraev <msuraev@sysmocom.de>
Max5c18e262016-02-05 13:55:38 +01005 *
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 */
23
24/*! \defgroup bitcomp Bit compression
25 * @{
Neels Hofmeyr17518fe2017-06-20 04:35:06 +020026 * \file bitcomp.c */
Max5c18e262016-02-05 13:55:38 +010027
28#include <stdint.h>
29#include <stdbool.h>
30#include <errno.h>
31#include <string.h>
32
33#include <osmocom/core/bitvec.h>
34#include <osmocom/core/bitcomp.h>
35
36/*
37 * Terminating codes for uninterrupted sequences of 0 and 1 up to 64 bit length
38 * according to TS 44.060 9.1.10
39 */
40static const unsigned t4_term[2][64] = {
41 {
42 0b0000110111,
43 0b10,
44 0b11,
45 0b010,
46 0b011,
47 0b0011,
48 0b0010,
49 0b00011,
50 0b000101,
51 0b000100,
52 0b0000100,
53 0b0000101,
54 0b0000111,
55 0b00000100,
56 0b00000111,
57 0b000011000,
58 0b0000010111,
59 0b0000011000,
60 0b0000001000,
61 0b00001100111,
62 0b00001101000,
63 0b00001101100,
64 0b00000110111,
65 0b00000101000,
66 0b00000010111,
67 0b00000011000,
68 0b000011001010,
69 0b000011001011,
70 0b000011001100,
71 0b000011001101,
72 0b000001101000,
73 0b000001101001,
74 0b000001101010,
75 0b000001101011,
76 0b000011010010,
77 0b000011010011,
78 0b000011010100,
79 0b000011010101,
80 0b000011010110,
81 0b000011010111,
82 0b000001101100,
83 0b000001101101,
84 0b000011011010,
85 0b000011011011,
86 0b000001010100,
87 0b000001010101,
88 0b000001010110,
89 0b000001010111,
90 0b000001100100,
91 0b000001100101,
92 0b000001010010,
93 0b000001010011,
94 0b000000100100,
95 0b000000110111,
96 0b000000111000,
97 0b000000100111,
98 0b000000101000,
99 0b000001011000,
100 0b000001011001,
101 0b000000101011,
102 0b000000101100,
103 0b000001011010,
104 0b000001100110,
105 0b000001100111
106 },
107 {
108 0b00110101,
109 0b000111,
110 0b0111,
111 0b1000,
112 0b1011,
113 0b1100,
114 0b1110,
115 0b1111,
116 0b10011,
117 0b10100,
118 0b00111,
119 0b01000,
120 0b001000,
121 0b000011,
122 0b110100,
123 0b110101,
124 0b101010,
125 0b101011,
126 0b0100111,
127 0b0001100,
128 0b0001000,
129 0b0010111,
130 0b0000011,
131 0b0000100,
132 0b0101000,
133 0b0101011,
134 0b0010011,
135 0b0100100,
136 0b0011000,
137 0b00000010,
138 0b00000011,
139 0b00011010,
140 0b00011011,
141 0b00010010,
142 0b00010011,
143 0b00010100,
144 0b00010101,
145 0b00010110,
146 0b00010111,
147 0b00101000,
148 0b00101001,
149 0b00101010,
150 0b00101011,
151 0b00101100,
152 0b00101101,
153 0b00000100,
154 0b00000101,
155 0b00001010,
156 0b00001011,
157 0b01010010,
158 0b01010011,
159 0b01010100,
160 0b01010101,
161 0b00100100,
162 0b00100101,
163 0b01011000,
164 0b01011001,
165 0b01011010,
166 0b01011011,
167 0b01001010,
168 0b01001011,
169 0b00110010,
170 0b00110011,
171 0b00110100
172 }
173};
174
175static const unsigned t4_term_length[2][64] = {
176 {10, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 7, 8, 8, 9, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12},
177 {8, 6, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}
178};
179
Max5c18e262016-02-05 13:55:38 +0100180static const unsigned t4_make_up_length[2][15] = {
181 {10, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13},
182 {5, 5, 6, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9}
183};
184
Max5c18e262016-02-05 13:55:38 +0100185static const unsigned t4_make_up[2][15] = {
186 {
187 0b0000001111,
188 0b000011001000,
189 0b000011001001,
190 0b000001011011,
191 0b000000110011,
192 0b000000110100,
193 0b000000110101,
194 0b0000001101100,
195 0b0000001101101,
196 0b0000001001010,
197 0b0000001001011,
198 0b0000001001100,
199 0b0000001001101,
200 0b0000001110010,
201 0b0000001110011
202 },
203 {
204 0b11011,
205 0b10010,
206 0b010111,
207 0b0110111,
208 0b00110110,
209 0b00110111,
210 0b01100100,
211 0b01100101,
212 0b01101000,
213 0b01100111,
214 0b011001100,
215 0b011001101,
216 0b011010010,
217 0b011010011,
218 0b011010100
219 }
220};
221
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200222/*! Make-up codes for a given length
Max5c18e262016-02-05 13:55:38 +0100223 *
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200224 * \return Return proper make-up code word for an uninterrupted
225 * sequence of b bits of length len according to modified ITU-T T.4
226 * from TS 44.060 Table 9.1.10.2 */
Max5c18e262016-02-05 13:55:38 +0100227static inline int t4_rle(struct bitvec *bv, unsigned len, bool b)
228{
229 if (len >= 960) {
230 bitvec_set_uint(bv, t4_make_up[b][14], t4_make_up_length[b][14]);
231 return bitvec_set_uint(bv, t4_term[b][len - 960], t4_term_length[b][len - 960]);
232 }
233
234 if (len >= 896) {
235 bitvec_set_uint(bv, t4_make_up[b][13], t4_make_up_length[b][13]);
236 return bitvec_set_uint(bv, t4_term[b][len - 896], t4_term_length[b][len - 896]);
237 }
238
239 if (len >= 832) {
240 bitvec_set_uint(bv, t4_make_up[b][12], t4_make_up_length[b][12]);
241 return bitvec_set_uint(bv, t4_term[b][len - 832], t4_term_length[b][len - 832]);
242 }
243
244 if (len >= 768) {
245 bitvec_set_uint(bv, t4_make_up[b][11], t4_make_up_length[b][11]);
246 return bitvec_set_uint(bv, t4_term[b][len - 768], t4_term_length[b][len - 768]);
247 }
248
249 if (len >= 704) {
250 bitvec_set_uint(bv, t4_make_up[b][10], t4_make_up_length[b][10]);
251 return bitvec_set_uint(bv, t4_term[b][len - 704], t4_term_length[b][len - 704]);
252 }
253
254 if (len >= 640) {
255 bitvec_set_uint(bv, t4_make_up[b][9], t4_make_up_length[b][9]);
256 return bitvec_set_uint(bv, t4_term[b][len - 640], t4_term_length[b][len - 640]);
257 }
258
259 if (len >= 576) {
260 bitvec_set_uint(bv, t4_make_up[b][8], t4_make_up_length[b][8]);
261 return bitvec_set_uint(bv, t4_term[b][len - 576], t4_term_length[b][len - 576]);
262 }
263
264 if (len >= 512) {
265 bitvec_set_uint(bv, t4_make_up[b][7], t4_make_up_length[b][7]);
266 return bitvec_set_uint(bv, t4_term[b][len - 512], t4_term_length[b][len - 512]);
267 }
268
269 if (len >= 448) {
270 bitvec_set_uint(bv, t4_make_up[b][6], t4_make_up_length[b][6]);
271 return bitvec_set_uint(bv, t4_term[b][len - 448], t4_term_length[b][len - 448]);
272 }
273
274 if (len >= 384) {
275 bitvec_set_uint(bv, t4_make_up[b][5], t4_make_up_length[b][5]);
276 return bitvec_set_uint(bv, t4_term[b][len - 384], t4_term_length[b][len - 384]);
277 }
278
279 if (len >= 320) {
280 bitvec_set_uint(bv, t4_make_up[b][4], t4_make_up_length[b][4]);
281 return bitvec_set_uint(bv, t4_term[b][len - 320], t4_term_length[b][len - 320]);
282 }
283
284 if (len >= 256) {
285 bitvec_set_uint(bv, t4_make_up[b][3], t4_make_up_length[b][3]);
286 return bitvec_set_uint(bv, t4_term[b][len - 256], t4_term_length[b][len - 256]);
287 }
288
289 if (len >= 192) {
290 bitvec_set_uint(bv, t4_make_up[b][2], t4_make_up_length[b][2]);
291 return bitvec_set_uint(bv, t4_term[b][len - 192], t4_term_length[b][len - 192]);
292 }
293
294 if (len >= 128) {
295 bitvec_set_uint(bv, t4_make_up[b][1], t4_make_up_length[b][1]);
296 return bitvec_set_uint(bv, t4_term[b][len - 128], t4_term_length[b][len - 128]);
297 }
298
299 if (len >= 64) {
300 bitvec_set_uint(bv, t4_make_up[b][0], t4_make_up_length[b][0]);
301 return bitvec_set_uint(bv, t4_term[b][len - 64], t4_term_length[b][len - 64]);
302 }
303
304 return bitvec_set_uint(bv, t4_term[b][len], t4_term_length[b][len]);
305}
306
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200307/*! encode bit vector in-place using T4 encoding
Max5c18e262016-02-05 13:55:38 +0100308 * Assumes MSB first encoding.
309 * \param[in] bv bit vector to be encoded
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200310 * \return color code (if the encoding started with 0 or 1) or -1 on
311 * failure (encoded is bigger than original)
Max5c18e262016-02-05 13:55:38 +0100312 */
313int osmo_t4_encode(struct bitvec *bv)
314{
315 unsigned rl0 = bitvec_rl(bv, false), rl1 = bitvec_rl(bv, true);
316 int r = (rl0 > rl1) ? 0 : 1;
317 uint8_t orig[bv->data_len], tmp[bv->data_len * 2]; /* FIXME: better estimate max possible encoding overhead */
318 struct bitvec comp, vec;
319 comp.data = tmp;
320 comp.data_len = bv->data_len * 2;
321 bitvec_zero(&comp);
322 vec.data = orig;
323 vec.data_len = bv->data_len;
324 bitvec_zero(&vec);
325 memcpy(vec.data, bv->data, bv->data_len);
326 vec.cur_bit = bv->cur_bit;
327
328 while (vec.cur_bit > 0) {
329 if (rl0 > rl1) {
330 bitvec_shiftl(&vec, rl0);
331 t4_rle(&comp, rl0, false);
332 } else {
333 bitvec_shiftl(&vec, rl1);
334 t4_rle(&comp, rl1, true);
335 }
336 /*
337 TODO: implement backtracking for optimal encoding
338 printf(" -> [%d/%d]", comp.cur_bit + vec.cur_bit, bv->cur_bit);
339 */
340 rl0 = bitvec_rl(&vec, false);
341 rl1 = bitvec_rl(&vec, true);
342 }
343 if (comp.cur_bit < bv->cur_bit) {
344 memcpy(bv->data, tmp, bv->data_len);
345 bv->cur_bit = comp.cur_bit;
346 return r;
347 }
348 return -1;
349}
350
351