use alloc::vec::Vec;
use super::super::arithmetic_encoder::{ArithmeticEncoder, ArithmeticEncoderContext};
use super::super::build::SubBandType;
use super::super::codestream::CodeBlockStyle;
use crate::writer::BitWriter;
pub(super) const SIGNIFICANT: u8 = 1 << 7;
const MAGNITUDE_REFINED: u8 = 1 << 6;
pub(super) const CODED_IN_CURRENT_PASS: u8 = 1 << 5;
pub(super) const NEGATIVE: u8 = 1 << 4;
#[rustfmt::skip]
const ZERO_CTX_LL_LH: [u8; 256] = [
0, 3, 1, 3, 5, 7, 6, 7, 1, 3, 2, 3, 6, 7, 6, 7, 5, 7, 6, 7, 8, 8, 8, 8, 6, 7, 6, 7, 8, 8, 8, 8,
1, 3, 2, 3, 6, 7, 6, 7, 2, 3, 2, 3, 6, 7, 6, 7, 6, 7, 6, 7, 8, 8, 8, 8, 6, 7, 6, 7, 8, 8, 8, 8,
3, 4, 3, 4, 7, 7, 7, 7, 3, 4, 3, 4, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 7, 7, 7, 7, 8, 8, 8, 8,
3, 4, 3, 4, 7, 7, 7, 7, 3, 4, 3, 4, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 7, 7, 7, 7, 8, 8, 8, 8,
1, 3, 2, 3, 6, 7, 6, 7, 2, 3, 2, 3, 6, 7, 6, 7, 6, 7, 6, 7, 8, 8, 8, 8, 6, 7, 6, 7, 8, 8, 8, 8,
2, 3, 2, 3, 6, 7, 6, 7, 2, 3, 2, 3, 6, 7, 6, 7, 6, 7, 6, 7, 8, 8, 8, 8, 6, 7, 6, 7, 8, 8, 8, 8,
3, 4, 3, 4, 7, 7, 7, 7, 3, 4, 3, 4, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 7, 7, 7, 7, 8, 8, 8, 8,
3, 4, 3, 4, 7, 7, 7, 7, 3, 4, 3, 4, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 7, 7, 7, 7, 8, 8, 8, 8,
];
#[rustfmt::skip]
const ZERO_CTX_HL: [u8; 256] = [
0, 5, 1, 6, 3, 7, 3, 7, 1, 6, 2, 6, 3, 7, 3, 7, 3, 7, 3, 7, 4, 7, 4, 7, 3,
7, 3, 7, 4, 7, 4, 7, 1, 6, 2, 6, 3, 7, 3, 7, 2, 6, 2, 6, 3, 7, 3, 7, 3, 7,
3, 7, 4, 7, 4, 7, 3, 7, 3, 7, 4, 7, 4, 7, 5, 8, 6, 8, 7, 8, 7, 8, 6, 8, 6,
8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 6, 8, 6, 8,
7, 8, 7, 8, 6, 8, 6, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7,
8, 7, 8, 1, 6, 2, 6, 3, 7, 3, 7, 2, 6, 2, 6, 3, 7, 3, 7, 3, 7, 3, 7, 4, 7,
4, 7, 3, 7, 3, 7, 4, 7, 4, 7, 2, 6, 2, 6, 3, 7, 3, 7, 2, 6, 2, 6, 3, 7, 3,
7, 3, 7, 3, 7, 4, 7, 4, 7, 3, 7, 3, 7, 4, 7, 4, 7, 6, 8, 6, 8, 7, 8, 7, 8,
6, 8, 6, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 6,
8, 6, 8, 7, 8, 7, 8, 6, 8, 6, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8,
7, 8, 7, 8, 7, 8,
];
#[rustfmt::skip]
const ZERO_CTX_HH: [u8; 256] = [
0, 1, 3, 4, 1, 2, 4, 5, 3, 4, 6, 7, 4, 5, 7, 7, 1, 2, 4, 5, 2, 2, 5, 5, 4,
5, 7, 7, 5, 5, 7, 7, 3, 4, 6, 7, 4, 5, 7, 7, 6, 7, 8, 8, 7, 7, 8, 8, 4, 5,
7, 7, 5, 5, 7, 7, 7, 7, 8, 8, 7, 7, 8, 8, 1, 2, 4, 5, 2, 2, 5, 5, 4, 5, 7,
7, 5, 5, 7, 7, 2, 2, 5, 5, 2, 2, 5, 5, 5, 5, 7, 7, 5, 5, 7, 7, 4, 5, 7, 7,
5, 5, 7, 7, 7, 7, 8, 8, 7, 7, 8, 8, 5, 5, 7, 7, 5, 5, 7, 7, 7, 7, 8, 8, 7,
7, 8, 8, 3, 4, 6, 7, 4, 5, 7, 7, 6, 7, 8, 8, 7, 7, 8, 8, 4, 5, 7, 7, 5, 5,
7, 7, 7, 7, 8, 8, 7, 7, 8, 8, 6, 7, 8, 8, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 7, 7, 8, 8, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 5, 7, 7, 5, 5, 7, 7,
7, 7, 8, 8, 7, 7, 8, 8, 5, 5, 7, 7, 5, 5, 7, 7, 7, 7, 8, 8, 7, 7, 8, 8, 7,
7, 8, 8, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8,
];
#[rustfmt::skip]
const SIGN_CONTEXT_LOOKUP: [(u8, u8); 256] = [
(9,0), (10,0), (10,1), (0,0), (12,0), (13,0), (11,0), (0,0), (12,1), (11,1),
(13,1), (0,0), (0,0), (0,0), (0,0), (0,0), (12,0), (13,0), (11,0), (0,0),
(12,0), (13,0), (11,0), (0,0), (9,0), (10,0), (10,1), (0,0), (0,0), (0,0),
(0,0), (0,0), (12,1), (11,1), (13,1), (0,0), (9,0), (10,0), (10,1), (0,0),
(12,1), (11,1), (13,1), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0),
(0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0),
(0,0), (0,0), (0,0), (10,0), (10,0), (9,0), (0,0), (13,0), (13,0), (12,0),
(0,0), (11,1), (11,1), (12,1), (0,0), (0,0), (0,0), (0,0), (0,0), (13,0),
(13,0), (12,0), (0,0), (13,0), (13,0), (12,0), (0,0), (10,0), (10,0), (9,0),
(0,0), (0,0), (0,0), (0,0), (0,0), (11,1), (11,1), (12,1), (0,0), (10,0),
(10,0), (9,0), (0,0), (11,1), (11,1), (12,1), (0,0), (0,0), (0,0), (0,0),
(0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0),
(0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (10,1), (9,0), (10,1), (0,0),
(11,0), (12,0), (11,0), (0,0), (13,1), (12,1), (13,1), (0,0), (0,0), (0,0),
(0,0), (0,0), (11,0), (12,0), (11,0), (0,0), (11,0), (12,0), (11,0), (0,0),
(10,1), (9,0), (10,1), (0,0), (0,0), (0,0), (0,0), (0,0), (13,1), (12,1),
(13,1), (0,0), (10,1), (9,0), (10,1), (0,0), (13,1), (12,1), (13,1), (0,0),
(0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0),
(0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0),
(0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0),
(0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0),
(0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0),
(0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0),
(0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0),
(0,0), (0,0), (0,0), (0,0), (0,0), (0,0), (0,0),
];
pub(super) fn mark_coded_in_current_pass(
idx: usize,
states: &mut [u8],
coded_indices: &mut Vec<usize>,
) {
if states[idx] & CODED_IN_CURRENT_PASS == 0 {
states[idx] |= CODED_IN_CURRENT_PASS;
coded_indices.push(idx);
}
}
pub(super) fn clear_coded_in_current_pass(states: &mut [u8], coded_indices: &mut Vec<usize>) {
for idx in coded_indices.drain(..) {
states[idx] &= !CODED_IN_CURRENT_PASS;
}
}
#[expect(clippy::too_many_arguments, reason = "stable pass boundary")]
#[expect(clippy::trivially_copy_pass_by_ref, reason = "shared style borrow")]
pub(super) fn significance_propagation_pass(
magnitudes: &[u64],
states: &mut [u8],
neighbors: &mut [u8],
coded_indices: &mut Vec<usize>,
encoder: &mut ArithmeticEncoder,
contexts: &mut [ArithmeticEncoderContext; 19],
w: usize,
h: usize,
pw: usize,
bit_mask: u64,
sub_band_type: SubBandType,
style: &CodeBlockStyle,
) {
if style.vertically_causal_context {
significance_propagation_pass_impl::<true>(
magnitudes,
states,
neighbors,
coded_indices,
encoder,
contexts,
w,
h,
pw,
bit_mask,
sub_band_type,
);
} else {
significance_propagation_pass_impl::<false>(
magnitudes,
states,
neighbors,
coded_indices,
encoder,
contexts,
w,
h,
pw,
bit_mask,
sub_band_type,
);
}
}
#[expect(clippy::too_many_arguments, reason = "explicit hot scan state")]
fn significance_propagation_pass_impl<const VERTICAL_CAUSAL: bool>(
magnitudes: &[u64],
states: &mut [u8],
neighbors: &mut [u8],
coded_indices: &mut Vec<usize>,
encoder: &mut ArithmeticEncoder,
contexts: &mut [ArithmeticEncoderContext; 19],
w: usize,
h: usize,
pw: usize,
bit_mask: u64,
sub_band_type: SubBandType,
) {
for y_base in (0..h).step_by(4) {
for x in 0..w {
let y_end = (y_base + 4).min(h);
for y in y_base..y_end {
let idx = (y + 1) * pw + (x + 1);
let is_significant = states[idx] & SIGNIFICANT != 0;
let neighbor_sig = effective_neighbor_sig::<VERTICAL_CAUSAL>(neighbors[idx], y, h);
let has_sig_neighbors = neighbor_sig != 0;
if !is_significant && has_sig_neighbors {
let ctx_label = zero_coding_ctx(neighbor_sig, sub_band_type);
let bit = u32::from(magnitudes[idx] & bit_mask != 0);
encoder.encode(bit, &mut contexts[ctx_label as usize]);
mark_coded_in_current_pass(idx, states, coded_indices);
if bit == 1 {
encode_sign::<VERTICAL_CAUSAL>(
idx, neighbors, states, encoder, contexts, pw, y, h,
);
set_significant(idx, states, neighbors, pw);
}
}
}
}
}
}
#[expect(clippy::too_many_arguments, reason = "stable raw pass boundary")]
#[expect(clippy::trivially_copy_pass_by_ref, reason = "shared style borrow")]
pub(super) fn significance_propagation_pass_raw(
magnitudes: &[u64],
states: &mut [u8],
neighbors: &mut [u8],
coded_indices: &mut Vec<usize>,
writer: &mut BitWriter,
w: usize,
h: usize,
pw: usize,
bit_mask: u64,
style: &CodeBlockStyle,
) {
if style.vertically_causal_context {
significance_propagation_pass_raw_impl::<true>(
magnitudes,
states,
neighbors,
coded_indices,
writer,
w,
h,
pw,
bit_mask,
);
} else {
significance_propagation_pass_raw_impl::<false>(
magnitudes,
states,
neighbors,
coded_indices,
writer,
w,
h,
pw,
bit_mask,
);
}
}
#[expect(clippy::too_many_arguments, reason = "explicit hot scan state")]
fn significance_propagation_pass_raw_impl<const VERTICAL_CAUSAL: bool>(
magnitudes: &[u64],
states: &mut [u8],
neighbors: &mut [u8],
coded_indices: &mut Vec<usize>,
writer: &mut BitWriter,
w: usize,
h: usize,
pw: usize,
bit_mask: u64,
) {
for y_base in (0..h).step_by(4) {
for x in 0..w {
let y_end = (y_base + 4).min(h);
for y in y_base..y_end {
let idx = (y + 1) * pw + (x + 1);
let is_significant = states[idx] & SIGNIFICANT != 0;
let neighbor_sig = effective_neighbor_sig::<VERTICAL_CAUSAL>(neighbors[idx], y, h);
if !is_significant && neighbor_sig != 0 {
let bit = u32::from(magnitudes[idx] & bit_mask != 0);
writer.write_bit(bit);
mark_coded_in_current_pass(idx, states, coded_indices);
if bit == 1 {
encode_sign_raw(idx, states, writer);
set_significant(idx, states, neighbors, pw);
}
}
}
}
}
}
#[expect(clippy::too_many_arguments, reason = "stable pass boundary")]
#[expect(clippy::trivially_copy_pass_by_ref, reason = "shared style borrow")]
pub(super) fn magnitude_refinement_pass(
magnitudes: &[u64],
states: &mut [u8],
neighbors: &mut [u8],
encoder: &mut ArithmeticEncoder,
contexts: &mut [ArithmeticEncoderContext; 19],
w: usize,
h: usize,
pw: usize,
bit_mask: u64,
style: &CodeBlockStyle,
) {
if style.vertically_causal_context {
magnitude_refinement_pass_impl::<true>(
magnitudes, states, neighbors, encoder, contexts, w, h, pw, bit_mask,
);
} else {
magnitude_refinement_pass_impl::<false>(
magnitudes, states, neighbors, encoder, contexts, w, h, pw, bit_mask,
);
}
}
#[expect(clippy::too_many_arguments, reason = "explicit hot scan state")]
fn magnitude_refinement_pass_impl<const VERTICAL_CAUSAL: bool>(
magnitudes: &[u64],
states: &mut [u8],
neighbors: &mut [u8],
encoder: &mut ArithmeticEncoder,
contexts: &mut [ArithmeticEncoderContext; 19],
w: usize,
h: usize,
pw: usize,
bit_mask: u64,
) {
for y_base in (0..h).step_by(4) {
for x in 0..w {
let y_end = (y_base + 4).min(h);
for y in y_base..y_end {
let idx = (y + 1) * pw + (x + 1);
let is_significant = states[idx] & SIGNIFICANT != 0;
let coded_this_pass = states[idx] & CODED_IN_CURRENT_PASS != 0;
if is_significant && !coded_this_pass {
let ctx_label = magnitude_refinement_ctx(
states[idx],
effective_neighbor_sig::<VERTICAL_CAUSAL>(neighbors[idx], y, h),
);
let bit = u32::from(magnitudes[idx] & bit_mask != 0);
encoder.encode(bit, &mut contexts[ctx_label as usize]);
states[idx] |= MAGNITUDE_REFINED;
}
}
}
}
}
#[expect(clippy::too_many_arguments, reason = "stable raw pass boundary")]
#[expect(clippy::trivially_copy_pass_by_ref, reason = "shared style borrow")]
pub(super) fn magnitude_refinement_pass_raw(
magnitudes: &[u64],
states: &mut [u8],
neighbors: &mut [u8],
writer: &mut BitWriter,
w: usize,
h: usize,
pw: usize,
bit_mask: u64,
style: &CodeBlockStyle,
) {
if style.vertically_causal_context {
magnitude_refinement_pass_raw_impl::<true>(
magnitudes, states, neighbors, writer, w, h, pw, bit_mask,
);
} else {
magnitude_refinement_pass_raw_impl::<false>(
magnitudes, states, neighbors, writer, w, h, pw, bit_mask,
);
}
}
#[expect(clippy::too_many_arguments, reason = "explicit hot scan state")]
fn magnitude_refinement_pass_raw_impl<const VERTICAL_CAUSAL: bool>(
magnitudes: &[u64],
states: &mut [u8],
neighbors: &mut [u8],
writer: &mut BitWriter,
w: usize,
h: usize,
pw: usize,
bit_mask: u64,
) {
for y_base in (0..h).step_by(4) {
for x in 0..w {
let y_end = (y_base + 4).min(h);
for y in y_base..y_end {
let idx = (y + 1) * pw + (x + 1);
let is_significant = states[idx] & SIGNIFICANT != 0;
let coded_this_pass = states[idx] & CODED_IN_CURRENT_PASS != 0;
let _neighbor_sig = effective_neighbor_sig::<VERTICAL_CAUSAL>(neighbors[idx], y, h);
if is_significant && !coded_this_pass {
let bit = u32::from(magnitudes[idx] & bit_mask != 0);
writer.write_bit(bit);
states[idx] |= MAGNITUDE_REFINED;
}
}
}
}
}
#[expect(clippy::too_many_arguments, reason = "stable cleanup boundary")]
#[expect(clippy::trivially_copy_pass_by_ref, reason = "shared style borrow")]
pub(super) fn cleanup_pass(
magnitudes: &[u64],
states: &mut [u8],
neighbors: &mut [u8],
encoder: &mut ArithmeticEncoder,
contexts: &mut [ArithmeticEncoderContext; 19],
w: usize,
h: usize,
pw: usize,
bit_mask: u64,
sub_band_type: SubBandType,
style: &CodeBlockStyle,
) {
if style.vertically_causal_context {
cleanup_pass_impl::<true>(
magnitudes,
states,
neighbors,
encoder,
contexts,
w,
h,
pw,
bit_mask,
sub_band_type,
);
} else {
cleanup_pass_impl::<false>(
magnitudes,
states,
neighbors,
encoder,
contexts,
w,
h,
pw,
bit_mask,
sub_band_type,
);
}
}
#[expect(clippy::cast_possible_truncation, reason = "four-row run position")]
#[expect(clippy::too_many_arguments, reason = "explicit hot scan state")]
fn cleanup_pass_impl<const VERTICAL_CAUSAL: bool>(
magnitudes: &[u64],
states: &mut [u8],
neighbors: &mut [u8],
encoder: &mut ArithmeticEncoder,
contexts: &mut [ArithmeticEncoderContext; 19],
w: usize,
h: usize,
pw: usize,
bit_mask: u64,
sub_band_type: SubBandType,
) {
for y_base in (0..h).step_by(4) {
for x in 0..w {
let y_end = (y_base + 4).min(h);
let stripe_height = y_end - y_base;
if stripe_height == 4 {
let mut all_zero_uncoded = true;
for y in y_base..y_end {
let idx = (y + 1) * pw + (x + 1);
if states[idx] & (SIGNIFICANT | CODED_IN_CURRENT_PASS) != 0
|| effective_neighbor_sig::<VERTICAL_CAUSAL>(neighbors[idx], y, h) != 0
{
all_zero_uncoded = false;
break;
}
}
if all_zero_uncoded {
let mut first_sig = None;
for (j, y) in (y_base..y_end).enumerate() {
let idx = (y + 1) * pw + (x + 1);
if magnitudes[idx] & bit_mask != 0 {
first_sig = Some(j);
break;
}
}
if let Some(pos) = first_sig {
encoder.encode(1, &mut contexts[17]); encoder.encode((pos >> 1) as u32 & 1, &mut contexts[18]); encoder.encode(pos as u32 & 1, &mut contexts[18]);
let y = y_base + pos;
let idx = (y + 1) * pw + (x + 1);
encode_sign::<VERTICAL_CAUSAL>(
idx, neighbors, states, encoder, contexts, pw, y, h,
);
set_significant(idx, states, neighbors, pw);
for y in (y_base + pos + 1)..y_end {
let idx = (y + 1) * pw + (x + 1);
if states[idx] & (SIGNIFICANT | CODED_IN_CURRENT_PASS) == 0 {
let ctx_label = zero_coding_ctx(
effective_neighbor_sig::<VERTICAL_CAUSAL>(neighbors[idx], y, h),
sub_band_type,
);
let bit = u32::from(magnitudes[idx] & bit_mask != 0);
encoder.encode(bit, &mut contexts[ctx_label as usize]);
if bit == 1 {
encode_sign::<VERTICAL_CAUSAL>(
idx, neighbors, states, encoder, contexts, pw, y, h,
);
set_significant(idx, states, neighbors, pw);
}
}
}
continue;
}
encoder.encode(0, &mut contexts[17]);
continue;
}
}
for y in y_base..y_end {
let idx = (y + 1) * pw + (x + 1);
if states[idx] & (SIGNIFICANT | CODED_IN_CURRENT_PASS) == 0 {
let ctx_label = zero_coding_ctx(
effective_neighbor_sig::<VERTICAL_CAUSAL>(neighbors[idx], y, h),
sub_band_type,
);
let bit = u32::from(magnitudes[idx] & bit_mask != 0);
encoder.encode(bit, &mut contexts[ctx_label as usize]);
if bit == 1 {
encode_sign::<VERTICAL_CAUSAL>(
idx, neighbors, states, encoder, contexts, pw, y, h,
);
set_significant(idx, states, neighbors, pw);
}
}
}
}
}
}
#[expect(clippy::too_many_arguments, reason = "explicit hot sign state")]
fn encode_sign<const VERTICAL_CAUSAL: bool>(
idx: usize,
neighbors: &[u8],
states: &[u8],
encoder: &mut ArithmeticEncoder,
contexts: &mut [ArithmeticEncoderContext; 19],
pw: usize,
y: usize,
h: usize,
) {
let significances =
effective_neighbor_sig::<VERTICAL_CAUSAL>(neighbors[idx], y, h) & 0b0101_0101;
let top_sign = if states[idx - pw] & SIGNIFICANT != 0 {
u8::from((states[idx - pw] & NEGATIVE) != 0)
} else {
0
};
let left_sign = if states[idx - 1] & SIGNIFICANT != 0 {
u8::from((states[idx - 1] & NEGATIVE) != 0)
} else {
0
};
let right_sign = if states[idx + 1] & SIGNIFICANT != 0 {
u8::from((states[idx + 1] & NEGATIVE) != 0)
} else {
0
};
let bottom_sign = if VERTICAL_CAUSAL && neighbor_in_next_stripe(y, h) {
0
} else if states[idx + pw] & SIGNIFICANT != 0 {
u8::from((states[idx + pw] & NEGATIVE) != 0)
} else {
0
};
let sign_bits = (top_sign << 6) | (left_sign << 4) | (right_sign << 2) | bottom_sign;
let negative_sigs = significances & sign_bits;
let positive_sigs = significances & !sign_bits;
let merged = (negative_sigs << 1) | positive_sigs;
let (ctx_label, xor_bit) = SIGN_CONTEXT_LOOKUP[merged as usize];
let sign_bit = u32::from((states[idx] & NEGATIVE) != 0);
encoder.encode(
sign_bit ^ u32::from(xor_bit),
&mut contexts[ctx_label as usize],
);
}
fn encode_sign_raw(idx: usize, states: &[u8], writer: &mut BitWriter) {
let is_significant = states[idx] & SIGNIFICANT != 0;
debug_assert!(!is_significant);
writer.write_bit(u32::from((states[idx] & NEGATIVE) != 0));
}
#[inline]
fn neighbor_in_next_stripe(y: usize, height: usize) -> bool {
y + 1 < height && ((y + 1) >> 2) > (y >> 2)
}
#[expect(clippy::inline_always, reason = "Tier-1 coefficient-loop hot path")]
#[inline(always)]
fn effective_neighbor_sig<const VERTICAL_CAUSAL: bool>(
neighbor_sig: u8,
y: usize,
height: usize,
) -> u8 {
if VERTICAL_CAUSAL && neighbor_in_next_stripe(y, height) {
neighbor_sig & 0b1111_0100
} else {
neighbor_sig
}
}
#[inline]
fn zero_coding_ctx(neighbor_sig: u8, sub_band_type: SubBandType) -> u8 {
match sub_band_type {
SubBandType::LowLow | SubBandType::LowHigh => ZERO_CTX_LL_LH[neighbor_sig as usize],
SubBandType::HighLow => ZERO_CTX_HL[neighbor_sig as usize],
SubBandType::HighHigh => ZERO_CTX_HH[neighbor_sig as usize],
}
}
#[inline]
fn magnitude_refinement_ctx(state: u8, neighbor_sig: u8) -> u8 {
if state & MAGNITUDE_REFINED != 0 {
16
} else {
14 + neighbor_sig.min(1)
}
}
fn set_significant(idx: usize, states: &mut [u8], neighbors: &mut [u8], pw: usize) {
states[idx] |= SIGNIFICANT;
let top = idx - pw;
let bottom = idx + pw;
neighbors[top - 1] |= 1 << 1; neighbors[top] |= 1; neighbors[top + 1] |= 1 << 3; neighbors[idx - 1] |= 1 << 2; neighbors[idx + 1] |= 1 << 4; neighbors[bottom - 1] |= 1 << 5; neighbors[bottom] |= 1 << 6; neighbors[bottom + 1] |= 1 << 7; }