Skip to main content

simd_brotli/enc/
prior_eval.rs

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
16// the high nibble, followed by the low nibbles
17pub 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    //    STRIDE8 = 8,
32    NUM_PRIORS = 8,
33    // future ideas
34}
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}
141/*impl StridePrior for Stride1Prior {
142    const STRIDE_OFFSET:usize = 0;
143}*/
144pub 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}
167/*impl StridePrior for Stride2Prior {
168    const STRIDE_OFFSET:usize = 1;
169}*/
170pub 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
194/*impl StridePrior for Stride3Prior {
195    const STRIDE_OFFSET:usize = 2;
196}*/
197pub 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
220/*impl StridePrior for Stride4Prior {
221    const STRIDE_OFFSET:usize = 3;
222}*/
223/*pub struct Stride8Prior{
224}
225impl StridePrior for Stride8Prior {
226    const STRIDE_OFFSET:usize = 7;
227}
228impl Stride8Prior {
229    #[inline(always)]
230    pub fn offset() -> usize{
231        7
232    }
233}
234impl Prior for Stride8Prior {
235    fn lookup_lin(stride_byte:u8, selected_context:u8, actual_context:usize, high_nibble: Option<u8>) -> usize {
236        stride_lookup_lin(stride_byte, selected_context, actual_context, high_nibble)
237    }
238    #[inline]
239    fn which() -> usize {
240      WhichPrior::STRIDE8 as usize
241    }
242}
243*/
244pub 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        // Bump every bucket at or above the coded nibble.
359        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            // Renormalize: scale the whole cdf down by 3/4, biased to keep it monotonic.
364            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    /// Detected once, so the per-literal cost update doesn't have to probe the CPU.
397    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                /*if do_alloc {m16x16.alloc_cell(STRIDE_PRIOR_SIZE)} else {
453                Alloc16x16::AllocatedMemory::default()},*/
454            ],
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.stride_priors[4].slice_mut());
470        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 = score[WhichPrior::STRIDE8] * 1.125 + 16.0;
489            let stride8_score = stride4_score + 1.0; // FIXME: never lowest -- ignore stride 8
490            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                    //bitmask[i] = WhichPrior::STRIDE8 as u8;
521                }
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                //eprintln!("Miss {}[{}] ~ {}", bitmask[i], i, max_popularity_index);
540            } 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                //eprintln!("Score {} {} {} {} {}: {}[{}] max={},{}", cm_score, adv_score, slow_cm_score, fast_cm_score, stride_score, bitmask[i], i, max_popularity, max_popularity_index);
547            }
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::replace(&mut self.stride_priors[4], alloc_default::<s16, Alloc>()));
561        <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        /*       {
774                   type CurPrior = Stride8Prior;
775                   let mut cdf = CurPrior::lookup_mut(self.stride_priors[4].slice_mut(),
776                                                      stride_prior[stride_prior_offset.wrapping_sub(CurPrior::offset())&7], selected_bits, cm_prior, None);
777                   h_score.as_mut_slice()[CurPrior::which()] = cdf.cost(literal>>4);
778                   cdf.update(literal >> 4, self.stride_speed[1]);
779               }
780               {
781                   type CurPrior = Stride8Prior;
782                   let mut cdf = CurPrior::lookup_mut(self.stride_priors[4].slice_mut(),
783                                                      stride_prior[stride_prior_offset.wrapping_sub(CurPrior::offset()) & 7],
784                                                      selected_bits,
785                                                      cm_prior,
786                                                      Some(literal >> 4));
787                   l_score.as_mut_slice()[CurPrior::which()] = cdf.cost(literal&0xf);
788                   cdf.update(literal&0xf, self.stride_speed[0]);
789               }
790        */
791        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 stride = self.cur_stride as usize;
863        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}