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;