code wiki / _hdl_build / _tensor_grad_authored.nx

_tensor_grad_authored.nx source

↩ module page · 553 lines · 22367 B

1// AUTHORED BY THE NISHI BUILDER (nx_module_author tensor-grad template) -- T6 tensor autograd. 2// Tutoring: specs/2026-06-09-tutoring-training-substrate-rung2-tensor.md 3import "nx_syscalls.nx" 4import "nx_f32.nx" 5import "nx_f32_div.nx" 6import "nx_f32_cvt.nx" 7func _tg_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 8func _tg_num(v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(1,"-" as *u8,1)}; let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48;k=1}; while m>0{t[k]=48+(m%10);m=m/10;k=k+1}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(1,bb,k); return 0 } 9func tg_q(n: i64, d: i64) -> i64 { return nx_f32_div(nx_i32_to_f32(n), nx_i32_to_f32(d)) } 10func tg_milli(v: i64) -> i64 { 11 var neg: i64 = 0 12 var a: i64 = v 13 if nx_f32_lt(a, 0) == 1 { neg = 1; a = nx_f32_abs(a) } 14 let m: i64 = nx_f32_mul(a, nx_i32_to_f32(1000)) 15 var lo: i64 = 0 16 var hi: i64 = 16777216 17 while lo < hi { 18 let mid: i64 = (lo + hi + 1) / 2 19 if nx_f32_lt(m, nx_i32_to_f32(mid)) == 1 { hi = mid - 1 } else { lo = mid } 20 } 21 if neg == 1 { return 0 - lo } 22 return lo 23} 24const TG_NCAP: i64 = 256 25const TG_ACAP: i64 = 16384 26func tg_alloc(arena: *i64, ab: *i64, n: i64) -> *i64 { 27 if ab[0] + n > TG_ACAP { _tg_puts("ARENA OVERFLOW (honest fail)\n" as *u8); sys_exit(1) } 28 let base: i64 = arena as i64 29 let q: *i64 = (base + ab[0] * 8) as *i64 30 var i: i64 = 0 31 while i < n { q[i] = 0; i = i + 1 } 32 ab[0] = ab[0] + n 33 return q 34} 35func tg_node(tape: *i64, nb: *i64, op: i64, ai: i64, bi: i64, rows: i64, cols: i64, valp: *i64, gradp: *i64) -> i64 { 36 if nb[0] >= TG_NCAP { _tg_puts("TAPE OVERFLOW (honest fail)\n" as *u8); sys_exit(1) } 37 let r: i64 = nb[0] 38 tape[r*8+0] = op 39 tape[r*8+1] = ai 40 tape[r*8+2] = bi 41 tape[r*8+3] = rows 42 tape[r*8+4] = cols 43 tape[r*8+5] = valp as i64 44 tape[r*8+6] = gradp as i64 45 tape[r*8+7] = 0 46 nb[0] = r + 1 47 return r 48} 49func tg_valp(tape: *i64, x: i64) -> *i64 { return tape[x*8+5] as *i64 } 50func tg_gradp(tape: *i64, x: i64) -> *i64 { return tape[x*8+6] as *i64 } 51func tg_leaf(tape: *i64, nb: *i64, arena: *i64, ab: *i64, p: *i64, rows: i64, cols: i64) -> i64 { 52 return tg_node(tape, nb, 0, 0, 0, rows, cols, p, tg_alloc(arena, ab, rows*cols)) 53} 54func tg_matvec(tape: *i64, nb: *i64, arena: *i64, ab: *i64, a: i64, x: i64) -> i64 { 55 let r: i64 = tape[a*8+3] 56 let c: i64 = tape[a*8+4] 57 let av: *i64 = tg_valp(tape, a) 58 let xv: *i64 = tg_valp(tape, x) 59 let y: *i64 = tg_alloc(arena, ab, r) 60 var i: i64 = 0 61 while i < r { 62 var s: i64 = 0 63 var j: i64 = 0 64 while j < c { s = nx_f32_add(s, nx_f32_mul(av[i*c+j], xv[j])); j = j + 1 } 65 y[i] = s 66 i = i + 1 67 } 68 return tg_node(tape, nb, 1, a, x, r, 1, y, tg_alloc(arena, ab, r)) 69} 70func tg_addvec(tape: *i64, nb: *i64, arena: *i64, ab: *i64, x: i64, y: i64) -> i64 { 71 let n: i64 = tape[x*8+3] 72 let xv: *i64 = tg_valp(tape, x) 73 let yv: *i64 = tg_valp(tape, y) 74 let o: *i64 = tg_alloc(arena, ab, n) 75 var i: i64 = 0 76 while i < n { o[i] = nx_f32_add(xv[i], yv[i]); i = i + 1 } 77 return tg_node(tape, nb, 2, x, y, n, 1, o, tg_alloc(arena, ab, n)) 78} 79func tg_reluvec(tape: *i64, nb: *i64, arena: *i64, ab: *i64, x: i64) -> i64 { 80 let n: i64 = tape[x*8+3] 81 let xv: *i64 = tg_valp(tape, x) 82 let o: *i64 = tg_alloc(arena, ab, n) 83 var i: i64 = 0 84 while i < n { 85 var v: i64 = xv[i] 86 if nx_f32_lt(v, 0) == 1 { v = 0 } 87 o[i] = v 88 i = i + 1 89 } 90 return tg_node(tape, nb, 3, x, 0, n, 1, o, tg_alloc(arena, ab, n)) 91} 92func tg_mse(tape: *i64, nb: *i64, arena: *i64, ab: *i64, p: i64, t: i64) -> i64 { 93 let n: i64 = tape[p*8+3] 94 let pv: *i64 = tg_valp(tape, p) 95 let tv: *i64 = tg_valp(tape, t) 96 var acc: i64 = 0 97 var i: i64 = 0 98 while i < n { 99 let d: i64 = nx_f32_sub(pv[i], tv[i]) 100 acc = nx_f32_add(acc, nx_f32_mul(d, d)) 101 i = i + 1 102 } 103 let o: *i64 = tg_alloc(arena, ab, 1) 104 o[0] = nx_f32_mul(acc, tg_q(1, n)) 105 return tg_node(tape, nb, 4, p, t, 1, 1, o, tg_alloc(arena, ab, 1)) 106} 107func tg_smul(tape: *i64, nb: *i64, arena: *i64, ab: *i64, x: i64, y: i64) -> i64 { 108 let xv: *i64 = tg_valp(tape, x) 109 let yv: *i64 = tg_valp(tape, y) 110 let o: *i64 = tg_alloc(arena, ab, 1) 111 o[0] = nx_f32_mul(xv[0], yv[0]) 112 return tg_node(tape, nb, 5, x, y, 1, 1, o, tg_alloc(arena, ab, 1)) 113} 114func tg_backward(tape: *i64, nt: i64, root: i64) -> i64 { 115 var i: i64 = 0 116 while i < nt { 117 let gp: *i64 = tg_gradp(tape, i) 118 let n: i64 = tape[i*8+3] * tape[i*8+4] 119 var k: i64 = 0 120 while k < n { gp[k] = 0; k = k + 1 } 121 i = i + 1 122 } 123 let rg: *i64 = tg_gradp(tape, root) 124 rg[0] = nx_i32_to_f32(1) 125 var r: i64 = nt - 1 126 while r >= 0 { 127 let op: i64 = tape[r*8+0] 128 let ai: i64 = tape[r*8+1] 129 let bi: i64 = tape[r*8+2] 130 let g: *i64 = tg_gradp(tape, r) 131 if op == 1 { 132 let rr: i64 = tape[ai*8+3] 133 let cc: i64 = tape[ai*8+4] 134 let av: *i64 = tg_valp(tape, ai) 135 let ag: *i64 = tg_gradp(tape, ai) 136 let xv: *i64 = tg_valp(tape, bi) 137 let xg: *i64 = tg_gradp(tape, bi) 138 var i2: i64 = 0 139 while i2 < rr { 140 var j: i64 = 0 141 while j < cc { 142 ag[i2*cc+j] = nx_f32_add(ag[i2*cc+j], nx_f32_mul(g[i2], xv[j])) 143 xg[j] = nx_f32_add(xg[j], nx_f32_mul(av[i2*cc+j], g[i2])) 144 j = j + 1 145 } 146 i2 = i2 + 1 147 } 148 } 149 if op == 2 { 150 let n2: i64 = tape[r*8+3] 151 let ag2: *i64 = tg_gradp(tape, ai) 152 let bg2: *i64 = tg_gradp(tape, bi) 153 var k2: i64 = 0 154 while k2 < n2 { ag2[k2] = nx_f32_add(ag2[k2], g[k2]); bg2[k2] = nx_f32_add(bg2[k2], g[k2]); k2 = k2 + 1 } 155 } 156 if op == 3 { 157 let n3: i64 = tape[r*8+3] 158 let xv3: *i64 = tg_valp(tape, ai) 159 let ag3: *i64 = tg_gradp(tape, ai) 160 var k3: i64 = 0 161 while k3 < n3 { 162 if nx_f32_gt(xv3[k3], 0) == 1 { ag3[k3] = nx_f32_add(ag3[k3], g[k3]) } 163 k3 = k3 + 1 164 } 165 } 166 if op == 4 { 167 let n4: i64 = tape[ai*8+3] 168 let pv4: *i64 = tg_valp(tape, ai) 169 let tv4: *i64 = tg_valp(tape, bi) 170 let pg4: *i64 = tg_gradp(tape, ai) 171 let c2n: i64 = tg_q(2, n4) 172 var k4: i64 = 0 173 while k4 < n4 { 174 pg4[k4] = nx_f32_add(pg4[k4], nx_f32_mul(g[0], nx_f32_mul(c2n, nx_f32_sub(pv4[k4], tv4[k4])))) 175 k4 = k4 + 1 176 } 177 } 178 if op == 5 { 179 let av5: *i64 = tg_valp(tape, ai) 180 let bv5: *i64 = tg_valp(tape, bi) 181 let ag5: *i64 = tg_gradp(tape, ai) 182 let bg5: *i64 = tg_gradp(tape, bi) 183 ag5[0] = nx_f32_add(ag5[0], nx_f32_mul(g[0], bv5[0])) 184 bg5[0] = nx_f32_add(bg5[0], nx_f32_mul(g[0], av5[0])) 185 } 186 r = r - 1 187 } 188 return 0 189} 190func tg_fwd_mlp(w1: *i64, b1: *i64, w2: *i64, b2: *i64, x: *i64, t: i64) -> i64 { 191 let h: *i64 = sys_mmap(64) as *i64 192 var i: i64 = 0 193 while i < 2 { 194 var s: i64 = b1[i] 195 var j: i64 = 0 196 while j < 2 { s = nx_f32_add(s, nx_f32_mul(w1[i*2+j], x[j])); j = j + 1 } 197 if nx_f32_lt(s, 0) == 1 { s = 0 } 198 h[i] = s 199 i = i + 1 200 } 201 var o: i64 = b2[0] 202 i = 0 203 while i < 2 { o = nx_f32_add(o, nx_f32_mul(w2[i], h[i])); i = i + 1 } 204 let d: i64 = nx_f32_sub(o, t) 205 return nx_f32_mul(d, d) 206} 207func tg_pget(w1: *i64, b1: *i64, w2: *i64, b2: *i64, k: i64) -> i64 { 208 if k < 4 { return w1[k] } 209 if k < 6 { return b1[k-4] } 210 if k < 8 { return w2[k-6] } 211 return b2[0] 212} 213func tg_pset(w1: *i64, b1: *i64, w2: *i64, b2: *i64, k: i64, v: i64) -> i64 { 214 if k < 4 { w1[k] = v; return 0 } 215 if k < 6 { b1[k-4] = v; return 0 } 216 if k < 8 { w2[k-6] = v; return 0 } 217 b2[0] = v 218 return 0 219} 220func gate_a(tape: *i64, nb: *i64, arena: *i64, ab: *i64) -> i64 { 221 let w1: *i64 = sys_mmap(64) as *i64 222 let b1: *i64 = sys_mmap(64) as *i64 223 let w2: *i64 = sys_mmap(64) as *i64 224 let b2: *i64 = sys_mmap(64) as *i64 225 let x: *i64 = sys_mmap(64) as *i64 226 let t: *i64 = sys_mmap(64) as *i64 227 w1[0] = tg_q(2,3) 228 w1[1] = nx_f32_neg(tg_q(1,2)) 229 w1[2] = tg_q(1,4) 230 w1[3] = tg_q(1,2) 231 b1[0] = tg_q(1,4) 232 b1[1] = tg_q(1,8) 233 w2[0] = tg_q(3,2) 234 w2[1] = nx_f32_neg(tg_q(3,4)) 235 b2[0] = tg_q(1,8) 236 x[0] = tg_q(3,4) 237 x[1] = tg_q(1,2) 238 t[0] = tg_q(1,2) 239 nb[0] = 0 240 ab[0] = 0 241 let lw1: i64 = tg_leaf(tape, nb, arena, ab, w1, 2, 2) 242 let lb1: i64 = tg_leaf(tape, nb, arena, ab, b1, 2, 1) 243 let lw2: i64 = tg_leaf(tape, nb, arena, ab, w2, 1, 2) 244 let lb2: i64 = tg_leaf(tape, nb, arena, ab, b2, 1, 1) 245 let lx: i64 = tg_leaf(tape, nb, arena, ab, x, 2, 1) 246 let lt: i64 = tg_leaf(tape, nb, arena, ab, t, 1, 1) 247 let hh: i64 = tg_reluvec(tape, nb, arena, ab, tg_addvec(tape, nb, arena, ab, tg_matvec(tape, nb, arena, ab, lw1, lx), lb1)) 248 let oo: i64 = tg_addvec(tape, nb, arena, ab, tg_matvec(tape, nb, arena, ab, lw2, hh), lb2) 249 let loss: i64 = tg_mse(tape, nb, arena, ab, oo, lt) 250 tg_backward(tape, nb[0], loss) 251 let h128: i64 = tg_q(1,128) 252 var pass: i64 = 1 253 var k: i64 = 0 254 while k < 9 { 255 var ga: i64 = 0 256 if k < 4 { let gp: *i64 = tg_gradp(tape, lw1); ga = gp[k] } 257 else { if k < 6 { let gp: *i64 = tg_gradp(tape, lb1); ga = gp[k-4] } 258 else { if k < 8 { let gp: *i64 = tg_gradp(tape, lw2); ga = gp[k-6] } 259 else { let gp: *i64 = tg_gradp(tape, lb2); ga = gp[0] } } } 260 let save: i64 = tg_pget(w1, b1, w2, b2, k) 261 tg_pset(w1, b1, w2, b2, k, nx_f32_add(save, h128)) 262 let fp: i64 = tg_fwd_mlp(w1, b1, w2, b2, x, t[0]) 263 tg_pset(w1, b1, w2, b2, k, nx_f32_sub(save, h128)) 264 let fm: i64 = tg_fwd_mlp(w1, b1, w2, b2, x, t[0]) 265 tg_pset(w1, b1, w2, b2, k, save) 266 let fdif: i64 = nx_f32_div(nx_f32_sub(fp, fm), tg_q(1,64)) 267 var den: i64 = nx_f32_abs(fdif) 268 if nx_f32_lt(den, tg_q(1,64)) == 1 { den = tg_q(1,64) } 269 let rel: i64 = nx_f32_div(nx_f32_abs(nx_f32_sub(ga, fdif)), den) 270 _tg_puts(" gradcheck p" as *u8); _tg_num(k) 271 _tg_puts(" analytic-milli=" as *u8); _tg_num(tg_milli(ga)) 272 _tg_puts(" fd-milli=" as *u8); _tg_num(tg_milli(fdif)) 273 _tg_puts(" rel-milli=" as *u8); _tg_num(tg_milli(rel)); _tg_puts("\n" as *u8) 274 if nx_f32_lt(rel, tg_q(1,32)) == 0 { pass = 0 } 275 k = k + 1 276 } 277 return pass 278} 279func tg_train(tape: *i64, nb: *i64, arena: *i64, ab: *i64, out: *i64) -> i64 { 280 let at: *i64 = sys_mmap(64) as *i64 281 let ct: *i64 = sys_mmap(64) as *i64 282 at[0] = tg_q(3,2) 283 at[1] = nx_f32_neg(tg_q(1,2)) 284 at[2] = tg_q(1,4) 285 at[3] = nx_i32_to_f32(1) 286 ct[0] = nx_f32_neg(tg_q(1,2)) 287 ct[1] = tg_q(3,4) 288 let xs: *i64 = sys_mmap(256) as *i64 289 let ys: *i64 = sys_mmap(256) as *i64 290 var k: i64 = 0 291 while k < 8 { 292 xs[k*2+0] = tg_q(k, 4) 293 xs[k*2+1] = tg_q((k*3) % 8, 8) 294 var i: i64 = 0 295 while i < 2 { 296 ys[k*2+i] = nx_f32_add(nx_f32_add(nx_f32_mul(at[i*2+0], xs[k*2+0]), nx_f32_mul(at[i*2+1], xs[k*2+1])), ct[i]) 297 i = i + 1 298 } 299 k = k + 1 300 } 301 let lr: i64 = tg_q(1,10) 302 let inv8: *i64 = sys_mmap(64) as *i64 303 inv8[0] = tg_q(1,8) 304 let ww: *i64 = sys_mmap(64) as *i64 305 let bb2: *i64 = sys_mmap(64) as *i64 306 var first: i64 = 0 307 var loss_v: i64 = 0 308 var ep: i64 = 0 309 while ep < 400 { 310 nb[0] = 0 311 ab[0] = 0 312 let lw: i64 = tg_leaf(tape, nb, arena, ab, ww, 2, 2) 313 let lb: i64 = tg_leaf(tape, nb, arena, ab, bb2, 2, 1) 314 var accn: i64 = 0 - 1 315 k = 0 316 while k < 8 { 317 let xb: i64 = xs as i64 318 let yb: i64 = ys as i64 319 let lx: i64 = tg_leaf(tape, nb, arena, ab, (xb + k*16) as *i64, 2, 1) 320 let ly: i64 = tg_leaf(tape, nb, arena, ab, (yb + k*16) as *i64, 2, 1) 321 let pred: i64 = tg_addvec(tape, nb, arena, ab, tg_matvec(tape, nb, arena, ab, lw, lx), lb) 322 let m: i64 = tg_mse(tape, nb, arena, ab, pred, ly) 323 if accn < 0 { accn = m } else { accn = tg_addvec(tape, nb, arena, ab, accn, m) } 324 k = k + 1 325 } 326 let li: i64 = tg_leaf(tape, nb, arena, ab, inv8, 1, 1) 327 let loss: i64 = tg_smul(tape, nb, arena, ab, accn, li) 328 tg_backward(tape, nb[0], loss) 329 let lv: *i64 = tg_valp(tape, loss) 330 loss_v = lv[0] 331 if ep == 0 { first = loss_v } 332 let gw: *i64 = tg_gradp(tape, lw) 333 let gb: *i64 = tg_gradp(tape, lb) 334 var q2: i64 = 0 335 while q2 < 4 { ww[q2] = nx_f32_sub(ww[q2], nx_f32_mul(lr, gw[q2])); q2 = q2 + 1 } 336 q2 = 0 337 while q2 < 2 { bb2[q2] = nx_f32_sub(bb2[q2], nx_f32_mul(lr, gb[q2])); q2 = q2 + 1 } 338 if ep % 100 == 0 { _tg_puts(" epoch=" as *u8); _tg_num(ep); _tg_puts(" loss-milli=" as *u8); _tg_num(tg_milli(loss_v)); _tg_puts("\n" as *u8) } 339 ep = ep + 1 340 } 341 var i3: i64 = 0 342 while i3 < 4 { out[i3] = ww[i3]; i3 = i3 + 1 } 343 out[4] = bb2[0] 344 out[5] = bb2[1] 345 out[6] = loss_v 346 out[7] = first 347 return 0 348} 349func ad_step(w: *i64, g: *i64, m: *i64, v: *i64, n: i64, lr: i64, b1: i64, b2: i64, eps: i64, wd: i64, t: i64) -> i64 { 350 var c1: i64 = nx_i32_to_f32(1) 351 var c2: i64 = nx_i32_to_f32(1) 352 var k: i64 = 0 353 while k < t { c1 = nx_f32_mul(c1, b1); c2 = nx_f32_mul(c2, b2); k = k + 1 } 354 let bc1: i64 = nx_f32_sub(nx_i32_to_f32(1), c1) 355 let bc2: i64 = nx_f32_sub(nx_i32_to_f32(1), c2) 356 let omb1: i64 = nx_f32_sub(nx_i32_to_f32(1), b1) 357 let omb2: i64 = nx_f32_sub(nx_i32_to_f32(1), b2) 358 var i: i64 = 0 359 while i < n { 360 m[i] = nx_f32_add(nx_f32_mul(b1, m[i]), nx_f32_mul(omb1, g[i])) 361 v[i] = nx_f32_add(nx_f32_mul(b2, v[i]), nx_f32_mul(omb2, nx_f32_mul(g[i], g[i]))) 362 let mh: i64 = nx_f32_div(m[i], bc1) 363 let vh: i64 = nx_f32_div(v[i], bc2) 364 let upd: i64 = nx_f32_div(mh, nx_f32_add(nx_f32_sqrt(vh), eps)) 365 w[i] = nx_f32_sub(w[i], nx_f32_add(nx_f32_mul(lr, upd), nx_f32_mul(nx_f32_mul(lr, wd), w[i]))) 366 i = i + 1 367 } 368 return 0 369} 370func ad_train(tape: *i64, nb: *i64, arena: *i64, ab: *i64, out: *i64) -> i64 { 371 let at: *i64 = sys_mmap(64) as *i64 372 let ct: *i64 = sys_mmap(64) as *i64 373 at[0] = tg_q(3,2) 374 at[1] = nx_f32_neg(tg_q(1,2)) 375 at[2] = tg_q(1,4) 376 at[3] = nx_i32_to_f32(1) 377 ct[0] = nx_f32_neg(tg_q(1,2)) 378 ct[1] = tg_q(3,4) 379 let xs: *i64 = sys_mmap(256) as *i64 380 let ys: *i64 = sys_mmap(256) as *i64 381 var k: i64 = 0 382 while k < 8 { 383 xs[k*2+0] = tg_q(k, 4) 384 xs[k*2+1] = tg_q((k*3) % 8, 8) 385 var i: i64 = 0 386 while i < 2 { 387 ys[k*2+i] = nx_f32_add(nx_f32_add(nx_f32_mul(at[i*2+0], xs[k*2+0]), nx_f32_mul(at[i*2+1], xs[k*2+1])), ct[i]) 388 i = i + 1 389 } 390 k = k + 1 391 } 392 let lr: i64 = tg_q(1,20) 393 let b1c: i64 = tg_q(9,10) 394 let b2c: i64 = tg_q(999,1000) 395 let eps: i64 = tg_q(1,100000) 396 let inv8: *i64 = sys_mmap(64) as *i64 397 inv8[0] = tg_q(1,8) 398 let ww: *i64 = sys_mmap(64) as *i64 399 let bb2: *i64 = sys_mmap(64) as *i64 400 let mw: *i64 = sys_mmap(64) as *i64 401 let vw: *i64 = sys_mmap(64) as *i64 402 let mb: *i64 = sys_mmap(64) as *i64 403 let vb: *i64 = sys_mmap(64) as *i64 404 var first: i64 = 0 405 var loss_v: i64 = 0 406 var ep: i64 = 0 407 while ep < 400 { 408 nb[0] = 0 409 ab[0] = 0 410 let lw: i64 = tg_leaf(tape, nb, arena, ab, ww, 2, 2) 411 let lb: i64 = tg_leaf(tape, nb, arena, ab, bb2, 2, 1) 412 var accn: i64 = 0 - 1 413 k = 0 414 while k < 8 { 415 let xb: i64 = xs as i64 416 let yb: i64 = ys as i64 417 let lx: i64 = tg_leaf(tape, nb, arena, ab, (xb + k*16) as *i64, 2, 1) 418 let ly: i64 = tg_leaf(tape, nb, arena, ab, (yb + k*16) as *i64, 2, 1) 419 let pred: i64 = tg_addvec(tape, nb, arena, ab, tg_matvec(tape, nb, arena, ab, lw, lx), lb) 420 let m2: i64 = tg_mse(tape, nb, arena, ab, pred, ly) 421 if accn < 0 { accn = m2 } else { accn = tg_addvec(tape, nb, arena, ab, accn, m2) } 422 k = k + 1 423 } 424 let li: i64 = tg_leaf(tape, nb, arena, ab, inv8, 1, 1) 425 let loss: i64 = tg_smul(tape, nb, arena, ab, accn, li) 426 tg_backward(tape, nb[0], loss) 427 let lv: *i64 = tg_valp(tape, loss) 428 loss_v = lv[0] 429 if ep == 0 { first = loss_v } 430 ad_step(ww, tg_gradp(tape, lw), mw, vw, 4, lr, b1c, b2c, eps, 0, ep + 1) 431 ad_step(bb2, tg_gradp(tape, lb), mb, vb, 2, lr, b1c, b2c, eps, 0, ep + 1) 432 if ep % 100 == 0 { _tg_puts(" adamw epoch=" as *u8); _tg_num(ep); _tg_puts(" loss-milli=" as *u8); _tg_num(tg_milli(loss_v)); _tg_puts("\n" as *u8) } 433 ep = ep + 1 434 } 435 var i4: i64 = 0 436 while i4 < 4 { out[i4] = ww[i4]; i4 = i4 + 1 } 437 out[4] = bb2[0] 438 out[5] = bb2[1] 439 out[6] = loss_v 440 out[7] = first 441 return 0 442} 443func main() -> i64 { 444 _tg_puts("=== BUILDER-AUTHORED TENSOR AUTOGRAD: T6 (matvec/relu/mse identities, arena, 9-param gradcheck) ===\n" as *u8) 445 let tape: *i64 = sys_mmap(32768) as *i64 446 let nb: *i64 = sys_mmap(16) as *i64 447 let arena: *i64 = sys_mmap(131072) as *i64 448 let ab: *i64 = sys_mmap(16) as *i64 449 let pa: i64 = gate_a(tape, nb, arena, ab) 450 if pa == 1 { _tg_puts(" GATE A MLP gradcheck (9 params): PASS\n" as *u8) } else { _tg_puts(" GATE A MLP gradcheck: FAIL\n" as *u8) } 451 let o1: *i64 = sys_mmap(128) as *i64 452 let o2: *i64 = sys_mmap(128) as *i64 453 tg_train(tape, nb, arena, ab, o1) 454 _tg_puts(" run1 W-milli: " as *u8) 455 var k: i64 = 0 456 while k < 4 { _tg_num(tg_milli(o1[k])); _tg_puts(" " as *u8); k = k + 1 } 457 _tg_puts(" b-milli: " as *u8); _tg_num(tg_milli(o1[4])); _tg_puts(" " as *u8); _tg_num(tg_milli(o1[5])) 458 _tg_puts(" loss-milli=" as *u8); _tg_num(tg_milli(o1[6])); _tg_puts("\n" as *u8) 459 let at2: *i64 = sys_mmap(64) as *i64 460 at2[0] = tg_q(3,2) 461 at2[1] = nx_f32_neg(tg_q(1,2)) 462 at2[2] = tg_q(1,4) 463 at2[3] = nx_i32_to_f32(1) 464 at2[4] = nx_f32_neg(tg_q(1,2)) 465 at2[5] = tg_q(3,4) 466 var pb: i64 = 1 467 if nx_f32_lt(o1[6], tg_q(1,1000)) == 0 { pb = 0 } 468 if nx_f32_lt(o1[6], o1[7]) == 0 { pb = 0 } 469 k = 0 470 while k < 6 { 471 if nx_f32_lt(nx_f32_abs(nx_f32_sub(o1[k], at2[k])), tg_q(1,16)) == 0 { pb = 0 } 472 k = k + 1 473 } 474 if pb == 1 { _tg_puts(" GATE B affine map recovered (all 6 cells within 1/16, loss < 1/1000): PASS\n" as *u8) } else { _tg_puts(" GATE B: FAIL\n" as *u8) } 475 tg_train(tape, nb, arena, ab, o2) 476 var pc: i64 = 1 477 k = 0 478 while k < 7 { if o1[k] != o2[k] { pc = 0 } k = k + 1 } 479 if pc == 1 { _tg_puts(" GATE C bit-exact tensor training: PASS (the EXCEED axis holds at rung 2)\n" as *u8) } else { _tg_puts(" GATE C: FAIL\n" as *u8) } 480 let aw: *i64 = sys_mmap(64) as *i64 481 let ag2: *i64 = sys_mmap(64) as *i64 482 let am: *i64 = sys_mmap(64) as *i64 483 let av2: *i64 = sys_mmap(64) as *i64 484 aw[0] = nx_i32_to_f32(1) 485 aw[1] = nx_i32_to_f32(0-2) 486 aw[2] = nx_i32_to_f32(3) 487 aw[3] = nx_i32_to_f32(0-4) 488 ag2[0] = nx_i32_to_f32(2) 489 ag2[1] = nx_i32_to_f32(0-3) 490 ag2[2] = tg_q(1,2) 491 ag2[3] = nx_i32_to_f32(0-5) 492 let wprev: *i64 = sys_mmap(64) as *i64 493 k = 0 494 while k < 4 { wprev[k] = aw[k]; am[k] = 0; av2[k] = 0; k = k + 1 } 495 let alr: i64 = tg_q(1,100) 496 ad_step(aw, ag2, am, av2, 4, alr, tg_q(9,10), tg_q(999,1000), tg_q(1,100000), 0, 1) 497 var pd: i64 = 1 498 k = 0 499 while k < 4 { 500 var want: i64 = nx_f32_sub(wprev[k], alr) 501 if nx_f32_lt(ag2[k], 0) == 1 { want = nx_f32_add(wprev[k], alr) } 502 if nx_f32_lt(nx_f32_abs(nx_f32_sub(aw[k], want)), tg_q(1,2000)) == 0 { pd = 0 } 503 k = k + 1 504 } 505 if pd == 1 { _tg_puts(" GATE D AdamW first-step sign property (|step| == lr per param): PASS\n" as *u8) } else { _tg_puts(" GATE D: FAIL\n" as *u8) } 506 aw[0] = nx_i32_to_f32(1) 507 am[0] = 0 508 av2[0] = 0 509 ag2[0] = 0 510 let dlr: i64 = tg_q(1,10) 511 let dwd: i64 = tg_q(1,10) 512 var st: i64 = 0 513 while st < 10 { ad_step(aw, ag2, am, av2, 1, dlr, tg_q(9,10), tg_q(999,1000), tg_q(1,100000), dwd, st + 1); st = st + 1 } 514 var expw: i64 = nx_i32_to_f32(1) 515 let fac: i64 = nx_f32_sub(nx_i32_to_f32(1), nx_f32_mul(dlr, dwd)) 516 st = 0 517 while st < 10 { expw = nx_f32_mul(expw, fac); st = st + 1 } 518 var pe: i64 = 1 519 if nx_f32_lt(nx_f32_abs(nx_f32_sub(aw[0], expw)), tg_q(1,1000)) == 0 { pe = 0 } 520 if am[0] != 0 { pe = 0 } 521 if av2[0] != 0 { pe = 0 } 522 _tg_puts(" decay-only w-milli=" as *u8); _tg_num(tg_milli(aw[0])) 523 _tg_puts(" expected-milli=" as *u8); _tg_num(tg_milli(expw)); _tg_puts("\n" as *u8) 524 if pe == 1 { _tg_puts(" GATE E decoupled decay exact ((1-lr*wd)^k, moments untouched): PASS\n" as *u8) } else { _tg_puts(" GATE E: FAIL\n" as *u8) } 525 let o3: *i64 = sys_mmap(128) as *i64 526 let o4: *i64 = sys_mmap(128) as *i64 527 ad_train(tape, nb, arena, ab, o3) 528 _tg_puts(" adamw W-milli: " as *u8) 529 k = 0 530 while k < 4 { _tg_num(tg_milli(o3[k])); _tg_puts(" " as *u8); k = k + 1 } 531 _tg_puts(" b-milli: " as *u8); _tg_num(tg_milli(o3[4])); _tg_puts(" " as *u8); _tg_num(tg_milli(o3[5])) 532 _tg_puts(" loss-milli=" as *u8); _tg_num(tg_milli(o3[6])); _tg_puts("\n" as *u8) 533 var pf: i64 = 1 534 if nx_f32_lt(o3[6], tg_q(1,1000)) == 0 { pf = 0 } 535 if nx_f32_lt(o3[6], o3[7]) == 0 { pf = 0 } 536 k = 0 537 while k < 6 { 538 if nx_f32_lt(nx_f32_abs(nx_f32_sub(o3[k], at2[k])), tg_q(1,16)) == 0 { pf = 0 } 539 k = k + 1 540 } 541 ad_train(tape, nb, arena, ab, o4) 542 k = 0 543 while k < 7 { if o3[k] != o4[k] { pf = 0 } k = k + 1 } 544 if pf == 1 { _tg_puts(" GATE F AdamW trains (recovered + bit-exact): PASS\n" as *u8) } else { _tg_puts(" GATE F: FAIL\n" as *u8) } 545 if pa == 1 { if pb == 1 { if pc == 1 { if pd == 1 { if pe == 1 { if pf == 1 { 546 _tg_puts(" TENSOR-AUTOGRAD T6 + ADAMW T5 GATE: PASS (verified matrix gradients + the modern optimizer, bits-up)\n" as *u8) 547 sys_exit(0) 548 return 0 549 } } } } } } 550 _tg_puts(" TENSOR-AUTOGRAD/ADAMW GATE: FAIL\n" as *u8) 551 sys_exit(1) 552 return 1 553}