brotli/enc/
block_splitter.rs

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        //super::vectorization::sum8(ymm_bits) as u8;
79        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        //println_stderr!("{:} ss {:} c {:?}", (index << 3) + 7, switch_signal[ix + index],*cost_it);
83    }
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        // main (vectorized) loop
281        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        //remainder loop for
304        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        /*for (i, cmd) in cmds[..num_commands].iter().enumerate() {
866            println_stderr!("C {:} {:} {:} {:} {:} {:}",
867                            i, cmd.insert_len_, cmd.copy_len_, cmd.dist_extra_, cmd.cmd_prefix_, cmd.dist_prefix_);
868        }*/
869        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}