code wiki / _hdl_build / nx_kinetics_gate.nx

nx_kinetics_gate.nx source

↩ module page · 66 lines · 4768 B

1// nx_kinetics_gate.nx -- NATIVE verify of the browser reaction-kinetics sim (base = mmap; SAME code runs in 2// sovereign WASM). Validates real chemical-kinetics laws: (a) FIRST-ORDER decay has a CONSTANT half-life -- 3// successive halvings (1e6->5e5->2.5e5->1.25e5) take EQUAL step counts (the exponential signature, e.g. carbon 4// dating), (b) mass is conserved ([A]+[B]=A0), (c) a reversible reaction A<=>B settles to equilibrium [B]/[A]=kf/kr. 5// Liar-kill: ZERO-order decay (constant rate) has a SHRINKING half-life (each halving takes ~half the time) -- so 6// the equal-interval test distinguishes reaction orders, exactly as a chemist does. license_tier: ORIGINAL expect_exit: 0 7import "nx_syscalls.nx" 8import "nx_kinetics.nx" 9import "nx_png.nx" 10 11func g_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 12func g_n(v: i64) -> i64 { var m: i64=v; if m<0{g_w("-");m=0-m} let t:*u8=sys_mmap(24); var k:i64=0; if m==0{t[0]=48 as u8;k=1}; while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}; var i:i64=0; let o:*u8=sys_mmap(24); while i<k{o[i]=t[k-1-i];i=i+1}; sys_write(1,o,k); return 0 } 13func g_row(id: *u8, ok: i64, pass: *i64) -> i64 { g_w(" "); g_w(id); g_w(": "); if ok==1 { g_w("OK\n"); pass[0]=pass[0]+1 } else { g_w("FAIL\n") } return 0 } 14func iabs(x: i64) -> i64 { if x<0 { return 0-x } return x } 15 16// step until [A] <= threshold; return steps taken (assumes [A] starts above threshold) 17func steps_to(base: i64, threshold: i64) -> i64 { 18 let A: *i64=(base+O_A) as *i64; var s: i64=0 19 while s<2000000 { step_one_impl(base); s=s+1; if A[0]<=threshold { return s } } 20 return s 21} 22 23func main() -> i64 { 24 let pass: *i64 = sys_mmap(8) as *i64; pass[0]=0 25 g_w("=== NX-KINETICS native verify (chemical reaction kinetics; SAME code runs in sovereign wasm) ===\n") 26 let base: i64 = sys_mmap(2*1048576) as i64 27 let A: *i64=(base+O_A) as *i64; let B: *i64=(base+O_B) as *i64; let M: *i64=(base+O_MODE) as *i64 28 let KN: *i64=(base+O_KNUM) as *i64; let KD: *i64=(base+O_KDEN) as *i64; let KR: *i64=(base+O_KRNUM) as *i64 29 30 // FIRST-ORDER: successive half-lives 31 init_impl(base); M[0]=0 32 let h1: i64=steps_to(base, 500000); let h2: i64=steps_to(base, 250000); let h3: i64=steps_to(base, 125000) 33 let mass_ok: i64 = ((A[0]+B[0])==A0) as i64 34 35 // ZERO-ORDER control (liar-kill): half-life shrinks 36 init_impl(base); M[0]=2 37 let z1: i64=steps_to(base, 500000); let z2: i64=steps_to(base, 250000) 38 39 // REVERSIBLE: equilibrium [B]/[A] = kf/kr (kf=3/1000, kr=1/1000 -> 3.0) 40 init_impl(base); M[0]=1; KN[0]=3; KD[0]=1000; KR[0]=1 41 var s: i64=0; while s<20000 { step_one_impl(base); s=s+1 } 42 let eqr: i64 = B[0]*1000/A[0] // x1000, expect ~3000 43 44 g_w(" first-order half-lives(steps): h1="); g_n(h1); g_w(" h2="); g_n(h2); g_w(" h3="); g_n(h3); g_w(" mass[A]+[B]="); g_n(A0); g_w("\n") 45 g_w(" zero-order: z1="); g_n(z1); g_w(" z2="); g_n(z2); g_w(" (shrinks) reversible eq [B]/[A]x1000="); g_n(eqr); g_w(" (kf/kr=3000)\n") 46 47 init_impl(base); var t: i64=0; while t<120 { tick_impl(base, 0); t=t+1 } 48 render_impl(base) 49 write_png((base + O_FB) as *i64, W, H, "knowledge/nx_kinetics.png" as *u8) 50 let m: *u8=(base+O_FB) as *u8; var nb: i64=0; var i: i64=0 51 while i<W*H { let b: i64=i*8; if (m[b] as i64)!=12 { nb=nb+1 } else { if (m[b+1] as i64)!=14 { nb=nb+1 } else { if (m[b+2] as i64)!=22 { nb=nb+1 } } } i=i+1 } 52 53 var ran: i64=0; if h1>0 { if h3>0 { ran=1 } } 54 g_row("RUNS: the decay integrated and successive half-times were measured" as *u8, ran, pass) 55 g_row("CONSTANT HALF-LIFE: first-order halvings take EQUAL steps (h2,h3 within 3% of h1) -- the exponential law" as *u8, ((iabs(h2-h1)*100/h1 < 3) as i64)*((iabs(h3-h1)*100/h1 < 3) as i64), pass) 56 g_row("MASS CONSERVED: [A]+[B] = A0 exactly at all times (no atoms created or destroyed)" as *u8, mass_ok, pass) 57 g_row("EQUILIBRIUM: reversible A<=>B settles to [B]/[A] = kf/kr = 3.0 within 3%" as *u8, (iabs(eqr-3000) < 90) as i64, pass) 58 g_row("LIAR-KILL: ZERO-order decay's half-life SHRINKS (z2 < 0.7*z1) -- the equal-interval test detects reaction order" as *u8, (z2 < z1*70/100) as i64, pass) 59 g_row("RASTER: framebuffer drawn (decay curve + [A]/[B] bars) -> knowledge/nx_kinetics.png" as *u8, (nb>100) as i64, pass) 60 var iface: i64=0; if ww()==W { if hh()==H { if fb_off()==O_FB { iface=1 } } } 61 g_row("WASM-READY: init/tick/render/ww/hh/fb_off interface intact" as *u8, iface, pass) 62 63 g_w("NX-KINETICS-GATE rows=7 pass="); g_n(pass[0]) 64 if pass[0]==7 { g_w(" verdict=GREEN (real reaction kinetics; constant half-life + equilibrium + mass conservation, browser-ready)\n"); sys_exit(0); return 0 } 65 g_w(" verdict=RED\n"); sys_exit(1); return 1 66}