#![allow(dead_code)]
pub const INTRA_MODE_CDF_LEN: usize = 14;
pub static DEFAULT_INTRA_MODE_CDF: [u16; INTRA_MODE_CDF_LEN] = [
30247, 27726, 25206, 22685, 20164, 17644, 15123, 12603, 10082, 7561, 5041, 2520, 0, 0, ];
pub const PARTITION_CDF_LEN: usize = 5;
pub static DEFAULT_PARTITION_CDF: [u16; PARTITION_CDF_LEN] = [
24576, 16384, 8192, 0, 0, ];
pub const SKIP_CDF_LEN: usize = 3;
pub static DEFAULT_SKIP_CDF: [u16; SKIP_CDF_LEN] = [
16384, 0, 0, ];
pub const TX_TYPE_CDF_LEN: usize = 10;
pub static DEFAULT_TX_TYPE_CDF: [u16; TX_TYPE_CDF_LEN] = [
29127, 25486, 21845, 18204, 14563, 10922, 7281, 3640, 0, 0, ];
pub const COEFF_BASE_CDF_LEN: usize = 5;
pub static DEFAULT_COEFF_BASE_CDF: [u16; COEFF_BASE_CDF_LEN] = [
24576, 16384, 8192, 0, 0, ];
pub const EOB_PT_CDF_LEN: usize = 6;
pub static DEFAULT_EOB_PT_CDF: [u16; EOB_PT_CDF_LEN] = [
26214, 19660, 13107, 6553, 0, 0, ];
pub const DC_SIGN_CDF_LEN: usize = 3;
pub static DEFAULT_DC_SIGN_CDF: [u16; DC_SIGN_CDF_LEN] = [
16384, 0, 0, ];
pub const GOLOMB_CDF_LEN: usize = 3;
pub static DEFAULT_GOLOMB_CDF: [u16; GOLOMB_CDF_LEN] = [
16384, 0, 0, ];
pub const NONZERO_CDF_LEN: usize = 3;
pub static DEFAULT_NONZERO_CDF: [u16; NONZERO_CDF_LEN] = [
16384, 0, 0, ];
pub const SIGN_CDF_LEN: usize = 3;
pub static DEFAULT_SIGN_CDF: [u16; SIGN_CDF_LEN] = [
16384, 0, 0, ];
pub const MAG_CLASS_CDF_LEN: usize = 13;
pub const MAG_CLASS_SYMS: usize = MAG_CLASS_CDF_LEN - 1;
pub const K_MAX: usize = MAG_CLASS_SYMS - 1;
pub static DEFAULT_MAG_CLASS_CDF: [u16; MAG_CLASS_CDF_LEN] = [
30037, 27306, 24576, 21845, 19114, 16384, 13653, 10922, 8192, 5461, 2730, 0, 0, ];
pub fn update_cdf(cdf: &mut [u16], sym: usize, nsymbs: usize) {
debug_assert!(cdf.len() >= nsymbs, "CDF slice too short");
debug_assert!(sym + 1 < nsymbs, "symbol index out of range");
let count = cdf[nsymbs - 1] as usize;
let n_syms = nsymbs - 1; let log2_n = (usize::BITS - n_syms.leading_zeros()) as usize - 1;
let rate = 3 + (count > 15) as usize + (count > 31) as usize + log2_n.min(2);
for (i, entry) in cdf.iter_mut().enumerate().take(n_syms - 1) {
if i < sym {
*entry -= *entry >> rate;
} else {
*entry += (32768u16 - *entry) >> rate;
}
}
if count < 32 {
cdf[nsymbs - 1] = (count + 1) as u16;
}
}
pub fn clone_cdf<const N: usize>(src: &[u16; N]) -> [u16; N] {
*src
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn intra_mode_cdf_length() {
assert_eq!(DEFAULT_INTRA_MODE_CDF.len(), INTRA_MODE_CDF_LEN);
assert_eq!(INTRA_MODE_CDF_LEN, 14, "13 symbols + 1 count slot");
}
#[test]
fn intra_mode_cdf_count_slot_zero() {
assert_eq!(
DEFAULT_INTRA_MODE_CDF[INTRA_MODE_CDF_LEN - 1], 0,
"count slot must start at 0"
);
}
#[test]
fn intra_mode_cdf_strictly_decreasing() {
for i in 0..INTRA_MODE_CDF_LEN - 2 {
assert!(
DEFAULT_INTRA_MODE_CDF[i] > DEFAULT_INTRA_MODE_CDF[i + 1],
"CDF not strictly decreasing at index {i}"
);
}
}
#[test]
fn skip_cdf_is_50_50() {
assert_eq!(DEFAULT_SKIP_CDF[0], 16384);
assert_eq!(DEFAULT_SKIP_CDF[1], 0);
assert_eq!(DEFAULT_SKIP_CDF[2], 0); }
#[test]
fn all_count_slots_zero() {
assert_eq!(DEFAULT_PARTITION_CDF[PARTITION_CDF_LEN - 1], 0);
assert_eq!(DEFAULT_SKIP_CDF[SKIP_CDF_LEN - 1], 0);
assert_eq!(DEFAULT_TX_TYPE_CDF[TX_TYPE_CDF_LEN - 1], 0);
assert_eq!(DEFAULT_COEFF_BASE_CDF[COEFF_BASE_CDF_LEN - 1], 0);
assert_eq!(DEFAULT_EOB_PT_CDF[EOB_PT_CDF_LEN - 1], 0);
assert_eq!(DEFAULT_DC_SIGN_CDF[DC_SIGN_CDF_LEN - 1], 0);
assert_eq!(DEFAULT_GOLOMB_CDF[GOLOMB_CDF_LEN - 1], 0);
assert_eq!(DEFAULT_NONZERO_CDF[NONZERO_CDF_LEN - 1], 0);
assert_eq!(DEFAULT_SIGN_CDF[SIGN_CDF_LEN - 1], 0);
assert_eq!(DEFAULT_MAG_CLASS_CDF[MAG_CLASS_CDF_LEN - 1], 0);
}
#[test]
fn new_coeff_cdfs_correct_length_and_terminator() {
assert_eq!(DEFAULT_NONZERO_CDF.len(), NONZERO_CDF_LEN);
assert_eq!(DEFAULT_SIGN_CDF.len(), SIGN_CDF_LEN);
assert_eq!(DEFAULT_MAG_CLASS_CDF.len(), MAG_CLASS_CDF_LEN);
assert_eq!(DEFAULT_NONZERO_CDF[NONZERO_CDF_LEN - 2], 0);
assert_eq!(DEFAULT_SIGN_CDF[SIGN_CDF_LEN - 2], 0);
assert_eq!(DEFAULT_MAG_CLASS_CDF[MAG_CLASS_CDF_LEN - 2], 0);
assert_eq!(MAG_CLASS_SYMS, 12);
assert_eq!(K_MAX, 11);
}
#[test]
fn mag_class_cdf_strictly_decreasing_in_prob_region() {
for i in 0..MAG_CLASS_CDF_LEN - 3 {
assert!(
DEFAULT_MAG_CLASS_CDF[i] > DEFAULT_MAG_CLASS_CDF[i + 1],
"MAG_CLASS CDF not decreasing at index {i}"
);
}
}
#[test]
fn update_cdf_symbol_0_increases_probability() {
let mut cdf = DEFAULT_SKIP_CDF;
let initial_cdf0 = cdf[0];
for _ in 0..50 {
update_cdf(&mut cdf, 0, SKIP_CDF_LEN);
}
assert!(
cdf[0] > initial_cdf0,
"cdf[0] should increase after many symbol-0 observations: \
initial={initial_cdf0} final={}",
cdf[0]
);
}
#[test]
fn update_cdf_symbol_1_decreases_cdf0() {
let mut cdf = DEFAULT_SKIP_CDF;
let initial_cdf0 = cdf[0];
for _ in 0..50 {
update_cdf(&mut cdf, 1, SKIP_CDF_LEN);
}
assert!(
cdf[0] < initial_cdf0,
"cdf[0] should decrease after many symbol-1 observations: \
initial={initial_cdf0} final={}",
cdf[0]
);
}
#[test]
fn update_cdf_count_saturates_at_32() {
let mut cdf = DEFAULT_SKIP_CDF;
for _ in 0..100 {
update_cdf(&mut cdf, 0, SKIP_CDF_LEN);
}
assert_eq!(
cdf[SKIP_CDF_LEN - 1],
32,
"count slot must saturate at 32"
);
}
#[test]
fn update_cdf_values_stay_in_range() {
let mut cdf = clone_cdf(&DEFAULT_INTRA_MODE_CDF);
for sym in (0..13usize).cycle().take(200) {
update_cdf(&mut cdf, sym, INTRA_MODE_CDF_LEN);
for (i, &v) in cdf[..13].iter().enumerate() {
assert!(
v <= 32768,
"CDF entry {i} exceeded 32768: {v}"
);
}
}
}
#[test]
fn update_cdf_values_bounded_after_updates() {
let mut cdf = clone_cdf(&DEFAULT_INTRA_MODE_CDF);
let symbols: [usize; 20] = [0, 3, 7, 12, 1, 6, 11, 2, 5, 10, 4, 9, 8, 0, 0, 12, 12, 6, 6, 6];
for &sym in &symbols {
update_cdf(&mut cdf, sym, INTRA_MODE_CDF_LEN);
}
for (i, &v) in cdf[..13].iter().enumerate() {
assert!(
v <= 32768,
"CDF entry {i} out of bounds after updates: {v}"
);
}
assert!(
cdf[INTRA_MODE_CDF_LEN - 1] > 0,
"count slot should be > 0 after updates, got {}",
cdf[INTRA_MODE_CDF_LEN - 1]
);
}
#[test]
fn update_cdf_frequent_symbol_gains_probability() {
let mut cdf = clone_cdf(&DEFAULT_INTRA_MODE_CDF);
let initial_cdf6 = cdf[6];
for _ in 0..40 {
update_cdf(&mut cdf, 6, INTRA_MODE_CDF_LEN);
}
assert!(
cdf[6] > initial_cdf6,
"cdf[6] should increase after many observations of symbol 6: \
initial={initial_cdf6} final={}",
cdf[6]
);
}
#[test]
fn clone_cdf_produces_equal_copy() {
let original = DEFAULT_INTRA_MODE_CDF;
let copy = clone_cdf(&original);
assert_eq!(original, copy);
let mut mutable_copy = copy;
mutable_copy[0] = 0;
assert_eq!(mutable_copy[0], 0, "mutable copy should reflect the write");
assert_ne!(original[0], 0, "original should be unchanged after modifying copy");
}
}