code wiki / (root) / nx_q6_k_to_f32_test.nx

nx_q6_k_to_f32_test.nx source

↩ module page · 54 lines · 1861 B

1// nx_q6_k_to_f32_test.nx -- KAT for ggml-correct Q6_K dequant. 2// 3// Block layout: ql:128 + qh:64 + scales:16 + d:2 = 210 bytes. 4// Per ggml dequantize_row_q6_K, super-block produces 256 values via 5// two 128-value chunks. Within each chunk, l=0..31 emits to 6// positions [l, l+32, l+64, l+96] using ql[l], ql[l+32], qh[l]. 7// 8// Synthetic block: 9// d = 1.0 (f16=0x3C00) 10// All scales = 1 (i8) 11// ql[0] = 0x32 (low=2, high=3) 12// qh[0] = 0x01 (bits01=1, bits23=0, bits45=0, bits67=0) 13// Everything else zero. 14// 15// Expected for chunk c=0, l=0: 16// y[0] = (ql[0].low | bits01<<4) - 32 = (2|16)-32 = -14 -> 0xC1600000 17// y[32] = (ql[32].low | bits23<<4) - 32 = (0|0) - 32 = -32 -> 0xC2000000 18// y[64] = (ql[0].high | bits45<<4) - 32 = (3|0)-32 = -29 -> 0xC1E80000 19// y[96] = (ql[32].high | bits67<<4) - 32 = (0|0)-32 = -32 -> 0xC2000000 20 21import "nx_syscalls.nx" 22import "nx_tier.nx" 23import "nx_le.nx" 24import "nx_f32.nx" 25import "nx_q6_k_to_f32.nx" 26 27func main() -> i64 { 28 let buf: *u8 = sys_mmap(256) 29 var z: i64 = 0 30 while z < 210 { buf[z] = 0 as u8; z = z + 1 } 31 32 buf[0] = 0x32 as u8 33 buf[128] = 0x01 as u8 34 var s: i64 = 0 35 while s < 16 { buf[192 + s] = 1 as u8; s = s + 1 } 36 nx_le_write_u16(buf, 208, 0x3C00) 37 38 let out: *i64 = sys_mmap(256 * 8) as *i64 39 nx_q6_k_to_f32(buf, 0, 256, out) 40 41 // c=0, l=0 emits at y[0], y[32], y[64], y[96] 42 if out[0] != 0xC1600000 { return 10 } // -14 43 if out[32] != 0xC2000000 { return 11 } // -32 44 if out[64] != 0xC1E80000 { return 12 } // -29 45 if out[96] != 0xC2000000 { return 13 } // -32 46 47 // Other positions: ql/qh all zero -> q6=0, signed=-32, value=-32 48 if out[1] != 0xC2000000 { return 20 } 49 if out[33] != 0xC2000000 { return 21 } 50 if out[128] != 0xC2000000 { return 22 } 51 if out[255] != 0xC2000000 { return 23 } 52 53 return 0 54}