add --eof-in-length option

This commit is contained in:
2022-09-26 23:41:17 +02:00
parent b12c8f8d93
commit 8715dede0e
5 changed files with 33 additions and 7 deletions

View File

@@ -21,7 +21,7 @@ pub fn pack(
if let Some(m) = match_finder.matches(pos).next() { if let Some(m) = match_finder.matches(pos).next() {
let max_offset = 1 << (m.length * 3 - 1).min(31); let max_offset = 1 << (m.length * 3 - 1).min(31);
let offset = pos - m.pos; let offset = pos - m.pos;
if offset < max_offset { if offset < max_offset && m.length >= config.min_length() {
lz::Op::Match { lz::Op::Match {
offset: offset as u32, offset: offset as u32,
len: m.length as u32, len: m.length as u32,
@@ -40,7 +40,7 @@ pub fn pack(
.zip(data[(pos - offset)..].iter()) .zip(data[(pos - offset)..].iter())
.take_while(|(a, b)| a == b) .take_while(|(a, b)| a == b)
.count(); .count();
if length > 0 { if length >= config.min_length() {
lz::Op::Match { lz::Op::Match {
offset: offset as u32, offset: offset as u32,
len: length as u32, len: length as u32,

View File

@@ -22,6 +22,7 @@ pub struct Config {
pub simplified_prob_update: bool, pub simplified_prob_update: bool,
pub no_repeated_offsets: bool, pub no_repeated_offsets: bool,
pub eof_in_length: bool,
} }
impl Default for Config { impl Default for Config {
@@ -39,6 +40,17 @@ impl Default for Config {
simplified_prob_update: false, simplified_prob_update: false,
no_repeated_offsets: false, no_repeated_offsets: false,
eof_in_length: false,
}
}
}
impl Config {
pub fn min_length(&self) -> usize {
if self.eof_in_length {
2
} else {
1
} }
} }
} }

View File

@@ -40,11 +40,12 @@ impl Op {
coder, coder,
state, state,
256 * state.parity_contexts + 1, 256 * state.parity_contexts + 1,
offset + 1, offset + if config.eof_in_length { 0 } else { 1 },
config, config,
); );
state.last_offset = offset; state.last_offset = offset;
} }
assert!(!config.eof_in_length || len > 1);
encode_length(coder, state, 256 * state.parity_contexts + 65, len, config); encode_length(coder, state, 256 * state.parity_contexts + 65, len, config);
state.prev_was_match = true; state.prev_was_match = true;
state.pos += len as usize; state.pos += len as usize;
@@ -60,15 +61,20 @@ pub fn encode_eof(coder: &mut dyn EntropyCoder, state: &mut CoderState, config:
state.pos % state.parity_contexts * 256, state.pos % state.parity_contexts * 256,
config.is_match_bit, config.is_match_bit,
); );
if !state.prev_was_match { if !state.prev_was_match && !config.no_repeated_offsets {
encode_bit( encode_bit(
coder, coder,
state, state,
256 * state.parity_contexts, 256 * state.parity_contexts,
config.new_offset_bit, config.new_offset_bit ^ config.eof_in_length,
); );
} }
encode_length(coder, state, 256 * state.parity_contexts + 1, 1, config); if !config.eof_in_length || config.no_repeated_offsets {
encode_length(coder, state, 256 * state.parity_contexts + 1, 1, config);
}
if config.eof_in_length {
encode_length(coder, state, 256 * state.parity_contexts + 65, 1, config);
}
} }
fn encode_bit( fn encode_bit(
@@ -183,7 +189,7 @@ pub fn unpack_internal(
&mut contexts, &mut contexts,
256 * config.parity_contexts + 1, 256 * config.parity_contexts + 1,
&config, &config,
) - 1; ) - if config.eof_in_length { 0 } else { 1 };
if offset == 0 { if offset == 0 {
break; break;
} }
@@ -194,6 +200,9 @@ pub fn unpack_internal(
256 * config.parity_contexts + 65, 256 * config.parity_contexts + 65,
&config, &config,
); );
if config.eof_in_length && length == 1 {
break;
}
if let Some(ref mut result) = result { if let Some(ref mut result) = result {
for _ in 0..length { for _ in 0..length {
result.push(result[result.len() - offset]); result.push(result[result.len() - offset]);

View File

@@ -30,12 +30,14 @@ fn main() -> Result<()> {
config.bitstream_is_big_endian = true; config.bitstream_is_big_endian = true;
} }
Long("no-repeated-offsets") => config.no_repeated_offsets = true, Long("no-repeated-offsets") => config.no_repeated_offsets = true,
Long("eof-in-length") => config.eof_in_length = true,
Long("z80") => { Long("z80") => {
config.use_bitstream = true; config.use_bitstream = true;
config.bitstream_is_big_endian = true; config.bitstream_is_big_endian = true;
config.invert_bit_encoding = true; config.invert_bit_encoding = true;
config.simplified_prob_update = true; config.simplified_prob_update = true;
level = 9;
} }
Long("x86") => { Long("x86") => {
config.use_bitstream = true; config.use_bitstream = true;

View File

@@ -110,6 +110,9 @@ fn parse(
max_arrivals: usize, max_arrivals: usize,
config: &crate::Config, config: &crate::Config,
) { ) {
if length < config.min_length() {
return;
}
cost_counter.reset(); cost_counter.reset();
let mut state = arrival.state.clone(); let mut state = arrival.state.clone();
let op = lz::Op::Match { let op = lz::Op::Match {