brotli/enc/
histogram.rs

1use core;
2use core::cmp::min;
3
4use super::super::alloc;
5use super::super::alloc::{SliceWrapper, SliceWrapperMut};
6use super::block_split::BlockSplit;
7use super::command::Command;
8use super::constants::{kSigned3BitContextLookup, kUTF8ContextLookup};
9use super::util::floatX;
10use super::vectorization::Mem256i;
11
12//#[derive(Clone)] clone is broken for arrays > 32
13pub struct HistogramLiteral {
14    pub data_: [u32; 256],
15    pub total_count_: usize,
16    pub bit_cost_: floatX,
17}
18impl Clone for HistogramLiteral {
19    #[inline(always)]
20    fn clone(&self) -> HistogramLiteral {
21        HistogramLiteral {
22            data_: self.data_,
23            total_count_: self.total_count_,
24            bit_cost_: self.bit_cost_,
25        }
26    }
27}
28impl Default for HistogramLiteral {
29    #[inline(always)]
30    fn default() -> HistogramLiteral {
31        HistogramLiteral {
32            data_: [0; 256],
33            total_count_: 0,
34            bit_cost_: 3.402e+38,
35        }
36    }
37}
38//#[derive(Clone)] clone is broken for arrays > 32
39pub struct HistogramCommand {
40    pub data_: [u32; 704],
41    pub total_count_: usize,
42    pub bit_cost_: floatX,
43}
44impl Clone for HistogramCommand {
45    #[inline(always)]
46    fn clone(&self) -> HistogramCommand {
47        HistogramCommand {
48            data_: self.data_,
49            total_count_: self.total_count_,
50            bit_cost_: self.bit_cost_,
51        }
52    }
53}
54impl Default for HistogramCommand {
55    #[inline(always)]
56    fn default() -> HistogramCommand {
57        HistogramCommand {
58            data_: [0; 704],
59            total_count_: 0,
60            bit_cost_: 3.402e+38,
61        }
62    }
63}
64//#[derive(Clone)] // #derive is broken for arrays > 32
65
66#[cfg(not(feature = "disallow_large_window_size"))]
67const BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS: usize = 544;
68#[cfg(feature = "disallow_large_window_size")]
69const BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS: usize = 520;
70
71pub struct HistogramDistance {
72    pub data_: [u32; BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS],
73    pub total_count_: usize,
74    pub bit_cost_: floatX,
75}
76impl Clone for HistogramDistance {
77    fn clone(&self) -> HistogramDistance {
78        HistogramDistance {
79            data_: self.data_,
80            total_count_: self.total_count_,
81            bit_cost_: self.bit_cost_,
82        }
83    }
84}
85impl Default for HistogramDistance {
86    fn default() -> HistogramDistance {
87        HistogramDistance {
88            data_: [0; BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS],
89            total_count_: 0,
90            bit_cost_: 3.402e+38,
91        }
92    }
93}
94
95pub trait CostAccessors {
96    type i32vec: Sized + SliceWrapper<Mem256i> + SliceWrapperMut<Mem256i>;
97    fn make_nnz_storage() -> Self::i32vec;
98    fn total_count(&self) -> usize;
99    fn bit_cost(&self) -> floatX;
100    fn set_bit_cost(&mut self, cost: floatX);
101    fn set_total_count(&mut self, count: usize);
102}
103impl SliceWrapper<u32> for HistogramLiteral {
104    #[inline(always)]
105    fn slice(&self) -> &[u32] {
106        &self.data_[..]
107    }
108}
109impl SliceWrapperMut<u32> for HistogramLiteral {
110    #[inline(always)]
111    fn slice_mut(&mut self) -> &mut [u32] {
112        &mut self.data_[..]
113    }
114}
115pub struct Array264i([Mem256i; 33]);
116impl SliceWrapperMut<Mem256i> for Array264i {
117    #[inline(always)]
118    fn slice_mut(&mut self) -> &mut [Mem256i] {
119        &mut self.0[..]
120    }
121}
122
123impl SliceWrapper<Mem256i> for Array264i {
124    #[inline(always)]
125    fn slice(&self) -> &[Mem256i] {
126        &self.0[..]
127    }
128}
129impl Default for Array264i {
130    #[inline(always)]
131    fn default() -> Array264i {
132        Array264i([Mem256i::default(); 33])
133    }
134}
135pub struct Array528i([Mem256i; 66]);
136impl SliceWrapperMut<Mem256i> for Array528i {
137    #[inline(always)]
138    fn slice_mut(&mut self) -> &mut [Mem256i] {
139        &mut self.0[..]
140    }
141}
142impl SliceWrapper<Mem256i> for Array528i {
143    #[inline(always)]
144    fn slice(&self) -> &[Mem256i] {
145        &self.0[..]
146    }
147}
148impl Default for Array528i {
149    #[inline(always)]
150    fn default() -> Array528i {
151        Array528i([Mem256i::default(); 66])
152    }
153}
154
155pub struct Array712i([Mem256i; 89]);
156impl SliceWrapperMut<Mem256i> for Array712i {
157    #[inline(always)]
158    fn slice_mut(&mut self) -> &mut [Mem256i] {
159        &mut self.0[..]
160    }
161}
162impl SliceWrapper<Mem256i> for Array712i {
163    #[inline(always)]
164    fn slice(&self) -> &[Mem256i] {
165        &self.0[..]
166    }
167}
168impl Default for Array712i {
169    #[inline(always)]
170    fn default() -> Array712i {
171        Array712i([Mem256i::default(); 89])
172    }
173}
174
175pub struct EmptyIVec {}
176
177impl SliceWrapperMut<Mem256i> for EmptyIVec {
178    #[inline(always)]
179    fn slice_mut(&mut self) -> &mut [Mem256i] {
180        &mut []
181    }
182}
183impl SliceWrapper<Mem256i> for EmptyIVec {
184    #[inline(always)]
185    fn slice(&self) -> &[Mem256i] {
186        &[]
187    }
188}
189
190impl Default for EmptyIVec {
191    #[inline(always)]
192    fn default() -> EmptyIVec {
193        EmptyIVec {}
194    }
195}
196
197#[cfg(feature = "vector_scratch_space")]
198pub type HistogramLiteralScratch = Array264i;
199
200#[cfg(not(feature = "vector_scratch_space"))]
201pub type HistogramLiteralScratch = EmptyIVec;
202
203impl CostAccessors for HistogramLiteral {
204    type i32vec = HistogramLiteralScratch;
205    fn make_nnz_storage() -> Self::i32vec {
206        HistogramLiteralScratch::default()
207    }
208    #[inline(always)]
209    fn total_count(&self) -> usize {
210        self.total_count_
211    }
212    #[inline(always)]
213    fn bit_cost(&self) -> floatX {
214        self.bit_cost_
215    }
216    #[inline(always)]
217    fn set_bit_cost(&mut self, data: floatX) {
218        self.bit_cost_ = data;
219    }
220    #[inline(always)]
221    fn set_total_count(&mut self, data: usize) {
222        self.total_count_ = data;
223    }
224}
225
226impl SliceWrapper<u32> for HistogramCommand {
227    #[inline(always)]
228    fn slice(&self) -> &[u32] {
229        &self.data_[..]
230    }
231}
232impl SliceWrapperMut<u32> for HistogramCommand {
233    #[inline(always)]
234    fn slice_mut(&mut self) -> &mut [u32] {
235        &mut self.data_[..]
236    }
237}
238
239#[cfg(feature = "vector_scratch_space")]
240pub type HistogramCommandScratch = Array712i;
241
242#[cfg(not(feature = "vector_scratch_space"))]
243pub type HistogramCommandScratch = EmptyIVec;
244
245impl CostAccessors for HistogramCommand {
246    type i32vec = HistogramCommandScratch;
247    fn make_nnz_storage() -> Self::i32vec {
248        HistogramCommandScratch::default()
249    }
250    #[inline(always)]
251    fn total_count(&self) -> usize {
252        self.total_count_
253    }
254    #[inline(always)]
255    fn bit_cost(&self) -> floatX {
256        self.bit_cost_
257    }
258    #[inline(always)]
259    fn set_bit_cost(&mut self, data: floatX) {
260        self.bit_cost_ = data;
261    }
262    #[inline(always)]
263    fn set_total_count(&mut self, data: usize) {
264        self.total_count_ = data;
265    }
266}
267
268impl SliceWrapper<u32> for HistogramDistance {
269    #[inline(always)]
270    fn slice(&self) -> &[u32] {
271        &self.data_[..]
272    }
273}
274impl SliceWrapperMut<u32> for HistogramDistance {
275    #[inline(always)]
276    fn slice_mut(&mut self) -> &mut [u32] {
277        &mut self.data_[..]
278    }
279}
280
281#[cfg(feature = "vector_scratch_space")]
282pub type HistogramDistanceScratch = Array528i;
283
284#[cfg(not(feature = "vector_scratch_space"))]
285pub type HistogramDistanceScratch = EmptyIVec;
286
287impl CostAccessors for HistogramDistance {
288    type i32vec = HistogramDistanceScratch;
289    fn make_nnz_storage() -> Self::i32vec {
290        HistogramDistanceScratch::default()
291    }
292
293    #[inline(always)]
294    fn total_count(&self) -> usize {
295        self.total_count_
296    }
297    #[inline(always)]
298    fn bit_cost(&self) -> floatX {
299        self.bit_cost_
300    }
301    #[inline(always)]
302    fn set_bit_cost(&mut self, data: floatX) {
303        self.bit_cost_ = data;
304    }
305    #[inline(always)]
306    fn set_total_count(&mut self, data: usize) {
307        self.total_count_ = data;
308    }
309}
310
311#[derive(Copy, Clone)]
312pub enum ContextType {
313    CONTEXT_LSB6 = 0,
314    CONTEXT_MSB6 = 1,
315    CONTEXT_UTF8 = 2,
316    CONTEXT_SIGNED = 3,
317}
318
319impl Default for ContextType {
320    #[inline(always)]
321    fn default() -> ContextType {
322        ContextType::CONTEXT_LSB6
323    }
324}
325
326pub struct BlockSplitIterator<'a, Alloc: alloc::Allocator<u8> + 'a + alloc::Allocator<u32> + 'a> {
327    pub split_: &'a BlockSplit<Alloc>,
328    pub idx_: usize,
329    pub type_: usize,
330    pub length_: usize,
331}
332
333impl<'a, Alloc: alloc::Allocator<u8> + alloc::Allocator<u32> + 'a> BlockSplitIterator<'a, Alloc> {
334    fn new(split: &'a BlockSplit<Alloc>) -> Self {
335        Self {
336            split_: split,
337            idx_: 0,
338            type_: 0,
339            length_: if !split.lengths.slice().is_empty() {
340                split.lengths.slice()[0] as usize
341            } else {
342                0
343            },
344        }
345    }
346
347    fn next(&mut self) {
348        if self.length_ == 0 {
349            self.idx_ = self.idx_.wrapping_add(1);
350            self.type_ = self.split_.types.slice()[self.idx_] as usize;
351            self.length_ = self.split_.lengths.slice()[self.idx_] as usize;
352        }
353        self.length_ = self.length_.wrapping_sub(1);
354    }
355}
356
357pub fn HistogramAddItem<HistogramType: SliceWrapper<u32> + SliceWrapperMut<u32> + CostAccessors>(
358    xself: &mut HistogramType,
359    val: usize,
360) {
361    {
362        let _rhs = 1;
363        let _lhs = &mut xself.slice_mut()[val];
364        let val = (*_lhs).wrapping_add(_rhs as u32);
365        *_lhs = val;
366    }
367    let new_count = xself.total_count().wrapping_add(1);
368    xself.set_total_count(new_count);
369}
370pub fn HistogramAddVector<
371    HistogramType: SliceWrapper<u32> + SliceWrapperMut<u32> + CostAccessors,
372    IntegerType: Sized + Clone,
373>(
374    xself: &mut HistogramType,
375    p: &[IntegerType],
376    n: usize,
377) where
378    u64: core::convert::From<IntegerType>,
379{
380    let new_tc = xself.total_count().wrapping_add(n);
381    xself.set_total_count(new_tc);
382    for p_item in p[..n].iter() {
383        let _rhs = 1;
384        let index: usize = u64::from(p_item.clone()) as usize;
385        let _lhs = &mut xself.slice_mut()[index];
386        *_lhs = (*_lhs).wrapping_add(_rhs as u32);
387    }
388}
389
390#[inline(always)]
391pub fn HistogramClear<HistogramType: SliceWrapperMut<u32> + CostAccessors>(
392    xself: &mut HistogramType,
393) {
394    for data_elem in xself.slice_mut().iter_mut() {
395        *data_elem = 0;
396    }
397    xself.set_total_count(0);
398    xself.set_bit_cost(3.402e+38);
399}
400pub fn ClearHistograms<HistogramType: SliceWrapperMut<u32> + CostAccessors>(
401    array: &mut [HistogramType],
402    length: usize,
403) {
404    for item in array[..length].iter_mut() {
405        HistogramClear(item)
406    }
407}
408
409#[inline(always)]
410pub fn HistogramAddHistogram<
411    HistogramType: SliceWrapperMut<u32> + SliceWrapper<u32> + CostAccessors,
412>(
413    xself: &mut HistogramType,
414    v: &HistogramType,
415) {
416    let old_total_count = xself.total_count();
417    xself.set_total_count(old_total_count + (*v).total_count());
418    let h0 = xself.slice_mut();
419    let h1 = v.slice();
420    let n = min(h0.len(), h1.len());
421    for i in 0..n {
422        let h0val = &mut h0[i];
423        let val = h0val.wrapping_add(h1[i]);
424        *h0val = val;
425    }
426}
427pub fn HistogramSelfAddHistogram<
428    HistogramType: SliceWrapperMut<u32> + SliceWrapper<u32> + CostAccessors,
429>(
430    xself: &mut [HistogramType],
431    i0: usize,
432    i1: usize,
433) {
434    let tc_new = xself[i1].total_count();
435    let tc_old = xself[i0].total_count();
436    xself[i0].set_total_count(tc_old.wrapping_add(tc_new));
437    let h0 = xself[i0].slice().len();
438    let h0a = xself[i0].slice().len();
439    let h1 = xself[i1].slice().len();
440    let n = min(h0, min(h0a, h1));
441    for h_index in 0..n {
442        let val = xself[i0].slice()[h_index].wrapping_add(xself[i1].slice()[h_index]);
443        xself[i0].slice_mut()[h_index] = val;
444    }
445}
446
447#[inline(always)]
448pub fn Context(p1: u8, p2: u8, mode: ContextType) -> u8 {
449    match mode {
450        ContextType::CONTEXT_SIGNED => {
451            (((kSigned3BitContextLookup[p1 as usize] as i32) << 3)
452                + kSigned3BitContextLookup[p2 as usize] as i32) as u8
453        }
454        ContextType::CONTEXT_UTF8 => {
455            (kUTF8ContextLookup[p1 as usize] as i32
456                | kUTF8ContextLookup[(p2 as i32 + 256i32) as usize] as i32) as u8
457        }
458        ContextType::CONTEXT_MSB6 => (p1 as i32 >> 2) as u8,
459        ContextType::CONTEXT_LSB6 => (p1 as i32 & 0x3fi32) as u8, /* else {
460                                                                  0u8
461                                                                  }*/
462    }
463}
464
465pub fn BrotliBuildHistogramsWithContext<'a, Alloc: alloc::Allocator<u8> + alloc::Allocator<u32>>(
466    cmds: &[Command],
467    num_commands: usize,
468    literal_split: &BlockSplit<Alloc>,
469    insert_and_copy_split: &BlockSplit<Alloc>,
470    dist_split: &BlockSplit<Alloc>,
471    ringbuffer: &[u8],
472    start_pos: usize,
473    mask: usize,
474    mut prev_byte: u8,
475    mut prev_byte2: u8,
476    context_modes: &[ContextType],
477    literal_histograms: &mut [HistogramLiteral],
478    insert_and_copy_histograms: &mut [HistogramCommand],
479    copy_dist_histograms: &mut [HistogramDistance],
480) {
481    let mut pos: usize = start_pos;
482    let mut literal_it: BlockSplitIterator<Alloc>;
483    let mut insert_and_copy_it: BlockSplitIterator<Alloc>;
484    let mut dist_it: BlockSplitIterator<Alloc>;
485    literal_it = BlockSplitIterator::new(literal_split);
486    insert_and_copy_it = BlockSplitIterator::new(insert_and_copy_split);
487    dist_it = BlockSplitIterator::new(dist_split);
488    for i in 0usize..num_commands {
489        let cmd = &cmds[i];
490        let mut j: usize;
491        insert_and_copy_it.next();
492        HistogramAddItem(
493            &mut insert_and_copy_histograms[insert_and_copy_it.type_],
494            cmd.cmd_prefix_ as usize,
495        );
496        j = cmd.insert_len_ as usize;
497        while j != 0usize {
498            {
499                literal_it.next();
500                let context: usize = if !context_modes.is_empty() {
501                    (literal_it.type_ << 6).wrapping_add(Context(
502                        prev_byte,
503                        prev_byte2,
504                        context_modes[literal_it.type_],
505                    ) as usize)
506                } else {
507                    literal_it.type_
508                };
509                HistogramAddItem(
510                    &mut literal_histograms[(context as usize)],
511                    ringbuffer[(pos & mask)] as usize,
512                );
513                prev_byte2 = prev_byte;
514                prev_byte = ringbuffer[(pos & mask)];
515                pos = pos.wrapping_add(1);
516            }
517            j = j.wrapping_sub(1);
518        }
519        pos = pos.wrapping_add(cmd.copy_len() as usize);
520        if cmd.copy_len() != 0 {
521            prev_byte2 = ringbuffer[(pos.wrapping_sub(2) & mask)];
522            prev_byte = ringbuffer[(pos.wrapping_sub(1) & mask)];
523            if cmd.cmd_prefix_ as i32 >= 128i32 {
524                dist_it.next();
525                let context: usize =
526                    (dist_it.type_ << 2).wrapping_add(cmd.distance_context() as usize);
527                HistogramAddItem(
528                    &mut copy_dist_histograms[(context as usize)],
529                    cmd.dist_prefix_ as usize & 0x3ff,
530                );
531            }
532        }
533    }
534}