Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
diegodox committed Jan 3, 2021
1 parent 0b96a71 commit 9773e13
Show file tree
Hide file tree
Showing 11 changed files with 266 additions and 343 deletions.
2 changes: 0 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,3 @@ edition = "2018"

[dependencies]
thiserror = "1.0.20"
log = "0.4.0"
env_logger = "0.7.1"
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
# range_coder_rust

Simple implimention of rangecoder in rust language.
Generic over probability models (eg. freq table) by `PModel(trait)`.

## Installation

Cargo.toml
Add dependency to your Cargo.toml

```toml
[dependencies]
range_coder = {git="https://github.com/diegodox/range_coder_rust.git", branch="carryless"}
```

## Example

You can run example by following command.

These examples use the default syntax for running examples, as found in the [Cargo documentation](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#examples).

```shell
cargo run --example sample_impl
```
126 changes: 126 additions & 0 deletions examples/sample_impl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
use range_coder::{decoder::Decoder, encoder::Encoder, pmodel::PModel};

#[derive(Clone, Copy, Debug)]
/// アルファベットの出現回数を示す構造体
struct AlphabetParam {
/// 文字の累積出現頻度
cum: u32,
/// 文字の出現頻度
c: u32,
}
struct FreqTable {
/// 全アルファベットの出現頻度
total_freq: u32,
/// アルファベットのパラメータを保持する配列
alphabet_params: Vec<AlphabetParam>,
}

impl PModel for FreqTable {
fn c_freq(&self, index: usize) -> u32 {
self.alphabet_params.get(index).unwrap().c
}
fn cum_freq(&self, index: usize) -> u32 {
self.alphabet_params.get(index).unwrap().cum
}
fn total_freq(&self) -> u32 {
self.total_freq
}
fn find_index(&self, decoder: &Decoder) -> usize {
let mut left = 0;
let mut right = self.alphabet_count() - 1;
let rfreq = (decoder.data() - decoder.range_coder().lower_bound())
/ decoder.range_coder().range_par_total(self.total_freq());
while left < right {
let mid = (left + right) / 2;
let mid_cum = self.cum_freq(mid + 1);
if mid_cum as u64 <= rfreq {
left = mid + 1;
} else {
right = mid;
}
}
left
}
}

impl FreqTable {
fn new(alphabet_count: usize) -> Self {
FreqTable {
total_freq: 0,
alphabet_params: vec![AlphabetParam { cum: 0, c: 0 }; alphabet_count],
}
}
fn alphabet_count(&self) -> usize {
self.alphabet_params.len()
}
fn add_alphabet_freq(&mut self, alphabet_index: usize) {
self.alphabet_params[alphabet_index].c += 1;
}
fn calc_cum(&mut self) {
self.total_freq = self
.alphabet_params
.iter_mut()
.fold(0, |cum_total, alphabet| {
alphabet.cum = cum_total;
cum_total + alphabet.c
})
}
}

fn main() {
// define test data
let test_data = vec![2, 1, 1, 4, 1, 4, 2, 1, 0, 1, 5, 9, 8, 7, 6, 5];

// create freq-table
let mut sd = FreqTable::new(10);
for &i in &test_data {
sd.add_alphabet_freq(i);
}
sd.calc_cum();
{
println!("FREQ TABLE");
for i in 0..sd.alphabet_params.len() {
println!("index:{}, c:{}, cum:{}", i, sd.c_freq(i), sd.cum_freq(i));
}
println!();
}

// encode
println!("ENCODING");
let mut encoder = Encoder::new();
print!("encode : ");
for &i in &test_data {
print!("{},", i);
encoder.encode::<FreqTable>(&sd, i);
}
let code = encoder.finish();
{
println!();
print!("output : 0x");
for i in &code {
print!("{:x}", i);
}
print!("\nlength : {}byte", code.len());
print!("\n\n");
}

// decode
let mut decoder = Decoder::new(code);
println!("DECODING");
print!("decode : ");
let decodeds = test_data
.iter()
.map(|_| {
let decoded = decoder.decode(&sd);
print!("{},", decoded);
decoded
})
.collect::<Vec<_>>();

// test
assert_eq!(decodeds, test_data);

println!();
println!();
println!("test passed🎉");
}
45 changes: 0 additions & 45 deletions src/alphabet_param.rs

This file was deleted.

53 changes: 14 additions & 39 deletions src/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,68 +4,43 @@ use crate::range_coder::RangeCoder;
use std::collections::VecDeque;
/// デコーダ構造体
pub struct Decoder {
// エンコーダの動作を再現するためのエンコーダ構造体
range_coder: RangeCoder,
// エンコーダの出力を入れる
// 符号のうち,未使用のものをバッファしておく
buffer: VecDeque<u8>,
// bufferから順に読み出して使う
// 符号のうち,レンジコーダの下限と同じ位置のビット列
data: u64,
}
impl Default for Decoder {
fn default() -> Self {
Self {
impl Decoder {
pub fn new<I: Into<VecDeque<u8>>>(code: I) -> Self {
let mut decoder = Self {
range_coder: RangeCoder::new(),
buffer: VecDeque::new(),
buffer: code.into(),
data: 0,
}
}
}
/// コンストラクタ,セッター,ゲッター
impl Decoder {
/// コンストラクタ
pub fn new() -> Self {
Decoder::default()
}
pub fn set_data(&mut self, data: VecDeque<u8>) {
self.buffer = data;
}
pub fn set_rangecoder(&mut self, range_coder: RangeCoder) {
self.range_coder = range_coder;
};
// 最初の64bit読み出し
decoder.shift_left_buffer(8);
decoder
}
pub fn range_coder(&self) -> &RangeCoder {
&self.range_coder
}
pub fn range_coder_mut(&mut self) -> &mut RangeCoder {
&mut self.range_coder
}
pub fn buffer(&self) -> &VecDeque<u8> {
&self.buffer
}
pub fn data(&self) -> u64 {
self.data
}
}
/// ロジック
impl Decoder {
/// デコード開始用の関数
pub fn decode_start(&mut self) {
// 最初の64bit読み出し
self.shift_left_buffer(8);
}
/// dataをn回左シフトして、バッファからデータを入れる
fn shift_left_buffer(&mut self, n: usize) {
for _ in 0..n {
self.data = (self.data << 8) | self.buffer.pop_front().unwrap() as u64;
}
}

/// 一文字デコードする関数
pub fn decode_one_alphabet<T: PModel>(&mut self, pmodel: &T) -> usize {
pub fn decode<T: PModel>(&mut self, pmodel: &T) -> usize {
// デコードするアルファベットのインデックスをとってくる
let decode_index = pmodel.find_index(self);
// println!("alphabet index is: {}", decode_index);
// エンコーダの状態の更新
// レンジコーダの状態の更新
let n = self
.range_coder_mut()
.range_coder
.param_update(
pmodel.c_freq(decode_index),
pmodel.cum_freq(decode_index),
Expand Down
40 changes: 16 additions & 24 deletions src/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,19 @@ use std::collections::VecDeque;

/// エンコーダ構造体
pub struct Encoder {
/// レンジコーダ
range_coder: RangeCoder,
pub range_coder: RangeCoder,
/// 出力する符号
data: VecDeque<u8>,
code: VecDeque<u8>,
}
/// ロジック
impl Encoder {
pub fn new() -> Self {
Encoder::default()
}
/// take ref to code
pub fn peek_code(&self) -> &VecDeque<u8> {
&self.code
}
/// 1アルファベット、エンコードを進める
///
/// 返値は出力したバイト数
Expand All @@ -26,38 +32,24 @@ impl Encoder {
)
.unwrap();
let len = out.len();
self.data.append(&mut out);
self.code.append(&mut out);
len as u32
}
/// エンコード終了後に呼び出して、
/// 下限を出力
pub fn finish(&mut self) {
/// エンコード終了処理
/// 下限を符号に出力し,符号を返す
pub fn finish(mut self) -> VecDeque<u8> {
// 現状の下限を出力
for _ in 0..8 {
self.data.push_back(self.range_coder.left_shift());
self.code.push_back(self.range_coder.left_shift());
}
self.code
}
}
impl Default for Encoder {
fn default() -> Self {
Self {
data: VecDeque::new(),
code: VecDeque::new(),
range_coder: RangeCoder::new(),
}
}
}
/// コンストラクタ
impl Encoder {
pub fn new() -> Self {
Encoder::default()
}
}
/// ゲッタ
impl Encoder {
pub fn data(&self) -> &VecDeque<u8> {
&self.data
}
pub fn range_coder(&self) -> &RangeCoder {
&self.range_coder
}
}
Loading

0 comments on commit 9773e13

Please sign in to comment.