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