]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/BrotliCompress/enc/block_splitter_inc.h
BaseTools: Update Brotli Compress to the latest one 1.0.6
[mirror_edk2.git] / BaseTools / Source / C / BrotliCompress / enc / block_splitter_inc.h
CommitLineData
11b7501a
SB
1/* NOLINT(build/header_guard) */\r
2/* Copyright 2013 Google Inc. All Rights Reserved.\r
3\r
4 Distributed under MIT license.\r
5 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\r
6*/\r
7\r
8/* template parameters: FN, DataType */\r
9\r
10#define HistogramType FN(Histogram)\r
11\r
12static void FN(InitialEntropyCodes)(const DataType* data, size_t length,\r
13 size_t stride,\r
14 size_t num_histograms,\r
15 HistogramType* histograms) {\r
dd4f667e 16 uint32_t seed = 7;\r
11b7501a
SB
17 size_t block_length = length / num_histograms;\r
18 size_t i;\r
19 FN(ClearHistograms)(histograms, num_histograms);\r
20 for (i = 0; i < num_histograms; ++i) {\r
21 size_t pos = length * i / num_histograms;\r
22 if (i != 0) {\r
23 pos += MyRand(&seed) % block_length;\r
24 }\r
25 if (pos + stride >= length) {\r
26 pos = length - stride - 1;\r
27 }\r
28 FN(HistogramAddVector)(&histograms[i], data + pos, stride);\r
29 }\r
30}\r
31\r
dd4f667e 32static void FN(RandomSample)(uint32_t* seed,\r
11b7501a
SB
33 const DataType* data,\r
34 size_t length,\r
35 size_t stride,\r
36 HistogramType* sample) {\r
37 size_t pos = 0;\r
38 if (stride >= length) {\r
11b7501a
SB
39 stride = length;\r
40 } else {\r
41 pos = MyRand(seed) % (length - stride + 1);\r
42 }\r
43 FN(HistogramAddVector)(sample, data + pos, stride);\r
44}\r
45\r
46static void FN(RefineEntropyCodes)(const DataType* data, size_t length,\r
47 size_t stride,\r
48 size_t num_histograms,\r
49 HistogramType* histograms) {\r
50 size_t iters =\r
51 kIterMulForRefining * length / stride + kMinItersForRefining;\r
dd4f667e 52 uint32_t seed = 7;\r
11b7501a
SB
53 size_t iter;\r
54 iters = ((iters + num_histograms - 1) / num_histograms) * num_histograms;\r
55 for (iter = 0; iter < iters; ++iter) {\r
56 HistogramType sample;\r
57 FN(HistogramClear)(&sample);\r
58 FN(RandomSample)(&seed, data, length, stride, &sample);\r
59 FN(HistogramAddHistogram)(&histograms[iter % num_histograms], &sample);\r
60 }\r
61}\r
62\r
dd4f667e 63/* Assigns a block id from the range [0, num_histograms) to each data element\r
11b7501a
SB
64 in data[0..length) and fills in block_id[0..length) with the assigned values.\r
65 Returns the number of blocks, i.e. one plus the number of block switches. */\r
66static size_t FN(FindBlocks)(const DataType* data, const size_t length,\r
67 const double block_switch_bitcost,\r
68 const size_t num_histograms,\r
69 const HistogramType* histograms,\r
70 double* insert_cost,\r
71 double* cost,\r
72 uint8_t* switch_signal,\r
dd4f667e 73 uint8_t* block_id) {\r
11b7501a
SB
74 const size_t data_size = FN(HistogramDataSize)();\r
75 const size_t bitmaplen = (num_histograms + 7) >> 3;\r
76 size_t num_blocks = 1;\r
77 size_t i;\r
78 size_t j;\r
dd4f667e 79 BROTLI_DCHECK(num_histograms <= 256);\r
11b7501a
SB
80 if (num_histograms <= 1) {\r
81 for (i = 0; i < length; ++i) {\r
82 block_id[i] = 0;\r
83 }\r
84 return 1;\r
85 }\r
86 memset(insert_cost, 0, sizeof(insert_cost[0]) * data_size * num_histograms);\r
87 for (i = 0; i < num_histograms; ++i) {\r
88 insert_cost[i] = FastLog2((uint32_t)histograms[i].total_count_);\r
89 }\r
90 for (i = data_size; i != 0;) {\r
91 --i;\r
92 for (j = 0; j < num_histograms; ++j) {\r
93 insert_cost[i * num_histograms + j] =\r
94 insert_cost[j] - BitCost(histograms[j].data_[i]);\r
95 }\r
96 }\r
97 memset(cost, 0, sizeof(cost[0]) * num_histograms);\r
98 memset(switch_signal, 0, sizeof(switch_signal[0]) * length * bitmaplen);\r
99 /* After each iteration of this loop, cost[k] will contain the difference\r
100 between the minimum cost of arriving at the current byte position using\r
101 entropy code k, and the minimum cost of arriving at the current byte\r
102 position. This difference is capped at the block switch cost, and if it\r
103 reaches block switch cost, it means that when we trace back from the last\r
104 position, we need to switch here. */\r
105 for (i = 0; i < length; ++i) {\r
106 const size_t byte_ix = i;\r
107 size_t ix = byte_ix * bitmaplen;\r
108 size_t insert_cost_ix = data[byte_ix] * num_histograms;\r
109 double min_cost = 1e99;\r
110 double block_switch_cost = block_switch_bitcost;\r
111 size_t k;\r
112 for (k = 0; k < num_histograms; ++k) {\r
113 /* We are coding the symbol in data[byte_ix] with entropy code k. */\r
114 cost[k] += insert_cost[insert_cost_ix + k];\r
115 if (cost[k] < min_cost) {\r
116 min_cost = cost[k];\r
117 block_id[byte_ix] = (uint8_t)k;\r
118 }\r
119 }\r
120 /* More blocks for the beginning. */\r
121 if (byte_ix < 2000) {\r
122 block_switch_cost *= 0.77 + 0.07 * (double)byte_ix / 2000;\r
123 }\r
124 for (k = 0; k < num_histograms; ++k) {\r
125 cost[k] -= min_cost;\r
126 if (cost[k] >= block_switch_cost) {\r
127 const uint8_t mask = (uint8_t)(1u << (k & 7));\r
128 cost[k] = block_switch_cost;\r
dd4f667e 129 BROTLI_DCHECK((k >> 3) < bitmaplen);\r
11b7501a
SB
130 switch_signal[ix + (k >> 3)] |= mask;\r
131 }\r
132 }\r
133 }\r
134 { /* Trace back from the last position and switch at the marked places. */\r
135 size_t byte_ix = length - 1;\r
136 size_t ix = byte_ix * bitmaplen;\r
137 uint8_t cur_id = block_id[byte_ix];\r
138 while (byte_ix > 0) {\r
139 const uint8_t mask = (uint8_t)(1u << (cur_id & 7));\r
dd4f667e 140 BROTLI_DCHECK(((size_t)cur_id >> 3) < bitmaplen);\r
11b7501a
SB
141 --byte_ix;\r
142 ix -= bitmaplen;\r
143 if (switch_signal[ix + (cur_id >> 3)] & mask) {\r
144 if (cur_id != block_id[byte_ix]) {\r
145 cur_id = block_id[byte_ix];\r
146 ++num_blocks;\r
147 }\r
148 }\r
149 block_id[byte_ix] = cur_id;\r
150 }\r
151 }\r
152 return num_blocks;\r
153}\r
154\r
155static size_t FN(RemapBlockIds)(uint8_t* block_ids, const size_t length,\r
156 uint16_t* new_id, const size_t num_histograms) {\r
157 static const uint16_t kInvalidId = 256;\r
158 uint16_t next_id = 0;\r
159 size_t i;\r
160 for (i = 0; i < num_histograms; ++i) {\r
161 new_id[i] = kInvalidId;\r
162 }\r
163 for (i = 0; i < length; ++i) {\r
dd4f667e 164 BROTLI_DCHECK(block_ids[i] < num_histograms);\r
11b7501a
SB
165 if (new_id[block_ids[i]] == kInvalidId) {\r
166 new_id[block_ids[i]] = next_id++;\r
167 }\r
168 }\r
169 for (i = 0; i < length; ++i) {\r
170 block_ids[i] = (uint8_t)new_id[block_ids[i]];\r
dd4f667e 171 BROTLI_DCHECK(block_ids[i] < num_histograms);\r
11b7501a 172 }\r
dd4f667e 173 BROTLI_DCHECK(next_id <= num_histograms);\r
11b7501a
SB
174 return next_id;\r
175}\r
176\r
177static void FN(BuildBlockHistograms)(const DataType* data, const size_t length,\r
178 const uint8_t* block_ids,\r
179 const size_t num_histograms,\r
180 HistogramType* histograms) {\r
181 size_t i;\r
182 FN(ClearHistograms)(histograms, num_histograms);\r
183 for (i = 0; i < length; ++i) {\r
184 FN(HistogramAdd)(&histograms[block_ids[i]], data[i]);\r
185 }\r
186}\r
187\r
188static void FN(ClusterBlocks)(MemoryManager* m,\r
189 const DataType* data, const size_t length,\r
190 const size_t num_blocks,\r
191 uint8_t* block_ids,\r
192 BlockSplit* split) {\r
193 uint32_t* histogram_symbols = BROTLI_ALLOC(m, uint32_t, num_blocks);\r
194 uint32_t* block_lengths = BROTLI_ALLOC(m, uint32_t, num_blocks);\r
195 const size_t expected_num_clusters = CLUSTERS_PER_BATCH *\r
196 (num_blocks + HISTOGRAMS_PER_BATCH - 1) / HISTOGRAMS_PER_BATCH;\r
197 size_t all_histograms_size = 0;\r
198 size_t all_histograms_capacity = expected_num_clusters;\r
199 HistogramType* all_histograms =\r
200 BROTLI_ALLOC(m, HistogramType, all_histograms_capacity);\r
201 size_t cluster_size_size = 0;\r
202 size_t cluster_size_capacity = expected_num_clusters;\r
203 uint32_t* cluster_size = BROTLI_ALLOC(m, uint32_t, cluster_size_capacity);\r
204 size_t num_clusters = 0;\r
205 HistogramType* histograms = BROTLI_ALLOC(m, HistogramType,\r
206 BROTLI_MIN(size_t, num_blocks, HISTOGRAMS_PER_BATCH));\r
207 size_t max_num_pairs =\r
208 HISTOGRAMS_PER_BATCH * HISTOGRAMS_PER_BATCH / 2;\r
209 size_t pairs_capacity = max_num_pairs + 1;\r
210 HistogramPair* pairs = BROTLI_ALLOC(m, HistogramPair, pairs_capacity);\r
211 size_t pos = 0;\r
212 uint32_t* clusters;\r
213 size_t num_final_clusters;\r
214 static const uint32_t kInvalidIndex = BROTLI_UINT32_MAX;\r
215 uint32_t* new_index;\r
11b7501a
SB
216 size_t i;\r
217 uint32_t sizes[HISTOGRAMS_PER_BATCH] = { 0 };\r
218 uint32_t new_clusters[HISTOGRAMS_PER_BATCH] = { 0 };\r
219 uint32_t symbols[HISTOGRAMS_PER_BATCH] = { 0 };\r
220 uint32_t remap[HISTOGRAMS_PER_BATCH] = { 0 };\r
221\r
222 if (BROTLI_IS_OOM(m)) return;\r
223\r
224 memset(block_lengths, 0, num_blocks * sizeof(uint32_t));\r
225\r
226 {\r
227 size_t block_idx = 0;\r
228 for (i = 0; i < length; ++i) {\r
dd4f667e 229 BROTLI_DCHECK(block_idx < num_blocks);\r
11b7501a
SB
230 ++block_lengths[block_idx];\r
231 if (i + 1 == length || block_ids[i] != block_ids[i + 1]) {\r
232 ++block_idx;\r
233 }\r
234 }\r
dd4f667e 235 BROTLI_DCHECK(block_idx == num_blocks);\r
11b7501a
SB
236 }\r
237\r
238 for (i = 0; i < num_blocks; i += HISTOGRAMS_PER_BATCH) {\r
239 const size_t num_to_combine =\r
240 BROTLI_MIN(size_t, num_blocks - i, HISTOGRAMS_PER_BATCH);\r
241 size_t num_new_clusters;\r
242 size_t j;\r
243 for (j = 0; j < num_to_combine; ++j) {\r
244 size_t k;\r
245 FN(HistogramClear)(&histograms[j]);\r
246 for (k = 0; k < block_lengths[i + j]; ++k) {\r
247 FN(HistogramAdd)(&histograms[j], data[pos++]);\r
248 }\r
249 histograms[j].bit_cost_ = FN(BrotliPopulationCost)(&histograms[j]);\r
250 new_clusters[j] = (uint32_t)j;\r
251 symbols[j] = (uint32_t)j;\r
252 sizes[j] = 1;\r
253 }\r
254 num_new_clusters = FN(BrotliHistogramCombine)(\r
255 histograms, sizes, symbols, new_clusters, pairs, num_to_combine,\r
256 num_to_combine, HISTOGRAMS_PER_BATCH, max_num_pairs);\r
257 BROTLI_ENSURE_CAPACITY(m, HistogramType, all_histograms,\r
258 all_histograms_capacity, all_histograms_size + num_new_clusters);\r
259 BROTLI_ENSURE_CAPACITY(m, uint32_t, cluster_size,\r
260 cluster_size_capacity, cluster_size_size + num_new_clusters);\r
261 if (BROTLI_IS_OOM(m)) return;\r
262 for (j = 0; j < num_new_clusters; ++j) {\r
263 all_histograms[all_histograms_size++] = histograms[new_clusters[j]];\r
264 cluster_size[cluster_size_size++] = sizes[new_clusters[j]];\r
265 remap[new_clusters[j]] = (uint32_t)j;\r
266 }\r
267 for (j = 0; j < num_to_combine; ++j) {\r
268 histogram_symbols[i + j] = (uint32_t)num_clusters + remap[symbols[j]];\r
269 }\r
270 num_clusters += num_new_clusters;\r
dd4f667e
LG
271 BROTLI_DCHECK(num_clusters == cluster_size_size);\r
272 BROTLI_DCHECK(num_clusters == all_histograms_size);\r
11b7501a
SB
273 }\r
274 BROTLI_FREE(m, histograms);\r
275\r
276 max_num_pairs =\r
277 BROTLI_MIN(size_t, 64 * num_clusters, (num_clusters / 2) * num_clusters);\r
278 if (pairs_capacity < max_num_pairs + 1) {\r
279 BROTLI_FREE(m, pairs);\r
280 pairs = BROTLI_ALLOC(m, HistogramPair, max_num_pairs + 1);\r
281 if (BROTLI_IS_OOM(m)) return;\r
282 }\r
283\r
284 clusters = BROTLI_ALLOC(m, uint32_t, num_clusters);\r
285 if (BROTLI_IS_OOM(m)) return;\r
286 for (i = 0; i < num_clusters; ++i) {\r
287 clusters[i] = (uint32_t)i;\r
288 }\r
289 num_final_clusters = FN(BrotliHistogramCombine)(\r
290 all_histograms, cluster_size, histogram_symbols, clusters, pairs,\r
291 num_clusters, num_blocks, BROTLI_MAX_NUMBER_OF_BLOCK_TYPES,\r
292 max_num_pairs);\r
293 BROTLI_FREE(m, pairs);\r
294 BROTLI_FREE(m, cluster_size);\r
295\r
296 new_index = BROTLI_ALLOC(m, uint32_t, num_clusters);\r
297 if (BROTLI_IS_OOM(m)) return;\r
298 for (i = 0; i < num_clusters; ++i) new_index[i] = kInvalidIndex;\r
299 pos = 0;\r
300 {\r
301 uint32_t next_index = 0;\r
302 for (i = 0; i < num_blocks; ++i) {\r
303 HistogramType histo;\r
304 size_t j;\r
305 uint32_t best_out;\r
306 double best_bits;\r
307 FN(HistogramClear)(&histo);\r
308 for (j = 0; j < block_lengths[i]; ++j) {\r
309 FN(HistogramAdd)(&histo, data[pos++]);\r
310 }\r
311 best_out = (i == 0) ? histogram_symbols[0] : histogram_symbols[i - 1];\r
312 best_bits =\r
313 FN(BrotliHistogramBitCostDistance)(&histo, &all_histograms[best_out]);\r
314 for (j = 0; j < num_final_clusters; ++j) {\r
315 const double cur_bits = FN(BrotliHistogramBitCostDistance)(\r
316 &histo, &all_histograms[clusters[j]]);\r
317 if (cur_bits < best_bits) {\r
318 best_bits = cur_bits;\r
319 best_out = clusters[j];\r
320 }\r
321 }\r
322 histogram_symbols[i] = best_out;\r
323 if (new_index[best_out] == kInvalidIndex) {\r
324 new_index[best_out] = next_index++;\r
325 }\r
326 }\r
327 }\r
328 BROTLI_FREE(m, clusters);\r
329 BROTLI_FREE(m, all_histograms);\r
330 BROTLI_ENSURE_CAPACITY(\r
331 m, uint8_t, split->types, split->types_alloc_size, num_blocks);\r
332 BROTLI_ENSURE_CAPACITY(\r
333 m, uint32_t, split->lengths, split->lengths_alloc_size, num_blocks);\r
334 if (BROTLI_IS_OOM(m)) return;\r
335 {\r
336 uint32_t cur_length = 0;\r
337 size_t block_idx = 0;\r
dd4f667e 338 uint8_t max_type = 0;\r
11b7501a
SB
339 for (i = 0; i < num_blocks; ++i) {\r
340 cur_length += block_lengths[i];\r
341 if (i + 1 == num_blocks ||\r
342 histogram_symbols[i] != histogram_symbols[i + 1]) {\r
343 const uint8_t id = (uint8_t)new_index[histogram_symbols[i]];\r
344 split->types[block_idx] = id;\r
345 split->lengths[block_idx] = cur_length;\r
346 max_type = BROTLI_MAX(uint8_t, max_type, id);\r
347 cur_length = 0;\r
348 ++block_idx;\r
349 }\r
350 }\r
351 split->num_blocks = block_idx;\r
352 split->num_types = (size_t)max_type + 1;\r
353 }\r
354 BROTLI_FREE(m, new_index);\r
355 BROTLI_FREE(m, block_lengths);\r
356 BROTLI_FREE(m, histogram_symbols);\r
357}\r
358\r
359static void FN(SplitByteVector)(MemoryManager* m,\r
360 const DataType* data, const size_t length,\r
361 const size_t literals_per_histogram,\r
362 const size_t max_histograms,\r
363 const size_t sampling_stride_length,\r
364 const double block_switch_cost,\r
365 const BrotliEncoderParams* params,\r
366 BlockSplit* split) {\r
367 const size_t data_size = FN(HistogramDataSize)();\r
368 size_t num_histograms = length / literals_per_histogram + 1;\r
369 HistogramType* histograms;\r
370 if (num_histograms > max_histograms) {\r
371 num_histograms = max_histograms;\r
372 }\r
373 if (length == 0) {\r
374 split->num_types = 1;\r
375 return;\r
376 } else if (length < kMinLengthForBlockSplitting) {\r
377 BROTLI_ENSURE_CAPACITY(m, uint8_t,\r
378 split->types, split->types_alloc_size, split->num_blocks + 1);\r
379 BROTLI_ENSURE_CAPACITY(m, uint32_t,\r
380 split->lengths, split->lengths_alloc_size, split->num_blocks + 1);\r
381 if (BROTLI_IS_OOM(m)) return;\r
382 split->num_types = 1;\r
383 split->types[split->num_blocks] = 0;\r
384 split->lengths[split->num_blocks] = (uint32_t)length;\r
385 split->num_blocks++;\r
386 return;\r
387 }\r
388 histograms = BROTLI_ALLOC(m, HistogramType, num_histograms);\r
389 if (BROTLI_IS_OOM(m)) return;\r
390 /* Find good entropy codes. */\r
391 FN(InitialEntropyCodes)(data, length,\r
392 sampling_stride_length,\r
393 num_histograms, histograms);\r
394 FN(RefineEntropyCodes)(data, length,\r
395 sampling_stride_length,\r
396 num_histograms, histograms);\r
397 {\r
398 /* Find a good path through literals with the good entropy codes. */\r
399 uint8_t* block_ids = BROTLI_ALLOC(m, uint8_t, length);\r
dd4f667e 400 size_t num_blocks = 0;\r
11b7501a
SB
401 const size_t bitmaplen = (num_histograms + 7) >> 3;\r
402 double* insert_cost = BROTLI_ALLOC(m, double, data_size * num_histograms);\r
403 double* cost = BROTLI_ALLOC(m, double, num_histograms);\r
404 uint8_t* switch_signal = BROTLI_ALLOC(m, uint8_t, length * bitmaplen);\r
405 uint16_t* new_id = BROTLI_ALLOC(m, uint16_t, num_histograms);\r
406 const size_t iters = params->quality < HQ_ZOPFLIFICATION_QUALITY ? 3 : 10;\r
407 size_t i;\r
408 if (BROTLI_IS_OOM(m)) return;\r
409 for (i = 0; i < iters; ++i) {\r
410 num_blocks = FN(FindBlocks)(data, length,\r
411 block_switch_cost,\r
412 num_histograms, histograms,\r
413 insert_cost, cost, switch_signal,\r
414 block_ids);\r
415 num_histograms = FN(RemapBlockIds)(block_ids, length,\r
416 new_id, num_histograms);\r
417 FN(BuildBlockHistograms)(data, length, block_ids,\r
418 num_histograms, histograms);\r
419 }\r
420 BROTLI_FREE(m, insert_cost);\r
421 BROTLI_FREE(m, cost);\r
422 BROTLI_FREE(m, switch_signal);\r
423 BROTLI_FREE(m, new_id);\r
424 BROTLI_FREE(m, histograms);\r
425 FN(ClusterBlocks)(m, data, length, num_blocks, block_ids, split);\r
426 if (BROTLI_IS_OOM(m)) return;\r
427 BROTLI_FREE(m, block_ids);\r
428 }\r
429}\r
430\r
431#undef HistogramType\r