nx_chaos.nx source
↩ module page · 86 lines · 4194 B
1const O_MAGIC_500000: i64 = 500000
2const O_MAGIC_500001: i64 = 500001
3const O_MAGIC_3900: i64 = 3900
4const O_MAGIC_4096: i64 = 4096
5// nx_chaos.nx -- BROWSER-RUNNABLE deterministic-chaos sim (base-relative, integer/no-float, no JS logic). SAME code
6// runs native (base = mmap -> PNG) and in the browser. The logistic map x' = r x (1-x) -- the textbook route to
7// chaos. Two trajectories start ONE unit apart (x0 and x0+1) at r=3.9: they track, then DIVERGE exponentially
8// (sensitive dependence on initial conditions). The deep point: in integer/no-float arithmetic the sequence is
9// BIT-EXACT REPRODUCIBLE -- a chaotic system, run twice, gives identical results -- exactly where IEEE-754 float
10// sims diverge machine-to-machine. So this is the live face of the census's Reproducibility EXCEEDS. Validated by
11// nx_chaos_gate (fixed point / period-2 / chaos / sensitive-dependence / determinism). nx_wasm auto-exports all.
12// license_tier: ORIGINAL
13const W: i64 = 256
14const H: i64 = 256
15const O_FB: i64 = 0
16const O_XA: i64 = 524288
17const O_XB: i64 = 524296
18const O_R: i64 = 524304 // r * 1000
19const O_STEP: i64 = 524312
20const O_HA: i64 = 524320 // trajectory A history
21const O_HB: i64 = 524320 + 240*8 // trajectory B history
22const HISTN: i64 = 240
23const SC: i64 = 1000000 // x in [0, SC] == [0,1]
24const STEPS_PER_TICK: i64 = 1
25
26func rgb(r: i64, g: i64, b: i64) -> i64 { return (r & 255) | ((g & 255) << 8) | ((b & 255) << 16) }
27// logistic map x' = r x (1-x), integer: tmp = x(SC-x)/SC ; x' = tmp * (r*1000) / 1000
28func logistic(x: i64, R: i64) -> i64 { let tmp: i64 = x*(SC-x)/SC; return tmp*R/1000 }
29
30func putpx(base: i64, px: i64, py: i64, c: i64) -> i64 {
31 if px<0 { return 0 } if px>=W { return 0 } if py<0 { return 0 } if py>=H { return 0 }
32 let fb: *i64 = (base + O_FB) as *i64; fb[py*W+px]=c; return 0
33}
34func disc(base: i64, px: i64, py: i64, r: i64, c: i64) -> i64 {
35 var dy: i64=0-r
36 while dy<=r { var dx: i64=0-r
37 while dx<=r { if dx*dx+dy*dy<=r*r { putpx(base,px+dx,py+dy,c) } dx=dx+1 }
38 dy=dy+1 }
39 return 0
40}
41func clear_fb(base: i64, c: i64) -> i64 { let fb: *i64=(base+O_FB) as *i64; var i: i64=0; while i<W*H { fb[i]=c; i=i+1 } return 0 }
42
43func init_impl(base: i64) -> i64 {
44 let XA: *i64=(base+O_XA) as *i64; let XB: *i64=(base+O_XB) as *i64; let R: *i64=(base+O_R) as *i64
45 XA[0]=O_MAGIC_500000; XB[0]=O_MAGIC_500001; R[0]=O_MAGIC_3900 // x0 vs x0+1 (one unit apart), r=3.9 (chaotic)
46 let stp: *i64=(base+O_STEP) as *i64; stp[0]=0
47 let HA: *i64=(base+O_HA) as *i64; let HB: *i64=(base+O_HB) as *i64
48 var i: i64=0; while i<HISTN { HA[i]=0-1; HB[i]=0-1; i=i+1 }
49 return 0
50}
51func step_one_impl(base: i64) -> i64 {
52 let XA: *i64=(base+O_XA) as *i64; let XB: *i64=(base+O_XB) as *i64; let R: *i64=(base+O_R) as *i64
53 XA[0]=logistic(XA[0], R[0]); XB[0]=logistic(XB[0], R[0])
54 return 0
55}
56func tick_impl(base: i64, cmd: i64) -> i64 {
57 if cmd==3 { init_impl(base); return 0 }
58 let stp: *i64=(base+O_STEP) as *i64
59 if stp[0]>=HISTN { init_impl(base); return 0 }
60 var s: i64=0; while s<STEPS_PER_TICK { step_one_impl(base); s=s+1 }
61 let XA: *i64=(base+O_XA) as *i64; let XB: *i64=(base+O_XB) as *i64
62 let HA: *i64=(base+O_HA) as *i64; let HB: *i64=(base+O_HB) as *i64
63 HA[stp[0]]=XA[0]; HB[stp[0]]=XB[0]; stp[0]=stp[0]+1
64 return 0
65}
66func render_impl(base: i64) -> i64 {
67 let HA: *i64=(base+O_HA) as *i64; let HB: *i64=(base+O_HB) as *i64
68 clear_fb(base, rgb(10,10,18))
69 var x: i64=0
70 while x<HISTN {
71 let a: i64=HA[x]; let b: i64=HB[x]
72 if a>=0 { let ya: i64=(H-8) - a*(H-16)/SC; disc(base, x+8, ya, 1, rgb(90,170,255)) } // trajectory A blue
73 if b>=0 { let yb: i64=(H-8) - b*(H-16)/SC; disc(base, x+8, yb, 1, rgb(255,110,90)) } // trajectory B red
74 x=x+1
75 }
76 return 0
77}
78
79// ---- wasm interface ----
80func ww() -> i64 { return W }
81func hh() -> i64 { return H }
82func fb_off() -> i64 { return O_FB }
83func init() -> i64 { return init_impl(0) }
84func tick(cmd: i64) -> i64 { return tick_impl(0, cmd) }
85func render() -> i64 { return render_impl(0) }
86func mem_bytes() -> i64 { return O_HB + HISTN*8 + O_MAGIC_4096 }