nx_q5_k_ggml_kat.nx source
↩ module page · 55 lines · 2553 B
1// nx_q5_k_ggml_kat.nx -- permanent golden KAT for nx_q5_k_to_f32 vs a ggml Q5_K oracle.
2//
3// Embeds the real 176-byte super-block 0 of blk.0.attn_v (Q5_K) from the Huihui Q4_K_M model (file offset
4// 1050331744) and asserts nx_q5k_block_to_f32 reproduces the ggml golden at POSITION-SENSITIVE points
5// (element0/32/64 + a non-uniform dot) -- so a wrong nibble/sub-block layout (the Q4_K failure mode) is
6// caught. Golden from a hand-rolled ggml dequantize_row_q5_K (scratchpad/q5k_golden.py):
7// element0=-0.004717 (bits 3147470080), element32=-0.049673 (3175839104), element64=-0.022964 (3166445568),
8// dot(sum y[i]*((i%5)+1))=-2.357033 (bits 3222722976).
9// license_tier: ORIGINAL
10import "nx_syscalls.nx"
11import "nx_tier.nx"
12import "nx_le.nx"
13import "nx_f32.nx"
14import "nx_f32_cvt.nx"
15import "nx_f32_div.nx"
16import "nx_q5_k_to_f32.nx"
17
18func kat_hexval(c: i64) -> i64 {
19 if c >= 48 { if c <= 57 { return c - 48 } } // '0'-'9'
20 if c >= 97 { if c <= 102 { return c - 87 } } // 'a'-'f' -> 10-15
21 return 0
22}
23
24func main() -> i64 {
25 let hex: *u8 = "82046f15fdf2eceaf3b5dfa56565ffef507dce3a4f59475b485ad67adf51a09d1a2e66ea649f53795b3abb32898066cb6f8dff9f44e8405cfdca236f97e20bf51ecf4c0bae2380a2d10f0d4deeffa056063f91a559cae694f08a53bc6a77f6304d34b4759101794638b36e94abdbf312d9222dcbaddaab104d50b290a0c86f148387702e2f4264f00f2a7f86dbe20db7c8c80200f5a63245f45553b0faeb686c3cf85b1ac435f183c067e82e572ffe53" as *u8
26 let buf: *u8 = sys_mmap(176)
27 var i: i64 = 0
28 while i < 176 {
29 let hi: i64 = kat_hexval((hex[i * 2]) as i64)
30 let lo: i64 = kat_hexval((hex[i * 2 + 1]) as i64)
31 buf[i] = ((hi << 4) | lo) as u8
32 i = i + 1
33 }
34
35 let out: *i64 = sys_mmap(256 * 8) as *i64
36 nx_q5k_block_to_f32(buf, 0, 256, out)
37
38 let tol: i64 = nx_f32_div(nx_i32_to_f32(1), nx_i32_to_f32(100000)) // 1e-5 (elements ~0.005-0.05)
39 if (nx_f32_sub(out[0], 3147470080) & 0x7FFFFFFF) >= tol { return 10 }
40 if (nx_f32_sub(out[32], 3175839104) & 0x7FFFFFFF) >= tol { return 11 }
41 if (nx_f32_sub(out[64], 3166445568) & 0x7FFFFFFF) >= tol { return 12 }
42
43 // non-uniform (position-sensitive) dot vs the ggml golden
44 var dot: i64 = 0
45 i = 0
46 while i < 256 {
47 let w: i64 = nx_i32_to_f32((i - (i / 5) * 5) + 1)
48 dot = nx_f32_add(dot, nx_f32_mul(out[i], w))
49 i = i + 1
50 }
51 let dtol: i64 = nx_f32_div(nx_i32_to_f32(1), nx_i32_to_f32(100)) // 1e-2 (256-term f32 accumulation)
52 if (nx_f32_sub(dot, 3222722976) & 0x7FFFFFFF) >= dtol { return 20 }
53
54 return 0
55}