1use core;
2use core::cmp::min;
3
4use fearless_simd::{Level, Select, Simd, SimdBase, f32x8, i16x16};
5
6use super::super::alloc;
7use super::super::alloc::{Allocator, SliceWrapper, SliceWrapperMut};
8use super::backward_references::BrotliEncoderParams;
9use super::input_pair::{InputPair, InputReference, InputReferenceMut};
10use super::ir_interpret::{IRInterpreter, push_base};
11use super::util::{FastLog2u16, floatX};
12use super::vectorization::detect_level;
13use super::{find_stride, interface, s16, v8};
14use crate::enc::combined_alloc::{alloc_default, alloc_if};
15
16pub const CONTEXT_MAP_PRIOR_SIZE: usize = 256 * 17;
18pub const STRIDE_PRIOR_SIZE: usize = 256 * 256 * 2;
19pub const ADV_PRIOR_SIZE: usize = 65536 + (20 << 16);
20pub const DEFAULT_SPEED: (u16, u16) = (8, 8192);
21
22pub enum WhichPrior {
23 CM = 0,
24 ADV = 1,
25 SLOW_CM = 2,
26 FAST_CM = 3,
27 STRIDE1 = 4,
28 STRIDE2 = 5,
29 STRIDE3 = 6,
30 STRIDE4 = 7,
31 NUM_PRIORS = 8,
33 }
35
36pub trait Prior {
37 fn lookup_lin(
38 stride_byte: u8,
39 selected_context: u8,
40 actual_context: usize,
41 high_nibble: Option<u8>,
42 ) -> usize;
43 #[inline(always)]
44 fn lookup_mut<S: Simd>(
45 simd: S,
46 data: &mut [s16],
47 stride_byte: u8,
48 selected_context: u8,
49 actual_context: usize,
50 high_nibble: Option<u8>,
51 ) -> CDF<'_, S> {
52 let index = Self::lookup_lin(stride_byte, selected_context, actual_context, high_nibble);
53 CDF::new(simd, &mut data[index])
54 }
55 #[inline(always)]
56 fn lookup(
57 data: &[s16],
58 stride_byte: u8,
59 selected_context: u8,
60 actual_context: usize,
61 high_nibble: Option<u8>,
62 ) -> &s16 {
63 let index = Self::lookup_lin(stride_byte, selected_context, actual_context, high_nibble);
64 &data[index]
65 }
66 #[allow(unused_variables)]
67 #[inline(always)]
68 fn score_index(
69 stride_byte: u8,
70 selected_context: u8,
71 actual_context: usize,
72 high_nibble: Option<u8>,
73 ) -> usize {
74 let which = Self::which();
75 assert!(which < WhichPrior::NUM_PRIORS as usize);
76 assert!(actual_context < 256);
77 if let Some(nibble) = high_nibble {
78 WhichPrior::NUM_PRIORS as usize * (actual_context + 4096 + 256 * nibble as usize)
79 + which
80 } else {
81 WhichPrior::NUM_PRIORS as usize * (actual_context + 256 * (stride_byte >> 4) as usize)
82 + which
83 }
84 }
85 fn which() -> usize;
86}
87
88#[inline(always)]
89fn upper_score_index(stride_byte: u8, _selected_context: u8, actual_context: usize) -> usize {
90 actual_context + 256 * (stride_byte >> 4) as usize
91}
92#[inline(always)]
93fn lower_score_index(
94 _stride_byte: u8,
95 _selected_context: u8,
96 actual_context: usize,
97 high_nibble: u8,
98) -> usize {
99 debug_assert!(actual_context < 256);
100 debug_assert!(high_nibble < 16);
101 actual_context + 4096 + 256 * high_nibble as usize
102}
103
104#[allow(unused_variables)]
105#[inline(always)]
106fn stride_lookup_lin(
107 stride_byte: u8,
108 selected_context: u8,
109 actual_context: usize,
110 high_nibble: Option<u8>,
111) -> usize {
112 if let Some(nibble) = high_nibble {
113 1 + 2 * (actual_context | ((stride_byte as usize & 0x0f) << 8) | ((nibble as usize) << 12))
114 } else {
115 2 * (actual_context | ((stride_byte as usize) << 8))
116 }
117}
118pub struct Stride1Prior {}
119impl Stride1Prior {
120 #[inline(always)]
121 pub fn offset() -> usize {
122 0
123 }
124}
125
126impl Prior for Stride1Prior {
127 #[inline(always)]
128 fn lookup_lin(
129 stride_byte: u8,
130 selected_context: u8,
131 actual_context: usize,
132 high_nibble: Option<u8>,
133 ) -> usize {
134 stride_lookup_lin(stride_byte, selected_context, actual_context, high_nibble)
135 }
136 #[inline(always)]
137 fn which() -> usize {
138 WhichPrior::STRIDE1 as usize
139 }
140}
141pub struct Stride2Prior {}
145impl Stride2Prior {
146 #[inline(always)]
147 pub fn offset() -> usize {
148 1
149 }
150}
151
152impl Prior for Stride2Prior {
153 #[inline(always)]
154 fn lookup_lin(
155 stride_byte: u8,
156 selected_context: u8,
157 actual_context: usize,
158 high_nibble: Option<u8>,
159 ) -> usize {
160 stride_lookup_lin(stride_byte, selected_context, actual_context, high_nibble)
161 }
162 #[inline]
163 fn which() -> usize {
164 WhichPrior::STRIDE2 as usize
165 }
166}
167pub struct Stride3Prior {}
171impl Stride3Prior {
172 #[inline(always)]
173 pub fn offset() -> usize {
174 2
175 }
176}
177
178impl Prior for Stride3Prior {
179 #[inline(always)]
180 fn lookup_lin(
181 stride_byte: u8,
182 selected_context: u8,
183 actual_context: usize,
184 high_nibble: Option<u8>,
185 ) -> usize {
186 stride_lookup_lin(stride_byte, selected_context, actual_context, high_nibble)
187 }
188 #[inline(always)]
189 fn which() -> usize {
190 WhichPrior::STRIDE3 as usize
191 }
192}
193
194pub struct Stride4Prior {}
198impl Stride4Prior {
199 #[inline(always)]
200 pub fn offset() -> usize {
201 3
202 }
203}
204impl Prior for Stride4Prior {
205 #[inline(always)]
206 fn lookup_lin(
207 stride_byte: u8,
208 selected_context: u8,
209 actual_context: usize,
210 high_nibble: Option<u8>,
211 ) -> usize {
212 stride_lookup_lin(stride_byte, selected_context, actual_context, high_nibble)
213 }
214 #[inline]
215 fn which() -> usize {
216 WhichPrior::STRIDE4 as usize
217 }
218}
219
220pub struct CMPrior {}
245impl Prior for CMPrior {
246 #[allow(unused_variables)]
247 #[inline(always)]
248 fn lookup_lin(
249 stride_byte: u8,
250 selected_context: u8,
251 actual_context: usize,
252 high_nibble: Option<u8>,
253 ) -> usize {
254 if let Some(nibble) = high_nibble {
255 (nibble as usize + 1) + 17 * actual_context
256 } else {
257 17 * actual_context
258 }
259 }
260 #[inline(always)]
261 fn which() -> usize {
262 WhichPrior::CM as usize
263 }
264}
265pub struct FastCMPrior {}
266impl Prior for FastCMPrior {
267 #[allow(unused_variables)]
268 #[inline(always)]
269 fn lookup_lin(
270 stride_byte: u8,
271 selected_context: u8,
272 actual_context: usize,
273 high_nibble: Option<u8>,
274 ) -> usize {
275 if let Some(nibble) = high_nibble {
276 2 * actual_context
277 } else {
278 2 * actual_context + 1
279 }
280 }
281 #[inline(always)]
282 fn which() -> usize {
283 WhichPrior::FAST_CM as usize
284 }
285}
286
287pub struct SlowCMPrior {}
288impl Prior for SlowCMPrior {
289 #[allow(unused_variables)]
290 #[inline(always)]
291 fn lookup_lin(
292 stride_byte: u8,
293 selected_context: u8,
294 actual_context: usize,
295 high_nibble: Option<u8>,
296 ) -> usize {
297 if let Some(nibble) = high_nibble {
298 (nibble as usize + 1) + 17 * actual_context
299 } else {
300 17 * actual_context
301 }
302 }
303 #[inline]
304 fn which() -> usize {
305 WhichPrior::SLOW_CM as usize
306 }
307}
308
309pub struct AdvPrior {}
310impl Prior for AdvPrior {
311 #[allow(unused_variables)]
312 #[inline(always)]
313 fn lookup_lin(
314 stride_byte: u8,
315 selected_context: u8,
316 actual_context: usize,
317 high_nibble: Option<u8>,
318 ) -> usize {
319 if let Some(nibble) = high_nibble {
320 65536
321 + (actual_context | ((stride_byte as usize) << 8) | ((nibble as usize & 0xf) << 16))
322 } else {
323 actual_context | ((stride_byte as usize & 0xf0) << 8)
324 }
325 }
326 #[inline(always)]
327 fn which() -> usize {
328 WhichPrior::ADV as usize
329 }
330}
331
332const ONE_TO_16: [i16; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
333
334pub struct CDF<'a, S: Simd> {
335 cdf: &'a mut s16,
336 simd: S,
337}
338
339impl<'a, S: Simd> CDF<'a, S> {
340 #[inline(always)]
341 pub fn new(simd: S, cdf: &'a mut s16) -> Self {
342 CDF { cdf, simd }
343 }
344 #[inline(always)]
345 pub fn cost(&self, nibble_u8: u8) -> floatX {
346 let nibble = nibble_u8 as usize & 0xf;
347 let mut pdf = self.cdf[nibble];
348 if nibble_u8 != 0 {
349 pdf -= self.cdf[(nibble - 1)];
350 }
351 FastLog2u16(self.cdf[15] as u16) - FastLog2u16(pdf as u16)
352 }
353 #[inline(always)]
354 pub fn update(&mut self, nibble_u8: u8, speed: (u16, u16)) {
355 let simd = self.simd;
356 let one_to_16 = i16x16::from_slice(simd, &ONE_TO_16);
357 let increment = i16x16::splat(simd, speed.0 as i16);
358 let above_nibble = one_to_16.simd_gt(i16x16::splat(simd, i16::from(nibble_u8)));
360 let mut cdf =
361 self.cdf.to_simd(simd) + above_nibble.select(increment, i16x16::splat(simd, 0));
362 if cdf.as_slice()[15] >= speed.1 as i16 {
363 let biased = cdf + one_to_16;
365 cdf = biased - (biased >> 2);
366 }
367 *self.cdf = s16::from_simd(cdf);
368 }
369}
370
371pub fn init_cdfs(cdfs: &mut [s16]) {
372 for item in cdfs.iter_mut() {
373 *item = s16::from([4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64]);
374 }
375}
376
377pub struct PriorEval<
378 'a,
379 Alloc: alloc::Allocator<s16> + alloc::Allocator<u32> + alloc::Allocator<v8>,
380> {
381 input: InputPair<'a>,
382 context_map: interface::PredictionModeContextMap<InputReferenceMut<'a>>,
383 block_type: u8,
384 local_byte_offset: usize,
385 _nop: <Alloc as Allocator<u32>>::AllocatedMemory,
386 cm_priors: <Alloc as Allocator<s16>>::AllocatedMemory,
387 slow_cm_priors: <Alloc as Allocator<s16>>::AllocatedMemory,
388 fast_cm_priors: <Alloc as Allocator<s16>>::AllocatedMemory,
389 stride_priors: [<Alloc as Allocator<s16>>::AllocatedMemory; 4],
390 adv_priors: <Alloc as Allocator<s16>>::AllocatedMemory,
391 _stride_pyramid_leaves: [u8; find_stride::NUM_LEAF_NODES],
392 score: <Alloc as Allocator<v8>>::AllocatedMemory,
393 cm_speed: [(u16, u16); 2],
394 stride_speed: [(u16, u16); 2],
395 cur_stride: u8,
396 level: Level,
398}
399
400impl<'a, Alloc: alloc::Allocator<s16> + alloc::Allocator<u32> + alloc::Allocator<v8>>
401 PriorEval<'a, Alloc>
402{
403 pub fn new(
404 alloc: &mut Alloc,
405 input: InputPair<'a>,
406 stride: [u8; find_stride::NUM_LEAF_NODES],
407 prediction_mode: interface::PredictionModeContextMap<InputReferenceMut<'a>>,
408 params: &BrotliEncoderParams,
409 ) -> Self {
410 let do_alloc = params.prior_bitmask_detection != 0;
411 let mut cm_speed = prediction_mode.context_map_speed();
412 let mut stride_speed = prediction_mode.stride_context_speed();
413 if cm_speed[0] == (0, 0) {
414 cm_speed[0] = params.literal_adaptation[2]
415 }
416 if cm_speed[0] == (0, 0) {
417 cm_speed[0] = DEFAULT_SPEED;
418 }
419 if cm_speed[1] == (0, 0) {
420 cm_speed[1] = params.literal_adaptation[3]
421 }
422 if cm_speed[1] == (0, 0) {
423 cm_speed[1] = cm_speed[0];
424 }
425 if stride_speed[0] == (0, 0) {
426 stride_speed[0] = params.literal_adaptation[0]
427 }
428 if stride_speed[0] == (0, 0) {
429 stride_speed[0] = DEFAULT_SPEED;
430 }
431 if stride_speed[1] == (0, 0) {
432 stride_speed[1] = params.literal_adaptation[1]
433 }
434 if stride_speed[1] == (0, 0) {
435 stride_speed[1] = stride_speed[0];
436 }
437 let mut ret = PriorEval::<Alloc> {
438 input,
439 context_map: prediction_mode,
440 block_type: 0,
441 cur_stride: 1,
442 local_byte_offset: 0,
443 _nop: alloc_default::<u32, Alloc>(),
444 cm_priors: alloc_if::<s16, _>(do_alloc, alloc, CONTEXT_MAP_PRIOR_SIZE),
445 slow_cm_priors: alloc_if::<s16, _>(do_alloc, alloc, CONTEXT_MAP_PRIOR_SIZE),
446 fast_cm_priors: alloc_if::<s16, _>(do_alloc, alloc, CONTEXT_MAP_PRIOR_SIZE),
447 stride_priors: [
448 alloc_if::<s16, _>(do_alloc, alloc, STRIDE_PRIOR_SIZE),
449 alloc_if::<s16, _>(do_alloc, alloc, STRIDE_PRIOR_SIZE),
450 alloc_if::<s16, _>(do_alloc, alloc, STRIDE_PRIOR_SIZE),
451 alloc_if::<s16, _>(do_alloc, alloc, STRIDE_PRIOR_SIZE),
452 ],
455 adv_priors: alloc_if::<s16, _>(do_alloc, alloc, ADV_PRIOR_SIZE),
456 _stride_pyramid_leaves: stride,
457 score: alloc_if::<v8, _>(do_alloc, alloc, 8192),
458 cm_speed,
459 stride_speed,
460 level: detect_level(),
461 };
462 init_cdfs(ret.cm_priors.slice_mut());
463 init_cdfs(ret.slow_cm_priors.slice_mut());
464 init_cdfs(ret.fast_cm_priors.slice_mut());
465 init_cdfs(ret.stride_priors[0].slice_mut());
466 init_cdfs(ret.stride_priors[1].slice_mut());
467 init_cdfs(ret.stride_priors[2].slice_mut());
468 init_cdfs(ret.stride_priors[3].slice_mut());
469 init_cdfs(ret.adv_priors.slice_mut());
471 ret
472 }
473 pub fn choose_bitmask(&mut self) {
474 let epsilon = 6.0;
475 let mut max_popularity = 0u32;
476 let mut max_popularity_index = 0u8;
477 assert_eq!(WhichPrior::NUM_PRIORS as usize, 8);
478 let mut popularity = [0u32; 8];
479 let mut bitmask = [0u8; super::interface::NUM_MIXING_VALUES];
480 for (i, score) in self.score.slice().iter().enumerate() {
481 let cm_score = score[WhichPrior::CM as usize];
482 let slow_cm_score = score[WhichPrior::SLOW_CM as usize];
483 let fast_cm_score = score[WhichPrior::FAST_CM as usize] + 16.0;
484 let stride1_score = score[WhichPrior::STRIDE1 as usize];
485 let stride2_score = score[WhichPrior::STRIDE2 as usize];
486 let stride3_score = score[WhichPrior::STRIDE3 as usize] + 16.0;
487 let stride4_score = score[WhichPrior::STRIDE4 as usize];
488 let stride8_score = stride4_score + 1.0; let stride_score = min(
491 stride1_score as u64,
492 min(
493 stride2_score as u64,
494 min(
495 stride3_score as u64,
496 min(stride4_score as u64, stride8_score as u64),
497 ),
498 ),
499 );
500
501 let adv_score = score[WhichPrior::ADV as usize];
502 if adv_score + epsilon < (stride_score as floatX)
503 && adv_score + epsilon < cm_score
504 && adv_score + epsilon < slow_cm_score
505 && adv_score + epsilon < fast_cm_score
506 {
507 bitmask[i] = 1;
508 } else if slow_cm_score + epsilon < (stride_score as floatX)
509 && slow_cm_score + epsilon < cm_score
510 && slow_cm_score + epsilon < fast_cm_score
511 {
512 bitmask[i] = 2;
513 } else if fast_cm_score + epsilon < (stride_score as floatX)
514 && fast_cm_score + epsilon < cm_score
515 {
516 bitmask[i] = 3;
517 } else if epsilon + (stride_score as floatX) < cm_score {
518 bitmask[i] = WhichPrior::STRIDE1 as u8;
519 if stride_score == stride8_score as u64 {
520 }
522 if stride_score == stride4_score as u64 {
523 bitmask[i] = WhichPrior::STRIDE4 as u8;
524 }
525 if stride_score == stride3_score as u64 {
526 bitmask[i] = WhichPrior::STRIDE3 as u8;
527 }
528 if stride_score == stride2_score as u64 {
529 bitmask[i] = WhichPrior::STRIDE2 as u8;
530 }
531 if stride_score == stride1_score as u64 {
532 bitmask[i] = WhichPrior::STRIDE1 as u8;
533 }
534 } else {
535 bitmask[i] = 0;
536 }
537 if stride_score == 0 {
538 bitmask[i] = max_popularity_index;
539 } else {
541 popularity[bitmask[i] as usize] += 1;
542 if popularity[bitmask[i] as usize] > max_popularity {
543 max_popularity = popularity[bitmask[i] as usize];
544 max_popularity_index = bitmask[i];
545 }
546 }
548 }
549 self.context_map.set_mixing_values(&bitmask);
550 }
551 pub fn free(&mut self, alloc: &mut Alloc) {
552 <Alloc as Allocator<v8>>::free_cell(alloc, core::mem::take(&mut self.score));
553 <Alloc as Allocator<s16>>::free_cell(alloc, core::mem::take(&mut self.cm_priors));
554 <Alloc as Allocator<s16>>::free_cell(alloc, core::mem::take(&mut self.slow_cm_priors));
555 <Alloc as Allocator<s16>>::free_cell(alloc, core::mem::take(&mut self.fast_cm_priors));
556 <Alloc as Allocator<s16>>::free_cell(alloc, core::mem::take(&mut self.stride_priors[0]));
557 <Alloc as Allocator<s16>>::free_cell(alloc, core::mem::take(&mut self.stride_priors[1]));
558 <Alloc as Allocator<s16>>::free_cell(alloc, core::mem::take(&mut self.stride_priors[2]));
559 <Alloc as Allocator<s16>>::free_cell(alloc, core::mem::take(&mut self.stride_priors[3]));
560 <Alloc as Allocator<s16>>::free_cell(alloc, core::mem::take(&mut self.adv_priors));
562 }
563
564 pub fn take_prediction_mode(
565 &mut self,
566 ) -> interface::PredictionModeContextMap<InputReferenceMut<'a>> {
567 core::mem::replace(
568 &mut self.context_map,
569 interface::PredictionModeContextMap::<InputReferenceMut<'a>> {
570 literal_context_map: InputReferenceMut::default(),
571 predmode_speed_and_distance_context_map: InputReferenceMut::default(),
572 },
573 )
574 }
575 fn update_cost_base<S: Simd>(
576 &mut self,
577 simd: S,
578 stride_prior: [u8; 8],
579 stride_prior_offset: usize,
580 selected_bits: u8,
581 cm_prior: usize,
582 literal: u8,
583 ) {
584 let mut l_score = f32x8::splat(simd, 0.0);
585 let mut h_score = f32x8::splat(simd, 0.0);
586 let base_stride_prior =
587 stride_prior[stride_prior_offset.wrapping_sub(self.cur_stride as usize) & 7];
588 let hscore_index = upper_score_index(base_stride_prior, selected_bits, cm_prior);
589 let lscore_index =
590 lower_score_index(base_stride_prior, selected_bits, cm_prior, literal >> 4);
591 {
592 type CurPrior = CMPrior;
593 let mut cdf = CurPrior::lookup_mut(
594 simd,
595 self.cm_priors.slice_mut(),
596 base_stride_prior,
597 selected_bits,
598 cm_prior,
599 None,
600 );
601 h_score.as_mut_slice()[CurPrior::which()] = cdf.cost(literal >> 4);
602 cdf.update(literal >> 4, self.cm_speed[1]);
603 }
604 {
605 type CurPrior = CMPrior;
606 let mut cdf = CurPrior::lookup_mut(
607 simd,
608 self.cm_priors.slice_mut(),
609 base_stride_prior,
610 selected_bits,
611 cm_prior,
612 Some(literal >> 4),
613 );
614 l_score.as_mut_slice()[CurPrior::which()] = cdf.cost(literal & 0xf);
615 cdf.update(literal & 0xf, self.cm_speed[0]);
616 }
617 {
618 type CurPrior = SlowCMPrior;
619 let mut cdf = CurPrior::lookup_mut(
620 simd,
621 self.slow_cm_priors.slice_mut(),
622 base_stride_prior,
623 selected_bits,
624 cm_prior,
625 None,
626 );
627 h_score.as_mut_slice()[CurPrior::which()] = cdf.cost(literal >> 4);
628 cdf.update(literal >> 4, (0, 1024));
629 }
630 {
631 type CurPrior = SlowCMPrior;
632 let mut cdf = CurPrior::lookup_mut(
633 simd,
634 self.slow_cm_priors.slice_mut(),
635 base_stride_prior,
636 selected_bits,
637 cm_prior,
638 Some(literal >> 4),
639 );
640 l_score.as_mut_slice()[CurPrior::which()] = cdf.cost(literal & 0xf);
641 cdf.update(literal & 0xf, (0, 1024));
642 }
643 {
644 type CurPrior = FastCMPrior;
645 let mut cdf = CurPrior::lookup_mut(
646 simd,
647 self.fast_cm_priors.slice_mut(),
648 base_stride_prior,
649 selected_bits,
650 cm_prior,
651 None,
652 );
653 h_score.as_mut_slice()[CurPrior::which()] = cdf.cost(literal >> 4);
654 cdf.update(literal >> 4, self.cm_speed[0]);
655 }
656 {
657 type CurPrior = FastCMPrior;
658 let mut cdf = CurPrior::lookup_mut(
659 simd,
660 self.fast_cm_priors.slice_mut(),
661 base_stride_prior,
662 selected_bits,
663 cm_prior,
664 Some(literal >> 4),
665 );
666 l_score.as_mut_slice()[CurPrior::which()] = cdf.cost(literal & 0xf);
667 cdf.update(literal & 0xf, self.cm_speed[0]);
668 }
669 {
670 type CurPrior = Stride1Prior;
671 let mut cdf = CurPrior::lookup_mut(
672 simd,
673 self.stride_priors[0].slice_mut(),
674 stride_prior[stride_prior_offset.wrapping_sub(CurPrior::offset()) & 7],
675 selected_bits,
676 cm_prior,
677 None,
678 );
679 h_score.as_mut_slice()[CurPrior::which()] = cdf.cost(literal >> 4);
680 cdf.update(literal >> 4, self.stride_speed[1]);
681 }
682 {
683 type CurPrior = Stride1Prior;
684 let mut cdf = CurPrior::lookup_mut(
685 simd,
686 self.stride_priors[0].slice_mut(),
687 stride_prior[stride_prior_offset.wrapping_sub(CurPrior::offset()) & 7],
688 selected_bits,
689 cm_prior,
690 Some(literal >> 4),
691 );
692 l_score.as_mut_slice()[CurPrior::which()] = cdf.cost(literal & 0xf);
693 cdf.update(literal & 0xf, self.stride_speed[0]);
694 }
695 {
696 type CurPrior = Stride2Prior;
697 let mut cdf = CurPrior::lookup_mut(
698 simd,
699 self.stride_priors[1].slice_mut(),
700 stride_prior[stride_prior_offset.wrapping_sub(CurPrior::offset()) & 7],
701 selected_bits,
702 cm_prior,
703 None,
704 );
705 h_score.as_mut_slice()[CurPrior::which()] = cdf.cost(literal >> 4);
706 cdf.update(literal >> 4, self.stride_speed[1]);
707 }
708 {
709 type CurPrior = Stride2Prior;
710 let mut cdf = CurPrior::lookup_mut(
711 simd,
712 self.stride_priors[1].slice_mut(),
713 stride_prior[stride_prior_offset.wrapping_sub(CurPrior::offset()) & 7],
714 selected_bits,
715 cm_prior,
716 Some(literal >> 4),
717 );
718 l_score.as_mut_slice()[CurPrior::which()] = cdf.cost(literal & 0xf);
719 cdf.update(literal & 0xf, self.stride_speed[0]);
720 }
721 {
722 type CurPrior = Stride3Prior;
723 let mut cdf = CurPrior::lookup_mut(
724 simd,
725 self.stride_priors[2].slice_mut(),
726 stride_prior[stride_prior_offset.wrapping_sub(CurPrior::offset()) & 7],
727 selected_bits,
728 cm_prior,
729 None,
730 );
731 h_score.as_mut_slice()[CurPrior::which()] = cdf.cost(literal >> 4);
732 cdf.update(literal >> 4, self.stride_speed[1]);
733 }
734 {
735 type CurPrior = Stride3Prior;
736 let mut cdf = CurPrior::lookup_mut(
737 simd,
738 self.stride_priors[2].slice_mut(),
739 stride_prior[stride_prior_offset.wrapping_sub(CurPrior::offset()) & 7],
740 selected_bits,
741 cm_prior,
742 Some(literal >> 4),
743 );
744 l_score.as_mut_slice()[CurPrior::which()] = cdf.cost(literal & 0xf);
745 cdf.update(literal & 0xf, self.stride_speed[0]);
746 }
747 {
748 type CurPrior = Stride4Prior;
749 let mut cdf = CurPrior::lookup_mut(
750 simd,
751 self.stride_priors[3].slice_mut(),
752 stride_prior[stride_prior_offset.wrapping_sub(CurPrior::offset()) & 7],
753 selected_bits,
754 cm_prior,
755 None,
756 );
757 h_score.as_mut_slice()[CurPrior::which()] = cdf.cost(literal >> 4);
758 cdf.update(literal >> 4, self.stride_speed[1]);
759 }
760 {
761 type CurPrior = Stride4Prior;
762 let mut cdf = CurPrior::lookup_mut(
763 simd,
764 self.stride_priors[3].slice_mut(),
765 stride_prior[stride_prior_offset.wrapping_sub(CurPrior::offset()) & 7],
766 selected_bits,
767 cm_prior,
768 Some(literal >> 4),
769 );
770 l_score.as_mut_slice()[CurPrior::which()] = cdf.cost(literal & 0xf);
771 cdf.update(literal & 0xf, self.stride_speed[0]);
772 }
773 type CurPrior = AdvPrior;
792 {
793 let mut cdf = CurPrior::lookup_mut(
794 simd,
795 self.adv_priors.slice_mut(),
796 base_stride_prior,
797 selected_bits,
798 cm_prior,
799 None,
800 );
801 h_score.as_mut_slice()[CurPrior::which()] = cdf.cost(literal >> 4);
802 cdf.update(literal >> 4, self.stride_speed[1]);
803 }
804 {
805 let mut cdf = CurPrior::lookup_mut(
806 simd,
807 self.adv_priors.slice_mut(),
808 base_stride_prior,
809 selected_bits,
810 cm_prior,
811 Some(literal >> 4),
812 );
813 l_score.as_mut_slice()[CurPrior::which()] = cdf.cost(literal & 0xf);
814 cdf.update(literal & 0xf, self.stride_speed[0]);
815 }
816 let score = self.score.slice_mut();
817 score[lscore_index] = v8::from_simd(score[lscore_index].to_simd(simd) + l_score);
818 score[hscore_index] = v8::from_simd(score[hscore_index].to_simd(simd) + h_score);
819 }
820}
821impl<'a, Alloc: alloc::Allocator<s16> + alloc::Allocator<u32> + alloc::Allocator<v8>> IRInterpreter
822 for PriorEval<'a, Alloc>
823{
824 #[inline]
825 fn inc_local_byte_offset(&mut self, inc: usize) {
826 self.local_byte_offset += inc;
827 }
828 #[inline]
829 fn local_byte_offset(&self) -> usize {
830 self.local_byte_offset
831 }
832 #[inline]
833 fn update_block_type(&mut self, new_type: u8, stride: u8) {
834 self.block_type = new_type;
835 self.cur_stride = stride;
836 }
837 #[inline]
838 fn block_type(&self) -> u8 {
839 self.block_type
840 }
841 #[inline]
842 fn literal_data_at_offset(&self, index: usize) -> u8 {
843 self.input[index]
844 }
845 #[inline]
846 fn literal_context_map(&self) -> &[u8] {
847 self.context_map.literal_context_map.slice()
848 }
849 #[inline]
850 fn prediction_mode(&self) -> crate::interface::LiteralPredictionModeNibble {
851 self.context_map.literal_prediction_mode()
852 }
853 #[inline]
854 fn update_cost(
855 &mut self,
856 stride_prior: [u8; 8],
857 stride_prior_offset: usize,
858 selected_bits: u8,
859 cm_prior: usize,
860 literal: u8,
861 ) {
862 let level = self.level;
864 dispatch!(level, simd => self.update_cost_base(
865 simd,
866 stride_prior,
867 stride_prior_offset,
868 selected_bits,
869 cm_prior,
870 literal,
871 ))
872 }
873}
874
875impl<'a, 'b, Alloc: alloc::Allocator<s16> + alloc::Allocator<u32> + alloc::Allocator<v8>>
876 interface::CommandProcessor<'b> for PriorEval<'a, Alloc>
877{
878 #[inline]
879 fn push(&mut self, val: interface::Command<InputReference<'b>>) {
880 push_base(self, val)
881 }
882}