Skip to content

Instantly share code, notes, and snippets.

@mocobeta
Created December 13, 2020 04:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mocobeta/39465e0d7cbf2e67c22b08c739c36183 to your computer and use it in GitHub Desktop.
Save mocobeta/39465e0d7cbf2e67c22b08c739c36183 to your computer and use it in GitHub Desktop.
golomb code in Rust
// https://crates.io/crates/bit-vec
use bit_vec::BitVec;
pub fn encode_golomb(li: &[usize], m: u32) -> BitVec {
fn encode_quotient(k: usize, m: u32) -> BitVec {
let q: usize = (((k - 1) / m as usize) as f64).floor() as usize;
// encode (quotient + 1) in unary code
let mut bv = BitVec::from_elem(q + 1, false);
bv.set(q, true);
bv
}
fn encode_remainder(k: usize, m: u32) -> BitVec {
let rem = (k - 1) % m as usize;
// encode remainder in truncated binary code
let bound = ((2u32.pow((m as f64).log2().ceil() as u32)) - m) as usize;
let nbits = if rem < bound {
(m as f64).log2().floor() as usize
} else {
(m as f64).log2().ceil() as usize
};
let mut bv = BitVec::from_elem(nbits, false);
let rem_bv = if rem < bound {
BitVec::from_bytes(&rem.to_be_bytes())
} else {
BitVec::from_bytes(&(rem + bound).to_be_bytes())
};
let mut pos: usize = 0;
for i in (rem_bv.len() - nbits)..rem_bv.len() {
if let Some(b) = rem_bv.get(i) {
bv.set(pos, b);
pos += 1;
}
}
bv
}
fn encode(k: usize, m: u32) -> BitVec {
let mut bv = encode_quotient(k, m);
let rem_bv = encode_remainder(k, m);
let mut pos = bv.len();
bv.grow(rem_bv.len(), false);
for bit in rem_bv.iter() {
bv.set(pos, bit);
pos += 1;
}
bv
}
let mut bv_all = BitVec::new();
for &k in li {
let bv = encode(k, m);
let mut offset = bv_all.len();
bv_all.grow(bv.len(), false);
for bit in bv.iter() {
bv_all.set(offset, bit);
offset += 1;
}
}
bv_all
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment