1#![allow(dead_code)]
2use super::super::alloc;
3use super::super::alloc::{Allocator, SliceWrapper, SliceWrapperMut};
4use super::backward_references::BrotliEncoderParams;
5use super::bit_cost::{BitsEntropy, BrotliPopulationCost};
6use super::block_split::BlockSplit;
7use super::block_splitter::BrotliSplitBlock;
8use super::brotli_bit_stream::MetaBlockSplit;
9use super::cluster::BrotliClusterHistograms;
10use super::combined_alloc::BrotliAlloc;
11use super::command::{
12 BrotliDistanceParams, Command, CommandCopyLen, CommandRestoreDistanceCode,
13 PrefixEncodeCopyDistance,
14};
15use super::constants::BROTLI_MAX_NPOSTFIX;
16use super::encode::{
17 BROTLI_DISTANCE_ALPHABET_SIZE, BROTLI_LARGE_MAX_DISTANCE_BITS, BROTLI_MAX_ALLOWED_DISTANCE,
18 BROTLI_MAX_DISTANCE_BITS,
19};
20use super::entropy_encode::BrotliOptimizeHuffmanCountsForRle;
21use super::histogram::{
22 BrotliBuildHistogramsWithContext, ClearHistograms, Context, ContextType, CostAccessors,
23 HistogramAddHistogram, HistogramAddItem, HistogramClear, HistogramCommand, HistogramDistance,
24 HistogramLiteral,
25};
26use super::util::{brotli_max_size_t, brotli_min_size_t};
27use core;
28
29pub fn BrotliInitDistanceParams(params: &mut BrotliEncoderParams, npostfix: u32, ndirect: u32) {
30 let dist_params = &mut params.dist;
31 let mut alphabet_size;
32 let mut max_distance;
33
34 dist_params.distance_postfix_bits = npostfix;
35 dist_params.num_direct_distance_codes = ndirect;
36
37 alphabet_size = BROTLI_DISTANCE_ALPHABET_SIZE(npostfix, ndirect, BROTLI_MAX_DISTANCE_BITS);
38 max_distance =
39 ndirect + (1u32 << (BROTLI_MAX_DISTANCE_BITS + npostfix + 2)) - (1u32 << (npostfix + 2));
40
41 if (params.large_window) {
42 let bound: [u32; BROTLI_MAX_NPOSTFIX + 1] = [0, 4, 12, 28];
43 let postfix = 1u32 << npostfix;
44 alphabet_size =
45 BROTLI_DISTANCE_ALPHABET_SIZE(npostfix, ndirect, BROTLI_LARGE_MAX_DISTANCE_BITS);
46 if (ndirect < bound[npostfix as usize]) {
50 max_distance =
51 BROTLI_MAX_ALLOWED_DISTANCE as u32 - (bound[npostfix as usize] - ndirect);
52 } else if (ndirect >= bound[npostfix as usize] + postfix) {
53 max_distance = (3u32 << 29) - 4 + (ndirect - bound[npostfix as usize]);
54 } else {
55 max_distance = BROTLI_MAX_ALLOWED_DISTANCE as u32;
56 }
57 }
58
59 dist_params.alphabet_size = alphabet_size;
60 dist_params.max_distance = max_distance as usize;
61}
62
63fn RecomputeDistancePrefixes(
64 cmds: &mut [Command],
65 num_commands: usize,
66 orig_params: &BrotliDistanceParams,
67 new_params: &BrotliDistanceParams,
68) {
69 if orig_params.distance_postfix_bits == new_params.distance_postfix_bits
70 && orig_params.num_direct_distance_codes == new_params.num_direct_distance_codes
71 {
72 return;
73 }
74
75 for cmd in cmds.split_at_mut(num_commands).0.iter_mut() {
76 if (CommandCopyLen(cmd) != 0 && cmd.cmd_prefix_ >= 128) {
77 let ret = CommandRestoreDistanceCode(cmd, orig_params);
78 PrefixEncodeCopyDistance(
79 ret as usize,
80 new_params.num_direct_distance_codes as usize,
81 new_params.distance_postfix_bits as u64,
82 &mut cmd.dist_prefix_,
83 &mut cmd.dist_extra_,
84 );
85 }
86 }
87}
88
89fn ComputeDistanceCost(
90 cmds: &[Command],
91 num_commands: usize,
92 orig_params: &BrotliDistanceParams,
93 new_params: &BrotliDistanceParams,
94 scratch: &mut <HistogramDistance as CostAccessors>::i32vec,
95 cost: &mut f64,
96) -> bool {
97 let mut equal_params = false;
98 let mut dist_prefix: u16 = 0;
99 let mut dist_extra: u32 = 0;
100 let mut extra_bits: f64 = 0.0;
101 let mut histo = HistogramDistance::default();
102
103 if (orig_params.distance_postfix_bits == new_params.distance_postfix_bits
104 && orig_params.num_direct_distance_codes == new_params.num_direct_distance_codes)
105 {
106 equal_params = true;
107 }
108 for cmd in cmds.split_at(num_commands).0 {
109 if CommandCopyLen(cmd) != 0 && cmd.cmd_prefix_ >= 128 {
110 if (equal_params) {
111 dist_prefix = cmd.dist_prefix_;
112 } else {
113 let distance = CommandRestoreDistanceCode(cmd, orig_params);
114 if distance > new_params.max_distance as u32 {
115 return false;
116 }
117 PrefixEncodeCopyDistance(
118 distance as usize,
119 new_params.num_direct_distance_codes as usize,
120 new_params.distance_postfix_bits as u64,
121 &mut dist_prefix,
122 &mut dist_extra,
123 );
124 }
125 HistogramAddItem(&mut histo, (dist_prefix & 0x3FF) as usize);
126 extra_bits += (dist_prefix >> 10) as f64;
127 }
128 }
129
130 *cost = BrotliPopulationCost(&histo, scratch) as f64 + extra_bits;
131 true
132}
133
134pub fn BrotliBuildMetaBlock<Alloc: BrotliAlloc>(
135 alloc: &mut Alloc,
136 ringbuffer: &[u8],
137 pos: usize,
138 mask: usize,
139 params: &mut BrotliEncoderParams,
140 prev_byte: u8,
141 prev_byte2: u8,
142 cmds: &mut [Command],
143 num_commands: usize,
144 literal_context_mode: ContextType,
145 lit_scratch_space: &mut <HistogramLiteral as CostAccessors>::i32vec,
146 cmd_scratch_space: &mut <HistogramCommand as CostAccessors>::i32vec,
147 dst_scratch_space: &mut <HistogramDistance as CostAccessors>::i32vec,
148 mb: &mut MetaBlockSplit<Alloc>,
149) {
150 static kMaxNumberOfHistograms: usize = 256usize;
151 let mut distance_histograms: <Alloc as Allocator<HistogramDistance>>::AllocatedMemory;
152 let mut literal_histograms: <Alloc as Allocator<HistogramLiteral>>::AllocatedMemory;
153 let mut literal_context_modes: <Alloc as Allocator<ContextType>>::AllocatedMemory =
154 <Alloc as Allocator<ContextType>>::AllocatedMemory::default();
155
156 let mut i: usize;
157 let mut literal_context_multiplier: usize = 1;
158 let mut ndirect_msb: u32 = 0;
159 let mut check_orig = true;
160 if !params.avoid_distance_prefix_search {
161 let mut best_dist_cost: f64 = 1e99;
162 let orig_params = params.clone();
163 let mut new_params = params.clone();
164
165 for npostfix in 0..(BROTLI_MAX_NPOSTFIX + 1) {
166 while ndirect_msb < 16 {
167 let ndirect = ndirect_msb << npostfix;
168
169 let mut dist_cost: f64 = 0.0;
170 BrotliInitDistanceParams(&mut new_params, npostfix as u32, ndirect);
171 if npostfix as u32 == orig_params.dist.distance_postfix_bits
172 && ndirect == orig_params.dist.num_direct_distance_codes
173 {
174 check_orig = false;
175 }
176 let skip: bool = !ComputeDistanceCost(
177 cmds,
178 num_commands,
179 &orig_params.dist,
180 &new_params.dist,
181 dst_scratch_space,
182 &mut dist_cost,
183 );
184 if skip || (dist_cost > best_dist_cost) {
185 break;
186 }
187 best_dist_cost = dist_cost;
188 params.dist = new_params.dist;
189 ndirect_msb += 1;
190 }
191 ndirect_msb = ndirect_msb.saturating_sub(1);
192 ndirect_msb /= 2;
193 }
194 if check_orig {
195 let mut dist_cost: f64 = 0.0;
196 ComputeDistanceCost(
197 cmds,
198 num_commands,
199 &orig_params.dist,
200 &orig_params.dist,
201 dst_scratch_space,
202 &mut dist_cost,
203 );
204 if dist_cost < best_dist_cost {
205 params.dist = orig_params.dist;
207 }
208 }
209 RecomputeDistancePrefixes(cmds, num_commands, &orig_params.dist, ¶ms.dist);
210 }
211 BrotliSplitBlock(
212 alloc,
213 cmds,
214 num_commands,
215 ringbuffer,
216 pos,
217 mask,
218 params,
219 lit_scratch_space,
220 cmd_scratch_space,
221 dst_scratch_space,
222 &mut mb.literal_split,
223 &mut mb.command_split,
224 &mut mb.distance_split,
225 );
226 if params.disable_literal_context_modeling == 0 {
227 literal_context_multiplier = (1i32 << 6) as usize;
228 literal_context_modes =
229 <Alloc as Allocator<ContextType>>::alloc_cell(alloc, mb.literal_split.num_types);
230 for item in literal_context_modes.slice_mut().iter_mut() {
231 *item = literal_context_mode;
232 }
233 }
234 let literal_histograms_size: usize = mb
235 .literal_split
236 .num_types
237 .wrapping_mul(literal_context_multiplier);
238 literal_histograms =
239 <Alloc as Allocator<HistogramLiteral>>::alloc_cell(alloc, literal_histograms_size);
240 let distance_histograms_size: usize = mb.distance_split.num_types << 2;
241 distance_histograms =
242 <Alloc as Allocator<HistogramDistance>>::alloc_cell(alloc, distance_histograms_size);
243 mb.command_histograms_size = mb.command_split.num_types;
244 mb.command_histograms =
245 <Alloc as Allocator<HistogramCommand>>::alloc_cell(alloc, mb.command_histograms_size);
246 BrotliBuildHistogramsWithContext(
247 cmds,
248 num_commands,
249 &mut mb.literal_split,
250 &mut mb.command_split,
251 &mut mb.distance_split,
252 ringbuffer,
253 pos,
254 mask,
255 prev_byte,
256 prev_byte2,
257 literal_context_modes.slice(),
258 literal_histograms.slice_mut(),
259 mb.command_histograms.slice_mut(),
260 distance_histograms.slice_mut(),
261 );
262 <Alloc as Allocator<ContextType>>::free_cell(alloc, literal_context_modes);
263 mb.literal_context_map_size = mb.literal_split.num_types << 6;
264 mb.literal_context_map =
265 <Alloc as Allocator<u32>>::alloc_cell(alloc, mb.literal_context_map_size);
266 mb.literal_histograms_size = mb.literal_context_map_size;
267 mb.literal_histograms =
268 <Alloc as Allocator<HistogramLiteral>>::alloc_cell(alloc, mb.literal_histograms_size);
269 BrotliClusterHistograms(
270 alloc,
271 literal_histograms.slice(),
272 literal_histograms_size,
273 kMaxNumberOfHistograms,
274 lit_scratch_space,
275 mb.literal_histograms.slice_mut(),
276 &mut mb.literal_histograms_size,
277 mb.literal_context_map.slice_mut(),
278 );
279 <Alloc as Allocator<HistogramLiteral>>::free_cell(alloc, literal_histograms);
280 if params.disable_literal_context_modeling != 0 {
281 i = mb.literal_split.num_types;
282 while i != 0usize {
283 let mut j: usize = 0usize;
284 i = i.wrapping_sub(1);
285 while j < (1i32 << 6) as usize {
286 {
287 let val = mb.literal_context_map.slice()[i];
288 mb.literal_context_map.slice_mut()[(i << 6).wrapping_add(j)] = val;
289 }
290 j = j.wrapping_add(1);
291 }
292 }
293 }
294 mb.distance_context_map_size = mb.distance_split.num_types << 2;
295 mb.distance_context_map =
296 <Alloc as Allocator<u32>>::alloc_cell(alloc, mb.distance_context_map_size);
297 mb.distance_histograms_size = mb.distance_context_map_size;
298 mb.distance_histograms =
299 <Alloc as Allocator<HistogramDistance>>::alloc_cell(alloc, mb.distance_histograms_size);
300 BrotliClusterHistograms(
301 alloc,
302 distance_histograms.slice(),
303 mb.distance_context_map_size,
304 kMaxNumberOfHistograms,
305 dst_scratch_space,
306 mb.distance_histograms.slice_mut(),
307 &mut mb.distance_histograms_size,
308 mb.distance_context_map.slice_mut(),
309 );
310 <Alloc as Allocator<HistogramDistance>>::free_cell(alloc, distance_histograms);
311}
312
313pub struct BlockSplitter {
320 pub alphabet_size_: usize,
321 pub min_block_size_: usize,
322 pub split_threshold_: super::util::floatX,
323 pub num_blocks_: usize,
324 pub target_block_size_: usize,
328 pub block_size_: usize,
329 pub curr_histogram_ix_: usize,
330 pub last_histogram_ix_: [usize; 2],
331 pub last_entropy_: [super::util::floatX; 2],
332 pub merge_last_count_: usize,
333}
334
335pub struct ContextBlockSplitter {
336 pub alphabet_size_: usize,
337 pub num_contexts_: usize,
338 pub max_block_types_: usize,
339 pub min_block_size_: usize,
340 pub split_threshold_: super::util::floatX,
341 pub num_blocks_: usize,
342 pub target_block_size_: usize,
346 pub block_size_: usize,
347 pub curr_histogram_ix_: usize,
348 pub last_histogram_ix_: [usize; 2],
349 pub last_entropy_: [super::util::floatX; 2 * BROTLI_MAX_STATIC_CONTEXTS],
350 pub merge_last_count_: usize,
351}
352
353enum LitBlocks {
354 plain(BlockSplitter), ctx(ContextBlockSplitter), }
357
358fn InitBlockSplitter<
396 HistogramType: SliceWrapper<u32> + SliceWrapperMut<u32> + CostAccessors,
397 Alloc: alloc::Allocator<u8> + alloc::Allocator<u32> + alloc::Allocator<HistogramType>,
398>(
399 alloc: &mut Alloc,
400 alphabet_size: usize,
401 min_block_size: usize,
402 split_threshold: super::util::floatX,
403 num_symbols: usize,
404 split: &mut BlockSplit<Alloc>,
405 histograms: &mut <Alloc as Allocator<HistogramType>>::AllocatedMemory,
406 histograms_size: &mut usize,
407) -> BlockSplitter {
408 let max_num_blocks: usize = num_symbols.wrapping_div(min_block_size).wrapping_add(1);
409 let max_num_types: usize = brotli_min_size_t(max_num_blocks, (256i32 + 1i32) as usize);
410 let mut xself = BlockSplitter {
411 last_entropy_: [0.0 as super::util::floatX; 2],
412 alphabet_size_: alphabet_size,
413 min_block_size_: min_block_size,
414 split_threshold_: split_threshold,
415 num_blocks_: 0usize,
416 target_block_size_: min_block_size,
419 block_size_: 0usize,
420 curr_histogram_ix_: 0usize,
421 merge_last_count_: 0usize,
422 last_histogram_ix_: [0; 2],
423 };
424 {
425 if split.types.slice().len() < max_num_blocks {
426 let mut _new_size: usize = if split.types.slice().is_empty() {
427 max_num_blocks
428 } else {
429 split.types.slice().len()
430 };
431 let mut new_array: <Alloc as Allocator<u8>>::AllocatedMemory;
432 while _new_size < max_num_blocks {
433 _new_size = _new_size.wrapping_mul(2);
434 }
435 new_array = <Alloc as Allocator<u8>>::alloc_cell(alloc, _new_size);
436 if (!split.types.slice().is_empty()) {
437 new_array.slice_mut()[..split.types.slice().len()]
438 .clone_from_slice(split.types.slice());
439 }
440 <Alloc as Allocator<u8>>::free_cell(
441 alloc,
442 core::mem::replace(&mut split.types, new_array),
443 );
444 }
445 }
446 {
447 if split.lengths.slice().len() < max_num_blocks {
448 let mut _new_size: usize = if split.lengths.slice().is_empty() {
449 max_num_blocks
450 } else {
451 split.lengths.slice().len()
452 };
453 while _new_size < max_num_blocks {
454 _new_size = _new_size.wrapping_mul(2);
455 }
456 let mut new_array = <Alloc as Allocator<u32>>::alloc_cell(alloc, _new_size);
457 new_array.slice_mut()[..split.lengths.slice().len()]
458 .clone_from_slice(split.lengths.slice());
459 <Alloc as Allocator<u32>>::free_cell(
460 alloc,
461 core::mem::replace(&mut split.lengths, new_array),
462 );
463 }
464 }
465 split.num_blocks = max_num_blocks;
466 *histograms_size = max_num_types;
467 let hlocal = <Alloc as Allocator<HistogramType>>::alloc_cell(alloc, *histograms_size);
468 <Alloc as Allocator<HistogramType>>::free_cell(
469 alloc,
470 core::mem::replace(&mut *histograms, hlocal),
471 );
472 HistogramClear(&mut histograms.slice_mut()[0]);
473 xself.last_histogram_ix_[0] = 0;
474 xself.last_histogram_ix_[1] = 0;
475 xself
476}
477fn InitContextBlockSplitter<
478 Alloc: alloc::Allocator<u8> + alloc::Allocator<u32> + alloc::Allocator<HistogramLiteral>,
479>(
480 alloc: &mut Alloc,
481 alphabet_size: usize,
482 num_contexts: usize,
483 min_block_size: usize,
484 split_threshold: super::util::floatX,
485 num_symbols: usize,
486 split: &mut BlockSplit<Alloc>,
487 histograms: &mut <Alloc as Allocator<HistogramLiteral>>::AllocatedMemory,
488 histograms_size: &mut usize,
489) -> ContextBlockSplitter {
490 let max_num_blocks: usize = num_symbols.wrapping_div(min_block_size).wrapping_add(1);
491
492 assert!(num_contexts <= BROTLI_MAX_STATIC_CONTEXTS);
493 let mut xself = ContextBlockSplitter {
494 alphabet_size_: alphabet_size,
495 num_contexts_: num_contexts,
496 max_block_types_: (256usize).wrapping_div(num_contexts),
497 min_block_size_: min_block_size,
498 split_threshold_: split_threshold,
499 num_blocks_: 0usize,
500 target_block_size_: min_block_size,
502 block_size_: 0usize,
503 curr_histogram_ix_: 0usize,
504 merge_last_count_: 0usize,
505 last_histogram_ix_: [0; 2],
506 last_entropy_: [0.0 as super::util::floatX; 2 * BROTLI_MAX_STATIC_CONTEXTS],
507 };
508 let max_num_types: usize =
509 brotli_min_size_t(max_num_blocks, xself.max_block_types_.wrapping_add(1));
510 {
511 if split.types.slice().len() < max_num_blocks {
512 let mut _new_size: usize = if split.types.slice().is_empty() {
513 max_num_blocks
514 } else {
515 split.types.slice().len()
516 };
517 while _new_size < max_num_blocks {
518 _new_size = _new_size.wrapping_mul(2);
519 }
520 let mut new_array = <Alloc as Allocator<u8>>::alloc_cell(alloc, _new_size);
521 if (!split.types.slice().is_empty()) {
522 new_array.slice_mut()[..split.types.slice().len()]
523 .clone_from_slice(split.types.slice());
524 }
525 <Alloc as Allocator<u8>>::free_cell(
526 alloc,
527 core::mem::replace(&mut split.types, new_array),
528 );
529 }
530 }
531 {
532 if split.lengths.slice().len() < max_num_blocks {
533 let mut _new_size: usize = if split.lengths.slice().is_empty() {
534 max_num_blocks
535 } else {
536 split.lengths.slice().len()
537 };
538 while _new_size < max_num_blocks {
539 _new_size = _new_size.wrapping_mul(2);
540 }
541 let mut new_array = <Alloc as Allocator<u32>>::alloc_cell(alloc, _new_size);
542 if (!split.lengths.slice().is_empty()) {
543 new_array.slice_mut()[..split.lengths.slice().len()]
544 .clone_from_slice(split.lengths.slice());
545 }
546 <Alloc as Allocator<u32>>::free_cell(
547 alloc,
548 core::mem::replace(&mut split.lengths, new_array),
549 );
550 }
551 }
552 split.num_blocks = max_num_blocks;
553 *histograms_size = max_num_types.wrapping_mul(num_contexts);
554 *histograms = <Alloc as Allocator<HistogramLiteral>>::alloc_cell(alloc, *histograms_size);
555 ClearHistograms(&mut histograms.slice_mut()[0..], num_contexts);
557 xself.last_histogram_ix_[0] = 0;
558 xself.last_histogram_ix_[1] = 0;
559 xself
560}
561
562fn BlockSplitterFinishBlock<
563 HistogramType: SliceWrapper<u32> + SliceWrapperMut<u32> + CostAccessors + Clone,
564 Alloc: alloc::Allocator<u8> + alloc::Allocator<u32>,
565>(
566 xself: &mut BlockSplitter,
567 split: &mut BlockSplit<Alloc>,
568 histograms: &mut [HistogramType],
569 histograms_size: &mut usize,
570 is_final: i32,
571) {
572 xself.block_size_ = brotli_max_size_t(xself.block_size_, xself.min_block_size_);
573 if xself.num_blocks_ == 0usize {
574 split.lengths.slice_mut()[0] = xself.block_size_ as u32;
575 split.types.slice_mut()[0] = 0u8;
576 xself.last_entropy_[0] = BitsEntropy((histograms[0]).slice(), xself.alphabet_size_);
577 xself.last_entropy_[1] = xself.last_entropy_[0];
578 xself.num_blocks_ = xself.num_blocks_.wrapping_add(1);
579 split.num_types = split.num_types.wrapping_add(1);
580 xself.curr_histogram_ix_ = xself.curr_histogram_ix_.wrapping_add(1);
581 if xself.curr_histogram_ix_ < *histograms_size {
582 HistogramClear(&mut histograms[xself.curr_histogram_ix_]);
583 }
584 xself.block_size_ = 0usize;
585 } else if xself.block_size_ > 0usize {
586 let entropy: super::util::floatX = BitsEntropy(
587 (histograms[xself.curr_histogram_ix_]).slice(),
588 xself.alphabet_size_,
589 );
590 let mut combined_histo: [HistogramType; 2] = [
591 histograms[xself.curr_histogram_ix_].clone(),
592 histograms[xself.curr_histogram_ix_].clone(),
593 ];
594
595 let mut combined_entropy: [super::util::floatX; 2] =
596 [0.0 as super::util::floatX, 0.0 as super::util::floatX];
597 let mut diff: [super::util::floatX; 2] =
598 [0.0 as super::util::floatX, 0.0 as super::util::floatX];
599 for j in 0..2 {
600 {
601 let last_histogram_ix: usize = xself.last_histogram_ix_[j];
602 HistogramAddHistogram(&mut combined_histo[j], &histograms[last_histogram_ix]);
603 combined_entropy[j] = BitsEntropy(
604 &mut combined_histo[j].slice_mut()[0..],
605 xself.alphabet_size_,
606 );
607 diff[j] = combined_entropy[j] - entropy - xself.last_entropy_[j];
608 }
609 }
610 if split.num_types < 256usize
611 && (diff[0] > xself.split_threshold_)
612 && (diff[1] > xself.split_threshold_)
613 {
614 split.lengths.slice_mut()[xself.num_blocks_] = xself.block_size_ as u32;
615 split.types.slice_mut()[xself.num_blocks_] = split.num_types as u8;
616 xself.last_histogram_ix_[1] = xself.last_histogram_ix_[0];
617 xself.last_histogram_ix_[0] = split.num_types as u8 as usize;
618 xself.last_entropy_[1] = xself.last_entropy_[0];
619 xself.last_entropy_[0] = entropy;
620 xself.num_blocks_ = xself.num_blocks_.wrapping_add(1);
621 split.num_types = split.num_types.wrapping_add(1);
622 xself.curr_histogram_ix_ = xself.curr_histogram_ix_.wrapping_add(1);
623 if xself.curr_histogram_ix_ < *histograms_size {
624 HistogramClear(&mut histograms[xself.curr_histogram_ix_]);
625 }
626 xself.block_size_ = 0usize;
627 xself.merge_last_count_ = 0usize;
628 xself.target_block_size_ = xself.min_block_size_;
629 } else if diff[1] < diff[0] - 20.0 as super::util::floatX {
630 split.lengths.slice_mut()[xself.num_blocks_] = xself.block_size_ as u32;
631 split.types.slice_mut()[xself.num_blocks_] =
632 split.types.slice()[xself.num_blocks_.wrapping_sub(2)]; {
634 xself.last_histogram_ix_.swap(0, 1);
635 }
636 histograms[xself.last_histogram_ix_[0]] = combined_histo[1].clone();
637 xself.last_entropy_[1] = xself.last_entropy_[0];
638 xself.last_entropy_[0] = combined_entropy[1];
639 xself.num_blocks_ = xself.num_blocks_.wrapping_add(1);
640 xself.block_size_ = 0usize;
641 HistogramClear(&mut histograms[xself.curr_histogram_ix_]);
642 xself.merge_last_count_ = 0usize;
643 xself.target_block_size_ = xself.min_block_size_;
644 } else {
645 {
646 let _rhs = xself.block_size_ as u32;
647 let _lhs = &mut split.lengths.slice_mut()[xself.num_blocks_.wrapping_sub(1)];
648 *_lhs = (*_lhs).wrapping_add(_rhs);
649 }
650 histograms[xself.last_histogram_ix_[0]] = combined_histo[0].clone();
651 xself.last_entropy_[0] = combined_entropy[0];
652 if split.num_types == 1 {
653 xself.last_entropy_[1] = xself.last_entropy_[0];
654 }
655 xself.block_size_ = 0usize;
656 HistogramClear(&mut histograms[xself.curr_histogram_ix_]);
657 if {
658 xself.merge_last_count_ = xself.merge_last_count_.wrapping_add(1);
659 xself.merge_last_count_
660 } > 1
661 {
662 xself.target_block_size_ =
663 xself.target_block_size_.wrapping_add(xself.min_block_size_);
664 }
665 }
666 }
667 if is_final != 0 {
668 *histograms_size = split.num_types;
669 split.num_blocks = xself.num_blocks_;
670 }
671}
672const BROTLI_MAX_STATIC_CONTEXTS: usize = 13;
673
674fn ContextBlockSplitterFinishBlock<
675 Alloc: alloc::Allocator<u8> + alloc::Allocator<u32> + alloc::Allocator<HistogramLiteral>,
676 AllocHL: alloc::Allocator<HistogramLiteral>,
677>(
678 xself: &mut ContextBlockSplitter,
679 m: &mut AllocHL,
680 split: &mut BlockSplit<Alloc>,
681 histograms: &mut [HistogramLiteral],
682 histograms_size: &mut usize,
683 is_final: i32,
684) {
685 let num_contexts: usize = xself.num_contexts_;
686 if xself.block_size_ < xself.min_block_size_ {
687 xself.block_size_ = xself.min_block_size_;
688 }
689 if xself.num_blocks_ == 0usize {
690 let mut i: usize;
691 split.lengths.slice_mut()[0] = xself.block_size_ as u32;
692 split.types.slice_mut()[0] = 0u8;
693 i = 0usize;
694 while i < num_contexts {
695 {
696 xself.last_entropy_[i] = BitsEntropy((histograms[i]).slice(), xself.alphabet_size_);
697 xself.last_entropy_[num_contexts.wrapping_add(i)] = xself.last_entropy_[i];
698 }
699 i = i.wrapping_add(1);
700 }
701 xself.num_blocks_ = xself.num_blocks_.wrapping_add(1);
702 split.num_types = split.num_types.wrapping_add(1);
703 xself.curr_histogram_ix_ = xself.curr_histogram_ix_.wrapping_add(num_contexts);
704 if xself.curr_histogram_ix_ < *histograms_size {
705 ClearHistograms(
706 &mut histograms[xself.curr_histogram_ix_..],
707 xself.num_contexts_,
708 );
709 }
710 xself.block_size_ = 0usize;
711 } else if xself.block_size_ > 0usize {
712 let mut entropy = [0.0 as super::util::floatX; BROTLI_MAX_STATIC_CONTEXTS];
713 let mut combined_histo = m.alloc_cell(2 * num_contexts);
714 let mut combined_entropy = [0.0 as super::util::floatX; 2 * BROTLI_MAX_STATIC_CONTEXTS];
715 let mut diff: [super::util::floatX; 2] = [0.0 as super::util::floatX; 2];
716 let mut i: usize;
717 i = 0usize;
718 while i < num_contexts {
719 {
720 let curr_histo_ix: usize = xself.curr_histogram_ix_.wrapping_add(i);
721 let mut j: usize;
722 entropy[i] = BitsEntropy((histograms[curr_histo_ix]).slice(), xself.alphabet_size_);
723 j = 0usize;
724 while j < 2usize {
725 {
726 let jx: usize = j.wrapping_mul(num_contexts).wrapping_add(i);
727 let last_histogram_ix: usize = xself.last_histogram_ix_[j].wrapping_add(i);
728 combined_histo.slice_mut()[jx] = histograms[curr_histo_ix].clone();
729 HistogramAddHistogram(
730 &mut combined_histo.slice_mut()[jx],
731 &mut histograms[last_histogram_ix],
732 );
733 combined_entropy[jx] =
734 BitsEntropy(combined_histo.slice()[jx].slice(), xself.alphabet_size_);
735 {
736 let _rhs = combined_entropy[jx] - entropy[i] - xself.last_entropy_[jx];
737 let _lhs = &mut diff[j];
738 *_lhs += _rhs;
739 }
740 }
741 j = j.wrapping_add(1);
742 }
743 }
744 i = i.wrapping_add(1);
745 }
746 if split.num_types < xself.max_block_types_
747 && (diff[0] > xself.split_threshold_)
748 && (diff[1] > xself.split_threshold_)
749 {
750 split.lengths.slice_mut()[xself.num_blocks_] = xself.block_size_ as u32;
751 split.types.slice_mut()[xself.num_blocks_] = split.num_types as u8;
752 xself.last_histogram_ix_[1] = xself.last_histogram_ix_[0];
753 xself.last_histogram_ix_[0] = split.num_types.wrapping_mul(num_contexts);
754 i = 0usize;
755 while i < num_contexts {
756 {
757 xself.last_entropy_[num_contexts.wrapping_add(i)] = xself.last_entropy_[i];
758 xself.last_entropy_[i] = entropy[i];
759 }
760 i = i.wrapping_add(1);
761 }
762 xself.num_blocks_ = xself.num_blocks_.wrapping_add(1);
763 split.num_types = split.num_types.wrapping_add(1);
764 xself.curr_histogram_ix_ = xself.curr_histogram_ix_.wrapping_add(num_contexts);
765 if xself.curr_histogram_ix_ < *histograms_size {
766 ClearHistograms(
767 &mut histograms[xself.curr_histogram_ix_..],
768 xself.num_contexts_,
769 );
770 }
771 xself.block_size_ = 0usize;
772 xself.merge_last_count_ = 0usize;
773 xself.target_block_size_ = xself.min_block_size_;
774 } else if diff[1] < diff[0] - 20.0 as super::util::floatX {
775 split.lengths.slice_mut()[xself.num_blocks_] = xself.block_size_ as u32;
776 let nbm2 = split.types.slice()[xself.num_blocks_.wrapping_sub(2)];
777 split.types.slice_mut()[xself.num_blocks_] = nbm2;
778
779 {
780 xself.last_histogram_ix_.swap(0, 1);
781 }
782 i = 0usize;
783 while i < num_contexts {
784 {
785 histograms[xself.last_histogram_ix_[0].wrapping_add(i)] =
786 combined_histo.slice()[num_contexts.wrapping_add(i)].clone();
787 xself.last_entropy_[num_contexts.wrapping_add(i)] = xself.last_entropy_[i];
788 xself.last_entropy_[i] = combined_entropy[num_contexts.wrapping_add(i)];
789 HistogramClear(&mut histograms[xself.curr_histogram_ix_.wrapping_add(i)]);
790 }
791 i = i.wrapping_add(1);
792 }
793 xself.num_blocks_ = xself.num_blocks_.wrapping_add(1);
794 xself.block_size_ = 0usize;
795 xself.merge_last_count_ = 0usize;
796 xself.target_block_size_ = xself.min_block_size_;
797 } else {
798 {
799 let _rhs = xself.block_size_ as u32;
800 let _lhs = &mut split.lengths.slice_mut()[xself.num_blocks_.wrapping_sub(1)];
801 let old_split_length = *_lhs;
802 *_lhs = old_split_length.wrapping_add(_rhs);
803 }
804 i = 0usize;
805 while i < num_contexts {
806 {
807 histograms[xself.last_histogram_ix_[0].wrapping_add(i)] =
808 combined_histo.slice()[i].clone();
809 xself.last_entropy_[i] = combined_entropy[i];
810 if split.num_types == 1 {
811 xself.last_entropy_[num_contexts.wrapping_add(i)] = xself.last_entropy_[i];
812 }
813 HistogramClear(&mut histograms[xself.curr_histogram_ix_.wrapping_add(i)]);
814 }
815 i = i.wrapping_add(1);
816 }
817 xself.block_size_ = 0usize;
818 if {
819 xself.merge_last_count_ = xself.merge_last_count_.wrapping_add(1);
820 xself.merge_last_count_
821 } > 1
822 {
823 xself.target_block_size_ =
824 xself.target_block_size_.wrapping_add(xself.min_block_size_);
825 }
826 }
827 m.free_cell(combined_histo);
828 }
829 if is_final != 0 {
830 *histograms_size = split.num_types.wrapping_mul(num_contexts);
831 split.num_blocks = xself.num_blocks_;
832 }
833}
834
835fn BlockSplitterAddSymbol<
836 HistogramType: SliceWrapper<u32> + SliceWrapperMut<u32> + CostAccessors + Clone,
837 Alloc: alloc::Allocator<u8> + alloc::Allocator<u32>,
838>(
839 xself: &mut BlockSplitter,
840 split: &mut BlockSplit<Alloc>,
841 histograms: &mut [HistogramType],
842 histograms_size: &mut usize,
843 symbol: usize,
844) {
845 HistogramAddItem(&mut histograms[xself.curr_histogram_ix_], symbol);
846 xself.block_size_ = xself.block_size_.wrapping_add(1);
847 if xself.block_size_ == xself.target_block_size_ {
848 BlockSplitterFinishBlock(xself, split, histograms, histograms_size, 0i32);
849 }
850}
851
852fn ContextBlockSplitterAddSymbol<
853 Alloc: alloc::Allocator<u8> + alloc::Allocator<u32> + alloc::Allocator<HistogramLiteral>,
854>(
855 xself: &mut ContextBlockSplitter,
856 m: &mut Alloc,
857 split: &mut BlockSplit<Alloc>,
858 histograms: &mut [HistogramLiteral],
859 histograms_size: &mut usize,
860 symbol: usize,
861 context: usize,
862) {
863 HistogramAddItem(
864 &mut histograms[xself.curr_histogram_ix_.wrapping_add(context)],
865 symbol,
866 );
867 xself.block_size_ = xself.block_size_.wrapping_add(1);
868 if xself.block_size_ == xself.target_block_size_ {
869 ContextBlockSplitterFinishBlock(xself, m, split, histograms, histograms_size, 0i32);
870 }
871}
872
873fn MapStaticContexts<
874 Alloc: alloc::Allocator<u8>
875 + alloc::Allocator<u32>
876 + alloc::Allocator<HistogramLiteral>
877 + alloc::Allocator<HistogramCommand>
878 + alloc::Allocator<HistogramDistance>,
879>(
880 m32: &mut Alloc,
881 num_contexts: usize,
882 static_context_map: &[u32],
883 mb: &mut MetaBlockSplit<Alloc>,
884) {
885 let mut i: usize;
886 mb.literal_context_map_size = mb.literal_split.num_types << 6;
887 let new_literal_context_map =
888 <Alloc as Allocator<u32>>::alloc_cell(m32, mb.literal_context_map_size);
889 <Alloc as Allocator<u32>>::free_cell(
890 m32,
891 core::mem::replace(&mut mb.literal_context_map, new_literal_context_map),
892 );
893 i = 0usize;
894 while i < mb.literal_split.num_types {
895 {
896 let offset: u32 = i.wrapping_mul(num_contexts) as u32;
897 let mut j: usize;
898 j = 0usize;
899 while j < (1u32 << 6) as usize {
900 {
901 mb.literal_context_map.slice_mut()[(i << 6).wrapping_add(j)] =
902 offset.wrapping_add(static_context_map[j]);
903 }
904 j = j.wrapping_add(1);
905 }
906 }
907 i = i.wrapping_add(1);
908 }
909}
910pub fn BrotliBuildMetaBlockGreedyInternal<
911 Alloc: alloc::Allocator<u8>
912 + alloc::Allocator<u32>
913 + alloc::Allocator<HistogramLiteral>
914 + alloc::Allocator<HistogramCommand>
915 + alloc::Allocator<HistogramDistance>,
916>(
917 alloc: &mut Alloc,
918 ringbuffer: &[u8],
919 mut pos: usize,
920 mask: usize,
921 mut prev_byte: u8,
922 mut prev_byte2: u8,
923 literal_context_mode: ContextType,
924 num_contexts: usize,
925 static_context_map: &[u32],
926 commands: &[Command],
927 n_commands: usize,
928 mb: &mut MetaBlockSplit<Alloc>,
929) {
930 let mut lit_blocks: LitBlocks;
931 let mut cmd_blocks: BlockSplitter;
932 let mut dist_blocks: BlockSplitter;
933 let mut num_literals: usize = 0usize;
934 let mut i: usize;
935 i = 0usize;
936 while i < n_commands {
937 {
938 num_literals = num_literals.wrapping_add((commands[i]).insert_len_ as usize);
939 }
940 i = i.wrapping_add(1);
941 }
942 lit_blocks = if num_contexts == 1 {
943 LitBlocks::plain(InitBlockSplitter::<HistogramLiteral, Alloc>(
944 alloc,
945 256usize,
946 512usize,
947 400.0 as super::util::floatX,
948 num_literals,
949 &mut mb.literal_split,
950 &mut mb.literal_histograms,
951 &mut mb.literal_histograms_size,
952 ))
953 } else {
954 LitBlocks::ctx(InitContextBlockSplitter::<Alloc>(
955 alloc,
956 256usize,
957 num_contexts,
958 512usize,
959 400.0 as super::util::floatX,
960 num_literals,
961 &mut mb.literal_split,
962 &mut mb.literal_histograms,
963 &mut mb.literal_histograms_size,
964 ))
965 };
966 cmd_blocks = InitBlockSplitter::<HistogramCommand, Alloc>(
967 alloc,
968 704usize,
969 1024usize,
970 500.0 as super::util::floatX,
971 n_commands,
972 &mut mb.command_split,
973 &mut mb.command_histograms,
974 &mut mb.command_histograms_size,
975 );
976 dist_blocks = InitBlockSplitter::<HistogramDistance, Alloc>(
977 alloc,
978 64usize,
979 512usize,
980 100.0 as super::util::floatX,
981 n_commands,
982 &mut mb.distance_split,
983 &mut mb.distance_histograms,
984 &mut mb.distance_histograms_size,
985 );
986
987 i = 0usize;
988 while i < n_commands {
989 {
990 let cmd: Command = commands[i];
991 let mut j: usize;
992 BlockSplitterAddSymbol(
993 &mut cmd_blocks,
994 &mut mb.command_split,
995 mb.command_histograms.slice_mut(),
996 &mut mb.command_histograms_size,
997 cmd.cmd_prefix_ as usize,
998 );
999 j = cmd.insert_len_ as usize;
1000 while j != 0usize {
1001 {
1002 let literal: u8 = ringbuffer[(pos & mask)];
1003 match (&mut lit_blocks) {
1004 &mut LitBlocks::plain(ref mut lit_blocks_plain) => BlockSplitterAddSymbol(
1005 lit_blocks_plain,
1006 &mut mb.literal_split,
1007 mb.literal_histograms.slice_mut(),
1008 &mut mb.literal_histograms_size,
1009 literal as usize,
1010 ),
1011 &mut LitBlocks::ctx(ref mut lit_blocks_ctx) => {
1012 let context: usize =
1013 Context(prev_byte, prev_byte2, literal_context_mode) as usize;
1014 ContextBlockSplitterAddSymbol(
1015 lit_blocks_ctx,
1016 alloc,
1017 &mut mb.literal_split,
1018 mb.literal_histograms.slice_mut(),
1019 &mut mb.literal_histograms_size,
1020 literal as usize,
1021 static_context_map[(context as usize)] as usize,
1022 );
1023 }
1024 }
1025 prev_byte2 = prev_byte;
1026 prev_byte = literal;
1027 pos = pos.wrapping_add(1);
1028 }
1029 j = j.wrapping_sub(1);
1030 }
1031 pos = pos.wrapping_add(CommandCopyLen(&cmd) as usize);
1032 if CommandCopyLen(&cmd) != 0 {
1033 prev_byte2 = ringbuffer[(pos.wrapping_sub(2) & mask)];
1034 prev_byte = ringbuffer[(pos.wrapping_sub(1) & mask)];
1035 if cmd.cmd_prefix_ as i32 >= 128i32 {
1036 BlockSplitterAddSymbol(
1037 &mut dist_blocks,
1038 &mut mb.distance_split,
1039 mb.distance_histograms.slice_mut(),
1040 &mut mb.distance_histograms_size,
1041 cmd.dist_prefix_ as usize & 0x3ff,
1042 );
1043 }
1044 }
1045 }
1046 i = i.wrapping_add(1);
1047 }
1048 match (&mut lit_blocks) {
1049 &mut LitBlocks::plain(ref mut lit_blocks_plain) => BlockSplitterFinishBlock(
1050 lit_blocks_plain,
1051 &mut mb.literal_split,
1052 mb.literal_histograms.slice_mut(),
1053 &mut mb.literal_histograms_size,
1054 1i32,
1055 ),
1056 &mut LitBlocks::ctx(ref mut lit_blocks_ctx) => ContextBlockSplitterFinishBlock(
1057 lit_blocks_ctx,
1058 alloc,
1059 &mut mb.literal_split,
1060 mb.literal_histograms.slice_mut(),
1061 &mut mb.literal_histograms_size,
1062 1i32,
1063 ),
1064 }
1065 BlockSplitterFinishBlock(
1066 &mut cmd_blocks,
1067 &mut mb.command_split,
1068 mb.command_histograms.slice_mut(),
1069 &mut mb.command_histograms_size,
1070 1i32,
1071 );
1072 BlockSplitterFinishBlock(
1073 &mut dist_blocks,
1074 &mut mb.distance_split,
1075 mb.distance_histograms.slice_mut(),
1076 &mut mb.distance_histograms_size,
1077 1i32,
1078 );
1079 if num_contexts > 1 {
1080 MapStaticContexts(alloc, num_contexts, static_context_map, mb);
1081 }
1082}
1083pub fn BrotliBuildMetaBlockGreedy<
1084 Alloc: alloc::Allocator<u8>
1085 + alloc::Allocator<u32>
1086 + alloc::Allocator<HistogramLiteral>
1087 + alloc::Allocator<HistogramCommand>
1088 + alloc::Allocator<HistogramDistance>,
1089>(
1090 alloc: &mut Alloc,
1091 ringbuffer: &[u8],
1092 pos: usize,
1093 mask: usize,
1094 prev_byte: u8,
1095 prev_byte2: u8,
1096 literal_context_mode: ContextType,
1097 _literal_context_lut: &[u8],
1098 num_contexts: usize,
1099 static_context_map: &[u32],
1100 commands: &[Command],
1101 n_commands: usize,
1102 mb: &mut MetaBlockSplit<Alloc>,
1103) {
1104 if num_contexts == 1 {
1105 BrotliBuildMetaBlockGreedyInternal(
1106 alloc,
1107 ringbuffer,
1108 pos,
1109 mask,
1110 prev_byte,
1111 prev_byte2,
1112 literal_context_mode,
1113 1,
1114 &[],
1115 commands,
1116 n_commands,
1117 mb,
1118 );
1119 } else {
1120 BrotliBuildMetaBlockGreedyInternal(
1121 alloc,
1122 ringbuffer,
1123 pos,
1124 mask,
1125 prev_byte,
1126 prev_byte2,
1127 literal_context_mode,
1128 num_contexts,
1129 static_context_map,
1130 commands,
1131 n_commands,
1132 mb,
1133 );
1134 }
1135}
1136
1137pub fn BrotliOptimizeHistograms<
1138 Alloc: alloc::Allocator<u8>
1139 + alloc::Allocator<u32>
1140 + alloc::Allocator<HistogramLiteral>
1141 + alloc::Allocator<HistogramCommand>
1142 + alloc::Allocator<HistogramDistance>,
1143>(
1144 num_distance_codes: usize,
1145 mb: &mut MetaBlockSplit<Alloc>,
1146) {
1147 let mut good_for_rle: [u8; 704] = [0; 704];
1148 let mut i: usize;
1149 i = 0usize;
1150 while i < mb.literal_histograms_size {
1151 {
1152 BrotliOptimizeHuffmanCountsForRle(
1153 256usize,
1154 mb.literal_histograms.slice_mut()[i].slice_mut(),
1155 &mut good_for_rle[..],
1156 );
1157 }
1158 i = i.wrapping_add(1);
1159 }
1160 i = 0usize;
1161 while i < mb.command_histograms_size {
1162 {
1163 BrotliOptimizeHuffmanCountsForRle(
1164 704usize,
1165 mb.command_histograms.slice_mut()[i].slice_mut(),
1166 &mut good_for_rle[..],
1167 );
1168 }
1169 i = i.wrapping_add(1);
1170 }
1171 i = 0usize;
1172 while i < mb.distance_histograms_size {
1173 {
1174 BrotliOptimizeHuffmanCountsForRle(
1175 num_distance_codes,
1176 mb.distance_histograms.slice_mut()[i].slice_mut(),
1177 &mut good_for_rle[..],
1178 );
1179 }
1180 i = i.wrapping_add(1);
1181 }
1182}