use super::super::build::SubBandType;
use j2k_codec_math::classic::{
SIGN_CONTEXT_LOOKUP, ZERO_CTX_HH_LOOKUP, ZERO_CTX_HL_LOOKUP, ZERO_CTX_LL_LH_LOOKUP,
};
pub(super) const SIGMA_THIS: u32 = 1 << 4;
pub(super) const SIGMA_NEIGHBOURS: u32 = 0x1EF;
pub(super) const MU_THIS: u32 = 1 << 20;
pub(super) const PI_THIS: u32 = 1 << 21;
pub(super) const PI_ALL: u32 = PI_THIS | PI_THIS << 3 | PI_THIS << 6 | PI_THIS << 9;
const fn zero_coding_window_table(byte_table: &[u8; 256]) -> [u8; 512] {
const fn bit(window: usize, index: usize) -> usize {
(window >> index) & 1
}
let mut table = [0_u8; 512];
let mut window = 0;
while window < 512 {
let byte = (bit(window, 0) << 7)
| (bit(window, 1) << 6)
| (bit(window, 2) << 5)
| (bit(window, 3) << 4)
| (bit(window, 6) << 3)
| (bit(window, 5) << 2)
| (bit(window, 8) << 1)
| bit(window, 7);
table[window] = byte_table[byte];
window += 1;
}
table
}
static ZERO_CODING_LL_LH: [u8; 512] = zero_coding_window_table(&ZERO_CTX_LL_LH_LOOKUP);
static ZERO_CODING_HL: [u8; 512] = zero_coding_window_table(&ZERO_CTX_HL_LOOKUP);
static ZERO_CODING_HH: [u8; 512] = zero_coding_window_table(&ZERO_CTX_HH_LOOKUP);
pub(super) fn zero_coding_table(sub_band_type: SubBandType) -> &'static [u8; 512] {
match sub_band_type {
SubBandType::LowLow | SubBandType::LowHigh => &ZERO_CODING_LL_LH,
SubBandType::HighLow => &ZERO_CODING_HL,
SubBandType::HighHigh => &ZERO_CODING_HH,
}
}
#[expect(
clippy::inline_always,
reason = "Tier-1 context lookup is a measured coefficient-loop hot path"
)]
#[inline(always)]
pub(super) fn zero_coding_label(table: &[u8; 512], flags: u32, row: u32) -> u8 {
table[((flags >> (3 * row)) & SIGMA_NEIGHBOURS) as usize]
}
#[expect(
clippy::inline_always,
reason = "Tier-1 context lookup is a measured coefficient-loop hot path"
)]
#[inline(always)]
pub(super) fn sign_coding_label(flags: u32, left: u32, right: u32, row: u32) -> (u8, u8) {
let window = flags >> (3 * row);
let significances = (((window >> 1) & 1) << 6)
| (((window >> 3) & 1) << 4)
| (((window >> 5) & 1) << 2)
| ((window >> 7) & 1);
let north_sign_bit = if row == 0 { 18 } else { 16 + 3 * row };
let signs = (((flags >> north_sign_bit) & 1) << 6)
| (((left >> (19 + 3 * row)) & 1) << 4)
| (((right >> (19 + 3 * row)) & 1) << 2)
| ((flags >> (22 + 3 * row)) & 1);
let merged = ((significances & signs) << 1) | (significances & !signs);
SIGN_CONTEXT_LOOKUP[merged as usize]
}
#[expect(clippy::inline_always, reason = "Tier-1 coefficient-loop hot path")]
#[inline(always)]
pub(super) fn set_significant(
flags: &mut [u32],
own: &mut u32,
index: usize,
stride: usize,
row: u32,
sign: u32,
) {
let shift = 3 * row;
*own |= (SIGMA_THIS | sign << 19) << shift;
flags[index - 1] |= (1 << 5) << shift;
flags[index + 1] |= (1 << 3) << shift;
if row == 0 {
let north = index - stride;
flags[north - 1] |= 1 << 17;
flags[north] |= 1 << 16 | sign << 31;
flags[north + 1] |= 1 << 15;
} else if row == 3 {
let south = index + stride;
flags[south - 1] |= 1 << 2;
flags[south] |= 1 << 1 | sign << 18;
flags[south + 1] |= 1;
}
}