1use core;
2use core::cmp::{max, min};
3#[cfg(feature = "simd")]
4use core::simd::prelude::{SimdFloat, SimdPartialOrd};
5
6use super::super::alloc::{Allocator, SliceWrapper, SliceWrapperMut};
7use super::backward_references::BrotliEncoderParams;
8use super::bit_cost::BrotliPopulationCost;
9use super::block_split::BlockSplit;
10use super::cluster::{BrotliHistogramBitCostDistance, BrotliHistogramCombine, HistogramPair};
11use super::command::Command;
12use super::histogram::{
13 ClearHistograms, CostAccessors, HistogramAddHistogram, HistogramAddItem, HistogramAddVector,
14 HistogramClear, HistogramCommand, HistogramDistance, HistogramLiteral,
15};
16use super::util::FastLog2;
17use super::vectorization::{sum8i, v256, v256i, Mem256f};
18use crate::enc::combined_alloc::allocate;
19use crate::enc::floatX;
20
21static kMaxLiteralHistograms: usize = 100usize;
22
23static kMaxCommandHistograms: usize = 50usize;
24
25static kLiteralBlockSwitchCost: floatX = 28.1;
26
27static kCommandBlockSwitchCost: floatX = 13.5;
28
29static kDistanceBlockSwitchCost: floatX = 14.6;
30
31static kLiteralStrideLength: usize = 70usize;
32
33static kCommandStrideLength: usize = 40usize;
34
35static kSymbolsPerLiteralHistogram: usize = 544usize;
36
37static kSymbolsPerCommandHistogram: usize = 530usize;
38
39static kSymbolsPerDistanceHistogram: usize = 544usize;
40
41static kMinLengthForBlockSplitting: usize = 128usize;
42
43static kIterMulForRefining: usize = 2usize;
44
45static kMinItersForRefining: usize = 100usize;
46
47#[inline(always)]
48fn update_cost_and_signal(
49 num_histograms32: u32,
50 ix: usize,
51 min_cost: floatX,
52 block_switch_cost: floatX,
53 cost: &mut [Mem256f],
54 switch_signal: &mut [u8],
55) {
56 let ymm_min_cost = v256::splat(min_cost);
57 let ymm_block_switch_cost = v256::splat(block_switch_cost);
58 let ymm_and_mask = v256i::from([
59 1 << 0,
60 1 << 1,
61 1 << 2,
62 1 << 3,
63 1 << 4,
64 1 << 5,
65 1 << 6,
66 1 << 7,
67 ]);
68
69 for (index, cost_it) in cost[..((num_histograms32 as usize + 7) >> 3)]
70 .iter_mut()
71 .enumerate()
72 {
73 let mut ymm_cost = *cost_it;
74 let costk_minus_min_cost = ymm_cost - ymm_min_cost;
75 let ymm_cmpge: v256i = costk_minus_min_cost.simd_ge(ymm_block_switch_cost).to_int();
76 let ymm_bits = ymm_cmpge & ymm_and_mask;
77 let result = sum8i(ymm_bits);
78 switch_signal[ix + index] |= result as u8;
80 ymm_cost = costk_minus_min_cost.simd_min(ymm_block_switch_cost);
81 *cost_it = Mem256f::from(ymm_cost);
82 }
84}
85fn CountLiterals(cmds: &[Command], num_commands: usize) -> usize {
86 let mut total_length: usize = 0usize;
87 for i in 0usize..num_commands {
88 total_length = total_length.wrapping_add((cmds[i]).insert_len_ as usize);
89 }
90 total_length
91}
92
93fn CopyLiteralsToByteArray(
94 cmds: &[Command],
95 num_commands: usize,
96 data: &[u8],
97 offset: usize,
98 mask: usize,
99 literals: &mut [u8],
100) {
101 let mut pos: usize = 0usize;
102 let mut from_pos: usize = offset & mask;
103 for i in 0usize..num_commands {
104 let mut insert_len: usize = (cmds[i]).insert_len_ as usize;
105 if from_pos.wrapping_add(insert_len) > mask {
106 let head_size: usize = mask.wrapping_add(1).wrapping_sub(from_pos);
107 literals[pos..(pos + head_size)]
108 .clone_from_slice(&data[from_pos..(from_pos + head_size)]);
109 from_pos = 0usize;
110 pos = pos.wrapping_add(head_size);
111 insert_len = insert_len.wrapping_sub(head_size);
112 }
113 if insert_len > 0usize {
114 literals[pos..(pos + insert_len)]
115 .clone_from_slice(&data[from_pos..(from_pos + insert_len)]);
116 pos = pos.wrapping_add(insert_len);
117 }
118 from_pos = from_pos
119 .wrapping_add(insert_len)
120 .wrapping_add(cmds[i].copy_len() as usize)
121 & mask;
122 }
123}
124
125fn MyRand(seed: &mut u32) -> u32 {
126 *seed = seed.wrapping_mul(16807);
127 if *seed == 0u32 {
128 *seed = 1u32;
129 }
130 *seed
131}
132
133fn InitialEntropyCodes<
134 HistogramType: SliceWrapper<u32> + SliceWrapperMut<u32> + CostAccessors,
135 IntegerType: Sized + Clone,
136>(
137 data: &[IntegerType],
138 length: usize,
139 stride: usize,
140 num_histograms: usize,
141 histograms: &mut [HistogramType],
142) where
143 u64: core::convert::From<IntegerType>,
144{
145 let mut seed: u32 = 7u32;
146 let block_length: usize = length.wrapping_div(num_histograms);
147 ClearHistograms(histograms, num_histograms);
148 for i in 0usize..num_histograms {
149 let mut pos: usize = length.wrapping_mul(i).wrapping_div(num_histograms);
150 if i != 0usize {
151 pos = pos.wrapping_add((MyRand(&mut seed) as usize).wrapping_rem(block_length));
152 }
153 if pos.wrapping_add(stride) >= length {
154 pos = length.wrapping_sub(stride).wrapping_sub(1);
155 }
156 HistogramAddVector(&mut histograms[i], &data[pos..], stride);
157 }
158}
159
160fn RandomSample<
161 HistogramType: SliceWrapper<u32> + SliceWrapperMut<u32> + CostAccessors,
162 IntegerType: Sized + Clone,
163>(
164 seed: &mut u32,
165 data: &[IntegerType],
166 length: usize,
167 mut stride: usize,
168 sample: &mut HistogramType,
169) where
170 u64: core::convert::From<IntegerType>,
171{
172 let pos: usize;
173 if stride >= length {
174 pos = 0usize;
175 stride = length;
176 } else {
177 pos = (MyRand(seed) as usize).wrapping_rem(length.wrapping_sub(stride).wrapping_add(1));
178 }
179 HistogramAddVector(sample, &data[pos..], stride);
180}
181
182fn RefineEntropyCodes<
183 HistogramType: SliceWrapper<u32> + SliceWrapperMut<u32> + CostAccessors + core::default::Default,
184 IntegerType: Sized + Clone,
185>(
186 data: &[IntegerType],
187 length: usize,
188 stride: usize,
189 num_histograms: usize,
190 histograms: &mut [HistogramType],
191) where
192 u64: core::convert::From<IntegerType>,
193{
194 let mut iters: usize = kIterMulForRefining
195 .wrapping_mul(length)
196 .wrapping_div(stride)
197 .wrapping_add(kMinItersForRefining);
198 let mut seed: u32 = 7u32;
199 iters = iters
200 .wrapping_add(num_histograms)
201 .wrapping_sub(1)
202 .wrapping_div(num_histograms)
203 .wrapping_mul(num_histograms);
204 for iter in 0usize..iters {
205 let mut sample = HistogramType::default();
206 HistogramClear(&mut sample);
207 RandomSample(&mut seed, data, length, stride, &mut sample);
208 HistogramAddHistogram(
209 &mut histograms[iter.wrapping_rem(num_histograms)],
210 &mut sample,
211 );
212 }
213}
214
215fn BitCost(count: usize) -> floatX {
216 if count == 0usize {
217 -2.0
218 } else {
219 FastLog2(count as u64)
220 }
221}
222
223fn FindBlocks<
224 HistogramType: SliceWrapper<u32> + SliceWrapperMut<u32> + CostAccessors,
225 IntegerType: Sized + Clone,
226>(
227 data: &[IntegerType],
228 length: usize,
229 block_switch_bitcost: floatX,
230 num_histograms: usize,
231 histograms: &[HistogramType],
232 insert_cost: &mut [floatX],
233 cost: &mut [Mem256f],
234 switch_signal: &mut [u8],
235 block_id: &mut [u8],
236) -> usize
237where
238 u64: core::convert::From<IntegerType>,
239{
240 if num_histograms == 0 {
241 return 0;
242 }
243 let data_size: usize = histograms[0].slice().len();
244 let bitmaplen: usize = num_histograms.wrapping_add(7) >> 3;
245 let mut num_blocks: usize = 1;
246 let mut i: usize;
247 if num_histograms <= 1 {
248 for i in 0usize..length {
249 block_id[i] = 0u8;
250 }
251 return 1;
252 }
253 for item in insert_cost[..(data_size * num_histograms)].iter_mut() {
254 *item = 0.0;
255 }
256 for i in 0usize..num_histograms {
257 insert_cost[i] = FastLog2((histograms[i]).total_count() as u32 as (u64));
258 }
259 i = data_size;
260 while i != 0usize {
261 i = i.wrapping_sub(1);
262 for j in 0usize..num_histograms {
263 insert_cost[i.wrapping_mul(num_histograms).wrapping_add(j)] =
264 insert_cost[j] - BitCost((histograms[j]).slice()[i] as usize);
265 }
266 }
267 for item in cost.iter_mut() {
268 *item = Mem256f::default();
269 }
270 for item in switch_signal[..(length * bitmaplen)].iter_mut() {
271 *item = 0;
272 }
273 for (byte_ix, data_byte_ix) in data[..length].iter().enumerate() {
274 let block_id_ptr = &mut block_id[byte_ix];
275 let ix: usize = byte_ix.wrapping_mul(bitmaplen);
276 let insert_cost_ix: usize =
277 u64::from(data_byte_ix.clone()).wrapping_mul(num_histograms as u64) as usize;
278 let mut min_cost: floatX = 1e38;
279 let mut block_switch_cost: floatX = block_switch_bitcost;
280 let insert_cost_slice = insert_cost.split_at(insert_cost_ix).1;
282 for (v_index, cost_iter) in cost
283 .split_at_mut(num_histograms >> 3)
284 .0
285 .iter_mut()
286 .enumerate()
287 {
288 let base_index = v_index << 3;
289 let mut local_insert_cost = [0.0; 8];
290 local_insert_cost
291 .clone_from_slice(insert_cost_slice.split_at(base_index).1.split_at(8).0);
292 for sub_index in 0usize..8usize {
293 cost_iter[sub_index] += local_insert_cost[sub_index];
294 let final_cost = cost_iter[sub_index];
295 if final_cost < min_cost {
296 min_cost = final_cost;
297 *block_id_ptr = (base_index + sub_index) as u8;
298 }
299 }
300 }
301 let vectorized_offset = ((num_histograms >> 3) << 3);
302 let mut k = vectorized_offset;
303 for insert_cost_iter in insert_cost
305 .split_at(insert_cost_ix + vectorized_offset)
306 .1
307 .split_at(num_histograms & 7)
308 .0
309 .iter()
310 {
311 let cost_iter = &mut cost[(k >> 3)];
312 cost_iter[k & 7] += *insert_cost_iter;
313 if cost_iter[k & 7] < min_cost {
314 min_cost = cost_iter[k & 7];
315 *block_id_ptr = k as u8;
316 }
317 k += 1;
318 }
319 if byte_ix < 2000usize {
320 block_switch_cost *= (0.77 + 0.07 * (byte_ix as floatX) / 2000.0);
321 }
322 update_cost_and_signal(
323 num_histograms as u32,
324 ix,
325 min_cost,
326 block_switch_cost,
327 cost,
328 switch_signal,
329 );
330 }
331 {
332 let mut byte_ix: usize = length.wrapping_sub(1);
333 let mut ix: usize = byte_ix.wrapping_mul(bitmaplen);
334 let mut cur_id: u8 = block_id[byte_ix];
335 while byte_ix > 0usize {
336 let mask: u8 = (1u32 << (cur_id as i32 & 7i32)) as u8;
337 byte_ix -= 1;
338 ix = ix.wrapping_sub(bitmaplen);
339 if switch_signal[ix.wrapping_add((cur_id as i32 >> 3) as usize)] as i32 & mask as i32
340 != 0
341 && cur_id as i32 != block_id[byte_ix] as i32
342 {
343 cur_id = block_id[byte_ix];
344 num_blocks = num_blocks.wrapping_add(1);
345 }
346 block_id[byte_ix] = cur_id;
347 }
348 }
349 num_blocks
350}
351
352fn RemapBlockIds(
353 block_ids: &mut [u8],
354 length: usize,
355 new_id: &mut [u16],
356 num_histograms: usize,
357) -> usize {
358 static kInvalidId: u16 = 256u16;
359 let mut next_id: u16 = 0u16;
360 for i in 0usize..num_histograms {
361 new_id[i] = kInvalidId;
362 }
363 for i in 0usize..length {
364 if new_id[(block_ids[i] as usize)] as i32 == kInvalidId as i32 {
365 new_id[(block_ids[i] as usize)] = {
366 let _old = next_id;
367 next_id = (next_id as i32 + 1) as u16;
368 _old
369 };
370 }
371 }
372 for i in 0usize..length {
373 block_ids[i] = new_id[(block_ids[i] as usize)] as u8;
374 }
375 next_id as usize
376}
377
378fn BuildBlockHistograms<
379 HistogramType: SliceWrapper<u32> + SliceWrapperMut<u32> + CostAccessors,
380 IntegerType: Sized + Clone,
381>(
382 data: &[IntegerType],
383 length: usize,
384 block_ids: &[u8],
385 num_histograms: usize,
386 histograms: &mut [HistogramType],
387) where
388 u64: core::convert::From<IntegerType>,
389{
390 ClearHistograms(histograms, num_histograms);
391 for i in 0usize..length {
392 HistogramAddItem(
393 &mut histograms[(block_ids[i] as usize)],
394 u64::from(data[i].clone()) as usize,
395 );
396 }
397}
398
399fn ClusterBlocks<
400 HistogramType: SliceWrapper<u32> + SliceWrapperMut<u32> + CostAccessors + core::default::Default + Clone,
401 Alloc: alloc::Allocator<u8>
402 + alloc::Allocator<u32>
403 + alloc::Allocator<HistogramType>
404 + alloc::Allocator<HistogramPair>,
405 IntegerType: Sized + Clone,
406>(
407 alloc: &mut Alloc,
408 data: &[IntegerType],
409 length: usize,
410 num_blocks: usize,
411 scratch_space: &mut HistogramType::i32vec,
412 block_ids: &mut [u8],
413 split: &mut BlockSplit<Alloc>,
414) where
415 u64: core::convert::From<IntegerType>,
416{
417 let mut histogram_symbols = allocate::<u32, _>(alloc, num_blocks);
418 let mut block_lengths = allocate::<u32, _>(alloc, num_blocks);
419 let expected_num_clusters: usize = (16usize)
420 .wrapping_mul(num_blocks.wrapping_add(64).wrapping_sub(1))
421 .wrapping_div(64);
422 let mut all_histograms_size: usize = 0usize;
423 let mut all_histograms_capacity: usize = expected_num_clusters;
424 let mut all_histograms = allocate::<HistogramType, _>(alloc, all_histograms_capacity);
425 let mut cluster_size_size: usize = 0usize;
426 let mut cluster_size_capacity: usize = expected_num_clusters;
427 let mut cluster_size = allocate::<u32, _>(alloc, cluster_size_capacity);
428 let mut num_clusters: usize = 0usize;
429 let mut histograms = allocate::<HistogramType, _>(alloc, min(num_blocks, 64));
430 let mut max_num_pairs: usize = (64i32 * 64i32 / 2i32) as usize;
431 let pairs_capacity: usize = max_num_pairs.wrapping_add(1);
432 let mut pairs = allocate::<HistogramPair, _>(alloc, pairs_capacity);
433 let mut pos: usize = 0usize;
434 let mut clusters: <Alloc as Allocator<u32>>::AllocatedMemory;
435
436 static kInvalidIndex: u32 = u32::MAX;
437 let mut i: usize;
438 let mut sizes: [u32; 64] = [0; 64];
439 let mut new_clusters: [u32; 64] = [0; 64];
440 let mut symbols: [u32; 64] = [0; 64];
441 let mut remap: [u32; 64] = [0; 64];
442 {
443 let mut block_idx: usize = 0usize;
444 i = 0usize;
445 while i < length {
446 {
447 {
448 let _rhs = 1;
449 let _lhs = &mut block_lengths.slice_mut()[block_idx];
450 *_lhs = (*_lhs).wrapping_add(_rhs as u32);
451 }
452 if i.wrapping_add(1) == length
453 || block_ids[i] as i32 != block_ids[i.wrapping_add(1)] as i32
454 {
455 block_idx = block_idx.wrapping_add(1);
456 }
457 }
458 i = i.wrapping_add(1);
459 }
460 }
461 i = 0usize;
462 while i < num_blocks {
463 {
464 let num_to_combine: usize = min(num_blocks.wrapping_sub(i), 64);
465
466 for j in 0usize..num_to_combine {
467 HistogramClear(&mut histograms.slice_mut()[j]);
468 for _k in 0usize..block_lengths.slice()[i.wrapping_add(j)] as usize {
469 HistogramAddItem(
470 &mut histograms.slice_mut()[j],
471 u64::from(data[pos].clone()) as usize,
472 );
473 pos = pos.wrapping_add(1);
474 }
475 let new_cost = BrotliPopulationCost(&histograms.slice()[j], scratch_space);
476 (histograms.slice_mut()[j]).set_bit_cost(new_cost);
477
478 new_clusters[j] = j as u32;
479 symbols[j] = j as u32;
480 sizes[j] = 1u32;
481 }
482 let num_new_clusters: usize = BrotliHistogramCombine(
483 histograms.slice_mut(),
484 &mut sizes[..],
485 &mut symbols[..],
486 &mut new_clusters[..],
487 pairs.slice_mut(),
488 num_to_combine,
489 num_to_combine,
490 64usize,
491 max_num_pairs,
492 scratch_space,
493 );
494 {
495 if all_histograms_capacity < all_histograms_size.wrapping_add(num_new_clusters) {
496 let mut _new_size: usize = if all_histograms_capacity == 0usize {
497 all_histograms_size.wrapping_add(num_new_clusters)
498 } else {
499 all_histograms_capacity
500 };
501 while _new_size < all_histograms_size.wrapping_add(num_new_clusters) {
502 _new_size = _new_size.wrapping_mul(2);
503 }
504 let mut new_array = allocate::<HistogramType, _>(alloc, _new_size);
505 new_array.slice_mut()[..all_histograms_capacity]
506 .clone_from_slice(&all_histograms.slice()[..all_histograms_capacity]);
507 <Alloc as Allocator<HistogramType>>::free_cell(
508 alloc,
509 core::mem::replace(&mut all_histograms, new_array),
510 );
511 all_histograms_capacity = _new_size;
512 }
513 }
514 {
515 if cluster_size_capacity < cluster_size_size.wrapping_add(num_new_clusters) {
516 let mut _new_size: usize = if cluster_size_capacity == 0usize {
517 cluster_size_size.wrapping_add(num_new_clusters)
518 } else {
519 cluster_size_capacity
520 };
521 while _new_size < cluster_size_size.wrapping_add(num_new_clusters) {
522 _new_size = _new_size.wrapping_mul(2);
523 }
524 let mut new_array = allocate::<u32, _>(alloc, _new_size);
525 new_array.slice_mut()[..cluster_size_capacity]
526 .clone_from_slice(&cluster_size.slice()[..cluster_size_capacity]);
527 <Alloc as Allocator<u32>>::free_cell(
528 alloc,
529 core::mem::replace(&mut cluster_size, new_array),
530 );
531 cluster_size_capacity = _new_size;
532 }
533 }
534 for j in 0usize..num_new_clusters {
535 all_histograms.slice_mut()[all_histograms_size] =
536 histograms.slice()[new_clusters[j] as usize].clone();
537 all_histograms_size = all_histograms_size.wrapping_add(1);
538 cluster_size.slice_mut()[cluster_size_size] = sizes[new_clusters[j] as usize];
539 cluster_size_size = cluster_size_size.wrapping_add(1);
540 remap[new_clusters[j] as usize] = j as u32;
541 }
542 for j in 0usize..num_to_combine {
543 histogram_symbols.slice_mut()[i.wrapping_add(j)] =
544 (num_clusters as u32).wrapping_add(remap[symbols[j] as usize]);
545 }
546 num_clusters = num_clusters.wrapping_add(num_new_clusters);
547 }
548 i = i.wrapping_add(64);
549 }
550 <Alloc as Allocator<HistogramType>>::free_cell(alloc, core::mem::take(&mut histograms));
551 max_num_pairs = min(
552 (64usize).wrapping_mul(num_clusters),
553 num_clusters.wrapping_div(2).wrapping_mul(num_clusters),
554 );
555 if pairs_capacity < max_num_pairs.wrapping_add(1) {
556 let new_cell = allocate::<HistogramPair, _>(alloc, max_num_pairs.wrapping_add(1));
557 <Alloc as Allocator<HistogramPair>>::free_cell(
558 alloc,
559 core::mem::replace(&mut pairs, new_cell),
560 );
561 }
562 clusters = allocate::<u32, _>(alloc, num_clusters);
563 i = 0usize;
564 for item in clusters.slice_mut()[..num_clusters].iter_mut() {
565 *item = i as u32;
566 i = i.wrapping_add(1);
567 }
568 let num_final_clusters: usize = BrotliHistogramCombine(
569 all_histograms.slice_mut(),
570 cluster_size.slice_mut(),
571 histogram_symbols.slice_mut(),
572 clusters.slice_mut(),
573 pairs.slice_mut(),
574 num_clusters,
575 num_blocks,
576 256usize,
577 max_num_pairs,
578 scratch_space,
579 );
580 <Alloc as Allocator<HistogramPair>>::free_cell(alloc, core::mem::take(&mut pairs));
581 <Alloc as Allocator<u32>>::free_cell(alloc, core::mem::take(&mut cluster_size));
582
583 let mut new_index = allocate::<u32, _>(alloc, num_clusters);
584 for item in new_index.slice_mut().iter_mut() {
585 *item = kInvalidIndex;
586 }
587 pos = 0usize;
588 {
589 let mut next_index: u32 = 0u32;
590 for i in 0usize..num_blocks {
591 let mut histo: HistogramType = HistogramType::default();
592 let mut best_out: u32;
593 let mut best_bits: floatX;
594 HistogramClear(&mut histo);
595 for _j in 0usize..block_lengths.slice()[i] as usize {
596 HistogramAddItem(&mut histo, u64::from(data[pos].clone()) as usize);
597 pos = pos.wrapping_add(1);
598 }
599 best_out = if i == 0usize {
600 histogram_symbols.slice()[0]
601 } else {
602 histogram_symbols.slice()[i.wrapping_sub(1)]
603 };
604 best_bits = BrotliHistogramBitCostDistance(
605 &mut histo,
606 &mut all_histograms.slice_mut()[(best_out as usize)],
607 scratch_space,
608 );
609 for j in 0usize..num_final_clusters {
610 let cur_bits: floatX = BrotliHistogramBitCostDistance(
611 &mut histo,
612 &mut all_histograms.slice_mut()[(clusters.slice()[j] as usize)],
613 scratch_space,
614 );
615 if cur_bits < best_bits {
616 best_bits = cur_bits;
617 best_out = clusters.slice()[j];
618 }
619 }
620 histogram_symbols.slice_mut()[i] = best_out;
621 if new_index.slice()[best_out as usize] == kInvalidIndex {
622 new_index.slice_mut()[best_out as usize] = next_index;
623 next_index = next_index.wrapping_add(1);
624 }
625 }
626 }
627 <Alloc as Allocator<u32>>::free_cell(alloc, core::mem::take(&mut clusters));
628 <Alloc as Allocator<HistogramType>>::free_cell(alloc, core::mem::take(&mut all_histograms));
629 {
630 if split.types_alloc_size() < num_blocks {
631 let mut _new_size: usize = if split.types_alloc_size() == 0usize {
632 num_blocks
633 } else {
634 split.types_alloc_size()
635 };
636 while _new_size < num_blocks {
637 _new_size = _new_size.wrapping_mul(2);
638 }
639 let mut new_array = allocate::<u8, _>(alloc, _new_size);
640 new_array.slice_mut()[..split.types_alloc_size()]
641 .clone_from_slice(&split.types.slice()[..split.types_alloc_size()]);
642 <Alloc as Allocator<u8>>::free_cell(
643 alloc,
644 core::mem::replace(&mut split.types, new_array),
645 );
646 }
647 }
648 {
649 if split.lengths_alloc_size() < num_blocks {
650 let mut _new_size: usize = if split.lengths_alloc_size() == 0usize {
651 num_blocks
652 } else {
653 split.lengths_alloc_size()
654 };
655 while _new_size < num_blocks {
656 _new_size = _new_size.wrapping_mul(2);
657 }
658 let mut new_array = allocate::<u32, _>(alloc, _new_size);
659 new_array.slice_mut()[..split.lengths_alloc_size()]
660 .clone_from_slice(split.lengths.slice());
661 <Alloc as Allocator<u32>>::free_cell(
662 alloc,
663 core::mem::replace(&mut split.lengths, new_array),
664 );
665 }
666 }
667 {
668 let mut cur_length: u32 = 0u32;
669 let mut block_idx: usize = 0usize;
670 let mut max_type: u8 = 0u8;
671 for i in 0usize..num_blocks {
672 cur_length = cur_length.wrapping_add(block_lengths.slice()[i]);
673 if i.wrapping_add(1) == num_blocks
674 || histogram_symbols.slice()[i] != histogram_symbols.slice()[i.wrapping_add(1)]
675 {
676 let id: u8 = new_index.slice()[(histogram_symbols.slice()[i] as usize)] as u8;
677 split.types.slice_mut()[block_idx] = id;
678 split.lengths.slice_mut()[block_idx] = cur_length;
679 max_type = max(max_type, id);
680 cur_length = 0u32;
681 block_idx = block_idx.wrapping_add(1);
682 }
683 }
684 split.num_blocks = block_idx;
685 split.num_types = (max_type as usize).wrapping_add(1);
686 }
687 <Alloc as Allocator<u32>>::free_cell(alloc, new_index);
688 <Alloc as Allocator<u32>>::free_cell(alloc, block_lengths);
689 <Alloc as Allocator<u32>>::free_cell(alloc, histogram_symbols);
690}
691
692fn SplitByteVector<
693 HistogramType: SliceWrapper<u32> + SliceWrapperMut<u32> + CostAccessors + core::default::Default + Clone,
694 Alloc: alloc::Allocator<u8>
695 + alloc::Allocator<u16>
696 + alloc::Allocator<u32>
697 + alloc::Allocator<floatX>
698 + alloc::Allocator<Mem256f>
699 + alloc::Allocator<HistogramType>
700 + alloc::Allocator<HistogramPair>,
701 IntegerType: Sized + Clone,
702>(
703 alloc: &mut Alloc,
704 data: &[IntegerType],
705 length: usize,
706 literals_per_histogram: usize,
707 max_histograms: usize,
708 sampling_stride_length: usize,
709 block_switch_cost: floatX,
710 params: &BrotliEncoderParams,
711 scratch_space: &mut HistogramType::i32vec,
712 split: &mut BlockSplit<Alloc>,
713) where
714 u64: core::convert::From<IntegerType>,
715{
716 let data_size: usize = HistogramType::default().slice().len();
717 let mut num_histograms: usize = length.wrapping_div(literals_per_histogram).wrapping_add(1);
718 if num_histograms > max_histograms {
719 num_histograms = max_histograms;
720 }
721 if length == 0usize {
722 split.num_types = 1;
723 return;
724 } else if length < kMinLengthForBlockSplitting {
725 {
726 if split.types_alloc_size() < split.num_blocks.wrapping_add(1) {
727 let mut _new_size: usize = if split.types_alloc_size() == 0usize {
728 split.num_blocks.wrapping_add(1)
729 } else {
730 split.types_alloc_size()
731 };
732
733 while _new_size < split.num_blocks.wrapping_add(1) {
734 _new_size = _new_size.wrapping_mul(2);
735 }
736 let mut new_array = allocate::<u8, _>(alloc, _new_size);
737 new_array.slice_mut()[..split.types_alloc_size()]
738 .clone_from_slice(&split.types.slice()[..split.types_alloc_size()]);
739 <Alloc as Allocator<u8>>::free_cell(
740 alloc,
741 core::mem::replace(&mut split.types, new_array),
742 );
743 }
744 }
745 {
746 if split.lengths_alloc_size() < split.num_blocks.wrapping_add(1) {
747 let mut _new_size: usize = if split.lengths_alloc_size() == 0usize {
748 split.num_blocks.wrapping_add(1)
749 } else {
750 split.lengths_alloc_size()
751 };
752 while _new_size < split.num_blocks.wrapping_add(1) {
753 _new_size = _new_size.wrapping_mul(2);
754 }
755 let mut new_array = allocate::<u32, _>(alloc, _new_size);
756 new_array.slice_mut()[..split.lengths_alloc_size()]
757 .clone_from_slice(&split.lengths.slice()[..split.lengths_alloc_size()]);
758 <Alloc as Allocator<u32>>::free_cell(
759 alloc,
760 core::mem::replace(&mut split.lengths, new_array),
761 );
762 }
763 }
764 split.num_types = 1;
765 split.types.slice_mut()[split.num_blocks] = 0u8;
766 split.lengths.slice_mut()[split.num_blocks] = length as u32;
767 split.num_blocks = split.num_blocks.wrapping_add(1);
768 return;
769 }
770 let mut histograms = allocate::<HistogramType, _>(alloc, num_histograms);
771
772 InitialEntropyCodes(
773 data,
774 length,
775 sampling_stride_length,
776 num_histograms,
777 histograms.slice_mut(),
778 );
779 RefineEntropyCodes(
780 data,
781 length,
782 sampling_stride_length,
783 num_histograms,
784 histograms.slice_mut(),
785 );
786 {
787 let mut block_ids = allocate::<u8, _>(alloc, length);
788 let mut num_blocks: usize = 0usize;
789 let bitmaplen: usize = num_histograms.wrapping_add(7) >> 3;
790 let mut insert_cost = allocate::<floatX, _>(alloc, data_size.wrapping_mul(num_histograms));
791 let mut cost = allocate::<Mem256f, _>(alloc, ((num_histograms + 7) >> 3));
792 let mut switch_signal = allocate::<u8, _>(alloc, length.wrapping_mul(bitmaplen));
793 let mut new_id = allocate::<u16, _>(alloc, num_histograms);
794 let iters: usize = (if params.quality <= 11 { 3i32 } else { 10i32 }) as usize;
795 for _i in 0usize..iters {
796 num_blocks = FindBlocks(
797 data,
798 length,
799 block_switch_cost,
800 num_histograms,
801 histograms.slice_mut(),
802 insert_cost.slice_mut(),
803 cost.slice_mut(),
804 switch_signal.slice_mut(),
805 block_ids.slice_mut(),
806 );
807 num_histograms = RemapBlockIds(
808 block_ids.slice_mut(),
809 length,
810 new_id.slice_mut(),
811 num_histograms,
812 );
813 BuildBlockHistograms(
814 data,
815 length,
816 block_ids.slice(),
817 num_histograms,
818 histograms.slice_mut(),
819 );
820 }
821 <Alloc as Allocator<floatX>>::free_cell(alloc, insert_cost);
822 <Alloc as Allocator<Mem256f>>::free_cell(alloc, cost);
823 <Alloc as Allocator<u8>>::free_cell(alloc, switch_signal);
824 <Alloc as Allocator<u16>>::free_cell(alloc, new_id);
825 <Alloc as Allocator<HistogramType>>::free_cell(alloc, histograms);
826 ClusterBlocks::<HistogramType, Alloc, IntegerType>(
827 alloc,
828 data,
829 length,
830 num_blocks,
831 scratch_space,
832 block_ids.slice_mut(),
833 split,
834 );
835 <Alloc as Allocator<u8>>::free_cell(alloc, block_ids);
836 }
837}
838
839pub fn BrotliSplitBlock<
840 Alloc: alloc::Allocator<u8>
841 + alloc::Allocator<u16>
842 + alloc::Allocator<u32>
843 + alloc::Allocator<floatX>
844 + alloc::Allocator<Mem256f>
845 + alloc::Allocator<HistogramLiteral>
846 + alloc::Allocator<HistogramCommand>
847 + alloc::Allocator<HistogramDistance>
848 + alloc::Allocator<HistogramPair>,
849>(
850 alloc: &mut Alloc,
851 cmds: &[Command],
852 num_commands: usize,
853 data: &[u8],
854 pos: usize,
855 mask: usize,
856 params: &BrotliEncoderParams,
857 lit_scratch_space: &mut <HistogramLiteral as CostAccessors>::i32vec,
858 cmd_scratch_space: &mut <HistogramCommand as CostAccessors>::i32vec,
859 dst_scratch_space: &mut <HistogramDistance as CostAccessors>::i32vec,
860 literal_split: &mut BlockSplit<Alloc>,
861 insert_and_copy_split: &mut BlockSplit<Alloc>,
862 dist_split: &mut BlockSplit<Alloc>,
863) {
864 {
865 let literals_count: usize = CountLiterals(cmds, num_commands);
870 let mut literals = allocate::<u8, _>(alloc, literals_count);
871 CopyLiteralsToByteArray(cmds, num_commands, data, pos, mask, literals.slice_mut());
872 SplitByteVector::<HistogramLiteral, Alloc, u8>(
873 alloc,
874 literals.slice(),
875 literals_count,
876 kSymbolsPerLiteralHistogram,
877 kMaxLiteralHistograms,
878 kLiteralStrideLength,
879 kLiteralBlockSwitchCost,
880 params,
881 lit_scratch_space,
882 literal_split,
883 );
884 <Alloc as Allocator<u8>>::free_cell(alloc, literals);
885 }
886 {
887 let mut insert_and_copy_codes = allocate::<u16, _>(alloc, num_commands);
888 for i in 0..min(num_commands, cmds.len()) {
889 insert_and_copy_codes.slice_mut()[i] = (cmds[i]).cmd_prefix_;
890 }
891 SplitByteVector::<HistogramCommand, Alloc, u16>(
892 alloc,
893 insert_and_copy_codes.slice(),
894 num_commands,
895 kSymbolsPerCommandHistogram,
896 kMaxCommandHistograms,
897 kCommandStrideLength,
898 kCommandBlockSwitchCost,
899 params,
900 cmd_scratch_space,
901 insert_and_copy_split,
902 );
903 <Alloc as Allocator<u16>>::free_cell(alloc, insert_and_copy_codes);
904 }
905 {
906 let mut distance_prefixes = allocate::<u16, _>(alloc, num_commands);
907 let mut j: usize = 0usize;
908 for i in 0usize..num_commands {
909 let cmd = &cmds[i];
910 if cmd.copy_len() != 0 && cmd.cmd_prefix_ >= 128 {
911 distance_prefixes.slice_mut()[j] = cmd.dist_prefix_ & 0x03ff;
912 j = j.wrapping_add(1);
913 }
914 }
915 SplitByteVector::<HistogramDistance, Alloc, u16>(
916 alloc,
917 distance_prefixes.slice(),
918 j,
919 kSymbolsPerDistanceHistogram,
920 kMaxCommandHistograms,
921 kCommandStrideLength,
922 kDistanceBlockSwitchCost,
923 params,
924 dst_scratch_space,
925 dist_split,
926 );
927 <Alloc as Allocator<u16>>::free_cell(alloc, distance_prefixes);
928 }
929}