use super::QuantValue;
use alloc::vec::Vec;
use num_traits::PrimInt;
pub fn pack_i8s_to_u32s(values: Vec<i8>) -> Vec<u32> {
values
.chunks(4)
.map(|x| {
x.iter()
.enumerate()
.fold(0u32, |acc, (i, x)| acc | (*x as u32 & 0xFF) << (i * 8))
})
.collect()
}
pub(super) fn unpack_q_to_i8s<Q: PrimInt>(
values: &[Q],
numel: usize,
value: &QuantValue,
) -> Vec<i8> {
let size_store = size_of::<Q>() * 8;
let size_quant = value.size_bits();
let num_quants = size_store / size_quant;
let mask = Q::from((1 << size_quant) - 1).unwrap();
let sign_shift = 8 - size_quant; values
.iter()
.enumerate()
.flat_map(|(i, &packed)| {
let n = core::cmp::min(num_quants, numel - i * num_quants);
(0..n).map(move |i| {
let raw = (packed >> (i * size_quant) & mask).to_u8().unwrap();
((raw << sign_shift) as i8) >> sign_shift
})
})
.collect()
}