code wiki / _hdl_build / nx_nofloat_attn.nx
nx_nofloat_attn.nx source
↩ module page · 80 lines · 6013 B
1// nx_nofloat_attn.nx -- SOVEREIGN NO-FLOAT ATTENTION (the transformer HEART), integer Q16, deterministic. The hard
2// part of attention is softmax (needs exp); this builds a fixed-point exp via 2^x decomposition (|x|*log2e -> integer
3// shift + quadratic 2^frac), then softmax (max-subtract for stability -> exp -> normalize) + attention (weighted sum
4// of V). KEY: even with an APPROXIMATE exp, softmax NORMALIZES (each / sum), so the weights sum to ONE exactly and
5// monotonicity holds -- all integer => bit-exact deterministic (the moat vs float/CUDA attention).
6// T1 weights non-negative + sum ~= ONE. T2 monotonic (highest logit -> highest weight, order preserved).
7// T3 (EXCEED) determinism bit-identical. T4 attention output = convex combo of V, dominated by the max-score key.
8// expect_exit: 0 Sovereign: nx_syscalls.
9import "nx_syscalls.nx"
10import "nx_g_puts_lib.nx"
11
12func g_pn(v: i64) -> i64 { let b: *u8=sys_mmap(28); var x: i64=v; if x<0{b[0]=45;sys_write(1,b,1);x=0-x} if x==0{b[0]=48;sys_write(1,b,1);return 0} var d: i64=0; var y: i64=x; while y>0{d=d+1;y=y/10} var i: i64=d-1; y=x; while i>=0{b[i]=(48+(y%10)) as u8;y=y/10;i=i-1} sys_write(1,b,d); return 0 }
13func ck(name: *u8, c: i64) -> i64 { if c==1 { g_puts(" PASS " as *u8) } else { g_puts(" FAIL " as *u8) } g_puts(name); g_puts("\n" as *u8); return c }
14
15const Q: i64 = 16
16const ONE: i64 = 65536
17const LOG2E: i64 = 94548 // 1.442695 in Q16
18const C1: i64 = 45426 // ln2 in Q16 (2^f linear term)
19const C2: i64 = 15743 // 0.2402 in Q16 (2^f quadratic term)
20func fxmul(a: i64, b: i64) -> i64 { return (a*b)>>Q }
21
22// fixed-point exp for x <= 0 (softmax subtracts the max, so inputs are <= 0). returns exp(x) in Q16, (0, ONE].
23func exp_fx(x: i64) -> i64 {
24 var xx: i64 = x; if xx>0 { xx=0 }
25 let yabs: i64 = fxmul(0-xx, LOG2E) // |x|*log2(e) >= 0
26 let nabs: i64 = yabs >> Q // integer part (>=0)
27 let fabs: i64 = yabs - (nabs<<Q) // fractional part [0, ONE)
28 let f2: i64 = fxmul(fabs, fabs)
29 let p: i64 = ONE + fxmul(fabs, C1) + fxmul(f2, C2) // 2^fabs in [ONE, 2*ONE)
30 let inv: i64 = (ONE*ONE)/p // 2^(-fabs) in (ONE/2, ONE]
31 if nabs >= 31 { return 0 }
32 return inv >> nabs // 2^(-fabs) * 2^(-nabs) = exp(x)
33}
34// softmax over scores[0..n) -> w[0..n) in Q16 summing to ONE.
35func softmax(scores: *i64, w: *i64, n: i64) -> i64 {
36 var mx: i64 = scores[0]; var i: i64=1; while i<n { if scores[i]>mx { mx=scores[i] } i=i+1 }
37 let e: *i64 = sys_mmap(n*8) as *i64; var sum: i64=0
38 i=0; while i<n { e[i]=exp_fx(scores[i]-mx); sum=sum+e[i]; i=i+1 }
39 i=0; while i<n { w[i]=(e[i]*ONE)/sum; i=i+1 }
40 return sum
41}
42func attention(w: *i64, V: *i64, n: i64) -> i64 { var out: i64=0; var i: i64=0; while i<n { out=out+fxmul(w[i], V[i]); i=i+1 } return out }
43
44func main() -> i64 {
45 g_puts("nx_nofloat_attn (SOVEREIGN no-float attention/softmax -- the transformer heart, integer Q16, deterministic)\n" as *u8)
46 var pass: i64=0; var total: i64=0
47 g_puts(" exp check (Q16): exp(0)="); g_pn(exp_fx(0)); g_puts(" (ONE=65536) exp(-1)="); g_pn(exp_fx(0-ONE)); g_puts(" (~24109=0.368) exp(-2)="); g_pn(exp_fx(0-2*ONE)); g_puts(" (~8847=0.135)\n" as *u8)
48
49 let scores: *i64 = sys_mmap(3*8) as *i64; scores[0]=ONE; scores[1]=3*ONE; scores[2]=2*ONE // logits 1.0, 3.0, 2.0
50 let w: *i64 = sys_mmap(3*8) as *i64
51 softmax(scores, w, 3)
52 g_puts(" softmax(1,3,2): w0="); g_pn(w[0]); g_puts(" w1="); g_pn(w[1]); g_puts(" w2="); g_pn(w[2]); g_puts(" sum="); g_pn(w[0]+w[1]+w[2]); g_puts(" (ONE=65536)\n" as *u8)
53 var t1: i64=0; let sm: i64=w[0]+w[1]+w[2]; if w[0]>=0 { if w[1]>=0 { if w[2]>=0 { var d: i64=sm-ONE; if d<0 {d=0-d} if d<(ONE/50) { t1=1 } } } }
54 pass=pass+ck("T1: softmax weights non-negative and sum ~= ONE (a valid probability distribution)" as *u8, t1); total=total+1
55
56 var t2: i64=0; if w[1]>w[2] { if w[2]>w[0] { t2=1 } }
57 pass=pass+ck("T2: MONOTONIC -- highest logit (3.0) gets highest weight; order w1>w2>w0 matches scores 3>2>1" as *u8, t2); total=total+1
58
59 let w2: *i64 = sys_mmap(3*8) as *i64; softmax(scores, w2, 3)
60 var t3: i64=0; if w[0]==w2[0] { if w[1]==w2[1] { if w[2]==w2[2] { t3=1 } } }
61 pass=pass+ck("T3 (EXCEED): DETERMINISTIC -- recomputed softmax is BIT-IDENTICAL (float/CUDA attention cannot guarantee)" as *u8, t3); total=total+1
62
63 let V: *i64 = sys_mmap(3*8) as *i64; V[0]=10*ONE; V[1]=30*ONE; V[2]=20*ONE // value vectors (scalar dim)
64 let out: i64 = attention(w, V, 3)
65 g_puts(" attention(V=[10,30,20]) = "); g_pn(out); g_puts(" (~"); g_pn(out/ONE); g_puts(".x; min10/max30, pulled toward 30 = the highest-score key)\n" as *u8)
66 var t4: i64=0; if out>(10*ONE) { if out<(30*ONE) { if out>(20*ONE) { t4=1 } } }
67 pass=pass+ck("T4: attention output is a CONVEX COMBINATION of V, dominated by the max-score key (between 10/30, above the uniform mean 20)" as *u8, t4); total=total+1
68
69 g_puts(" >> the transformer HEART now runs in pure integer + deterministic. CLIMB: multi-head + Q/K/V projections (matmul we have)\n" as *u8)
70 g_puts(" + positional encoding + layernorm (integer) -> a full no-float transformer block; MEASURE accuracy vs MLPerf.\n" as *u8)
71
72 var okall: i64=0; if pass==total { okall=1 }
73 g_puts("---- nx_nofloat_attn: passed "); g_pn(pass); g_puts(" / "); g_pn(total); g_puts(" ----\n" as *u8)
74 if okall==1 {
75 let logf: i64=sys_openat_append("knowledge/status/nofloat_attn.log" as *u8, 420)
76 if logf>=0 { let z: i64=sys_write(logf,"NXNOFLOATATTN GREEN: integer fixed-point exp + softmax (sums to ONE, monotonic) + attention (convex combo); deterministic transformer heart\n" as *u8,134); sys_close(logf) }
77 g_puts("verdict=GREEN (the transformer HEART in pure integer: fixed-point exp + softmax + attention, deterministic; the rung toward a sovereign no-float LLM)\n" as *u8); sys_exit(0); return 0
78 }
79 g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1
80}