use alloc::vec::Vec;
use fearless_simd::Simd;
use super::hashers::{
DistanceCache, MatchQuery, MatchRun, Matcher, RunVisitor, prepare_distance_cache,
};
use super::params::GreedyParams;
use crate::compressor::core::rfc9841::context::SharedContextInner;
use crate::shared::command::Command;
use crate::shared::dictionary::DictionaryStats;
use crate::shared::distance::NUM_DISTANCE_SHORT_CODES;
use crate::shared::ringbuffer::{BlockSpan, Window};
use crate::shared::score::{MIN_SCORE, SearchResult};
const COST_DIFF_LAZY: usize = 175;
const MAX_DELAYED_IN_A_ROW: usize = 4;
pub(crate) fn compute_distance_code(
distance: usize,
max_distance: usize,
cache: &DistanceCache,
) -> usize {
if distance <= max_distance {
let distance_plus_3 = distance + 3;
let offset0 = distance_plus_3.wrapping_sub(cache[0] as usize);
let offset1 = distance_plus_3.wrapping_sub(cache[1] as usize);
if distance == cache[0] as usize {
return 0;
}
if distance == cache[1] as usize {
return 1;
}
if offset0 < 7 {
return (0x975_0468usize >> (4 * offset0)) & 0xF;
}
if offset1 < 7 {
return (0xFDB_1ACEusize >> (4 * offset1)) & 0xF;
}
if distance == cache[2] as usize {
return 2;
}
if distance == cache[3] as usize {
return 3;
}
}
distance + NUM_DISTANCE_SHORT_CODES as usize - 1
}
pub(crate) struct ReferenceState {
pub(crate) dist_cache: DistanceCache,
pub(crate) last_insert_len: usize,
pub(crate) num_literals: usize,
pub(crate) dictionary: DictionaryStats,
}
impl Default for ReferenceState {
fn default() -> Self {
Self {
dist_cache: super::hashers::INITIAL_DISTANCE_CACHE,
last_insert_len: 0,
num_literals: 0,
dictionary: DictionaryStats::default(),
}
}
}
#[derive(Copy, Clone)]
struct Block<'a> {
params: &'a GreedyParams,
ringbuffer: &'a [u8],
window: &'a [u8],
mask: usize,
attached: Option<&'a SharedContextInner>,
pos_end: usize,
store_end: usize,
max_backward_limit: usize,
position_offset: usize,
gap: usize,
max_distance_code: usize,
heuristics_window: usize,
extensive: bool,
last_distances: usize,
}
impl<'a> Block<'a> {
#[inline(always)]
fn query<const ENABLE_PREFIX: bool>(
&self,
cache: &'a DistanceCache,
position: usize,
max_length: usize,
) -> MatchQuery<'a> {
let max_backward = position.min(self.max_backward_limit);
MatchQuery {
#[cfg(feature = "experimental")]
custom: if ENABLE_PREFIX {
self.attached
.and_then(|c| c.static_index.as_ref())
.map(|index| {
index.combination(super::context_model::context(
crate::compressor::core::rfc9841::static_index::previous(
self.ringbuffer,
position,
self.mask,
1,
),
crate::compressor::core::rfc9841::static_index::previous(
self.ringbuffer,
position,
self.mask,
2,
),
))
})
} else {
None
},
data: self.ringbuffer,
window: self.window,
mask: self.mask,
cache,
cur_ix: position,
max_length,
max_backward,
position_offset: self.position_offset,
dictionary_limit: self.max_backward_limit,
gap: self.gap,
max_distance: self.max_distance_code,
}
}
#[inline(always)]
fn search<S: Simd, R: MatchRun, const ENABLE_PREFIX: bool>(
&self,
simd: S,
matcher: &mut R,
state: &mut ReferenceState,
position: usize,
max_length: usize,
out: &mut SearchResult,
) {
let query = self.query::<ENABLE_PREFIX>(&state.dist_cache, position, max_length);
let dictionary_start = query.dictionary_start();
matcher.find_longest_match(simd, &mut state.dictionary, query, out);
if ENABLE_PREFIX && let Some(context) = self.attached {
context.find_match(
simd,
self.ringbuffer,
self.mask,
&state.dist_cache,
position,
max_length,
dictionary_start,
self.max_distance_code,
out,
);
}
}
}
#[derive(Copy, Clone)]
struct Cursor {
position: usize,
insert_length: usize,
apply_random_heuristics: usize,
}
#[expect(
clippy::too_many_arguments,
reason = "mirrors CreateBackwardReferences, whose parameters are all needed"
)]
#[cfg_attr(all(feature = "hotpath", not(feature = "no_std")), hotpath::measure)]
pub(crate) fn create_backward_references<
S: Simd,
M: Matcher,
const ENABLE_PREFIX: bool,
const INDEPENDENT: bool,
>(
simd: S,
matcher: &mut M,
params: &GreedyParams,
window: Window<'_>,
span: BlockSpan,
attached: Option<&SharedContextInner>,
state: &mut ReferenceState,
commands: &mut Vec<Command>,
) {
let num_bytes = span.bytes as usize;
let position = span.position as usize;
let pos_end = position + num_bytes;
#[cfg(feature = "experimental")]
let position_offset = params.stream_offset;
#[cfg(not(feature = "experimental"))]
let position_offset = 0;
let block = Block {
params,
ringbuffer: window.data,
window: window
.data
.get(..window.mask.saturating_add(1))
.unwrap_or(window.data),
mask: window.mask,
attached,
pos_end,
store_end: position,
max_backward_limit: params.max_backward_limit(),
position_offset,
gap: if ENABLE_PREFIX {
attached.map_or(0, SharedContextInner::total_size)
} else {
0
},
max_distance_code: params.dist.max_distance as usize,
heuristics_window: params.random_heuristics_window_size(),
extensive: params.quality.extensive_reference_search(),
last_distances: matcher.last_distances_to_check(),
};
let cursor = Cursor {
position,
insert_length: state.last_insert_len,
apply_random_heuristics: position + block.heuristics_window,
};
prepare_distance_cache(&mut state.dist_cache, block.last_distances);
let mut cursor = matcher.visit_run(SearchLoop::<S, ENABLE_PREFIX, INDEPENDENT> {
simd,
block,
cursor,
state,
commands,
});
cursor.insert_length += pos_end - cursor.position;
state.last_insert_len = cursor.insert_length;
}
struct SearchLoop<'a, S, const ENABLE_PREFIX: bool, const INDEPENDENT: bool> {
simd: S,
block: Block<'a>,
cursor: Cursor,
state: &'a mut ReferenceState,
commands: &'a mut Vec<Command>,
}
impl<S: Simd, const ENABLE_PREFIX: bool, const INDEPENDENT: bool> RunVisitor
for SearchLoop<'_, S, ENABLE_PREFIX, INDEPENDENT>
{
type Output = Cursor;
#[inline(always)]
fn visit<R: MatchRun>(self, mut run: R) -> Cursor {
let Self {
simd,
mut block,
cursor,
state,
commands,
} = self;
let pos_end = block.pos_end;
block.store_end = if pos_end - cursor.position >= R::STORE_LOOKAHEAD {
pos_end - R::STORE_LOOKAHEAD + 1
} else {
cursor.position
};
let block = block;
simd.vectorize(
#[inline(always)]
move || {
let hot = block;
let Cursor {
mut position,
mut insert_length,
mut apply_random_heuristics,
} = cursor;
while position + R::HASH_TYPE_LENGTH < pos_end {
let max_length = pos_end - position;
let mut sr = SearchResult::empty();
hot.search::<S, R, ENABLE_PREFIX>(
simd, &mut run, state, position, max_length, &mut sr,
);
if sr.is_match() {
let committed;
(run, committed) = commit_match::<S, R, ENABLE_PREFIX, INDEPENDENT>(
simd,
run,
&block,
Cursor {
position,
insert_length,
apply_random_heuristics,
},
state,
commands,
sr,
max_length,
);
position = committed.position;
insert_length = committed.insert_length;
apply_random_heuristics = committed.apply_random_heuristics;
continue;
}
insert_length += 1;
position += 1;
if position <= apply_random_heuristics {
continue;
}
let (stride, margin_floor) =
if position > apply_random_heuristics + 4 * hot.heuristics_window {
(4usize, 4usize)
} else {
(2usize, 2usize)
};
let margin = (R::STORE_LOOKAHEAD - 1).max(margin_floor);
let pos_jump = (position + 4 * stride).min(pos_end.saturating_sub(margin));
while position < pos_jump {
run.store(hot.ringbuffer, hot.mask, position);
insert_length += stride;
position += stride;
}
}
Cursor {
position,
insert_length,
apply_random_heuristics,
}
},
)
}
}
#[expect(
clippy::too_many_arguments,
reason = "the second half of CreateBackwardReferences' loop body"
)]
#[inline]
fn commit_match<S: Simd, R: MatchRun, const ENABLE_PREFIX: bool, const INDEPENDENT: bool>(
simd: S,
mut matcher: R,
block: &Block<'_>,
mut cursor: Cursor,
state: &mut ReferenceState,
commands: &mut Vec<Command>,
mut sr: SearchResult,
mut max_length: usize,
) -> (R, Cursor) {
simd.vectorize(
#[inline(always)]
move || {
let pos_end = block.pos_end;
let mut delayed = 0usize;
max_length -= 1;
loop {
let mut sr2 = SearchResult {
len: if block.extensive {
0
} else {
(sr.len - 1).min(max_length)
},
distance: 0,
score: MIN_SCORE,
len_code_delta: 0,
};
block.search::<S, R, ENABLE_PREFIX>(
simd,
&mut matcher,
state,
cursor.position + 1,
max_length,
&mut sr2,
);
if sr2.score >= sr.score + COST_DIFF_LAZY {
cursor.position += 1;
cursor.insert_length += 1;
sr = sr2;
delayed += 1;
if delayed < MAX_DELAYED_IN_A_ROW
&& cursor.position + R::HASH_TYPE_LENGTH < pos_end
{
max_length -= 1;
continue;
}
}
break;
}
let position = cursor.position;
cursor.apply_random_heuristics = position + 2 * sr.len + block.heuristics_window;
let dictionary_start = (position + block.position_offset).min(block.max_backward_limit);
let distance_code = if INDEPENDENT {
sr.distance + NUM_DISTANCE_SHORT_CODES as usize - 1
} else {
compute_distance_code(sr.distance, dictionary_start + block.gap, &state.dist_cache)
};
if sr.distance <= dictionary_start + block.gap && distance_code > 0 {
state.dist_cache[3] = state.dist_cache[2];
state.dist_cache[2] = state.dist_cache[1];
state.dist_cache[1] = state.dist_cache[0];
state.dist_cache[0] = sr.distance as i32;
prepare_distance_cache(&mut state.dist_cache, block.last_distances);
}
commands.push(Command::new(
&block.params.dist,
cursor.insert_length,
sr.len,
sr.len_code_delta,
distance_code,
));
state.num_literals += cursor.insert_length;
cursor.insert_length = 0;
let mut range_start = position + 2;
let range_end = (position + sr.len).min(block.store_end);
if sr.distance < (sr.len >> 2) {
range_start =
range_end.min(range_start.max(position + sr.len - (sr.distance << 2)));
}
matcher.store_range(block.ringbuffer, block.mask, range_start, range_end);
cursor.position += sr.len;
(matcher, cursor)
},
)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::compressor::core::greedy::hashers::{
INITIAL_DISTANCE_CACHE, NUM_REMEMBERED_DISTANCES, QuickMatcher,
};
use crate::compressor::core::greedy::params::GreedyQuality;
use crate::compressor::{CompressParams, QualityLevel, WindowBits};
use fearless_simd::{Level, dispatch};
fn params(quality: QualityLevel) -> GreedyParams {
let public = CompressParams::new(quality, WindowBits::DEFAULT);
GreedyParams::new(&public, 0).expect("supported quality")
}
fn run(quality: QualityLevel, data: &[u8]) -> (Vec<Command>, ReferenceState) {
let params = params(quality);
let mut matcher = QuickMatcher::<{ 1 << 16 }, 1, 5, false>::new();
matcher.prepare(true, data.len(), data, true);
let mut state = ReferenceState::default();
let mut commands = Vec::new();
let level = Level::try_detect().unwrap_or_else(Level::baseline);
let window = Window {
data,
mask: usize::MAX,
};
let span = BlockSpan {
position: 0,
bytes: data.len() as u32,
};
dispatch!(level, simd => create_backward_references::<_, _, false, false>(
simd, &mut matcher, ¶ms, window, span, None, &mut state, &mut commands,
));
(commands, state)
}
fn consumed(commands: &[Command], state: &ReferenceState) -> usize {
commands
.iter()
.map(|command| command.insert_len as usize + command.copy_len() as usize)
.sum::<usize>()
+ state.last_insert_len
}
#[test]
fn every_input_byte_is_accounted_for() {
for quality in [QualityLevel::Q3, QualityLevel::Q4, QualityLevel::Q5] {
for payload in [
b"abcabcabcabcabcabcabcabcabcabc".to_vec(),
vec![b'z'; 5000],
(0..5000u32).map(|i| (i % 251) as u8).collect(),
Vec::new(),
b"a".to_vec(),
] {
let mut data = payload.clone();
data.extend_from_slice(&[0u8; 8]);
let params = params(quality);
let mut matcher = QuickMatcher::<{ 1 << 16 }, 1, 5, false>::new();
matcher.prepare(true, payload.len(), &data, true);
let mut state = ReferenceState::default();
let mut commands = Vec::new();
let level = Level::try_detect().unwrap_or_else(Level::baseline);
let window = Window {
data: &data,
mask: usize::MAX,
};
let span = BlockSpan {
position: 0,
bytes: payload.len() as u32,
};
dispatch!(level, simd => create_backward_references::<_, _, false, false>(
simd, &mut matcher, ¶ms, window, span, None, &mut state, &mut commands,
));
assert_eq!(
consumed(&commands, &state),
payload.len(),
"quality {quality:?}, {} bytes",
payload.len()
);
}
}
}
#[test]
fn a_repeated_string_becomes_one_long_copy() {
let mut data = b"the quick brown fox ".repeat(40);
data.extend_from_slice(&[0u8; 8]);
let payload = data.len() - 8;
let params = params(QualityLevel::Q3);
let mut matcher = QuickMatcher::<{ 1 << 16 }, 1, 5, false>::new();
matcher.prepare(true, payload, &data, true);
let mut state = ReferenceState::default();
let mut commands = Vec::new();
let level = Level::try_detect().unwrap_or_else(Level::baseline);
let window = Window {
data: &data,
mask: usize::MAX,
};
let span = BlockSpan {
position: 0,
bytes: payload as u32,
};
dispatch!(level, simd => create_backward_references::<_, _, false, false>(
simd, &mut matcher, ¶ms, window, span, None, &mut state, &mut commands,
));
assert!(!commands.is_empty());
let longest = commands
.iter()
.map(|command| command.copy_len())
.max()
.unwrap_or(0);
assert!(longest > 500, "longest copy was only {longest}");
}
#[test]
fn incompressible_data_produces_no_commands() {
let (commands, state) = run(QualityLevel::Q3, &[]);
assert!(commands.is_empty());
assert_eq!(state.last_insert_len, 0);
}
#[test]
fn the_distance_cache_only_records_real_distances() {
let mut data = b"abcdefgh".repeat(200);
data.extend_from_slice(&[0u8; 8]);
let payload = data.len() - 8;
let params = params(QualityLevel::Q3);
let mut matcher = QuickMatcher::<{ 1 << 16 }, 1, 5, false>::new();
matcher.prepare(true, payload, &data, true);
let mut state = ReferenceState::default();
let mut commands = Vec::new();
let level = Level::try_detect().unwrap_or_else(Level::baseline);
let window = Window {
data: &data,
mask: usize::MAX,
};
let span = BlockSpan {
position: 0,
bytes: payload as u32,
};
dispatch!(level, simd => create_backward_references::<_, _, false, false>(
simd, &mut matcher, ¶ms, window, span, None, &mut state, &mut commands,
));
assert!(
state.dist_cache[..NUM_REMEMBERED_DISTANCES]
.iter()
.all(|&distance| distance > 0)
);
}
#[test]
fn distance_codes_prefer_the_cache() {
let cache: DistanceCache = INITIAL_DISTANCE_CACHE;
assert_eq!(compute_distance_code(4, 1 << 20, &cache), 0);
assert_eq!(compute_distance_code(11, 1 << 20, &cache), 1);
assert_eq!(compute_distance_code(15, 1 << 20, &cache), 2);
assert_eq!(compute_distance_code(16, 1 << 20, &cache), 3);
assert_eq!(compute_distance_code(3, 1 << 20, &cache), 4);
assert_eq!(compute_distance_code(5, 1 << 20, &cache), 5);
assert_eq!(compute_distance_code(1000, 1 << 20, &cache), 1015);
assert_eq!(compute_distance_code(4, 3, &cache), 19);
}
#[test]
fn every_short_distance_code_is_in_range() {
let cache: DistanceCache = INITIAL_DISTANCE_CACHE;
for distance in 1usize..64 {
let code = compute_distance_code(distance, 1 << 20, &cache);
assert!(code < 16 || code == distance + 15, "distance {distance}");
}
}
#[test]
fn quality_five_searches_more_than_quality_four() {
assert!(GreedyQuality::Q5.extensive_reference_search());
assert!(!GreedyQuality::Q4.extensive_reference_search());
}
}