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
12pub 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}
38pub 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#[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, }
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}