code wiki / _hdl_build / nx_nofloat_mxfp4.nx
nx_nofloat_mxfp4.nx source
↩ module page · 50 lines · 2370 B
1// nx_nofloat_mxfp4.nx -- SOVEREIGN no-float MXFP4 dequant (K3 F406 gap; operator 2026-07-19 "beyond SOTA").
2// OCP Microscaling Formats (MX) Spec v1.0: a block = 32 elements, each E2M1 (4-bit float: sign(1) + 3-bit
3// magnitude field) sharing ONE E8M0 scale byte (8-bit unsigned exponent, value = 2^(e-127), 0xFF = NaN).
4// E2M1 magnitude set (3-bit field 0..7) = {0, 0.5, 1, 1.5, 2, 3, 4, 6}. Dequant is PURE INTEGER (a Q16
5// magnitude lookup + a power-of-2 shift by (e-127) + sign) -- no float touches the weights, deterministic,
6// the exact no-float treatment we gave Q6_K/Q5_0. Kimi K3 uses MXFP4 weights / MXFP8 activations; this
7// closes the weight-format half. Grounded: OCP MX v1.0; arXiv 2310.10537 (Microscaling Data Formats).
8// license_tier: ORIGINAL No hw writes (Rule 26).
9import "nx_syscalls.nx"
10
11const MX_BIAS: i64 = 127 // E8M0 exponent bias
12const MX_NAN: i64 = 255 // 0xFF E8M0 scale = NaN/uninitialised
13const MX_BLK: i64 = 32 // elements per MX block
14const MX_Q: i64 = 65536 // Q16 one
15
16// E2M1 3-bit magnitude field -> Q16 magnitude. {0, .5, 1, 1.5, 2, 3, 4, 6}
17func mx_mag_q16(idx: i64) -> i64 {
18 if idx == 0 { return 0 }
19 if idx == 1 { return 32768 } // 0.5
20 if idx == 2 { return 65536 } // 1.0
21 if idx == 3 { return 98304 } // 1.5
22 if idx == 4 { return 131072 } // 2.0
23 if idx == 5 { return 196608 } // 3.0
24 if idx == 6 { return 262144 } // 4.0
25 return 393216 // 6.0
26}
27// one E2M1 nibble (0..15) + E8M0 scale exponent e -> Q16 value (sign * mag * 2^(e-127)); NaN scale -> 0
28func mx_e2m1(nib: i64, e: i64) -> i64 {
29 if e == MX_NAN { return 0 }
30 let sign: i64 = (nib >> 3) & 1
31 let magi: i64 = nib & 7
32 var v: i64 = mx_mag_q16(magi)
33 let sh: i64 = e - MX_BIAS
34 if sh >= 0 { v = v << sh } else { v = v >> (0 - sh) }
35 if sign == 1 { v = 0 - v }
36 return v
37}
38// dequant one MX block: buf has 16 packed bytes (32 nibbles, low-nibble first) at boff + 1 E8M0 scale
39// byte at soff. writes 32 Q16 ints to out.
40func mx_block(buf: *u8, boff: i64, soff: i64, out: *i64) -> i64 {
41 let e: i64 = buf[soff] as i64
42 var i: i64 = 0
43 while i < 16 {
44 let b: i64 = buf[boff + i] as i64
45 out[i*2] = mx_e2m1(b & 15, e)
46 out[i*2 + 1] = mx_e2m1((b >> 4) & 15, e)
47 i = i + 1
48 }
49 return 0
50}