use crate::prefix::golomb;
use crate::prefix::unary;
use deepmesa_collections::bitvec::bitvec::BitVector;
use deepmesa_collections::bitvec::BitOrder;
pub struct GolombEncoder {
pub(super) bitvec: BitVector,
pub(super) elements: usize,
pub(super) b: u128,
pub(super) c: usize,
pub(super) u: u128,
}
pub struct GolombDecoder<'a> {
pub(super) bitvec: &'a BitVector,
pub(super) cursor: usize,
pub(super) b: u128,
pub(super) c: usize,
pub(super) u: u128,
}
impl GolombEncoder {
pub fn new(param: u128) -> GolombEncoder {
let c = (param as f64).log2() as usize;
let u = 2u128.pow((c + 1) as u32) - param;
GolombEncoder {
bitvec: BitVector::with_capacity(1024),
elements: 0,
b: param,
c,
u,
}
}
pub fn encode(&mut self, val: u128) {
let q = (val - 1) / self.b;
let r = val - (q * self.b) - 1;
unary::encode(&mut self.bitvec, q);
if r < self.u {
self.bitvec.push_bits_u128(r, self.c, BitOrder::Lsb0);
} else {
self.bitvec
.push_bits_u128(r + self.u, (self.c + 1) as usize, BitOrder::Lsb0);
}
self.elements += 1;
}
pub fn encoded(&self) -> &BitVector {
&self.bitvec
}
pub fn encoded_len(&self) -> usize {
self.bitvec.len()
}
pub fn elements(&self) -> usize {
self.elements
}
pub fn comp_ratio(&self) -> f64 {
self.bitvec.len() as f64 / self.elements as f64
}
}
impl<'a> GolombDecoder<'a> {
pub fn new(bitvec: &'a BitVector, param: u128) -> GolombDecoder {
let c = (param as f64).log2() as usize;
let u = 2u128.pow((c + 1) as u32) - param;
GolombDecoder {
bitvec: bitvec,
cursor: 0,
b: param,
c,
u,
}
}
pub fn decode(&mut self) -> Option<u128> {
match decode(&self.bitvec, self.cursor, self.b, self.c, self.u) {
None => None,
Some((val, bits_read)) => {
self.cursor += bits_read;
Some(val)
}
}
}
pub fn decode_many(&self, max_elements: usize) -> Vec<u128> {
let mut vec = Vec::<u128>::with_capacity(max_elements);
let mut ct = 0;
let mut iter = self.iter();
loop {
match iter.next() {
None => return vec,
Some(val) => {
vec.push(val);
ct += 1;
if ct >= max_elements {
return vec;
}
}
}
}
}
pub fn iter(&self) -> GolombDecodingIterator {
GolombDecodingIterator::<'a>::new(self.bitvec, self.b)
}
}
pub struct GolombDecodingIterator<'a> {
pub(super) bitvec: &'a BitVector,
pub(super) cursor: usize,
pub(super) b: u128,
pub(super) c: usize,
pub(super) u: u128,
}
impl<'a> GolombDecodingIterator<'a> {
pub(super) fn new(bitvec: &'a BitVector, param: u128) -> GolombDecodingIterator<'a> {
let c = (param as f64).log2() as usize;
let u = 2u128.pow((c + 1) as u32) - param;
GolombDecodingIterator {
bitvec,
cursor: 0,
b: param,
c,
u,
}
}
}
impl<'a> Iterator for GolombDecoder<'a> {
type Item = u128;
fn next(&mut self) -> Option<Self::Item> {
self.decode()
}
}
impl<'a> Iterator for GolombDecodingIterator<'a> {
type Item = u128;
fn next(&mut self) -> Option<Self::Item> {
match golomb::decode(self.bitvec, self.cursor, self.b, self.c, self.u) {
None => None,
Some((val, bits_read)) => {
self.cursor += bits_read;
Some(val)
}
}
}
}
pub(super) fn decode(
bitvec: &BitVector,
index: usize,
b: u128,
c: usize,
u: u128,
) -> Option<(u128, usize)> {
match unary::decode(bitvec, index) {
None => return None,
Some((q, unary_bits)) => {
let cursor = index + unary_bits;
match bitvec.get(cursor) {
None => panic!("invalid input. Expected valid bit at index {}", cursor),
Some(true) => {
let (r, read_bits) = bitvec.read_bits_u128(cursor, c + 1);
return Some((q * b + r - u + 1, unary_bits + read_bits));
}
Some(false) => {
let (r, read_bits) = bitvec.read_bits_u128(cursor, c);
return Some((q * b + r + 1, unary_bits + read_bits));
}
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_encode_decode() {
let param = 6;
let mut ge = GolombEncoder::new(param);
ge.encode(9);
ge.encode(13);
let mut gd = GolombDecoder::new(ge.encoded(), param);
assert_eq!(gd.decode(), Some(9));
assert_eq!(gd.decode(), Some(13));
}
}