code wiki / _hdl_build / nx_softjiggle_gate.nx
nx_softjiggle_gate.nx source
↩ module page · 244 lines · 10862 B
1// nx_softjiggle_gate.nx -- gate for the jiggle-bone substrate. The jiggle ESSENCE is measured, not asserted:
2// T1 REST: node parked at its anchor stays put (gravity variant settles at the k/g equilibrium and stays)
3// T2 LAG + OVERSHOOT: step the anchor -> the node measurably LAGS, then OVERSHOOTS past, then settles = the
4// damped-oscillation signature that IS jiggle
5// T3 DECAY: successive overshoot peaks strictly shrink (energy dissipates -- no runaway)
6// T4 NO-EXPLOSION: violent anchor teleport -> displacement NEVER exceeds maxstretch (clamp by construction)
7// T5 DETERMINISM: two lattices, same shake script -> byte-identical states
8// T6 CONFIG-IS-DATA: stiffer/looser nodes produce different trajectories (profiles are data, mod-shippable)
9// + PNG knowledge/nx_jiggle_trace.png: the anchor step vs node response TRACE (lag/overshoot/decay, visible)
10// license_tier: ORIGINAL expect_exit: 0
11import "nx_syscalls.nx"
12import "nx_png.nx"
13import "nx_softjiggle.nx"
14
15func hw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
16func pn(v: i64) -> i64 {
17 let b: *u8 = sys_mmap(32) as *u8
18 var x: i64 = v
19 var neg: i64 = 0
20 if x < 0 { neg = 1; x = 0 - x }
21 var i: i64 = 31
22 if x == 0 { b[i] = 48 as u8; i = i - 1 }
23 while x > 0 { b[i] = (48 + x % 10) as u8; x = x / 10; i = i - 1 }
24 if neg == 1 { b[i] = 45 as u8; i = i - 1 }
25 sys_write(1, (b as i64 + i + 1) as *u8, 31 - i)
26 return 0
27}
28func gabs(v: i64) -> i64 { if v < 0 { return 0 - v } return v }
29
30func main() -> i64 {
31 var fails: i64 = 0
32
33 // ---- T1 rest ----
34 let w1: i64 = sys_mmap(sj_bytes()) as i64
35 sj_init(w1)
36 let r0: i64 = sj_add(w1, 1000, 1000, 0, 24, 40, 200, 0)
37 let rg: i64 = sj_add(w1, 3000, 1000, 0, 24, 40, 200, 60)
38 var t: i64 = 0
39 while t < 400 { sj_step(w1); t = t + 1 }
40 let n0: *i64 = sj_node(w1, r0)
41 let ng: *i64 = sj_node(w1, rg)
42 var t1: i64 = 1
43 if n0[0] != 1000 { t1 = 0 }
44 if n0[1] != 1000 { t1 = 0 }
45 let sagy: i64 = ng[1]
46 var t2i: i64 = 0
47 while t2i < 100 { sj_step(w1); t2i = t2i + 1 }
48 if ng[1] != sagy { t1 = 0 } // gravity node settled and STAYS
49 if sagy >= 1000 { t1 = 0 } // it sags BELOW the anchor
50 if t1 == 1 { hw("T1 PASS rest: anchored node exact; gravity node sags to equilibrium (y=" as *u8); pn(sagy); hw(") and stays\n" as *u8) }
51 else { hw("T1 FAIL n0x=" as *u8); pn(n0[0]); hw(" sagy=" as *u8); pn(sagy); hw("\n" as *u8); fails = fails + 1 }
52
53 // ---- T2+T3 lag, overshoot, decay + the PNG trace ----
54 let w2: i64 = sys_mmap(sj_bytes()) as i64
55 sj_init(w2)
56 let j: i64 = sj_add(w2, 0, 0, 0, 18, 28, 400, 0)
57 sj_anchor(w2, j, 300, 0, 0) // step input: anchor jumps +300 (1.17 units)
58 let nj: *i64 = sj_node(w2, j)
59 // trace buffers
60 let TW: i64 = 256
61 let TH: i64 = 160
62 let fb: *i64 = sys_mmap(TW * TH * 8) as *i64
63 var pi: i64 = 0
64 while pi < TW * TH { fb[pi] = 24 + 28 * 256 + 38 * 65536; pi = pi + 1 }
65 var lag_seen: i64 = 0
66 var over_seen: i64 = 0
67 var peak1: i64 = 0
68 var peak2: i64 = 0
69 var inpeak: i64 = 0
70 var curpeak: i64 = 0
71 var peakn: i64 = 0
72 t = 0
73 while t < 256 {
74 sj_step(w2)
75 let x: i64 = nj[0]
76 if t < 6 { if x < 260 { lag_seen = 1 } }
77 if x > 304 { over_seen = 1 }
78 // peak envelope: track |x-300| local maxima above a noise floor
79 let dev: i64 = gabs(x - 300)
80 if dev > 12 {
81 if dev > curpeak { curpeak = dev }
82 inpeak = 1
83 } else {
84 if inpeak == 1 {
85 peakn = peakn + 1
86 if peakn == 1 { peak1 = curpeak }
87 if peakn == 2 { peak2 = curpeak }
88 curpeak = 0
89 inpeak = 0
90 }
91 }
92 // trace plot: anchor row (green) vs node row (amber): y = 130 - x/4
93 var py: i64 = 130 - x / 4
94 if py < 2 { py = 2 }
95 if py > TH - 3 { py = TH - 3 }
96 fb[py * TW + t] = 90 + 220 * 256 + 130 * 65536
97 let ay: i64 = 130 - 300 / 4
98 fb[ay * TW + t] = 70 + 110 * 256 + 235 * 65536
99 t = t + 1
100 }
101 write_png(fb, TW, TH, "knowledge/nx_jiggle_trace.png" as *u8)
102 var t2: i64 = 1
103 if lag_seen == 0 { t2 = 0 }
104 if over_seen == 0 { t2 = 0 }
105 if gabs(nj[0] - 300) > 6 { t2 = 0 }
106 if t2 == 1 { hw("T2 PASS jiggle signature: LAGS the anchor step, OVERSHOOTS past it, settles (final dev=" as *u8); pn(gabs(nj[0] - 300)); hw(") + PNG trace\n" as *u8) }
107 else { hw("T2 FAIL lag=" as *u8); pn(lag_seen); hw(" over=" as *u8); pn(over_seen); hw(" final=" as *u8); pn(nj[0]); hw("\n" as *u8); fails = fails + 1 }
108 var t3: i64 = 1
109 if peakn < 2 { t3 = 0 }
110 if peak2 >= peak1 { t3 = 0 }
111 if t3 == 1 { hw("T3 PASS decay: overshoot peaks shrink (" as *u8); pn(peak1); hw(" -> " as *u8); pn(peak2); hw(", n=" as *u8); pn(peakn); hw(")\n" as *u8) }
112 else { hw("T3 FAIL peaks " as *u8); pn(peak1); hw(" -> " as *u8); pn(peak2); hw(" n=" as *u8); pn(peakn); hw("\n" as *u8); fails = fails + 1 }
113
114 // ---- T4 no-explosion clamp ----
115 let w4: i64 = sys_mmap(sj_bytes()) as i64
116 sj_init(w4)
117 let v: i64 = sj_add(w4, 0, 0, 0, 18, 28, 150, 0)
118 sj_anchor(w4, v, 20000, 0 - 20000, 20000)
119 let nv: *i64 = sj_node(w4, v)
120 var t4: i64 = 1
121 t = 0
122 while t < 200 {
123 sj_step(w4)
124 if gabs(nv[0] - 20000) > 151 { t4 = 0 }
125 if gabs(nv[1] + 20000) > 151 { t4 = 0 }
126 if gabs(nv[2] - 20000) > 151 { t4 = 0 }
127 t = t + 1
128 }
129 if t4 == 1 { hw("T4 PASS no-explosion: violent teleport, displacement NEVER exceeds maxstretch (by construction)\n" as *u8) }
130 else { hw("T4 FAIL clamp breached\n" as *u8); fails = fails + 1 }
131
132 // ---- T5 determinism (chained 3-node tail + shake script) ----
133 let wa: i64 = sys_mmap(sj_bytes()) as i64
134 let wb: i64 = sys_mmap(sj_bytes()) as i64
135 sj_init(wa); sj_init(wb)
136 var c: i64 = 0
137 while c < 3 {
138 sj_add(wa, 0, 0 - c * 100, 0, 20 + c * 6, 30, 300, 40)
139 sj_add(wb, 0, 0 - c * 100, 0, 20 + c * 6, 30, 300, 40)
140 if c > 0 { sj_chain(wa, c, c - 1); sj_chain(wb, c, c - 1) }
141 c = c + 1
142 }
143 sj_add_capsule(wa, 0, 0 - 500, 0, 0, 500, 0, 90) // capsule in the shake path: determinism must cover pushout
144 sj_add_capsule(wb, 0, 0 - 500, 0, 0, 500, 0, 90)
145 t = 0
146 while t < 300 {
147 var sx: i64 = 0
148 if (t / 25) % 2 == 0 { sx = 240 } else { sx = 0 - 240 }
149 sj_anchor(wa, 0, sx, 0, 0)
150 sj_anchor(wb, 0, sx, 0, 0)
151 sj_step(wa)
152 sj_step(wb)
153 t = t + 1
154 }
155 var diff: i64 = 0
156 var si: i64 = 0
157 while si < 3 * 16 {
158 let va: *i64 = (wa + 64) as *i64
159 let vb: *i64 = (wb + 64) as *i64
160 if va[si] != vb[si] { diff = diff + 1 }
161 si = si + 1
162 }
163 if diff == 0 { hw("T5 PASS determinism: chained 3-node tail, 300-tick shake -> byte-identical\n" as *u8) }
164 else { hw("T5 FAIL diff=" as *u8); pn(diff); hw("\n" as *u8); fails = fails + 1 }
165
166 // ---- T6 config-is-data: different k -> different trajectory ----
167 let w6: i64 = sys_mmap(sj_bytes()) as i64
168 sj_init(w6)
169 let s1: i64 = sj_add(w6, 0, 0, 0, 10, 28, 400, 0)
170 let s2: i64 = sj_add(w6, 0, 0, 0, 48, 28, 400, 0)
171 sj_anchor(w6, s1, 300, 0, 0)
172 sj_anchor(w6, s2, 300, 0, 0)
173 var traj_differs: i64 = 0
174 t = 0
175 while t < 40 {
176 sj_step(w6)
177 if sj_pos(w6, s1, 0) != sj_pos(w6, s2, 0) { traj_differs = traj_differs + 1 }
178 t = t + 1
179 }
180 if traj_differs > 20 { hw("T6 PASS profiles are DATA: k=10 vs k=48 diverge on " as *u8); pn(traj_differs); hw("/40 ticks (mod-shippable body profiles)\n" as *u8) }
181 else { hw("T6 FAIL differs=" as *u8); pn(traj_differs); hw("\n" as *u8); fails = fails + 1 }
182
183 // ---- T7 capsule surface: node anchored INSIDE a capsule settles ON the surface, never inside ----
184 let w7: i64 = sys_mmap(sj_bytes()) as i64
185 sj_init(w7)
186 sj_add_capsule(w7, 500, 0 - 400, 0, 500, 400, 0, 120)
187 let cn2: i64 = sj_add(w7, 700, 0, 0, 18, 30, 500, 0)
188 sj_anchor(w7, cn2, 500, 0, 0) // anchor ON the capsule axis: spring pulls in, pushout holds
189 let nn: *i64 = sj_node(w7, cn2)
190 var t7: i64 = 1
191 var minr2: i64 = 99999999
192 t = 0
193 while t < 300 {
194 sj_step(w7)
195 if t > 5 {
196 let exx: i64 = nn[0] - 500
197 let ezz: i64 = nn[2]
198 let dd: i64 = exx * exx + ezz * ezz + 0 * nn[1]
199 if nn[1] > 0 - 400 { if nn[1] < 400 {
200 if dd < minr2 { minr2 = dd }
201 } }
202 }
203 t = t + 1
204 }
205 if minr2 < 116 * 116 { t7 = 0 }
206 let fexx: i64 = nn[0] - 500
207 let fezz: i64 = nn[2]
208 let fd2: i64 = fexx * fexx + fezz * fezz
209 if fd2 < 117 * 117 { t7 = 0 }
210 if fd2 > 190 * 190 { t7 = 0 }
211 if t7 == 1 { hw("T7 PASS capsule: spring pulls to the axis, node HELD ON the surface (min-r=" as *u8); pn(sj_isqrt(minr2)); hw("/120, settles at r)\n" as *u8) }
212 else { hw("T7 FAIL minr2=" as *u8); pn(minr2); hw(" fd2=" as *u8); pn(fd2); hw("\n" as *u8); fails = fails + 1 }
213
214 // ---- T8 transit: dragged THROUGH a capsule -> slides AROUND it, never penetrates, reaches the far side ----
215 let w8: i64 = sys_mmap(sj_bytes()) as i64
216 sj_init(w8)
217 sj_add_capsule(w8, 500, 0 - 400, 0, 500, 400, 0, 120)
218 let tn: i64 = sj_add(w8, 700, 40, 0, 18, 30, 600, 0)
219 // far side WITH a z-offset: a perfectly z-symmetric pull sits in the saddle equilibrium forever (the
220 // first run proved it: min-r exactly 120, stuck at x=620) -- real rigs are never measure-zero symmetric
221 sj_anchor(w8, tn, 300, 40, 60)
222 let tb: *i64 = sj_node(w8, tn)
223 var t8: i64 = 1
224 var minr2b: i64 = 99999999
225 t = 0
226 while t < 400 {
227 sj_step(w8)
228 if tb[1] > 0 - 400 { if tb[1] < 400 {
229 let ex2: i64 = tb[0] - 500
230 let ez2: i64 = tb[2]
231 let dd2: i64 = ex2 * ex2 + ez2 * ez2
232 if dd2 < minr2b { minr2b = dd2 }
233 } }
234 t = t + 1
235 }
236 if minr2b < 116 * 116 { t8 = 0 }
237 if gabs(tb[0] - 300) > 60 { t8 = 0 } // reached the far anchor (outside the capsule)
238 if t8 == 1 { hw("T8 PASS transit: dragged through -> slides AROUND (min-r=" as *u8); pn(sj_isqrt(minr2b)); hw("/120), reaches the far side (x=" as *u8); pn(tb[0]); hw(")\n" as *u8) }
239 else { hw("T8 FAIL minr2=" as *u8); pn(minr2b); hw(" x=" as *u8); pn(tb[0]); hw("\n" as *u8); fails = fails + 1 }
240
241 if fails == 0 { hw("VERDICT GREEN: nx_softjiggle 8/8 -- jiggle measured (lag/overshoot/decay) + CAPSULE collision (surface-hold + slide-around), never-explode, deterministic, profiles=data (PNG knowledge/nx_jiggle_trace.png)\n" as *u8) }
242 else { hw("VERDICT RED fails=" as *u8); pn(fails); hw("\n" as *u8) }
243 return fails
244}