#![expect(
clippy::inline_always,
reason = "the row operations must inline into the kernel compiled for the instruction set, or they run without it"
)]
#![expect(
unsafe_code,
reason = "row operations and loads through pointers bounds-checked on entry"
)]
use super::row::Row;
use super::{GROUP, LANES, ROWS, WORD_BYTES, group_bytes, mask};
#[inline(always)]
pub(super) unsafe fn pack<R: Row, const W: u32>(src: &[u32], out: &mut [u8]) {
assert!(src.len() >= R::GROUPS * GROUP, "a group's numbers");
assert!(out.len() >= R::GROUPS * group_bytes(W), "a group's bytes");
let rows = src.as_ptr();
let dst = out.as_mut_ptr();
let (src_stride, out_stride) = (GROUP, group_bytes(W));
unsafe {
let mut acc = R::zero();
let (mut filled, mut word) = (0u32, 0usize);
for r in 0..ROWS {
let row = R::load_words(rows.add(r * LANES), src_stride);
acc = acc.or(row.shl(filled));
filled += W;
if filled >= u32::BITS {
acc.store_bytes(dst.add(word * LANES * WORD_BYTES), out_stride);
word += 1;
filled -= u32::BITS;
acc = if filled == 0 {
R::zero()
} else {
row.shr(W - filled)
};
}
}
}
}
#[inline(always)]
pub(super) unsafe fn unpack<R: Row, const W: u32>(src: &[u8], out: &mut [u32]) {
assert!(src.len() >= R::GROUPS * group_bytes(W), "a group's bytes");
assert!(out.len() >= R::GROUPS * GROUP, "a group's numbers");
let words = src.as_ptr();
let rows = out.as_mut_ptr();
let (src_stride, out_stride) = (group_bytes(W), GROUP);
unsafe {
let m = R::splat(mask(W));
let mut cur = R::load_bytes(words, src_stride);
let (mut used, mut word) = (0u32, 1usize);
for r in 0..ROWS {
let end = used + W;
let v = if end > u32::BITS {
let next = R::load_bytes(words.add(word * LANES * WORD_BYTES), src_stride);
word += 1;
let v = cur.shr(used).or(next.shl(u32::BITS - used));
cur = next;
used = end - u32::BITS;
v
} else {
let v = cur.shr(used);
used = end;
if used == u32::BITS && word < W as usize {
cur = R::load_bytes(words.add(word * LANES * WORD_BYTES), src_stride);
word += 1;
used = 0;
}
v
};
v.and(m).store_words(rows.add(r * LANES), out_stride);
}
}
}