use crate::error::Error;
const SYMBOLS: usize = 314;
const NODES: usize = 2 * SYMBOLS - 1; const ROOT: usize = NODES - 1; const RESCALE: u32 = 0x8000;
pub struct Tree {
freq: [u32; NODES + 1],
son: [u16; NODES],
parent: [u16; NODES + SYMBOLS],
leaf_index: [u16; SYMBOLS],
}
impl Tree {
pub fn new() -> Self {
let mut t = Tree {
freq: [0; NODES + 1],
son: [0; NODES],
parent: [0; NODES + SYMBOLS],
leaf_index: [0; SYMBOLS],
};
for i in 0..SYMBOLS {
t.freq[i] = 1;
t.son[i] = (i + NODES) as u16; t.parent[i + NODES] = i as u16; t.leaf_index[i] = i as u16;
}
let mut i = 0usize;
let mut j = SYMBOLS;
while j < NODES {
t.freq[j] = t.freq[i] + t.freq[i + 1];
t.son[j] = i as u16; t.parent[i] = j as u16;
t.parent[i + 1] = j as u16;
i += 2;
j += 1;
}
t.freq[NODES] = 0xFFFF;
t
}
pub fn decode_symbol<F: FnMut() -> u32>(&self, mut read_bit: F) -> Result<u16, Error> {
let mut c = self.son[ROOT] as usize;
let mut steps = 0usize;
loop {
if c >= NODES {
return Err(Error::Corrupt);
}
let bit = read_bit();
let node = if bit == 0 { c } else { c + 1 };
if node >= NODES {
return Err(Error::Corrupt);
}
let s = self.son[node] as usize;
if s >= NODES {
return Ok((s - NODES) as u16);
}
c = s;
steps += 1;
if steps > NODES {
return Err(Error::Corrupt);
}
}
}
pub fn update(&mut self, symbol: u16) {
if self.freq[ROOT] >= RESCALE {
self.rebuild();
}
let mut c = self.leaf_index[symbol as usize] as usize;
loop {
self.freq[c] += 1;
let f = self.freq[c];
if c + 1 < NODES && f > self.freq[c + 1] {
let mut l = c + 1;
while f > self.freq[l + 1] {
l += 1;
}
self.swap_nodes(c, l);
c = l;
}
if c == ROOT {
break;
}
c = self.parent[c] as usize;
}
}
fn swap_nodes(&mut self, a: usize, b: usize) {
if a == b {
return;
}
self.freq.swap(a, b);
self.son.swap(a, b);
self.fix_links(a);
self.fix_links(b);
}
fn fix_links(&mut self, s: usize) {
let son = self.son[s] as usize;
if son >= NODES {
self.parent[son] = s as u16;
self.leaf_index[son - NODES] = s as u16;
} else {
self.parent[son] = s as u16;
self.parent[son + 1] = s as u16;
}
}
fn rebuild(&mut self) {
let mut j = 0usize;
for i in 0..NODES {
if self.son[i] as usize >= NODES {
self.freq[j] = self.freq[i].div_ceil(2);
self.son[j] = self.son[i];
j += 1;
}
}
debug_assert_eq!(j, SYMBOLS);
let mut f = 0usize; let mut i = SYMBOLS; while i < NODES {
let sum = self.freq[f] + self.freq[f + 1];
let mut k = i - 1;
while sum < self.freq[k] {
if k == 0 {
break;
}
k -= 1;
}
let insert_at = if sum < self.freq[k] { k } else { k + 1 };
let mut m = i;
while m > insert_at {
self.freq[m] = self.freq[m - 1];
self.son[m] = self.son[m - 1];
m -= 1;
}
self.freq[insert_at] = sum;
self.son[insert_at] = f as u16;
f += 2;
i += 1;
}
for k in 0..SYMBOLS {
self.leaf_index[k] = 0;
}
for slot in 0..NODES {
let son = self.son[slot] as usize;
if son >= NODES {
self.parent[son] = slot as u16;
self.leaf_index[son - NODES] = slot as u16;
} else {
self.parent[son] = slot as u16;
self.parent[son + 1] = slot as u16;
}
}
self.freq[NODES] = 0xFFFF;
}
}