1 /* NOLINT(build/header_guard) */
2 /* Copyright 2013 Google Inc. All Rights Reserved.
4 Distributed under MIT license.
5 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
8 /* template parameters: FN, DataType */
10 #define HistogramType FN(Histogram)
12 static void FN(InitialEntropyCodes
)(const DataType
* data
, size_t length
,
14 size_t num_histograms
,
15 HistogramType
* histograms
) {
16 unsigned int seed
= 7;
17 size_t block_length
= length
/ num_histograms
;
19 FN(ClearHistograms
)(histograms
, num_histograms
);
20 for (i
= 0; i
< num_histograms
; ++i
) {
21 size_t pos
= length
* i
/ num_histograms
;
23 pos
+= MyRand(&seed
) % block_length
;
25 if (pos
+ stride
>= length
) {
26 pos
= length
- stride
- 1;
28 FN(HistogramAddVector
)(&histograms
[i
], data
+ pos
, stride
);
32 static void FN(RandomSample
)(unsigned int* seed
,
36 HistogramType
* sample
) {
38 if (stride
>= length
) {
42 pos
= MyRand(seed
) % (length
- stride
+ 1);
44 FN(HistogramAddVector
)(sample
, data
+ pos
, stride
);
47 static void FN(RefineEntropyCodes
)(const DataType
* data
, size_t length
,
49 size_t num_histograms
,
50 HistogramType
* histograms
) {
52 kIterMulForRefining
* length
/ stride
+ kMinItersForRefining
;
53 unsigned int seed
= 7;
55 iters
= ((iters
+ num_histograms
- 1) / num_histograms
) * num_histograms
;
56 for (iter
= 0; iter
< iters
; ++iter
) {
58 FN(HistogramClear
)(&sample
);
59 FN(RandomSample
)(&seed
, data
, length
, stride
, &sample
);
60 FN(HistogramAddHistogram
)(&histograms
[iter
% num_histograms
], &sample
);
64 /* Assigns a block id from the range [0, vec.size()) to each data element
65 in data[0..length) and fills in block_id[0..length) with the assigned values.
66 Returns the number of blocks, i.e. one plus the number of block switches. */
67 static size_t FN(FindBlocks
)(const DataType
* data
, const size_t length
,
68 const double block_switch_bitcost
,
69 const size_t num_histograms
,
70 const HistogramType
* histograms
,
73 uint8_t* switch_signal
,
75 const size_t data_size
= FN(HistogramDataSize
)();
76 const size_t bitmaplen
= (num_histograms
+ 7) >> 3;
77 size_t num_blocks
= 1;
80 assert(num_histograms
<= 256);
81 if (num_histograms
<= 1) {
82 for (i
= 0; i
< length
; ++i
) {
87 memset(insert_cost
, 0, sizeof(insert_cost
[0]) * data_size
* num_histograms
);
88 for (i
= 0; i
< num_histograms
; ++i
) {
89 insert_cost
[i
] = FastLog2((uint32_t)histograms
[i
].total_count_
);
91 for (i
= data_size
; i
!= 0;) {
93 for (j
= 0; j
< num_histograms
; ++j
) {
94 insert_cost
[i
* num_histograms
+ j
] =
95 insert_cost
[j
] - BitCost(histograms
[j
].data_
[i
]);
98 memset(cost
, 0, sizeof(cost
[0]) * num_histograms
);
99 memset(switch_signal
, 0, sizeof(switch_signal
[0]) * length
* bitmaplen
);
100 /* After each iteration of this loop, cost[k] will contain the difference
101 between the minimum cost of arriving at the current byte position using
102 entropy code k, and the minimum cost of arriving at the current byte
103 position. This difference is capped at the block switch cost, and if it
104 reaches block switch cost, it means that when we trace back from the last
105 position, we need to switch here. */
106 for (i
= 0; i
< length
; ++i
) {
107 const size_t byte_ix
= i
;
108 size_t ix
= byte_ix
* bitmaplen
;
109 size_t insert_cost_ix
= data
[byte_ix
] * num_histograms
;
110 double min_cost
= 1e99
;
111 double block_switch_cost
= block_switch_bitcost
;
113 for (k
= 0; k
< num_histograms
; ++k
) {
114 /* We are coding the symbol in data[byte_ix] with entropy code k. */
115 cost
[k
] += insert_cost
[insert_cost_ix
+ k
];
116 if (cost
[k
] < min_cost
) {
118 block_id
[byte_ix
] = (uint8_t)k
;
121 /* More blocks for the beginning. */
122 if (byte_ix
< 2000) {
123 block_switch_cost
*= 0.77 + 0.07 * (double)byte_ix
/ 2000;
125 for (k
= 0; k
< num_histograms
; ++k
) {
127 if (cost
[k
] >= block_switch_cost
) {
128 const uint8_t mask
= (uint8_t)(1u << (k
& 7));
129 cost
[k
] = block_switch_cost
;
130 assert((k
>> 3) < bitmaplen
);
131 switch_signal
[ix
+ (k
>> 3)] |= mask
;
135 { /* Trace back from the last position and switch at the marked places. */
136 size_t byte_ix
= length
- 1;
137 size_t ix
= byte_ix
* bitmaplen
;
138 uint8_t cur_id
= block_id
[byte_ix
];
139 while (byte_ix
> 0) {
140 const uint8_t mask
= (uint8_t)(1u << (cur_id
& 7));
141 assert(((size_t)cur_id
>> 3) < bitmaplen
);
144 if (switch_signal
[ix
+ (cur_id
>> 3)] & mask
) {
145 if (cur_id
!= block_id
[byte_ix
]) {
146 cur_id
= block_id
[byte_ix
];
150 block_id
[byte_ix
] = cur_id
;
156 static size_t FN(RemapBlockIds
)(uint8_t* block_ids
, const size_t length
,
157 uint16_t* new_id
, const size_t num_histograms
) {
158 static const uint16_t kInvalidId
= 256;
159 uint16_t next_id
= 0;
161 for (i
= 0; i
< num_histograms
; ++i
) {
162 new_id
[i
] = kInvalidId
;
164 for (i
= 0; i
< length
; ++i
) {
165 assert(block_ids
[i
] < num_histograms
);
166 if (new_id
[block_ids
[i
]] == kInvalidId
) {
167 new_id
[block_ids
[i
]] = next_id
++;
170 for (i
= 0; i
< length
; ++i
) {
171 block_ids
[i
] = (uint8_t)new_id
[block_ids
[i
]];
172 assert(block_ids
[i
] < num_histograms
);
174 assert(next_id
<= num_histograms
);
178 static void FN(BuildBlockHistograms
)(const DataType
* data
, const size_t length
,
179 const uint8_t* block_ids
,
180 const size_t num_histograms
,
181 HistogramType
* histograms
) {
183 FN(ClearHistograms
)(histograms
, num_histograms
);
184 for (i
= 0; i
< length
; ++i
) {
185 FN(HistogramAdd
)(&histograms
[block_ids
[i
]], data
[i
]);
189 static void FN(ClusterBlocks
)(MemoryManager
* m
,
190 const DataType
* data
, const size_t length
,
191 const size_t num_blocks
,
194 uint32_t* histogram_symbols
= BROTLI_ALLOC(m
, uint32_t, num_blocks
);
195 uint32_t* block_lengths
= BROTLI_ALLOC(m
, uint32_t, num_blocks
);
196 const size_t expected_num_clusters
= CLUSTERS_PER_BATCH
*
197 (num_blocks
+ HISTOGRAMS_PER_BATCH
- 1) / HISTOGRAMS_PER_BATCH
;
198 size_t all_histograms_size
= 0;
199 size_t all_histograms_capacity
= expected_num_clusters
;
200 HistogramType
* all_histograms
=
201 BROTLI_ALLOC(m
, HistogramType
, all_histograms_capacity
);
202 size_t cluster_size_size
= 0;
203 size_t cluster_size_capacity
= expected_num_clusters
;
204 uint32_t* cluster_size
= BROTLI_ALLOC(m
, uint32_t, cluster_size_capacity
);
205 size_t num_clusters
= 0;
206 HistogramType
* histograms
= BROTLI_ALLOC(m
, HistogramType
,
207 BROTLI_MIN(size_t, num_blocks
, HISTOGRAMS_PER_BATCH
));
208 size_t max_num_pairs
=
209 HISTOGRAMS_PER_BATCH
* HISTOGRAMS_PER_BATCH
/ 2;
210 size_t pairs_capacity
= max_num_pairs
+ 1;
211 HistogramPair
* pairs
= BROTLI_ALLOC(m
, HistogramPair
, pairs_capacity
);
214 size_t num_final_clusters
;
215 static const uint32_t kInvalidIndex
= BROTLI_UINT32_MAX
;
217 uint8_t max_type
= 0;
219 uint32_t sizes
[HISTOGRAMS_PER_BATCH
] = { 0 };
220 uint32_t new_clusters
[HISTOGRAMS_PER_BATCH
] = { 0 };
221 uint32_t symbols
[HISTOGRAMS_PER_BATCH
] = { 0 };
222 uint32_t remap
[HISTOGRAMS_PER_BATCH
] = { 0 };
224 if (BROTLI_IS_OOM(m
)) return;
226 memset(block_lengths
, 0, num_blocks
* sizeof(uint32_t));
229 size_t block_idx
= 0;
230 for (i
= 0; i
< length
; ++i
) {
231 assert(block_idx
< num_blocks
);
232 ++block_lengths
[block_idx
];
233 if (i
+ 1 == length
|| block_ids
[i
] != block_ids
[i
+ 1]) {
237 assert(block_idx
== num_blocks
);
240 for (i
= 0; i
< num_blocks
; i
+= HISTOGRAMS_PER_BATCH
) {
241 const size_t num_to_combine
=
242 BROTLI_MIN(size_t, num_blocks
- i
, HISTOGRAMS_PER_BATCH
);
243 size_t num_new_clusters
;
245 for (j
= 0; j
< num_to_combine
; ++j
) {
247 FN(HistogramClear
)(&histograms
[j
]);
248 for (k
= 0; k
< block_lengths
[i
+ j
]; ++k
) {
249 FN(HistogramAdd
)(&histograms
[j
], data
[pos
++]);
251 histograms
[j
].bit_cost_
= FN(BrotliPopulationCost
)(&histograms
[j
]);
252 new_clusters
[j
] = (uint32_t)j
;
253 symbols
[j
] = (uint32_t)j
;
256 num_new_clusters
= FN(BrotliHistogramCombine
)(
257 histograms
, sizes
, symbols
, new_clusters
, pairs
, num_to_combine
,
258 num_to_combine
, HISTOGRAMS_PER_BATCH
, max_num_pairs
);
259 BROTLI_ENSURE_CAPACITY(m
, HistogramType
, all_histograms
,
260 all_histograms_capacity
, all_histograms_size
+ num_new_clusters
);
261 BROTLI_ENSURE_CAPACITY(m
, uint32_t, cluster_size
,
262 cluster_size_capacity
, cluster_size_size
+ num_new_clusters
);
263 if (BROTLI_IS_OOM(m
)) return;
264 for (j
= 0; j
< num_new_clusters
; ++j
) {
265 all_histograms
[all_histograms_size
++] = histograms
[new_clusters
[j
]];
266 cluster_size
[cluster_size_size
++] = sizes
[new_clusters
[j
]];
267 remap
[new_clusters
[j
]] = (uint32_t)j
;
269 for (j
= 0; j
< num_to_combine
; ++j
) {
270 histogram_symbols
[i
+ j
] = (uint32_t)num_clusters
+ remap
[symbols
[j
]];
272 num_clusters
+= num_new_clusters
;
273 assert(num_clusters
== cluster_size_size
);
274 assert(num_clusters
== all_histograms_size
);
276 BROTLI_FREE(m
, histograms
);
279 BROTLI_MIN(size_t, 64 * num_clusters
, (num_clusters
/ 2) * num_clusters
);
280 if (pairs_capacity
< max_num_pairs
+ 1) {
281 BROTLI_FREE(m
, pairs
);
282 pairs
= BROTLI_ALLOC(m
, HistogramPair
, max_num_pairs
+ 1);
283 if (BROTLI_IS_OOM(m
)) return;
286 clusters
= BROTLI_ALLOC(m
, uint32_t, num_clusters
);
287 if (BROTLI_IS_OOM(m
)) return;
288 for (i
= 0; i
< num_clusters
; ++i
) {
289 clusters
[i
] = (uint32_t)i
;
291 num_final_clusters
= FN(BrotliHistogramCombine
)(
292 all_histograms
, cluster_size
, histogram_symbols
, clusters
, pairs
,
293 num_clusters
, num_blocks
, BROTLI_MAX_NUMBER_OF_BLOCK_TYPES
,
295 BROTLI_FREE(m
, pairs
);
296 BROTLI_FREE(m
, cluster_size
);
298 new_index
= BROTLI_ALLOC(m
, uint32_t, num_clusters
);
299 if (BROTLI_IS_OOM(m
)) return;
300 for (i
= 0; i
< num_clusters
; ++i
) new_index
[i
] = kInvalidIndex
;
303 uint32_t next_index
= 0;
304 for (i
= 0; i
< num_blocks
; ++i
) {
309 FN(HistogramClear
)(&histo
);
310 for (j
= 0; j
< block_lengths
[i
]; ++j
) {
311 FN(HistogramAdd
)(&histo
, data
[pos
++]);
313 best_out
= (i
== 0) ? histogram_symbols
[0] : histogram_symbols
[i
- 1];
315 FN(BrotliHistogramBitCostDistance
)(&histo
, &all_histograms
[best_out
]);
316 for (j
= 0; j
< num_final_clusters
; ++j
) {
317 const double cur_bits
= FN(BrotliHistogramBitCostDistance
)(
318 &histo
, &all_histograms
[clusters
[j
]]);
319 if (cur_bits
< best_bits
) {
320 best_bits
= cur_bits
;
321 best_out
= clusters
[j
];
324 histogram_symbols
[i
] = best_out
;
325 if (new_index
[best_out
] == kInvalidIndex
) {
326 new_index
[best_out
] = next_index
++;
330 BROTLI_FREE(m
, clusters
);
331 BROTLI_FREE(m
, all_histograms
);
332 BROTLI_ENSURE_CAPACITY(
333 m
, uint8_t, split
->types
, split
->types_alloc_size
, num_blocks
);
334 BROTLI_ENSURE_CAPACITY(
335 m
, uint32_t, split
->lengths
, split
->lengths_alloc_size
, num_blocks
);
336 if (BROTLI_IS_OOM(m
)) return;
338 uint32_t cur_length
= 0;
339 size_t block_idx
= 0;
340 for (i
= 0; i
< num_blocks
; ++i
) {
341 cur_length
+= block_lengths
[i
];
342 if (i
+ 1 == num_blocks
||
343 histogram_symbols
[i
] != histogram_symbols
[i
+ 1]) {
344 const uint8_t id
= (uint8_t)new_index
[histogram_symbols
[i
]];
345 split
->types
[block_idx
] = id
;
346 split
->lengths
[block_idx
] = cur_length
;
347 max_type
= BROTLI_MAX(uint8_t, max_type
, id
);
352 split
->num_blocks
= block_idx
;
353 split
->num_types
= (size_t)max_type
+ 1;
355 BROTLI_FREE(m
, new_index
);
356 BROTLI_FREE(m
, block_lengths
);
357 BROTLI_FREE(m
, histogram_symbols
);
360 static void FN(SplitByteVector
)(MemoryManager
* m
,
361 const DataType
* data
, const size_t length
,
362 const size_t literals_per_histogram
,
363 const size_t max_histograms
,
364 const size_t sampling_stride_length
,
365 const double block_switch_cost
,
366 const BrotliEncoderParams
* params
,
368 const size_t data_size
= FN(HistogramDataSize
)();
369 size_t num_histograms
= length
/ literals_per_histogram
+ 1;
370 HistogramType
* histograms
;
371 if (num_histograms
> max_histograms
) {
372 num_histograms
= max_histograms
;
375 split
->num_types
= 1;
377 } else if (length
< kMinLengthForBlockSplitting
) {
378 BROTLI_ENSURE_CAPACITY(m
, uint8_t,
379 split
->types
, split
->types_alloc_size
, split
->num_blocks
+ 1);
380 BROTLI_ENSURE_CAPACITY(m
, uint32_t,
381 split
->lengths
, split
->lengths_alloc_size
, split
->num_blocks
+ 1);
382 if (BROTLI_IS_OOM(m
)) return;
383 split
->num_types
= 1;
384 split
->types
[split
->num_blocks
] = 0;
385 split
->lengths
[split
->num_blocks
] = (uint32_t)length
;
389 histograms
= BROTLI_ALLOC(m
, HistogramType
, num_histograms
);
390 if (BROTLI_IS_OOM(m
)) return;
391 /* Find good entropy codes. */
392 FN(InitialEntropyCodes
)(data
, length
,
393 sampling_stride_length
,
394 num_histograms
, histograms
);
395 FN(RefineEntropyCodes
)(data
, length
,
396 sampling_stride_length
,
397 num_histograms
, histograms
);
399 /* Find a good path through literals with the good entropy codes. */
400 uint8_t* block_ids
= BROTLI_ALLOC(m
, uint8_t, length
);
402 const size_t bitmaplen
= (num_histograms
+ 7) >> 3;
403 double* insert_cost
= BROTLI_ALLOC(m
, double, data_size
* num_histograms
);
404 double* cost
= BROTLI_ALLOC(m
, double, num_histograms
);
405 uint8_t* switch_signal
= BROTLI_ALLOC(m
, uint8_t, length
* bitmaplen
);
406 uint16_t* new_id
= BROTLI_ALLOC(m
, uint16_t, num_histograms
);
407 const size_t iters
= params
->quality
< HQ_ZOPFLIFICATION_QUALITY
? 3 : 10;
409 if (BROTLI_IS_OOM(m
)) return;
410 for (i
= 0; i
< iters
; ++i
) {
411 num_blocks
= FN(FindBlocks
)(data
, length
,
413 num_histograms
, histograms
,
414 insert_cost
, cost
, switch_signal
,
416 num_histograms
= FN(RemapBlockIds
)(block_ids
, length
,
417 new_id
, num_histograms
);
418 FN(BuildBlockHistograms
)(data
, length
, block_ids
,
419 num_histograms
, histograms
);
421 BROTLI_FREE(m
, insert_cost
);
422 BROTLI_FREE(m
, cost
);
423 BROTLI_FREE(m
, switch_signal
);
424 BROTLI_FREE(m
, new_id
);
425 BROTLI_FREE(m
, histograms
);
426 FN(ClusterBlocks
)(m
, data
, length
, num_blocks
, block_ids
, split
);
427 if (BROTLI_IS_OOM(m
)) return;
428 BROTLI_FREE(m
, block_ids
);