-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement order-n parametrizable model & binary (#13)
I'll add & analyze results later
- Loading branch information
Showing
7 changed files
with
181 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,3 +37,9 @@ name = "order0" | |
|
||
[[bin]] | ||
name = "ac-over-huffman" | ||
|
||
[[bin]] | ||
name = "cmp" | ||
|
||
[[bin]] | ||
name = "ordern" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
use std::{ | ||
fs::File, | ||
io::{BufWriter, Result}, | ||
time::Instant, | ||
}; | ||
|
||
use weath3rb0i::{ | ||
entropy_coding::{arithmetic_coder::ArithmeticCoder, io::ACWriter}, | ||
helpers::cmp, | ||
models::{Model, Order0, OrderN}, | ||
unroll_for, | ||
}; | ||
|
||
fn main() -> Result<()> { | ||
let model = Order0::new(); | ||
exec(model, "order0")?; | ||
|
||
let model = OrderN::new(11, 3); | ||
exec(model, "ordern")?; | ||
|
||
cmp("order0.bin", "ordern.bin")?; | ||
|
||
Ok(()) | ||
} | ||
|
||
fn exec(mut model: impl Model, name: &str) -> Result<()> { | ||
let timer = Instant::now(); | ||
let buf = std::fs::read("/Users/mitiko/_data/enwik7")?; | ||
let mut ac = ArithmeticCoder::new_coder(); | ||
let file = File::create(format!("{}.bin", name))?; | ||
let mut writer = ACWriter::new(BufWriter::new(&file)); | ||
|
||
for byte in &buf { | ||
unroll_for!(bit in byte, { | ||
let p = model.predict(); | ||
model.update(bit); | ||
ac.encode(bit, p, &mut writer)?; | ||
}); | ||
} | ||
ac.flush(&mut writer)?; | ||
|
||
let res = File::metadata(&file)?.len(); | ||
let time = timer.elapsed(); | ||
println!( | ||
"[{}] csize: {} (ratio: {:.3}), ctime: {:?} ({:?} per bit)", | ||
name, | ||
res, | ||
res as f64 / buf.len() as f64, | ||
time, | ||
time.div_f64(buf.len() as f64 * 8.0) | ||
); | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
use std::{io::Result, time::Instant}; | ||
use weath3rb0i::{ | ||
entropy_coding::arithmetic_coder::ArithmeticCoder, | ||
helpers::ACStats, | ||
models::{Model, OrderN}, | ||
u64, unroll_for, | ||
}; | ||
|
||
fn main() -> Result<()> { | ||
let buf = std::fs::read("/Users/mitiko/_data/book1")?; | ||
|
||
let levels = 2; | ||
let mut best = vec![u64!(buf.len()); levels]; | ||
let mut params = vec![(0, 0); levels]; | ||
|
||
for ctx_bits in 8..=26 { | ||
best[1] = u64!(buf.len()); | ||
params[1] = (0, 0); | ||
for alignment_bits in 0..=4 { | ||
let res = exec(&buf, ctx_bits, alignment_bits)?; | ||
for i in 0..levels { | ||
if res > best[i] { | ||
continue; | ||
} | ||
best[i] = res; | ||
params[i] = (ctx_bits, alignment_bits); | ||
} | ||
} | ||
println!( | ||
"-> best: {} for [ctx: {}, align: {}]", | ||
best[1], params[1].0, params[1].1 | ||
); | ||
} | ||
println!( | ||
"-> gloabl best: {} for [ctx: {}, align: {}]", | ||
best[0], params[0].0, params[0].1 | ||
); | ||
|
||
Ok(()) | ||
} | ||
|
||
fn exec(buf: &[u8], ctx_bits: u8, alignment_bits: u8) -> Result<u64> { | ||
let timer = Instant::now(); | ||
let mut ac = ArithmeticCoder::new_coder(); | ||
let mut model = OrderN::new(ctx_bits, alignment_bits); | ||
let mut writer = ACStats::new(); | ||
|
||
for &byte in buf { | ||
unroll_for!(bit in byte, { | ||
let p = model.predict(); | ||
model.update(bit); | ||
ac.encode(bit, p, &mut writer)?; | ||
}); | ||
} | ||
ac.flush(&mut writer)?; | ||
|
||
let time = timer.elapsed(); | ||
println!( | ||
"[ordern] [ctx: {:2} align: {}] csize: {} (ratio: {:.3}), ctime: {:?} ({:?} per bit)", | ||
ctx_bits, | ||
alignment_bits, | ||
writer.result(), | ||
writer.result() as f64 / buf.len() as f64, | ||
time, | ||
time.div_f64(buf.len() as f64 * 8.0) | ||
); | ||
|
||
Ok(writer.result()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
use super::{counter::Counter, Model}; | ||
use crate::usize; | ||
|
||
pub struct OrderN { | ||
stats: Vec<Counter>, | ||
ctx: u32, | ||
history: u32, | ||
alignment: u8, | ||
bits_in_context: u8, | ||
alignment_bits: u8, | ||
} | ||
|
||
impl OrderN { | ||
pub fn new(bits_in_context: u8, alignment_bits: u8) -> Self { | ||
Self { | ||
stats: vec![Counter::new(); 1 << bits_in_context], | ||
ctx: 0, | ||
history: 0, | ||
alignment: 0, | ||
bits_in_context, | ||
alignment_bits, | ||
} | ||
} | ||
} | ||
|
||
impl Model for OrderN { | ||
fn predict(&self) -> u16 { | ||
self.stats[usize!(self.ctx)].p() | ||
} | ||
|
||
fn update(&mut self, bit: u8) { | ||
self.stats[usize!(self.ctx)].update(bit); | ||
|
||
let mask_bits = self.bits_in_context - self.alignment_bits; | ||
let mask = (1 << mask_bits) - 1; | ||
let alignment_mask = (1 << self.alignment_bits) - 1; | ||
|
||
self.history = ((self.history << 1) | u32::from(bit)) & mask; | ||
self.alignment = (self.alignment + 1) & alignment_mask; | ||
self.ctx = (self.history << self.alignment_bits) | u32::from(self.alignment) | ||
} | ||
} |