pub(crate) fn f16_to_f32(bits: u16) -> f32 {
trueno::f16_to_f32(bits)
}
#[inline]
pub(crate) fn extract_scale_min_apr(scales: &[u8], block_idx: usize) -> (f32, f32) {
let j = block_idx;
let (scale_bits, min_bits) = if j < 4 {
let d = scales[j] & 63;
let m = scales[j + 4] & 63;
(d, m)
} else {
let d = (scales[j + 4] & 0x0F) | ((scales[j - 4] >> 6) << 4);
let m = (scales[j + 4] >> 4) | ((scales[j] >> 6) << 4);
(d, m)
};
(f32::from(scale_bits), f32::from(min_bits))
}
pub(crate) fn dequantize_q4_k_apr(data: &[u8], num_elements: usize) -> Vec<f32> {
const QK_K: usize = 256; const SUPER_BLOCK_BYTES: usize = 2 + 2 + 12 + 128;
let num_blocks = num_elements.div_ceil(QK_K);
let total_bytes = num_blocks * SUPER_BLOCK_BYTES;
if total_bytes > data.len() {
return vec![0.0; num_elements];
}
let mut result = vec![0.0f32; num_blocks * QK_K];
for sb_idx in 0..num_blocks {
let sb_start = sb_idx * SUPER_BLOCK_BYTES;
let out_start = sb_idx * QK_K;
let d = f16_to_f32(u16::from_le_bytes([data[sb_start], data[sb_start + 1]]));
let dmin = f16_to_f32(u16::from_le_bytes([data[sb_start + 2], data[sb_start + 3]]));
let scales = &data[sb_start + 4..sb_start + 16];
let qs = &data[sb_start + 16..sb_start + 144];
let mut ys_index = out_start;
for j in (0..QK_K).step_by(64) {
let q = &qs[j / 2..j / 2 + 32];
let is = j / 32;
let (sc1, m1) = extract_scale_min_apr(scales, is);
let d1 = d * sc1;
let dm1 = dmin * m1;
let (sc2, m2) = extract_scale_min_apr(scales, is + 1);
let d2 = d * sc2;
let dm2 = dmin * m2;
for &byte in q {
result[ys_index] = d1 * (byte & 0xF) as f32 - dm1;
ys_index += 1;
}
for &byte in q {
result[ys_index] = d2 * (byte >> 4) as f32 - dm2;
ys_index += 1;
}
}
}
result.truncate(num_elements);
result
}
pub(crate) fn dequantize_q6_k_apr(data: &[u8], num_elements: usize) -> Vec<f32> {
const QK_K: usize = 256;
const SUPER_BLOCK_BYTES: usize = 210;
let num_blocks = num_elements.div_ceil(QK_K);
let total_bytes = num_blocks * SUPER_BLOCK_BYTES;
if total_bytes > data.len() {
return vec![0.0; num_elements];
}
let mut result = vec![0.0f32; num_blocks * QK_K];
for sb_idx in 0..num_blocks {
let sb_start = sb_idx * SUPER_BLOCK_BYTES;
let out_start = sb_idx * QK_K;
let ql = &data[sb_start..sb_start + 128];
let qh = &data[sb_start + 128..sb_start + 192];
let mut scales = [0i8; 16];
#[allow(clippy::cast_possible_wrap)]
for (i, scale) in scales.iter_mut().enumerate() {
*scale = data[sb_start + 192 + i] as i8;
}
let d = f16_to_f32(u16::from_le_bytes([
data[sb_start + 208],
data[sb_start + 209],
]));
for n in (0..QK_K).step_by(128) {
let idx = n / 128;
let sc = &scales[8 * idx..];
let ql_slice = &ql[64 * idx..];
let qh_slice = &qh[32 * idx..];
for l in 0..32 {
let is = l / 16;
let q1 = ((ql_slice[l] & 0xF) | ((qh_slice[l] & 3) << 4)) as i32 - 32;
let q2 = ((ql_slice[l + 32] & 0xF) | (((qh_slice[l] >> 2) & 3) << 4)) as i32 - 32;
let q3 = ((ql_slice[l] >> 4) | (((qh_slice[l] >> 4) & 3) << 4)) as i32 - 32;
let q4 = ((ql_slice[l + 32] >> 4) | (((qh_slice[l] >> 6) & 3) << 4)) as i32 - 32;
result[out_start + n + l] = d * (sc[is] as f32) * (q1 as f32);
result[out_start + n + l + 32] = d * (sc[is + 2] as f32) * (q2 as f32);
result[out_start + n + l + 64] = d * (sc[is + 4] as f32) * (q3 as f32);
result[out_start + n + l + 96] = d * (sc[is + 6] as f32) * (q4 as f32);
}
}
}
result.truncate(num_elements);
result
}
pub(crate) fn dequantize_q8_0_apr(data: &[u8], num_elements: usize) -> Vec<f32> {
const BLOCK_SIZE: usize = 34; const ELEMENTS_PER_BLOCK: usize = 32;
let num_blocks = num_elements.div_ceil(ELEMENTS_PER_BLOCK);
let total_bytes = num_blocks * BLOCK_SIZE;
if total_bytes > data.len() {
return vec![0.0; num_elements];
}
let mut result = vec![0.0f32; num_blocks * ELEMENTS_PER_BLOCK];
for blk in 0..num_blocks {
let blk_start = blk * BLOCK_SIZE;
let out_start = blk * ELEMENTS_PER_BLOCK;
let scale = f16_to_f32(u16::from_le_bytes([data[blk_start], data[blk_start + 1]]));
#[allow(clippy::cast_possible_wrap)]
for i in 0..ELEMENTS_PER_BLOCK {
let q = data[blk_start + 2 + i] as i8;
result[out_start + i] = scale * (q as f32);
}
}
result.truncate(num_elements);
result
}
pub(crate) fn dequantize_apr_q8_native(data: &[u8], num_elements: usize) -> Vec<f32> {
if data.len() < 4 {
return vec![0.0; num_elements];
}
let scale = f32::from_le_bytes([data[0], data[1], data[2], data[3]]);
let mut result = Vec::with_capacity(num_elements);
#[allow(clippy::cast_possible_wrap)]
for i in 0..num_elements {
if 4 + i < data.len() {
result.push(scale * (data[4 + i] as i8) as f32);
} else {
result.push(0.0);
}
}
result
}
pub(crate) fn dequantize_apr_q4_native(data: &[u8], num_elements: usize) -> Vec<f32> {
const BLOCK_SIZE: usize = 32;
let mut result = Vec::with_capacity(num_elements);
let mut pos = 0;
let mut remaining = num_elements;
while remaining > 0 && pos + 2 <= data.len() {
let scale = f16_to_f32(u16::from_le_bytes([data[pos], data[pos + 1]]));
pos += 2;
let count = remaining.min(BLOCK_SIZE);
#[allow(clippy::cast_possible_wrap)]
for i in 0..count {
let byte_idx = pos + i / 2;
if byte_idx >= data.len() {
result.push(0.0);
continue;
}
let byte = data[byte_idx];
let nibble = if i % 2 == 0 { byte & 0x0F } else { byte >> 4 };
let q = (nibble as i8) - 8;
result.push(scale * (q as f32));
}
pos += 16; remaining -= count;
}
result.resize(num_elements, 0.0);
result
}
include!("dequant_falsify_gh44.rs");