brotli/enc/
block_splitter.rs

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