pub(crate) fn do_offset_history(offset_value: u32, lit_len: u32, scratch: &mut [u32; 3]) -> u32 {
if offset_value >= 4 {
let actual = offset_value - 3;
scratch[2] = scratch[1];
scratch[1] = scratch[0];
scratch[0] = actual;
return actual;
}
do_offset_history_repcode(offset_value, lit_len, scratch)
}
fn do_offset_history_repcode(offset_value: u32, lit_len: u32, scratch: &mut [u32; 3]) -> u32 {
#[derive(Copy, Clone)]
struct Rule {
scratch_idx: usize,
use_new_offset: bool,
subtract_one: bool,
update_mode: u8,
}
const RULES: [Rule; 8] = [
Rule {
scratch_idx: 0,
use_new_offset: false,
subtract_one: false,
update_mode: 0,
},
Rule {
scratch_idx: 1,
use_new_offset: false,
subtract_one: false,
update_mode: 1,
},
Rule {
scratch_idx: 1,
use_new_offset: false,
subtract_one: false,
update_mode: 1,
},
Rule {
scratch_idx: 2,
use_new_offset: false,
subtract_one: false,
update_mode: 2,
},
Rule {
scratch_idx: 2,
use_new_offset: false,
subtract_one: false,
update_mode: 2,
},
Rule {
scratch_idx: 0,
use_new_offset: false,
subtract_one: true,
update_mode: 2,
},
Rule {
scratch_idx: 0,
use_new_offset: true,
subtract_one: false,
update_mode: 2,
},
Rule {
scratch_idx: 0,
use_new_offset: true,
subtract_one: false,
update_mode: 2,
},
];
#[inline(always)]
fn mask_from_bool(cond: bool) -> u32 {
0u32.wrapping_sub(u32::from(cond))
}
#[inline(always)]
fn select_u32(a: u32, b: u32, choose_b: bool) -> u32 {
let mask = mask_from_bool(choose_b);
(a & !mask) | (b & mask)
}
let valid_offset = offset_value != 0;
let class = offset_value.saturating_sub(1).min(3) as usize;
let lit_is_zero = usize::from(lit_len == 0);
let rule = RULES[class * 2 + lit_is_zero];
let from_history = scratch[rule.scratch_idx];
let from_new = offset_value.wrapping_sub(3);
let mut actual_offset = select_u32(from_new, from_history, !rule.use_new_offset);
actual_offset = actual_offset.wrapping_sub(u32::from(rule.subtract_one));
actual_offset = select_u32(actual_offset, 0, !valid_offset);
let old0 = scratch[0];
let old1 = scratch[1];
let old2 = scratch[2];
let update_none = rule.update_mode == 0 || !valid_offset;
let update_b = rule.update_mode == 2 && valid_offset;
let update_any = !update_none;
scratch[0] = select_u32(old0, actual_offset, update_any);
scratch[1] = select_u32(old0, old1, update_none);
scratch[2] = select_u32(old2, old1, update_b);
actual_offset
}
#[cfg(test)]
mod tests;