Coverage Report

Created: 2024-09-08 06:14

/src/astc-encoder/Source/astcenc_integer_sequence.cpp
Line
Count
Source (jump to first uncovered line)
1
// SPDX-License-Identifier: Apache-2.0
2
// ----------------------------------------------------------------------------
3
// Copyright 2011-2024 Arm Limited
4
//
5
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
// use this file except in compliance with the License. You may obtain a copy
7
// of the License at:
8
//
9
//     http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing, software
12
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
// License for the specific language governing permissions and limitations
15
// under the License.
16
// ----------------------------------------------------------------------------
17
18
/**
19
 * @brief Functions for encoding/decoding Bounded Integer Sequence Encoding.
20
 */
21
22
#include "astcenc_internal.h"
23
24
#include <array>
25
26
/** @brief Unpacked quint triplets <low,middle,high> for each packed value */
27
// TODO: Bitpack these into a uint16_t?
28
static const uint8_t quints_of_integer[128][3] {
29
  {0, 0, 0}, {1, 0, 0}, {2, 0, 0}, {3, 0, 0},
30
  {4, 0, 0}, {0, 4, 0}, {4, 4, 0}, {4, 4, 4},
31
  {0, 1, 0}, {1, 1, 0}, {2, 1, 0}, {3, 1, 0},
32
  {4, 1, 0}, {1, 4, 0}, {4, 4, 1}, {4, 4, 4},
33
  {0, 2, 0}, {1, 2, 0}, {2, 2, 0}, {3, 2, 0},
34
  {4, 2, 0}, {2, 4, 0}, {4, 4, 2}, {4, 4, 4},
35
  {0, 3, 0}, {1, 3, 0}, {2, 3, 0}, {3, 3, 0},
36
  {4, 3, 0}, {3, 4, 0}, {4, 4, 3}, {4, 4, 4},
37
  {0, 0, 1}, {1, 0, 1}, {2, 0, 1}, {3, 0, 1},
38
  {4, 0, 1}, {0, 4, 1}, {4, 0, 4}, {0, 4, 4},
39
  {0, 1, 1}, {1, 1, 1}, {2, 1, 1}, {3, 1, 1},
40
  {4, 1, 1}, {1, 4, 1}, {4, 1, 4}, {1, 4, 4},
41
  {0, 2, 1}, {1, 2, 1}, {2, 2, 1}, {3, 2, 1},
42
  {4, 2, 1}, {2, 4, 1}, {4, 2, 4}, {2, 4, 4},
43
  {0, 3, 1}, {1, 3, 1}, {2, 3, 1}, {3, 3, 1},
44
  {4, 3, 1}, {3, 4, 1}, {4, 3, 4}, {3, 4, 4},
45
  {0, 0, 2}, {1, 0, 2}, {2, 0, 2}, {3, 0, 2},
46
  {4, 0, 2}, {0, 4, 2}, {2, 0, 4}, {3, 0, 4},
47
  {0, 1, 2}, {1, 1, 2}, {2, 1, 2}, {3, 1, 2},
48
  {4, 1, 2}, {1, 4, 2}, {2, 1, 4}, {3, 1, 4},
49
  {0, 2, 2}, {1, 2, 2}, {2, 2, 2}, {3, 2, 2},
50
  {4, 2, 2}, {2, 4, 2}, {2, 2, 4}, {3, 2, 4},
51
  {0, 3, 2}, {1, 3, 2}, {2, 3, 2}, {3, 3, 2},
52
  {4, 3, 2}, {3, 4, 2}, {2, 3, 4}, {3, 3, 4},
53
  {0, 0, 3}, {1, 0, 3}, {2, 0, 3}, {3, 0, 3},
54
  {4, 0, 3}, {0, 4, 3}, {0, 0, 4}, {1, 0, 4},
55
  {0, 1, 3}, {1, 1, 3}, {2, 1, 3}, {3, 1, 3},
56
  {4, 1, 3}, {1, 4, 3}, {0, 1, 4}, {1, 1, 4},
57
  {0, 2, 3}, {1, 2, 3}, {2, 2, 3}, {3, 2, 3},
58
  {4, 2, 3}, {2, 4, 3}, {0, 2, 4}, {1, 2, 4},
59
  {0, 3, 3}, {1, 3, 3}, {2, 3, 3}, {3, 3, 3},
60
  {4, 3, 3}, {3, 4, 3}, {0, 3, 4}, {1, 3, 4}
61
};
62
63
/** @brief Packed quint values for each unpacked value, indexed [hi][mid][lo]. */
64
static const uint8_t integer_of_quints[5][5][5] {
65
  {
66
    {0, 1, 2, 3, 4},
67
    {8, 9, 10, 11, 12},
68
    {16, 17, 18, 19, 20},
69
    {24, 25, 26, 27, 28},
70
    {5, 13, 21, 29, 6}
71
  },
72
  {
73
    {32, 33, 34, 35, 36},
74
    {40, 41, 42, 43, 44},
75
    {48, 49, 50, 51, 52},
76
    {56, 57, 58, 59, 60},
77
    {37, 45, 53, 61, 14}
78
  },
79
  {
80
    {64, 65, 66, 67, 68},
81
    {72, 73, 74, 75, 76},
82
    {80, 81, 82, 83, 84},
83
    {88, 89, 90, 91, 92},
84
    {69, 77, 85, 93, 22}
85
  },
86
  {
87
    {96, 97, 98, 99, 100},
88
    {104, 105, 106, 107, 108},
89
    {112, 113, 114, 115, 116},
90
    {120, 121, 122, 123, 124},
91
    {101, 109, 117, 125, 30}
92
  },
93
  {
94
    {102, 103, 70, 71, 38},
95
    {110, 111, 78, 79, 46},
96
    {118, 119, 86, 87, 54},
97
    {126, 127, 94, 95, 62},
98
    {39, 47, 55, 63, 31}
99
  }
100
};
101
102
/** @brief Unpacked trit quintuplets <low,...,high> for each packed value */
103
// TODO: Bitpack these into a uint16_t?
104
static const uint8_t trits_of_integer[256][5] {
105
  {0, 0, 0, 0, 0}, {1, 0, 0, 0, 0}, {2, 0, 0, 0, 0}, {0, 0, 2, 0, 0},
106
  {0, 1, 0, 0, 0}, {1, 1, 0, 0, 0}, {2, 1, 0, 0, 0}, {1, 0, 2, 0, 0},
107
  {0, 2, 0, 0, 0}, {1, 2, 0, 0, 0}, {2, 2, 0, 0, 0}, {2, 0, 2, 0, 0},
108
  {0, 2, 2, 0, 0}, {1, 2, 2, 0, 0}, {2, 2, 2, 0, 0}, {2, 0, 2, 0, 0},
109
  {0, 0, 1, 0, 0}, {1, 0, 1, 0, 0}, {2, 0, 1, 0, 0}, {0, 1, 2, 0, 0},
110
  {0, 1, 1, 0, 0}, {1, 1, 1, 0, 0}, {2, 1, 1, 0, 0}, {1, 1, 2, 0, 0},
111
  {0, 2, 1, 0, 0}, {1, 2, 1, 0, 0}, {2, 2, 1, 0, 0}, {2, 1, 2, 0, 0},
112
  {0, 0, 0, 2, 2}, {1, 0, 0, 2, 2}, {2, 0, 0, 2, 2}, {0, 0, 2, 2, 2},
113
  {0, 0, 0, 1, 0}, {1, 0, 0, 1, 0}, {2, 0, 0, 1, 0}, {0, 0, 2, 1, 0},
114
  {0, 1, 0, 1, 0}, {1, 1, 0, 1, 0}, {2, 1, 0, 1, 0}, {1, 0, 2, 1, 0},
115
  {0, 2, 0, 1, 0}, {1, 2, 0, 1, 0}, {2, 2, 0, 1, 0}, {2, 0, 2, 1, 0},
116
  {0, 2, 2, 1, 0}, {1, 2, 2, 1, 0}, {2, 2, 2, 1, 0}, {2, 0, 2, 1, 0},
117
  {0, 0, 1, 1, 0}, {1, 0, 1, 1, 0}, {2, 0, 1, 1, 0}, {0, 1, 2, 1, 0},
118
  {0, 1, 1, 1, 0}, {1, 1, 1, 1, 0}, {2, 1, 1, 1, 0}, {1, 1, 2, 1, 0},
119
  {0, 2, 1, 1, 0}, {1, 2, 1, 1, 0}, {2, 2, 1, 1, 0}, {2, 1, 2, 1, 0},
120
  {0, 1, 0, 2, 2}, {1, 1, 0, 2, 2}, {2, 1, 0, 2, 2}, {1, 0, 2, 2, 2},
121
  {0, 0, 0, 2, 0}, {1, 0, 0, 2, 0}, {2, 0, 0, 2, 0}, {0, 0, 2, 2, 0},
122
  {0, 1, 0, 2, 0}, {1, 1, 0, 2, 0}, {2, 1, 0, 2, 0}, {1, 0, 2, 2, 0},
123
  {0, 2, 0, 2, 0}, {1, 2, 0, 2, 0}, {2, 2, 0, 2, 0}, {2, 0, 2, 2, 0},
124
  {0, 2, 2, 2, 0}, {1, 2, 2, 2, 0}, {2, 2, 2, 2, 0}, {2, 0, 2, 2, 0},
125
  {0, 0, 1, 2, 0}, {1, 0, 1, 2, 0}, {2, 0, 1, 2, 0}, {0, 1, 2, 2, 0},
126
  {0, 1, 1, 2, 0}, {1, 1, 1, 2, 0}, {2, 1, 1, 2, 0}, {1, 1, 2, 2, 0},
127
  {0, 2, 1, 2, 0}, {1, 2, 1, 2, 0}, {2, 2, 1, 2, 0}, {2, 1, 2, 2, 0},
128
  {0, 2, 0, 2, 2}, {1, 2, 0, 2, 2}, {2, 2, 0, 2, 2}, {2, 0, 2, 2, 2},
129
  {0, 0, 0, 0, 2}, {1, 0, 0, 0, 2}, {2, 0, 0, 0, 2}, {0, 0, 2, 0, 2},
130
  {0, 1, 0, 0, 2}, {1, 1, 0, 0, 2}, {2, 1, 0, 0, 2}, {1, 0, 2, 0, 2},
131
  {0, 2, 0, 0, 2}, {1, 2, 0, 0, 2}, {2, 2, 0, 0, 2}, {2, 0, 2, 0, 2},
132
  {0, 2, 2, 0, 2}, {1, 2, 2, 0, 2}, {2, 2, 2, 0, 2}, {2, 0, 2, 0, 2},
133
  {0, 0, 1, 0, 2}, {1, 0, 1, 0, 2}, {2, 0, 1, 0, 2}, {0, 1, 2, 0, 2},
134
  {0, 1, 1, 0, 2}, {1, 1, 1, 0, 2}, {2, 1, 1, 0, 2}, {1, 1, 2, 0, 2},
135
  {0, 2, 1, 0, 2}, {1, 2, 1, 0, 2}, {2, 2, 1, 0, 2}, {2, 1, 2, 0, 2},
136
  {0, 2, 2, 2, 2}, {1, 2, 2, 2, 2}, {2, 2, 2, 2, 2}, {2, 0, 2, 2, 2},
137
  {0, 0, 0, 0, 1}, {1, 0, 0, 0, 1}, {2, 0, 0, 0, 1}, {0, 0, 2, 0, 1},
138
  {0, 1, 0, 0, 1}, {1, 1, 0, 0, 1}, {2, 1, 0, 0, 1}, {1, 0, 2, 0, 1},
139
  {0, 2, 0, 0, 1}, {1, 2, 0, 0, 1}, {2, 2, 0, 0, 1}, {2, 0, 2, 0, 1},
140
  {0, 2, 2, 0, 1}, {1, 2, 2, 0, 1}, {2, 2, 2, 0, 1}, {2, 0, 2, 0, 1},
141
  {0, 0, 1, 0, 1}, {1, 0, 1, 0, 1}, {2, 0, 1, 0, 1}, {0, 1, 2, 0, 1},
142
  {0, 1, 1, 0, 1}, {1, 1, 1, 0, 1}, {2, 1, 1, 0, 1}, {1, 1, 2, 0, 1},
143
  {0, 2, 1, 0, 1}, {1, 2, 1, 0, 1}, {2, 2, 1, 0, 1}, {2, 1, 2, 0, 1},
144
  {0, 0, 1, 2, 2}, {1, 0, 1, 2, 2}, {2, 0, 1, 2, 2}, {0, 1, 2, 2, 2},
145
  {0, 0, 0, 1, 1}, {1, 0, 0, 1, 1}, {2, 0, 0, 1, 1}, {0, 0, 2, 1, 1},
146
  {0, 1, 0, 1, 1}, {1, 1, 0, 1, 1}, {2, 1, 0, 1, 1}, {1, 0, 2, 1, 1},
147
  {0, 2, 0, 1, 1}, {1, 2, 0, 1, 1}, {2, 2, 0, 1, 1}, {2, 0, 2, 1, 1},
148
  {0, 2, 2, 1, 1}, {1, 2, 2, 1, 1}, {2, 2, 2, 1, 1}, {2, 0, 2, 1, 1},
149
  {0, 0, 1, 1, 1}, {1, 0, 1, 1, 1}, {2, 0, 1, 1, 1}, {0, 1, 2, 1, 1},
150
  {0, 1, 1, 1, 1}, {1, 1, 1, 1, 1}, {2, 1, 1, 1, 1}, {1, 1, 2, 1, 1},
151
  {0, 2, 1, 1, 1}, {1, 2, 1, 1, 1}, {2, 2, 1, 1, 1}, {2, 1, 2, 1, 1},
152
  {0, 1, 1, 2, 2}, {1, 1, 1, 2, 2}, {2, 1, 1, 2, 2}, {1, 1, 2, 2, 2},
153
  {0, 0, 0, 2, 1}, {1, 0, 0, 2, 1}, {2, 0, 0, 2, 1}, {0, 0, 2, 2, 1},
154
  {0, 1, 0, 2, 1}, {1, 1, 0, 2, 1}, {2, 1, 0, 2, 1}, {1, 0, 2, 2, 1},
155
  {0, 2, 0, 2, 1}, {1, 2, 0, 2, 1}, {2, 2, 0, 2, 1}, {2, 0, 2, 2, 1},
156
  {0, 2, 2, 2, 1}, {1, 2, 2, 2, 1}, {2, 2, 2, 2, 1}, {2, 0, 2, 2, 1},
157
  {0, 0, 1, 2, 1}, {1, 0, 1, 2, 1}, {2, 0, 1, 2, 1}, {0, 1, 2, 2, 1},
158
  {0, 1, 1, 2, 1}, {1, 1, 1, 2, 1}, {2, 1, 1, 2, 1}, {1, 1, 2, 2, 1},
159
  {0, 2, 1, 2, 1}, {1, 2, 1, 2, 1}, {2, 2, 1, 2, 1}, {2, 1, 2, 2, 1},
160
  {0, 2, 1, 2, 2}, {1, 2, 1, 2, 2}, {2, 2, 1, 2, 2}, {2, 1, 2, 2, 2},
161
  {0, 0, 0, 1, 2}, {1, 0, 0, 1, 2}, {2, 0, 0, 1, 2}, {0, 0, 2, 1, 2},
162
  {0, 1, 0, 1, 2}, {1, 1, 0, 1, 2}, {2, 1, 0, 1, 2}, {1, 0, 2, 1, 2},
163
  {0, 2, 0, 1, 2}, {1, 2, 0, 1, 2}, {2, 2, 0, 1, 2}, {2, 0, 2, 1, 2},
164
  {0, 2, 2, 1, 2}, {1, 2, 2, 1, 2}, {2, 2, 2, 1, 2}, {2, 0, 2, 1, 2},
165
  {0, 0, 1, 1, 2}, {1, 0, 1, 1, 2}, {2, 0, 1, 1, 2}, {0, 1, 2, 1, 2},
166
  {0, 1, 1, 1, 2}, {1, 1, 1, 1, 2}, {2, 1, 1, 1, 2}, {1, 1, 2, 1, 2},
167
  {0, 2, 1, 1, 2}, {1, 2, 1, 1, 2}, {2, 2, 1, 1, 2}, {2, 1, 2, 1, 2},
168
  {0, 2, 2, 2, 2}, {1, 2, 2, 2, 2}, {2, 2, 2, 2, 2}, {2, 1, 2, 2, 2}
169
};
170
171
/** @brief Packed trit values for each unpacked value, indexed [hi][][][][lo]. */
172
static const uint8_t integer_of_trits[3][3][3][3][3] {
173
  {
174
    {
175
      {
176
        {0, 1, 2},
177
        {4, 5, 6},
178
        {8, 9, 10}
179
      },
180
      {
181
        {16, 17, 18},
182
        {20, 21, 22},
183
        {24, 25, 26}
184
      },
185
      {
186
        {3, 7, 15},
187
        {19, 23, 27},
188
        {12, 13, 14}
189
      }
190
    },
191
    {
192
      {
193
        {32, 33, 34},
194
        {36, 37, 38},
195
        {40, 41, 42}
196
      },
197
      {
198
        {48, 49, 50},
199
        {52, 53, 54},
200
        {56, 57, 58}
201
      },
202
      {
203
        {35, 39, 47},
204
        {51, 55, 59},
205
        {44, 45, 46}
206
      }
207
    },
208
    {
209
      {
210
        {64, 65, 66},
211
        {68, 69, 70},
212
        {72, 73, 74}
213
      },
214
      {
215
        {80, 81, 82},
216
        {84, 85, 86},
217
        {88, 89, 90}
218
      },
219
      {
220
        {67, 71, 79},
221
        {83, 87, 91},
222
        {76, 77, 78}
223
      }
224
    }
225
  },
226
  {
227
    {
228
      {
229
        {128, 129, 130},
230
        {132, 133, 134},
231
        {136, 137, 138}
232
      },
233
      {
234
        {144, 145, 146},
235
        {148, 149, 150},
236
        {152, 153, 154}
237
      },
238
      {
239
        {131, 135, 143},
240
        {147, 151, 155},
241
        {140, 141, 142}
242
      }
243
    },
244
    {
245
      {
246
        {160, 161, 162},
247
        {164, 165, 166},
248
        {168, 169, 170}
249
      },
250
      {
251
        {176, 177, 178},
252
        {180, 181, 182},
253
        {184, 185, 186}
254
      },
255
      {
256
        {163, 167, 175},
257
        {179, 183, 187},
258
        {172, 173, 174}
259
      }
260
    },
261
    {
262
      {
263
        {192, 193, 194},
264
        {196, 197, 198},
265
        {200, 201, 202}
266
      },
267
      {
268
        {208, 209, 210},
269
        {212, 213, 214},
270
        {216, 217, 218}
271
      },
272
      {
273
        {195, 199, 207},
274
        {211, 215, 219},
275
        {204, 205, 206}
276
      }
277
    }
278
  },
279
  {
280
    {
281
      {
282
        {96, 97, 98},
283
        {100, 101, 102},
284
        {104, 105, 106}
285
      },
286
      {
287
        {112, 113, 114},
288
        {116, 117, 118},
289
        {120, 121, 122}
290
      },
291
      {
292
        {99, 103, 111},
293
        {115, 119, 123},
294
        {108, 109, 110}
295
      }
296
    },
297
    {
298
      {
299
        {224, 225, 226},
300
        {228, 229, 230},
301
        {232, 233, 234}
302
      },
303
      {
304
        {240, 241, 242},
305
        {244, 245, 246},
306
        {248, 249, 250}
307
      },
308
      {
309
        {227, 231, 239},
310
        {243, 247, 251},
311
        {236, 237, 238}
312
      }
313
    },
314
    {
315
      {
316
        {28, 29, 30},
317
        {60, 61, 62},
318
        {92, 93, 94}
319
      },
320
      {
321
        {156, 157, 158},
322
        {188, 189, 190},
323
        {220, 221, 222}
324
      },
325
      {
326
        {31, 63, 127},
327
        {159, 191, 255},
328
        {252, 253, 254}
329
      }
330
    }
331
  }
332
};
333
334
/**
335
 * @brief The number of bits, trits, and quints needed for a quant level.
336
 */
337
struct btq_count
338
{
339
  /** @brief The number of bits. */
340
  uint8_t bits:6;
341
342
  /** @brief The number of trits. */
343
  uint8_t trits:1;
344
345
  /** @brief The number of quints. */
346
  uint8_t quints:1;
347
};
348
349
/**
350
 * @brief The table of bits, trits, and quints needed for a quant encode.
351
 */
352
static const std::array<btq_count, 21> btq_counts {{
353
  { 1, 0, 0 }, // QUANT_2
354
  { 0, 1, 0 }, // QUANT_3
355
  { 2, 0, 0 }, // QUANT_4
356
  { 0, 0, 1 }, // QUANT_5
357
  { 1, 1, 0 }, // QUANT_6
358
  { 3, 0, 0 }, // QUANT_8
359
  { 1, 0, 1 }, // QUANT_10
360
  { 2, 1, 0 }, // QUANT_12
361
  { 4, 0, 0 }, // QUANT_16
362
  { 2, 0, 1 }, // QUANT_20
363
  { 3, 1, 0 }, // QUANT_24
364
  { 5, 0, 0 }, // QUANT_32
365
  { 3, 0, 1 }, // QUANT_40
366
  { 4, 1, 0 }, // QUANT_48
367
  { 6, 0, 0 }, // QUANT_64
368
  { 4, 0, 1 }, // QUANT_80
369
  { 5, 1, 0 }, // QUANT_96
370
  { 7, 0, 0 }, // QUANT_128
371
  { 5, 0, 1 }, // QUANT_160
372
  { 6, 1, 0 }, // QUANT_192
373
  { 8, 0, 0 }  // QUANT_256
374
}};
375
376
/**
377
 * @brief The sequence scale, round, and divisors needed to compute sizing.
378
 *
379
 * The length of a quantized sequence in bits is:
380
 *     (scale * <sequence_len> + round) / divisor
381
 */
382
struct ise_size
383
{
384
  /** @brief The scaling parameter. */
385
  uint8_t scale:6;
386
387
  /** @brief The divisor parameter. */
388
  uint8_t divisor:2;
389
};
390
391
/**
392
 * @brief The table of scale, round, and divisors needed for quant sizing.
393
 */
394
static const std::array<ise_size, 21> ise_sizes {{
395
  {  1, 0 }, // QUANT_2
396
  {  8, 2 }, // QUANT_3
397
  {  2, 0 }, // QUANT_4
398
  {  7, 1 }, // QUANT_5
399
  { 13, 2 }, // QUANT_6
400
  {  3, 0 }, // QUANT_8
401
  { 10, 1 }, // QUANT_10
402
  { 18, 2 }, // QUANT_12
403
  {  4, 0 }, // QUANT_16
404
  { 13, 1 }, // QUANT_20
405
  { 23, 2 }, // QUANT_24
406
  {  5, 0 }, // QUANT_32
407
  { 16, 1 }, // QUANT_40
408
  { 28, 2 }, // QUANT_48
409
  {  6, 0 }, // QUANT_64
410
  { 19, 1 }, // QUANT_80
411
  { 33, 2 }, // QUANT_96
412
  {  7, 0 }, // QUANT_128
413
  { 22, 1 }, // QUANT_160
414
  { 38, 2 }, // QUANT_192
415
  {  8, 0 }  // QUANT_256
416
}};
417
418
/* See header for documentation. */
419
unsigned int get_ise_sequence_bitcount(
420
  unsigned int character_count,
421
  quant_method quant_level
422
20.5k
) {
423
  // Cope with out-of bounds values - input might be invalid
424
20.5k
  if (static_cast<size_t>(quant_level) >= ise_sizes.size())
425
0
  {
426
    // Arbitrary large number that's more than an ASTC block can hold
427
0
    return 1024;
428
0
  }
429
430
20.5k
  auto& entry = ise_sizes[quant_level];
431
20.5k
  unsigned int divisor = (entry.divisor << 1) + 1;
432
20.5k
  return (entry.scale * character_count + divisor - 1) / divisor;
433
20.5k
}
434
435
/**
436
 * @brief Write up to 8 bits at an arbitrary bit offset.
437
 *
438
 * The stored value is at most 8 bits, but can be stored at an offset of between 0 and 7 bits so may
439
 * span two separate bytes in memory.
440
 *
441
 * @param         value       The value to write.
442
 * @param         bitcount    The number of bits to write, starting from LSB.
443
 * @param         bitoffset   The bit offset to store at, between 0 and 7.
444
 * @param[in,out] ptr         The data pointer to write to.
445
 */
446
static inline void write_bits(
447
  unsigned int value,
448
  unsigned int bitcount,
449
  unsigned int bitoffset,
450
  uint8_t ptr[2]
451
0
) {
452
0
  unsigned int mask = (1 << bitcount) - 1;
453
0
  value &= mask;
454
0
  ptr += bitoffset >> 3;
455
0
  bitoffset &= 7;
456
0
  value <<= bitoffset;
457
0
  mask <<= bitoffset;
458
0
  mask = ~mask;
459
460
0
  ptr[0] &= mask;
461
0
  ptr[0] |= value;
462
0
  ptr[1] &= mask >> 8;
463
0
  ptr[1] |= value >> 8;
464
0
}
465
466
/**
467
 * @brief Read up to 16 bits from two bytes.
468
 *
469
 * This function reads a packed N-bit field from two bytes in memory. The stored value must exist
470
 * within the two bytes, but can start at an arbitary bit offset and span the two bytes in memory.
471
 *
472
 * @param         bitcount    The number of bits to read.
473
 * @param         bitoffset   The bit offset to read from, between 0 and 7.
474
 * @param[in,out] ptr         The data pointer to read from.
475
 *
476
 * @return The read value.
477
 */
478
static inline unsigned int read_bits(
479
  unsigned int bitcount,
480
  unsigned int bitoffset,
481
  const uint8_t* ptr
482
2.82k
) {
483
2.82k
  unsigned int mask = (1 << bitcount) - 1;
484
2.82k
  ptr += bitoffset >> 3;
485
2.82k
  bitoffset &= 7;
486
2.82k
  unsigned int value = ptr[0] | (ptr[1] << 8);
487
2.82k
  value >>= bitoffset;
488
2.82k
  value &= mask;
489
2.82k
  return value;
490
2.82k
}
491
492
/* See header for documentation. */
493
void encode_ise(
494
  quant_method quant_level,
495
  unsigned int character_count,
496
  const uint8_t* input_data,
497
  uint8_t* output_data,
498
  unsigned int bit_offset
499
0
) {
500
0
  promise(character_count > 0);
501
502
0
  unsigned int bits = btq_counts[quant_level].bits;
503
0
  unsigned int trits = btq_counts[quant_level].trits;
504
0
  unsigned int quints = btq_counts[quant_level].quints;
505
0
  unsigned int mask = (1 << bits) - 1;
506
507
  // Write out trits and bits
508
0
  if (trits)
509
0
  {
510
0
    unsigned int i = 0;
511
0
    unsigned int full_trit_blocks = character_count / 5;
512
513
0
    for (unsigned int j = 0; j < full_trit_blocks; j++)
514
0
    {
515
0
      unsigned int i4 = input_data[i + 4] >> bits;
516
0
      unsigned int i3 = input_data[i + 3] >> bits;
517
0
      unsigned int i2 = input_data[i + 2] >> bits;
518
0
      unsigned int i1 = input_data[i + 1] >> bits;
519
0
      unsigned int i0 = input_data[i + 0] >> bits;
520
521
0
      uint8_t T = integer_of_trits[i4][i3][i2][i1][i0];
522
523
      // The max size of a trit bit count is 6, so we can always safely
524
      // pack a single MX value with the following 1 or 2 T bits.
525
0
      uint8_t pack;
526
527
      // Element 0 + T0 + T1
528
0
      pack = (input_data[i++] & mask) | (((T >> 0) & 0x3) << bits);
529
0
      write_bits(pack, bits + 2, bit_offset, output_data);
530
0
      bit_offset += bits + 2;
531
532
      // Element 1 + T2 + T3
533
0
      pack = (input_data[i++] & mask) | (((T >> 2) & 0x3) << bits);
534
0
      write_bits(pack, bits + 2, bit_offset, output_data);
535
0
      bit_offset += bits + 2;
536
537
      // Element 2 + T4
538
0
      pack = (input_data[i++] & mask) | (((T >> 4) & 0x1) << bits);
539
0
      write_bits(pack, bits + 1, bit_offset, output_data);
540
0
      bit_offset += bits + 1;
541
542
      // Element 3 + T5 + T6
543
0
      pack = (input_data[i++] & mask) | (((T >> 5) & 0x3) << bits);
544
0
      write_bits(pack, bits + 2, bit_offset, output_data);
545
0
      bit_offset += bits + 2;
546
547
      // Element 4 + T7
548
0
      pack = (input_data[i++] & mask) | (((T >> 7) & 0x1) << bits);
549
0
      write_bits(pack, bits + 1, bit_offset, output_data);
550
0
      bit_offset += bits + 1;
551
0
    }
552
553
    // Loop tail for a partial block
554
0
    if (i != character_count)
555
0
    {
556
      // i4 cannot be present - we know the block is partial
557
      // i0 must be present - we know the block isn't empty
558
0
      unsigned int i4 =                            0;
559
0
      unsigned int i3 = i + 3 >= character_count ? 0 : input_data[i + 3] >> bits;
560
0
      unsigned int i2 = i + 2 >= character_count ? 0 : input_data[i + 2] >> bits;
561
0
      unsigned int i1 = i + 1 >= character_count ? 0 : input_data[i + 1] >> bits;
562
0
      unsigned int i0 =                                input_data[i + 0] >> bits;
563
564
0
      uint8_t T = integer_of_trits[i4][i3][i2][i1][i0];
565
566
0
      for (unsigned int j = 0; i < character_count; i++, j++)
567
0
      {
568
        // Truncated table as this iteration is always partital
569
0
        static const uint8_t tbits[4]  { 2, 2, 1, 2 };
570
0
        static const uint8_t tshift[4] { 0, 2, 4, 5 };
571
572
0
        uint8_t pack = (input_data[i] & mask) |
573
0
                       (((T >> tshift[j]) & ((1 << tbits[j]) - 1)) << bits);
574
575
0
        write_bits(pack, bits + tbits[j], bit_offset, output_data);
576
0
        bit_offset += bits + tbits[j];
577
0
      }
578
0
    }
579
0
  }
580
  // Write out quints and bits
581
0
  else if (quints)
582
0
  {
583
0
    unsigned int i = 0;
584
0
    unsigned int full_quint_blocks = character_count / 3;
585
586
0
    for (unsigned int j = 0; j < full_quint_blocks; j++)
587
0
    {
588
0
      unsigned int i2 = input_data[i + 2] >> bits;
589
0
      unsigned int i1 = input_data[i + 1] >> bits;
590
0
      unsigned int i0 = input_data[i + 0] >> bits;
591
592
0
      uint8_t T = integer_of_quints[i2][i1][i0];
593
594
      // The max size of a quint bit count is 5, so we can always safely
595
      // pack a single M value with the following 2 or 3 T bits.
596
0
      uint8_t pack;
597
598
      // Element 0
599
0
      pack = (input_data[i++] & mask) | (((T >> 0) & 0x7) << bits);
600
0
      write_bits(pack, bits + 3, bit_offset, output_data);
601
0
      bit_offset += bits + 3;
602
603
      // Element 1
604
0
      pack = (input_data[i++] & mask) | (((T >> 3) & 0x3) << bits);
605
0
      write_bits(pack, bits + 2, bit_offset, output_data);
606
0
      bit_offset += bits + 2;
607
608
      // Element 2
609
0
      pack = (input_data[i++] & mask) | (((T >> 5) & 0x3) << bits);
610
0
      write_bits(pack, bits + 2, bit_offset, output_data);
611
0
      bit_offset += bits + 2;
612
0
    }
613
614
    // Loop tail for a partial block
615
0
    if (i != character_count)
616
0
    {
617
      // i2 cannot be present - we know the block is partial
618
      // i0 must be present - we know the block isn't empty
619
0
      unsigned int i2 =                            0;
620
0
      unsigned int i1 = i + 1 >= character_count ? 0 : input_data[i + 1] >> bits;
621
0
      unsigned int i0 =                                input_data[i + 0] >> bits;
622
623
0
      uint8_t T = integer_of_quints[i2][i1][i0];
624
625
0
      for (unsigned int j = 0; i < character_count; i++, j++)
626
0
      {
627
        // Truncated table as this iteration is always partital
628
0
        static const uint8_t tbits[2]  { 3, 2 };
629
0
        static const uint8_t tshift[2] { 0, 3 };
630
631
0
        uint8_t pack = (input_data[i] & mask) |
632
0
                       (((T >> tshift[j]) & ((1 << tbits[j]) - 1)) << bits);
633
634
0
        write_bits(pack, bits + tbits[j], bit_offset, output_data);
635
0
        bit_offset += bits + tbits[j];
636
0
      }
637
0
    }
638
0
  }
639
  // Write out just bits
640
0
  else
641
0
  {
642
0
    for (unsigned int i = 0; i < character_count; i++)
643
0
    {
644
0
      write_bits(input_data[i], bits, bit_offset, output_data);
645
0
      bit_offset += bits;
646
0
    }
647
0
  }
648
0
}
649
650
/* See header for documentation. */
651
void decode_ise(
652
  quant_method quant_level,
653
  unsigned int character_count,
654
  const uint8_t* input_data,
655
  uint8_t* output_data,
656
  unsigned int bit_offset
657
74
) {
658
74
  promise(character_count > 0);
659
660
  // Note: due to how the trit/quint-block unpacking is done in this function, we may write more
661
  // temporary results than the number of outputs. The maximum actual number of results is 64 bit,
662
  // but we keep 4 additional character_count of padding.
663
74
  uint8_t results[68];
664
74
  uint8_t tq_blocks[22] { 0 }; // Trit-blocks or quint-blocks, must be zeroed
665
666
74
  unsigned int bits = btq_counts[quant_level].bits;
667
74
  unsigned int trits = btq_counts[quant_level].trits;
668
74
  unsigned int quints = btq_counts[quant_level].quints;
669
670
74
  unsigned int lcounter = 0;
671
74
  unsigned int hcounter = 0;
672
673
  // Collect bits for each element, as well as bits for any trit-blocks and quint-blocks.
674
1.91k
  for (unsigned int i = 0; i < character_count; i++)
675
1.84k
  {
676
1.84k
    results[i] = static_cast<uint8_t>(read_bits(bits, bit_offset, input_data));
677
1.84k
    bit_offset += bits;
678
679
1.84k
    if (trits)
680
569
    {
681
569
      static const uint8_t bits_to_read[5]  { 2, 2, 1, 2, 1 };
682
569
      static const uint8_t block_shift[5]   { 0, 2, 4, 5, 7 };
683
569
      static const uint8_t next_lcounter[5] { 1, 2, 3, 4, 0 };
684
569
      static const uint8_t hcounter_incr[5] { 0, 0, 0, 0, 1 };
685
569
      unsigned int tdata = read_bits(bits_to_read[lcounter], bit_offset, input_data);
686
569
      bit_offset += bits_to_read[lcounter];
687
569
      tq_blocks[hcounter] |= tdata << block_shift[lcounter];
688
569
      hcounter += hcounter_incr[lcounter];
689
569
      lcounter = next_lcounter[lcounter];
690
569
    }
691
692
1.84k
    if (quints)
693
411
    {
694
411
      static const uint8_t bits_to_read[3]  { 3, 2, 2 };
695
411
      static const uint8_t block_shift[3]   { 0, 3, 5 };
696
411
      static const uint8_t next_lcounter[3] { 1, 2, 0 };
697
411
      static const uint8_t hcounter_incr[3] { 0, 0, 1 };
698
411
      unsigned int tdata = read_bits(bits_to_read[lcounter], bit_offset, input_data);
699
411
      bit_offset += bits_to_read[lcounter];
700
411
      tq_blocks[hcounter] |= tdata << block_shift[lcounter];
701
411
      hcounter += hcounter_incr[lcounter];
702
411
      lcounter = next_lcounter[lcounter];
703
411
    }
704
1.84k
  }
705
706
  // Unpack trit-blocks or quint-blocks as needed
707
74
  if (trits)
708
19
  {
709
19
    unsigned int trit_blocks = (character_count + 4) / 5;
710
19
    promise(trit_blocks > 0);
711
139
    for (unsigned int i = 0; i < trit_blocks; i++)
712
120
    {
713
120
      const uint8_t *tritptr = trits_of_integer[tq_blocks[i]];
714
120
      results[5 * i    ] |= tritptr[0] << bits;
715
120
      results[5 * i + 1] |= tritptr[1] << bits;
716
120
      results[5 * i + 2] |= tritptr[2] << bits;
717
120
      results[5 * i + 3] |= tritptr[3] << bits;
718
120
      results[5 * i + 4] |= tritptr[4] << bits;
719
120
    }
720
19
  }
721
722
74
  if (quints)
723
21
  {
724
21
    unsigned int quint_blocks = (character_count + 2) / 3;
725
21
    promise(quint_blocks > 0);
726
164
    for (unsigned int i = 0; i < quint_blocks; i++)
727
143
    {
728
143
      const uint8_t *quintptr = quints_of_integer[tq_blocks[i]];
729
143
      results[3 * i    ] |= quintptr[0] << bits;
730
143
      results[3 * i + 1] |= quintptr[1] << bits;
731
143
      results[3 * i + 2] |= quintptr[2] << bits;
732
143
    }
733
21
  }
734
735
1.91k
  for (unsigned int i = 0; i < character_count; i++)
736
1.84k
  {
737
1.84k
    output_data[i] = results[i];
738
1.84k
  }
739
74
}