Skip to main content

trueno/backends/q6k/
mod.rs

1//! Fused Q6_K Matrix-Vector Multiply
2//!
3//! Q6_K format (210 bytes per 256 elements):
4//! - `ql`: 128 bytes (lower 4 bits of each value)
5//! - `qh`: 64 bytes (upper 2 bits, packed 4 values per byte)
6//! - `scales`: 16 bytes (8-bit scales for 16 groups of 16 values)
7//! - `d`: 2 bytes (f16 global scale)
8
9// Sub-modules
10mod colmajor;
11mod gemv;
12
13// Re-exports
14#[allow(deprecated)]
15pub use colmajor::{matmul_q6k_f32_colmajor, matmul_q6k_f32_colmajor_dispatch};
16pub use gemv::{matmul_q6k_f32, matmul_q6k_f32_dispatch, matmul_q6k_f32_scalar};
17
18// Constants (pub(crate) for submodule access)
19pub(crate) const SUPER_BLOCK_SIZE: usize = 256;
20pub(crate) const SUPER_BLOCK_BYTES: usize = 210;
21
22/// Convert f16 bits to f32
23#[inline(always)]
24pub(crate) fn f16_to_f32(bits: u16) -> f32 {
25    let sign = ((bits & 0x8000) as u32) << 16;
26    let exp = (bits >> 10) & 0x1F;
27    let mantissa = (bits & 0x3FF) as u32;
28
29    if exp == 0 {
30        if mantissa == 0 {
31            f32::from_bits(sign)
32        } else {
33            // Subnormal
34            let mut m = mantissa;
35            let mut e = 0i32;
36            while (m & 0x400) == 0 {
37                m <<= 1;
38                e -= 1;
39            }
40            let new_exp = ((127 - 15 + 1 + e) as u32) << 23;
41            let new_mantissa = (m & 0x3FF) << 13;
42            f32::from_bits(sign | new_exp | new_mantissa)
43        }
44    } else if exp == 31 {
45        f32::from_bits(sign | (0xFF << 23) | (mantissa << 13))
46    } else {
47        let new_exp = ((exp as i32 - 15 + 127) as u32) << 23;
48        f32::from_bits(sign | new_exp | (mantissa << 13))
49    }
50}
51
52#[cfg(test)]
53mod tests_core;
54#[cfg(test)]
55mod tests_extended;