Expand description
ferrox-quant: dequantization kernels for the block-quantized tensor formats used by GGUF files (Q4_0, Q8_0, Q4_K, Q5_K, Q6_K).
These block layouts are a public, widely documented convention
(originated in ggml). The functions here are independent
implementations written against that public layout description, not
copied from any other project’s source. Q4_K and Q6_K in particular
are the dominant real-world GGUF quantization formats (most
published checkpoints ship as Q4_K_M or similar K-quant mixes, not
the legacy Q4_0/Q8_0 formats). These are checked against independent
Python cross-validation, following the same discipline as
ferrox-models’
GGUF-roundtrip tests.
Re-exports§
pub use repack::gemm_q4_0x4_group;pub use repack::gemm_q4_0x4_group_x4;pub use repack::gemm_q4_kx8_group;pub use repack::gemm_q4_kx8_group_x4;pub use repack::gemm_q5_kx8_group;pub use repack::gemm_q5_kx8_group_x4;pub use repack::gemm_q6_kx8_group;pub use repack::gemm_q6_kx8_group_x4;pub use repack::gemm_q8_0x4_group;pub use repack::gemm_q8_0x4_group_x4;pub use repack::gemv_q4_0x4_group;pub use repack::gemv_q4_kx8_group;pub use repack::gemv_q4_kx8_q8_k;pub use repack::gemv_q5_kx8_group;pub use repack::gemv_q5_kx8_q8_k;pub use repack::gemv_q6_kx8_group;pub use repack::gemv_q6_kx8_q8_k;pub use repack::gemv_q8_0x4_group;pub use repack::gemv_q8_0x4_q8_0;pub use repack::make_block_q4_0x4;pub use repack::make_block_q4_kx8;pub use repack::make_block_q5_kx8;pub use repack::make_block_q6_kx8;pub use repack::make_block_q8_0x4;pub use repack::pack_q4_0_matrix_x4;pub use repack::pack_q4_k_matrix_x8;pub use repack::pack_q5_k_matrix_x8;pub use repack::pack_q6_k_matrix_x8;pub use repack::pack_q8_0_matrix_x4;pub use repack::prepare_q8_acts_x4;pub use repack::prepare_q8_k_acts_x4;pub use repack::q4_0x4_gemm_uses_acts_x4;pub use repack::q4_0x4_interleave;pub use repack::q4_kx8_gemm_uses_acts_x4;pub use repack::q4_kx8_interleave;pub use repack::q5_kx8_gemm_uses_acts_x4;pub use repack::q5_kx8_interleave;pub use repack::q6_kx8_gemm_uses_acts_x4;pub use repack::q6_kx8_interleave;pub use repack::q8_0x4_gemm_uses_acts_x4;pub use repack::q8_0x4_interleave;pub use repack::Q8ActsX4;pub use repack::Q8KActsX4;pub use repack::Q4_0X4_BLOCK_BYTES;pub use repack::Q4_0X4_GEMM_NC;pub use repack::Q4_0X4_INTERLEAVE;pub use repack::Q4_0X4_NROWS;pub use repack::Q4_KX8_BLOCK_BYTES;pub use repack::Q4_KX8_GEMM_NC;pub use repack::Q4_KX8_NROWS;pub use repack::Q5_KX8_BLOCK_BYTES;pub use repack::Q5_KX8_GEMM_NC;pub use repack::Q5_KX8_NROWS;pub use repack::Q6_KX8_BLOCK_BYTES;pub use repack::Q6_KX8_GEMM_NC;pub use repack::Q6_KX8_NROWS;pub use repack::Q8K_ACTS_X4_NC;pub use repack::Q8_0X4_BLOCK_BYTES;pub use repack::Q8_0X4_GEMM_NC;pub use repack::Q8_0X4_INTERLEAVE;pub use repack::Q8_0X4_NROWS;
Modules§
- iq_
tables - Codebook/grid tables for the IQ1_S / IQ1_M / IQ2_XXS / IQ2_XS / IQ2_S / IQ3_XXS / IQ3_S quantization formats.
- repack
- Interleaved Q4_K / Q5_K × Q8_K and Q8_0 × Q8 GEMV (llama.cpp repack layouts).
Structs§
- Q8Activations
- An activation vector quantized to signed 8-bit in 32-element blocks,
each with its own f32 scale (
d), so it can feed the integervec_dotpaths against Q8_0 weights. This mirrors llama.cpp’squantize_row_q8_1(minus the block sum, which is only needed for asymmetric weight formats): quantizing the shared activation once per matvec turns every weight-row dot into an int8×int8 → int32 reduction (vdotq_s32/_mm256_maddubs-class ops) plus a single scale, which is what lets llama.cpp’s CPU matmul stay in integer SIMD. - Q8KActivations
- ggml
block_q8_Kactivations for K-quant int-dot (Q4_K/Q5_K/Q6_K). Super-blocks of 256 elements with 16-widebsumsfor the min term.
Enums§
Constants§
- FP8_
KV_ BLOCK_ BYTES - FP8_
KV_ GROUP - Metal
FERROX_CTK=fp8KV block: 32 elems → f16 scale + 32 E4M3-ish bytes. Codes are absmax-scaled int8 in [-127,127] (portable stand-in for E4M3). - IQ1_
M_ BLOCK_ BYTES - IQ1_M: 32 low-index bytes + 16 qh bytes (3 high index bits + a
sign-of-delta bit per 8-element group) + 8 scale bytes. 1.75 bpw.
The only IQ format with no f16 scale field – see
for_each_iq1_m. - IQ1_
M_ BLOCK_ ELEMS - IQ1_
S_ BLOCK_ BYTES - IQ1_S: d(f16) + 32 low-index bytes + 8 u16 (3 high index bits + 3 scale bits + sign-of-delta per 32-element group). 1.5625 bpw.
- IQ1_
S_ BLOCK_ ELEMS - IQ2_
S_ BLOCK_ BYTES - IQ2_S: d(f16) + 32 low-index bytes + 32 literal sign bytes + 8 qh bytes (2 high index bits per group of 8) + 8 scale bytes. 2.5625 bpw.
- IQ2_
S_ BLOCK_ ELEMS - IQ2_
XS_ BLOCK_ BYTES - IQ2_XS: d(f16) + 32 u16 codes (9-bit grid index + 7-bit sign index)
- IQ2_
XS_ BLOCK_ ELEMS - IQ2_
XXS_ BLOCK_ BYTES - IQ2_XXS: d(f16) + 32 u16 codes (grid indices + packed scale/signs). 2.0625 bpw.
- IQ2_
XXS_ BLOCK_ ELEMS - IQ3_
S_ BLOCK_ BYTES - IQ3_S: d(f16) + 64 low-index bytes + 8 qh bytes (one 9th index bit per grid code) + 32 literal sign bytes + 4 scale bytes (two 4-bit scales per pair of 32-element groups). 3.4375 bpw.
- IQ3_
S_ BLOCK_ ELEMS - IQ3_
XXS_ BLOCK_ BYTES - IQ3_XXS: d(f16) + 64 grid-index bytes + 8 u32 scale/sign words. 3.0625 bpw.
- IQ3_
XXS_ BLOCK_ ELEMS - IQ4_
NL_ BLOCK_ BYTES - IQ4_
NL_ BLOCK_ ELEMS - IQ4_
XS_ BLOCK_ BYTES - IQ4_
XS_ BLOCK_ ELEMS - MXFP4_
GGUF_ BLOCK_ BYTES - GGUF block-MXFP4 (ggml type tag 39): one 17-byte block = 1 E8M0
scale byte + 16 nibble bytes covering 32 elements, low nibble ->
element
j, high nibble -> elementj+16. Same E2M1 codebook and E8M0 scale math as the Kimi safetensors two-buffer MXFP4 path above (dot_mxfp4_row_f32) – ggml expresses it as doubled-integer kvalues times a half scale (2^(e-128)), this module as true E2M1 values times the full2^(e-127)scale; the products are identical across the whole E8M0 range including thee < 2denormal patterns. Only the byte layout differs: interleaved 17-byte blocks in one stream here, two separate packed/scale tensors there. - MXFP4_
GGUF_ BLOCK_ ELEMS - MXFP4_
GROUP_ SIZE - Elements per MXFP4 scale group (real, confirmed both from ggml’s
QK_MXFP4and directly from a real Kimi K3 shard’s own tensor shapes:*.weight_scaleisin_dim/32bytes,*.weight_packedisin_dim/2bytes). - Q2_
K_ BLOCK_ BYTES - Q2_K: a 256-element super-block, 16 sub-blocks of 16, each with its
own 4-bit scale and 4-bit min packed one byte per sub-block (not
Q4_K’s cross-byte 6-bit packing – a real, verified difference, not
assumed), plus one shared f16 super-block scale
dand f16 super-block min-scaledmin. Layout: scales(16) + qs(64) + d(2) + dmin(2) = 84 bytes – noted/dmincome afterscales/qs, the opposite field order from every other K-quant format here, verified directly against realggml-common.h/ggml-quants.csource (block_q2_K,dequantize_row_q2_K). - Q2_
K_ BLOCK_ ELEMS - Q3_
K_ BLOCK_ BYTES - Q3_K: a 256-element super-block, 16 sub-blocks of 16, each with its
own signed 6-bit scale (packed via a byte-wise interleaving scheme
across 12 bytes, verified against
dequantize_row_q3_K’s realaux[]unpacking – seeq3_k_unpack_scales’s doc comment), a 3-bit value per element (2 low bits fromqs, 1 high bit fromhmask, centered by-4when the high bit is clear), scaled by one shared f16d. Layout: hmask(32) + qs(64) + scales(12) + d(2) = 110 bytes. - Q3_
K_ BLOCK_ ELEMS - Q4_
0_ BLOCK_ BYTES - Q4_0: 32 packed 4-bit values (16 bytes) sharing one f16 scale. 18 bytes per block.
- Q4_
0_ BLOCK_ ELEMS - Q4_
1_ BLOCK_ BYTES - Q4_1: like Q4_0 but asymmetric – an f16 scale
dand an f16 minm(value =q*d + m, no-8bias), 32 packed 4-bit values. Layout: d(2) + m(2) + qs(16) = 20 bytes. Verified against realggml-common.h/ggml-quants.csource, not guessed. - Q4_
1_ BLOCK_ ELEMS - Q4_
K_ BLOCK_ BYTES - Q4_K: a 256-element super-block, split into 8 32-element sub-blocks,
each with its own 6-bit scale and 6-bit min (packed into 12 bytes),
plus one shared f16 scale-of-scales
dand scale-of-minsdmin. Layout: d(2) + dmin(2) + scales(12) + qs(128) = 144 bytes. - Q4_
K_ BLOCK_ ELEMS - Q5_
0_ BLOCK_ BYTES - Q5_0: like Q4_0 (single f16 scale
d, symmetric-16bias) but each element gets a 5th bit from a 4-byteqhbitplane. Layout: d(2) + qh(4) + qs(16) = 22 bytes. - Q5_
0_ BLOCK_ ELEMS - Q5_
1_ BLOCK_ BYTES - Q5_1: Q5_0’s 5th-bit scheme combined with Q4_1’s asymmetric
d+m(no bias subtraction). Layout: d(2) + m(2) + qh(4) + qs(16) = 24 bytes. - Q5_
1_ BLOCK_ ELEMS - Q5_
K_ BLOCK_ BYTES - Q5_K: the same 8-sub-blocks-of-32 / 6-bit-scale-and-min layout as
Q4_K (same 12-byte packed scales, same unpacking), but each element
gets a 5th bit from a separate 32-byte
qhbitplane (one bit per element, 256 bits total) instead of Q4_K’s plain 4-bit nibble. Layout: d(2) + dmin(2) + scales(12) + qh(32) + qs(128) = 176 bytes. - Q5_
K_ BLOCK_ ELEMS - Q5_
K_ GEMM_ NC - How many activations one
gemm_q5_k_q8_row/gemm_q6_k_q8_rowkeeps in flight. Amortizes weight-block scale/qh/qs loads over the batch (Phi-4 Q5_K qkv / Q6_K ffn_down) without full Kx8 repack. - Q6_
K_ BLOCK_ BYTES - Q6_K: a 256-element super-block, split into 16 16-element sub-blocks
each with its own signed 8-bit scale, plus one shared f16
super-block scale
d. Layout: ql(128) + qh(64) + scales(16) + d(2) = 210 bytes. - Q6_
K_ BLOCK_ ELEMS - Q6_
K_ GEMM_ NC - Q8_
0_ BLOCK_ BYTES - Q8_0: 32 int8 values sharing one f16 scale. 34 bytes per block.
- Q8_
0_ BLOCK_ ELEMS - Q8_
1_ BLOCK_ BYTES - Q8_1: like Q8_0 (32 signed 8-bit values, one f16 scale
d) plus an extra f16 fieldsthat upstream ggml uses only as a precomputed per-block sum for its own fused SIMD dot-product kernels – not needed for correct dequantization, sincey = qs*dis unaffected by it. Layout: d(2) + s(2) + qs(32) = 36 bytes. - Q8_
1_ BLOCK_ ELEMS - TURB
O4_ KV_ BLOCK_ BYTES - TURB
O4_ KV_ GROUP - Metal
FERROX_CTK=turbo4KV block: 32 elems → f16 scale + 16 nibble bytes.
Functions§
- dequant_
bf16 - BF16 isn’t a block-quantized format at all – it’s IEEE-754 binary32
truncated to its sign bit + 8 exponent bits + 7 mantissa bits (the
upper 16 bits of an f32), so widening it back to f32 is an exact,
lossless bit shift:
f32::from_bits((bits as u32) << 16), zero- padding the low 16 mantissa bits rather than any real dequantization math. Included here anyway (rather than as a one-off inferrox-models::loader) so every real element type ferrox recognizes has one obvious home. - dequant_
f16 - F16 (IEEE-754 binary16) widened to f32. Like
dequant_bf16this is a plain element type, not a block format: every f16 value is exactly representable in f32, so the widening is lossless.GgmlType::F16is whatllama-quantize --pure-free conversions and every*-f16.ggufcarry, and it is also the dtype ggml uses fortoken_embdin some mixed checkpoints. - dequant_
iq1_ m - dequant_
iq1_ s - dequant_
iq2_ s - dequant_
iq2_ xs - dequant_
iq2_ xxs - dequant_
iq3_ s - dequant_
iq3_ xxs - dequant_
iq4_ nl - dequant_
iq4_ xs - dequant_
mxfp4_ gguf - dequant_
mxfp4_ row - Dequantizes one row of Kimi K3’s MXFP4-packed expert weights. Unlike
every other kernel in this module, MXFP4 here is NOT a single
interleaved byte stream – Kimi K3’s real safetensors checkpoint
stores the packed 4-bit codes and the per-group E8M0 scales as two
separate tensors (
*.weight_packed,*.weight_scale; confirmed directly against a real shard header’s tensor shapes, not ggml’s own combined-block GGUF convention), so this takes both buffers directly rather than one combined block stream.packedisin_dim/2bytes (2 nibble-packed E2M1 codes per byte, low-nibble-first-half / high-nibble-second-half within each 32-element group – same convention as this module’s other nibble-packed formats);scalesisin_dim/MXFP4_GROUP_SIZEbytes (one E8M0 scale byte per group). - dequant_
q2_ k - Dequantize a Q2_K buffer into f32. Formula verified against real
ggml-quants.c::dequantize_row_q2_K: 16 sub-blocks of 16 elements, each sub-block’s(scale, min)packed one byte per sub-block (sc & 0xF= 4-bit scale,sc >> 4= 4-bit min – much simpler than Q4_K’s cross-byte 6-bit packing), value =d*scale*raw2bit - dmin*min,raw2bitin 0..=3 (2 bits per element fromqs, 4 elements packed per byte). - dequant_
q3_ k - Dequantize a Q3_K buffer into f32. Formula verified against real
ggml-quants.c::dequantize_row_q3_K: 16 sub-blocks of 16 elements, value =d_all*(scale-32)*(raw3bit-bias),raw3bit= 2 bits fromqsplus 1 high bit fromhmask(bitm,msweeping all 8 bit positions across the whole block –hmaskis indexed the same way regardless of which half ofqsis active, only the bit tested changes),bias= 4 when the high bit is clear, 0 when set. - dequant_
q4_ 0 - Dequantize a Q4_0 buffer into f32. Each byte packs two 4-bit nibbles (low nibble = element i, high nibble = element i+16), each nibble biased by -8 before scaling, matching the public Q4_0 convention.
- dequant_
q4_ 1 - Dequantize a Q4_1 buffer into f32. Formula verified against real
ggml-quants.c::dequantize_row_q4_1:y = q*d + m, no bias subtraction (unlike Q4_0’s symmetricq-8). - dequant_
q4_ k - Dequantize a Q4_K buffer into f32. See the module doc comment and
Q4_K_BLOCK_BYTESfor the block layout. - dequant_
q5_ 0 - Dequantize a Q5_0 buffer into f32. Formula verified against real
ggml-quants.c::dequantize_row_q5_0: symmetric,y = (q-16)*dwhereqis the 4-bit nibble with the 5th bit fromqhORed in. - dequant_
q5_ 1 - Dequantize a Q5_1 buffer into f32. Formula verified against real
ggml-quants.c::dequantize_row_q5_1: Q5_0’s 5th-bit scheme, but asymmetric like Q4_1 (y = q*d + m, no-16bias). - dequant_
q5_ k - Dequantize a Q5_K buffer into f32. See the module doc comment and
Q5_K_BLOCK_BYTESfor the block layout. Shares Q4_K’s scale/min packing (q4_k_scale_min) and 4-outer-iteration structure; the only difference is each nibble gets a 5th bit fromqh, whose 32 bytes are reused across all 4 outer iterations at different bit positions (u1/u2, doubling by 4 each iteration) rather than being consumed sequentially the wayqsis. - dequant_
q6_ k - Dequantize a Q6_K buffer into f32. See the module doc comment and
Q6_K_BLOCK_BYTESfor the block layout. - dequant_
q8_ 0 - Dequantize a Q8_0 buffer into f32.
- dequant_
q8_ 1 - Dequantize a Q8_1 buffer into f32. Formula verified against real
ggml-quants.c::dequantize_row_q8_1: identical to Q8_0 (y = q*d) – the extrasfield (upstream: a precomputed per-block sum used only by ggml’s own fused SIMD dot kernels) doesn’t change the dequantized value and is intentionally unread here. - dot_
iq1_ m_ f32 - dot_
iq1_ m_ f32_ scalar - dot_
iq1_ s_ f32 - dot_
iq1_ s_ f32_ scalar - dot_
iq2_ s_ f32 - dot_
iq2_ s_ f32_ scalar - dot_
iq2_ xs_ f32 - IQ2_XS / IQ2_S / IQ3_S / IQ1_M dispatch: scalar only. These landed
for coverage – before them, tags 17/21/22/29 fell to
GgmlType::Otherand the tensor could not be decoded at all, which silently ruled out 5 of the 16 published UnslothUD-*variants. They deliberately match the state of their older siblings’ NEON/GPU story (none), rather than growing a vectorized path that no golden vector would then be able to distinguish from the scalar one. - dot_
iq2_ xs_ f32_ scalar - dot_
iq2_ xxs_ f32 - dot_
iq2_ xxs_ f32_ scalar - dot_
iq3_ s_ f32 - dot_
iq3_ s_ f32_ scalar - dot_
iq3_ xxs_ f32 - dot_
iq3_ xxs_ f32_ scalar - dot_
iq4_ nl_ f32 - Fused IQ4_NL dequant+dot, same math as
dequant_iq4_nl. Dispatches to AVX2+FMA or NEON when available, same mechanism asdot_q4_0_f32. - dot_
iq4_ nl_ f32_ scalar - dot_
iq4_ xs_ f32 - Fused IQ4_XS dequant+dot, same math as
dequant_iq4_xs. Dispatches to AVX2+FMA or NEON when available, same mechanism asdot_q4_0_f32. - dot_
iq4_ xs_ f32_ scalar - dot_
mxfp4_ gguf_ f32 - GGUF block-MXFP4 dispatch: scalar only so far (the two-buffer safetensors MXFP4 form has AVX2/NEON kernels above; this block form hasn’t needed one yet).
- dot_
mxfp4_ gguf_ f32_ scalar - dot_
mxfp4_ row_ f32 - Fused MXFP4 dequant+dot, same math as
dequant_mxfp4_row. Dispatches to AVX2+FMA or NEON when available (seesimd_x86::dot_mxfp4_row_f32_avx2/simd_aarch64::dot_mxfp4_row_f32_neon), same mechanism asdot_q4_0_f32– this is the hot path for every routed expert’s FFN in a real Kimi K3 forward pass, so unlike Q4_0/Q8_0’s optional legacy-format status, keeping this scalar-only directly costs real inference speed. - dot_
mxfp4_ row_ f32_ scalar - dot_
q2_ k_ f32 - Fused Q2_K dequant+dot, same math as
dequant_q2_k. Dispatches to AVX2+FMA or NEON when available, same mechanism asdot_q4_k_f32. - dot_
q2_ k_ f32_ scalar - dot_
q3_ k_ f32 - Fused Q3_K dequant+dot, same math as
dequant_q3_k. Dispatches to AVX2+FMA or NEON when available, same mechanism asdot_q4_k_f32. - dot_
q3_ k_ f32_ scalar - dot_
q4_ 0_ f32 - Same idea for Q4_0: fused dequant + dot, no intermediate f32 buffer.
Dispatches to AVX2+FMA when available, same mechanism as
dot_q8_0_f32. - dot_
q4_ 0_ f32_ scalar - dot_
q4_ 0_ q8 - Integer
vec_dotof a Q4_0 weight row against pre-quantized Q8 activations (llama.cppggml_vec_dot_q4_0_q8_0). Opt-in viaFERROX_CPU_INT_DOTfor Q4_0 matvecs. - dot_
q4_ 0_ q8_ 2row - Two contiguous Q4_0 rows × one Q8 act (shared act loads). Faster than
two
dot_q4_0_q8calls on Apple DotProd. - dot_
q4_ 0_ q8_ scalar - dot_
q4_ 1_ f32 - Fused Q4_1 dequant+dot, same math as
dequant_q4_1. Dispatches to AVX2+FMA or NEON when available, same mechanism asdot_q4_0_f32. - dot_
q4_ 1_ f32_ scalar - dot_
q4_ k_ f32 - Fused Q4_K dequant+dot: identical math to
dequant_q4_k, but accumulated directly againstxinstead of materializing a dequantized row. Dispatches to SIMD when the host CPU supports it, same mechanism asdot_q8_0_f32. - dot_
q4_ k_ f32_ scalar - dot_
q4_ k_ q8 - Integer
vec_dotof a Q4_K weight row againstQ8KActivations(llama.cppggml_vec_dot_q4_K_q8_K). Opt-in viaFERROX_CPU_INT_DOT. - dot_
q4_ k_ q8_ scalar - dot_
q5_ 0_ f32 - Fused Q5_0 dequant+dot, same math as
dequant_q5_0. Dispatches to AVX2+FMA or NEON when available, same mechanism asdot_q4_0_f32. - dot_
q5_ 0_ f32_ scalar - dot_
q5_ 1_ f32 - Fused Q5_1 dequant+dot, same math as
dequant_q5_1. Dispatches to AVX2+FMA or NEON when available, same mechanism asdot_q4_0_f32. - dot_
q5_ 1_ f32_ scalar - dot_
q5_ k_ f32 - Fused Q5_K dequant+dot: identical math to
dequant_q5_k, but accumulated directly againstxinstead of materializing a dequantized row. Dispatches to SIMD when available, same mechanism asdot_q8_0_f32. - dot_
q5_ k_ f32_ scalar - dot_
q5_ k_ q8 - Integer
vec_dotof a Q5_K weight row againstQ8KActivations(llama.cppggml_vec_dot_q5_K_q8_K). Opt-in viaFERROX_CPU_INT_DOT. - dot_
q5_ k_ q8_ scalar - dot_
q6_ k_ f32 - Fused Q6_K dequant+dot: identical math to
dequant_q6_k, but accumulated directly againstxinstead of materializing a dequantized row. Dispatches to SIMD when available, same mechanism asdot_q8_0_f32. - dot_
q6_ k_ f32_ scalar - dot_
q6_ k_ q8 - Integer
vec_dotof a Q6_K weight row againstQ8KActivations(llama.cppggml_vec_dot_q6_K_q8_K). Opt-in viaFERROX_CPU_INT_DOT. - dot_
q6_ k_ q8_ scalar - dot_
q8_ 0_ f32 - Fused dot product between one Q8_0-quantized row (stored as raw block bytes) and an f32 activation vector, without ever materializing a dequantized f32 copy of the row. This is the memory-bandwidth-saving trick llama.cpp’s quantized matmul kernels rely on: for large weight matrices, bandwidth (not FLOPs) dominates inference cost, and Q8_0 moves 4x fewer bytes than a dequant-then- matmul approach that expands every weight to f32 up front.
- dot_
q8_ 0_ f32_ scalar - dot_
q8_ 0_ q8 - Integer
vec_dotof a Q8_0 weight row against pre-quantized Q8 activations:Σ_blocks d_w * d_a * Σ_i (q_w · q_a). Dispatches to a NEONdotprod/ AVX2 kernel when available, else the scalar loop. Numerically ≈dot_q8_0_f32up to activation-quant error. - dot_
q8_ 0_ q8_ scalar - dot_
q8_ 1_ f32 - Fused Q8_1 dequant+dot, same math as
dequant_q8_1. Dispatches to AVX2+FMA or NEON when available – mathematically identical to Q8_0 (y = q*d), so the SIMD kernels are Q8_0’s kernels with the quantized bytes read from offset 4 instead of offset 2 (Q8_1’s block has an extra 2-byte field betweendand the int8 values). - dot_
q8_ 1_ f32_ scalar - gemm_
q5_ k_ q8_ row - One Q5_K weight row ×
acts.len()Q8_K activations →out[j]. - gemm_
q5_ k_ q8_ row_ scalar - gemm_
q6_ k_ q8_ row - One Q6_K weight row ×
acts.len()Q8_K activations →out[j]. - gemm_
q6_ k_ q8_ row_ scalar - pack_
fp8_ kv_ blocks - Pack f32 into Metal fp8-style KV blocks (scaled int8, Q8_0-compatible layout).
- pack_
turbo4_ kv_ blocks - Pack f32 into Metal turbo4 KV blocks (no WHT).
- quantize_
activations_ q8 - Quantize an activation row to
Q8Activations(32-element blocks, ggmlquantize_row_q8_0rounding:d = amax/127,q = round(x/d)).x.len()must be a multiple of 32. - quantize_
activations_ q8_ k - Quantize activations to ggml
Q8_K(256-elem super-blocks). Positive scale convention (d = amax/127) matching ourQ8_0path;bsumsenable the Q4_K min correction without re-scanningq. - quantize_
q8_ 0 - Quantize an f32 slice into Q8_0 blocks (used by test fixtures and by the CPU reference “quantize activations for a symmetric int8 matmul” path). Not performance tuned; correctness-first reference only.
- unpack_
fp8_ kv_ blocks - Unpack
pack_fp8_kv_blocks. - unpack_
turbo4_ kv_ blocks - Unpack
pack_turbo4_kv_blocks.