arithmetic-coding 0.5.0

fast and flexible arithmetic coding library
Documentation
use std::ops::Range;

use arithmetic_coding_core::BitStore;

use crate::Model;

#[derive(Debug)]
pub struct State<B: BitStore> {
    pub precision: u32,
    pub low: B,
    pub high: B,
}

impl<B> State<B>
where
    B: BitStore,
{
    pub fn new(precision: u32) -> Self {
        let low = B::ZERO;
        let high = (B::ONE << precision) - B::ONE;

        Self {
            precision,
            low,
            high,
        }
    }

    pub fn half(&self) -> B {
        B::ONE << (self.precision - 1)
    }

    pub fn quarter(&self) -> B {
        B::ONE << (self.precision - 2)
    }

    pub fn three_quarter(&self) -> B {
        self.half() + self.quarter()
    }

    pub fn scale(&mut self, p: Range<B>, denominator: B) {
        let range = self.high - self.low + B::ONE;

        self.high = self.low + (range * p.end) / denominator - B::ONE;
        self.low += (range * p.start) / denominator;
    }
}

pub fn assert_precision_sufficient<M: Model>(max_denominator: M::B, precision: u32) {
    let frequency_bits = max_denominator.log2() + 1;
    assert!(
        (precision >= (frequency_bits + 2)),
        "not enough bits of precision to prevent overflow/underflow",
    );
    assert!(
        (frequency_bits + precision) <= M::B::BITS,
        "not enough bits in BitStore to support the required precision",
    );
}