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}