use super::range_coder::Encoder;
const PROB_PRICES: [u32; 512] = build_prob_prices();
const NUM_BITS: i32 = 9;
const fn build_prob_prices() -> [u32; 512] {
let mut table = [0u32; 512];
let mut i = NUM_BITS - 1;
while i >= 0 {
let start = 1u32 << (NUM_BITS - i - 1);
let end = 1u32 << (NUM_BITS - i);
let mut j = start;
while j < end {
table[j as usize] = ((i as u32) << 6) + (((end - j) << 6) >> (NUM_BITS - i - 1));
j += 1;
}
i -= 1;
}
table
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct BitEncoder {
prob: u32,
}
impl BitEncoder {
pub const NUM_BIT_MODEL_TOTAL_BITS: i32 = 11;
pub const BIT_MODEL_TOTAL: u32 = 1 << Self::NUM_BIT_MODEL_TOTAL_BITS;
pub const NUM_MOVE_BITS: i32 = 5;
pub const NUM_MOVE_REDUCING_BITS: i32 = 2;
pub const NUM_BIT_PRICE_SHIFT_BITS: i32 = 6;
pub fn new() -> Self {
Self::default()
}
pub fn init(&mut self) {
self.prob = Self::BIT_MODEL_TOTAL >> 1;
}
pub fn prob(&self) -> u32 {
self.prob
}
pub fn update_model(&mut self, symbol: u32) {
if symbol == 0 {
self.prob += (Self::BIT_MODEL_TOTAL - self.prob) >> Self::NUM_MOVE_BITS;
} else {
self.prob -= self.prob >> Self::NUM_MOVE_BITS;
}
}
pub fn encode(&mut self, encoder: &mut Encoder, symbol: u32) {
let new_bound = (encoder.range >> Self::NUM_BIT_MODEL_TOTAL_BITS) * self.prob;
if symbol == 0 {
encoder.range = new_bound;
self.prob += (Self::BIT_MODEL_TOTAL - self.prob) >> Self::NUM_MOVE_BITS;
} else {
encoder.low = encoder.low.wrapping_add(new_bound as u64);
encoder.range -= new_bound;
self.prob -= self.prob >> Self::NUM_MOVE_BITS;
}
if encoder.range < Encoder::TOP_VALUE {
encoder.range <<= 8;
encoder.shift_low();
}
}
pub fn get_price(&self, symbol: u32) -> u32 {
let index = (self.prob.wrapping_sub(symbol) ^ ((symbol as i32).wrapping_neg() as u32))
& (Self::BIT_MODEL_TOTAL - 1);
PROB_PRICES[(index >> Self::NUM_MOVE_REDUCING_BITS) as usize]
}
pub fn get_price0(&self) -> u32 {
PROB_PRICES[(self.prob >> Self::NUM_MOVE_REDUCING_BITS) as usize]
}
pub fn get_price1(&self) -> u32 {
PROB_PRICES[((Self::BIT_MODEL_TOTAL - self.prob) >> Self::NUM_MOVE_REDUCING_BITS) as usize]
}
}