use super::{
CTX_ONE_STATE, EXP_ESCAPE, INT_BITS, Model, SS, STATE_SIZE, hi_bits_flag3, update_prob_1,
};
use crate::error::Result;
use crate::rc::{RangeEncoder, internal};
impl Model {
#[inline(always)]
pub fn encode_symbol<E: RangeEncoder>(&mut self, rc: &mut E, sym: Option<u8>) -> Result<()> {
self.encode_char(rc, sym.map_or(crate::SYM_END, i32::from));
if rc.faulted() {
return Err(internal("frequency total exceeds the encoder's range"));
}
Ok(())
}
#[allow(dead_code)] pub(crate) fn encode_bytes<E: RangeEncoder>(&mut self, rc: &mut E, data: &[u8]) -> Result<()> {
for &byte in data {
self.encode_symbol(rc, Some(byte))?;
}
Ok(())
}
#[inline(always)]
fn encode_char<E: RangeEncoder>(&mut self, rc: &mut E, symbol: i32) {
let entry_order_fall = self.order_fall;
let mut char_mask: [u8; 256];
let mc = self.min_context;
let ns = self.num_stats(mc);
if ns != 1 {
let mut s = self.stats(mc);
let summ_freq = self.summ_freq(mc);
if self.sym(s) as i32 == symbol {
rc.encode(0, self.freq(s), summ_freq);
self.found_state = s;
self.update1_0();
return;
}
self.prev_success = 0;
let mut sum = self.freq(s);
let mut p = s as usize;
let last = p + (ns as usize - 1) * SS;
while p != last {
p += SS;
if self.sym_at(p) as i32 == symbol {
rc.encode(sum, self.freq_at(p), summ_freq);
self.found_state = p as u32;
self.update1();
return;
}
sum += self.freq_at(p);
}
s = p as u32;
rc.encode(sum, summ_freq - sum, summ_freq);
self.hi_bits_flag = hi_bits_flag3(self.sym(self.found_state));
char_mask = [u8::MAX; 256];
self.mask_symbols(&mut char_mask, s, self.stats(mc));
} else {
let s = mc + CTX_ONE_STATE;
let (row, col) = self.bin_summ_index();
let pr = self.bin_summ[row][col] as u32;
if self.sym(s) as i32 == symbol {
self.bin_summ[row][col] = (update_prob_1(pr) + (1 << INT_BITS)) as u16;
rc.encode_bit(pr, 0);
self.update_bin(s);
return;
}
let pr1 = update_prob_1(pr);
self.bin_summ[row][col] = pr1 as u16;
self.init_esc = EXP_ESCAPE[(pr1 >> 10) as usize] as u32;
rc.encode_bit(pr, 1);
char_mask = [u8::MAX; 256];
char_mask[self.sym(s) as usize] = 0;
self.prev_success = 0;
}
loop {
let mut mc = self.min_context;
let num_masked = self.num_stats(mc);
let mut i;
loop {
self.order_fall += 1;
let suffix = self.suffix(mc);
if suffix == 0 {
self.abandon_symbol(entry_order_fall);
return;
}
mc = suffix;
i = self.num_stats(mc);
if i != num_masked {
break;
}
}
self.min_context = mc;
let (see, esc_freq) = self.make_esc_freq(num_masked);
let stats = self.stats(mc);
let mut s = stats as usize;
let end = s + i as usize * SS;
let mut sum = 0u32;
while s < end {
let cur = self.sym_at(s);
if cur as i32 == symbol {
let low = sum;
let freq = self.freq_at(s);
self.see.get(see).update();
self.found_state = s as u32;
sum += esc_freq;
let i = ((end - s) / SS) as u32;
let odd = i & 1;
sum += freq & 0u32.wrapping_sub(odd);
s += odd as usize * SS;
while s < end {
let sym0 = self.sym_at(s);
let sym1 = self.sym_at(s + SS);
sum += self.freq_at(s) & char_mask[sym0 as usize] as u32;
sum += self.freq_at(s + SS) & char_mask[sym1 as usize] as u32;
s += 2 * SS;
}
rc.encode(low, freq, sum);
self.update2();
return;
}
sum += self.freq_at(s) & char_mask[cur as usize] as u32;
s += SS;
}
let s = s as u32;
let total = sum + esc_freq;
let cell = self.see.get(see);
cell.summ = (cell.summ as u32).wrapping_add(total) as u16;
rc.encode(sum, esc_freq, total);
self.mask_symbols(&mut char_mask, s - STATE_SIZE, stats);
}
}
}