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