code wiki / (root) / nx_swarm_tile.nx

nx_swarm_tile.nx source

↩ module page · 387 lines · 15585 B

1// nx_swarm_tile.nx -- SWARM FABRIC chunk EXECUTOR (SF-R3 real-artifact): a sovereign, embarrassingly- 2// parallel image generator. Each "chunk" = a horizontal BAND of a fixed-point Mandelbrot render; bands 3// are INDEPENDENT (no cross-tile state) = the exact workload class the operator named (3D render / Monte 4// Carlo / brute-force). The job engine (nx_swarm_job) stays GENERIC -- it leases opaque chunk ids; THIS 5// organ turns chunk id -> real pixels; a DRIVER wires place->lease->render->complete->assemble (rule 9). 6// Proves the north-star "generate an image by combining/parallelizing across the fabric" with REAL output 7// (was SIMULATED in the SF-R3 gate). When remote workers join, the SAME job engine dispatches the SAME 8// bands to them -- distribution is placement, already proven; this is the executor + assembler. 9// 10// render <W> <H> <ntiles> <tile_id> <outdir> -- render band tile_id -> outdir/tile_<id>.raw (RGB) 11// assemble <W> <H> <ntiles> <outdir> <out.ppm> -- stitch bands in order -> a real P6 PPM image 12// [gate] -- self-gate: determinism + structure + coverage + size 13// Fully integer (Q16 fixed-point escape-time) -> bit-identical across any device (the sovereign EXCEED axis: 14// float raster is non-deterministic across hardware). outdir: bare name or under /tmp/. license_tier: ORIGINAL 15import "nx_swarm_lib.nx" 16const T_MAGIC_1048576: i64 = 1048576 17const T_MAGIC_65536: i64 = 65536 18 19const T_SCALE: i64 = 65536 // Q16 20const T_MAXITER: i64 = 128 21const T_ESCAPE: i64 = 262144 // 4 << 16 (|z|^2 > 4) 22// complex window (Q16): real [-2.5, 1.0], imag [-1.25, 1.25] 23const T_XMIN: i64 = 0 - 163840 // -2.5 * 65536 24const T_XSPAN: i64 = 229376 // 3.5 * 65536 25const T_YMIN: i64 = 0 - 81920 // -1.25 * 65536 26const T_YSPAN: i64 = 163840 // 2.5 * 65536 27 28func tl_puts(s: *u8) -> i64 { sys_write(1, s, fa_len(s)); return 0 } 29func tl_eq(a: *u8, b: *u8) -> i64 { 30 var i: i64 = 0 31 while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } 32 if b[i] != (0 as u8) { return 0 } 33 return 1 34} 35 36// outdir guard: bare basename OR under /tmp/, no ".." 37func tl_dir_ok(p: *u8) -> i64 { 38 let n: i64 = fa_len(p) 39 if n < 1 { return 0 } 40 var i: i64 = 0 41 while i + 1 < n { if (p[i] as i64) == 46 { if (p[i+1] as i64) == 46 { return 0 } } i = i + 1 } 42 var slash: i64 = 0 43 i = 0 44 while i < n { if (p[i] as i64) == 47 { slash = 1 } i = i + 1 } 45 if slash == 0 { return 1 } 46 if n < 4 { return 0 } 47 if (p[0] as i64) != 47 { return 0 } 48 if (p[1] as i64) != 116 { return 0 } 49 if (p[2] as i64) != 109 { return 0 } 50 if (p[3] as i64) != 112 { return 0 } 51 if n == 4 { return 1 } 52 if (p[4] as i64) != 47 { return 0 } 53 return 1 54} 55 56// escape-time iteration count for c=(cre,cim) in Q16 fixed-point. Returns iters (0..T_MAXITER). 57func tl_iter(cre: i64, cim: i64) -> i64 { 58 var zr: i64 = 0 59 var zi: i64 = 0 60 var it: i64 = 0 61 var go: i64 = 1 62 while go == 1 { 63 if it >= T_MAXITER { go = 0 } else { 64 let zr2: i64 = (zr * zr) / T_SCALE // zr^2 in Q16 65 let zi2: i64 = (zi * zi) / T_SCALE 66 if zr2 + zi2 > T_ESCAPE { go = 0 } else { 67 let nzr: i64 = zr2 - zi2 + cre // zr' = zr^2 - zi^2 + cre 68 let cross: i64 = (zr * zi) / T_SCALE 69 let nzi: i64 = cross + cross + cim // zi' = 2*zr*zi + cim 70 zr = nzr 71 zi = nzi 72 it = it + 1 73 } 74 } 75 } 76 return it 77} 78 79// color for an iteration count -> rgb[0..2]. In-set (it==MAXITER) = black; else banded palette. 80func tl_color(it: i64, rgb: *u8) -> i64 { 81 if it >= T_MAXITER { 82 rgb[0] = 0 as u8; rgb[1] = 0 as u8; rgb[2] = 0 as u8 83 return 0 84 } 85 rgb[0] = ((it * 8) % 256) as u8 86 rgb[1] = ((it * 5) % 256) as u8 87 rgb[2] = ((64 + it * 11) % 256) as u8 88 return 0 89} 90 91// band row range for tile_id of ntiles over height H: [y0, y1). 92func tl_y0(H: i64, ntiles: i64, tid: i64) -> i64 { return tid * H / ntiles } 93func tl_y1(H: i64, ntiles: i64, tid: i64) -> i64 { return (tid + 1) * H / ntiles } 94 95// build "<dir>/tile_<id>.raw" into out. 96func tl_tile_path(dir: *u8, tid: i64, out: *u8) -> i64 { 97 var o: i64 = 0 98 o = fa_cat(out, o, dir) 99 out[o] = 47 as u8; o = o + 1 100 o = fa_cat(out, o, "tile_" as *u8) 101 o = fa_catn(out, o, tid) 102 o = fa_cat(out, o, ".raw" as *u8) 103 out[o] = 0 as u8 104 return o 105} 106 107func tl_write_all(fd: i64, buf: *u8, n: i64) -> i64 { 108 var off: i64 = 0 109 while off < n { 110 let w: i64 = sys_write(fd, (buf as i64 + off) as *u8, n - off) 111 if w <= 0 { return 0 - 1 } 112 off = off + w 113 } 114 return 0 115} 116 117// render band tid -> outdir/tile_<tid>.raw (RGB rows for [y0,y1)). Returns bytes written or -1. 118func tl_render(W: i64, H: i64, ntiles: i64, tid: i64, outdir: *u8) -> i64 { 119 let y0: i64 = tl_y0(H, ntiles, tid) 120 let y1: i64 = tl_y1(H, ntiles, tid) 121 let rows: i64 = y1 - y0 122 if rows <= 0 { return 0 } 123 let nbytes: i64 = rows * W * 3 124 let buf: *u8 = sys_mmap(nbytes + 16) 125 let rgb: *u8 = sys_mmap(8) 126 var py: i64 = y0 127 var bo: i64 = 0 128 while py < y1 { 129 let cim: i64 = T_YMIN + (py * T_YSPAN) / H 130 var px: i64 = 0 131 while px < W { 132 let cre: i64 = T_XMIN + (px * T_XSPAN) / W 133 let it: i64 = tl_iter(cre, cim) 134 tl_color(it, rgb) 135 buf[bo] = rgb[0]; buf[bo+1] = rgb[1]; buf[bo+2] = rgb[2] 136 bo = bo + 3 137 px = px + 1 138 } 139 py = py + 1 140 } 141 let path: *u8 = sys_mmap(512) 142 tl_tile_path(outdir, tid, path) 143 let fd: i64 = sys_openat_wr(path, 0x1a4) 144 if fd < 0 { return 0 - 1 } 145 let wr: i64 = tl_write_all(fd, buf, bo) 146 sys_close(fd) 147 if wr < 0 { return 0 - 1 } 148 return bo 149} 150 151// assemble: write P6 PPM header + concat tile_0.raw..tile_{n-1}.raw -> outfile. Returns total bytes or -1. 152func tl_assemble(W: i64, H: i64, ntiles: i64, outdir: *u8, outfile: *u8) -> i64 { 153 let fd: i64 = sys_openat_wr(outfile, 0x1a4) 154 if fd < 0 { return 0 - 1 } 155 // header "P6\n<W> <H>\n255\n" 156 let hdr: *u8 = sys_mmap(64) 157 var ho: i64 = 0 158 ho = fa_cat(hdr, ho, "P6\n" as *u8) 159 ho = fa_catn(hdr, ho, W) 160 hdr[ho] = 32 as u8; ho = ho + 1 161 ho = fa_catn(hdr, ho, H) 162 hdr[ho] = 10 as u8; ho = ho + 1 163 ho = fa_cat(hdr, ho, "255\n" as *u8) 164 if tl_write_all(fd, hdr, ho) < 0 { sys_close(fd); return 0 - 1 } 165 var total: i64 = ho 166 let path: *u8 = sys_mmap(512) 167 let rbuf: *u8 = sys_mmap(T_MAGIC_1048576) // 1 MiB streaming 168 var tid: i64 = 0 169 var ok: i64 = 1 170 while tid < ntiles { 171 if ok == 1 { 172 tl_tile_path(outdir, tid, path) 173 let rfd: i64 = sys_openat_rd(path) 174 if rfd < 0 { ok = 0 } else { 175 var go: i64 = 1 176 while go == 1 { 177 let r: i64 = sys_read(rfd, rbuf, T_MAGIC_1048576) 178 if r <= 0 { go = 0 } else { 179 if tl_write_all(fd, rbuf, r) < 0 { go = 0; ok = 0 } 180 total = total + r 181 } 182 } 183 sys_close(rfd) 184 } 185 } 186 tid = tid + 1 187 } 188 sys_close(fd) 189 if ok == 0 { return 0 - 1 } 190 return total 191} 192 193// count distinct byte-triples in a file (bounded) -> a cheap "has structure" probe. 194func tl_distinct_colors(path: *u8, cap: i64) -> i64 { 195 let buf: *u8 = sys_mmap(cap + 16) 196 let n: i64 = sb_read(path, buf, cap) 197 if n < 3 { return 0 } 198 // sample: count how many pixels differ from pixel 0 (structure => >0) 199 let r0: i64 = buf[0] as i64 200 let g0: i64 = buf[1] as i64 201 let b0: i64 = buf[2] as i64 202 var diff: i64 = 0 203 var i: i64 = 3 204 while i + 2 < n { 205 if (buf[i] as i64) != r0 { diff = diff + 1 } else { if (buf[i+1] as i64) != g0 { diff = diff + 1 } else { if (buf[i+2] as i64) != b0 { diff = diff + 1 } } } 206 i = i + 3 207 } 208 return diff 209} 210 211func tl_filesize(path: *u8) -> i64 { 212 let fd: i64 = sys_openat_rd(path) 213 if fd < 0 { return 0 - 1 } 214 var tot: i64 = 0 215 let b: *u8 = sys_mmap(T_MAGIC_65536) 216 var go: i64 = 1 217 while go == 1 { 218 let r: i64 = sys_read(fd, b, T_MAGIC_65536) 219 if r <= 0 { go = 0 } else { tot = tot + r } 220 } 221 sys_close(fd) 222 return tot 223} 224 225func tl_gate() -> i64 { 226 var pass: i64 = 0 227 var total: i64 = 0 228 let now: i64 = sys_now_us() 229 // fresh outdir under /tmp 230 let dir: *u8 = sys_mmap(256) 231 var od: i64 = 0 232 od = fa_cat(dir, od, "/tmp/tile_" as *u8); od = fa_catn(dir, od, now); dir[od] = 0 as u8 233 __syscall(258, AT_FDCWD, dir as i64, 0x1ff, 0, 0, 0) // mkdirat 0777 (raw: SYS_MKDIRAT not in nx_syscalls) 234 235 let W: i64 = 64 236 let H: i64 = 48 237 let NT: i64 = 4 238 239 // T1 render all bands -> each writes rows*W*3 bytes; coverage sums to H 240 total = total + 1 241 var covered: i64 = 0 242 var allok: i64 = 1 243 var tid: i64 = 0 244 while tid < NT { 245 let got: i64 = tl_render(W, H, NT, tid, dir) 246 let rows: i64 = tl_y1(H, NT, tid) - tl_y0(H, NT, tid) 247 if got != rows * W * 3 { allok = 0 } 248 covered = covered + rows 249 tid = tid + 1 250 } 251 if allok == 1 { if covered == H { pass = pass + 1; tl_puts("T1 render+coverage OK\n" as *u8) } } 252 253 // T2 assemble -> PPM size == header + W*H*3 254 total = total + 1 255 let ppm: *u8 = sys_mmap(256) 256 var po: i64 = 0 257 po = fa_cat(ppm, po, dir); ppm[po] = 47 as u8; po = po + 1 258 po = fa_cat(ppm, po, "out.ppm" as *u8); ppm[po] = 0 as u8 259 let asz: i64 = tl_assemble(W, H, NT, dir, ppm) 260 let fsz: i64 = tl_filesize(ppm) 261 // header len for 64x48: "P6\n64 48\n255\n" = 3+2+1+2+1+4 = 13 262 let pixbytes: i64 = W * H * 3 263 var t2: i64 = 0 264 if asz == fsz { if fsz > pixbytes { if fsz < pixbytes + 32 { t2 = 1 } } } 265 if t2 == 1 { pass = pass + 1; tl_puts("T2 assemble-size OK\n" as *u8) } 266 267 // T3 STRUCTURE: the fractal is not a flat color (distinct pixels > 0, and a lot) 268 total = total + 1 269 let diff: i64 = tl_distinct_colors(ppm, pixbytes + 64) 270 if diff > 100 { pass = pass + 1; tl_puts("T3 has-structure OK\n" as *u8) } 271 272 // T4 DETERMINISM (the sovereign EXCEED axis): re-render a band -> byte-identical to the first 273 total = total + 1 274 let dir2: *u8 = sys_mmap(256) 275 var o2: i64 = 0 276 o2 = fa_cat(dir2, o2, "/tmp/tile2_" as *u8); o2 = fa_catn(dir2, o2, now); dir2[o2] = 0 as u8 277 __syscall(258, AT_FDCWD, dir2 as i64, 0x1ff, 0, 0, 0) // mkdirat 0777 278 tl_render(W, H, NT, 1, dir2) 279 let p1: *u8 = sys_mmap(512) 280 let p2: *u8 = sys_mmap(512) 281 tl_tile_path(dir, 1, p1) 282 tl_tile_path(dir2, 1, p2) 283 let b1: *u8 = sys_mmap(T_MAGIC_65536) 284 let b2: *u8 = sys_mmap(T_MAGIC_65536) 285 let n1: i64 = sb_read(p1, b1, T_MAGIC_65536) 286 let n2: i64 = sb_read(p2, b2, T_MAGIC_65536) 287 var iden: i64 = 0 288 if n1 == n2 { if n1 > 0 { 289 var k: i64 = 0 290 var same: i64 = 1 291 while k < n1 { if b1[k] != b2[k] { same = 0; k = n1 } else { k = k + 1 } } 292 if same == 1 { iden = 1 } 293 } } 294 if iden == 1 { pass = pass + 1; tl_puts("T4 deterministic OK\n" as *u8) } 295 296 // T5 the SET is present: some pixels are black (in-set, it==MAXITER) -> the render is a real Mandelbrot 297 total = total + 1 298 let buf: *u8 = sys_mmap(pixbytes + 128) 299 let nn: i64 = sb_read(ppm, buf, pixbytes + 128) 300 var black: i64 = 0 301 var i: i64 = 13 // skip header 302 while i + 2 < nn { if (buf[i] as i64) == 0 { if (buf[i+1] as i64) == 0 { if (buf[i+2] as i64) == 0 { black = black + 1 } } } i = i + 3 } 303 if black > 20 { pass = pass + 1; tl_puts("T5 mandelbrot-set-present OK\n" as *u8) } 304 305 let t: *u8 = sys_mmap(128) 306 var to: i64 = 0 307 to = fa_cat(t, to, "SWARMTILEGATE " as *u8) 308 to = fa_catn(t, to, pass) 309 to = fa_cat(t, to, "/" as *u8) 310 to = fa_catn(t, to, total) 311 if pass == total { to = fa_cat(t, to, " verdict=GREEN\n" as *u8) } else { to = fa_cat(t, to, " verdict=RED\n" as *u8) } 312 sys_write(1, t, to) 313 if pass == total { return 0 } 314 return 1 315} 316 317// ASCII preview to stdout (no files) -- makes the sovereign render visible in a terminal/chat. 318func tl_preview(W: i64, H: i64) -> i64 { 319 let ramp: *u8 = " .:-=+*o#@" as *u8 // 10 chars, low iter -> high iter; in-set = '@' 320 let line: *u8 = sys_mmap(W + 2) 321 var py: i64 = 0 322 while py < H { 323 let cim: i64 = T_YMIN + (py * T_YSPAN) / H 324 var px: i64 = 0 325 while px < W { 326 let cre: i64 = T_XMIN + (px * T_XSPAN) / W 327 let it: i64 = tl_iter(cre, cim) 328 var idx: i64 = it * 9 / T_MAXITER 329 if idx > 9 { idx = 9 } 330 line[px] = ramp[idx] 331 px = px + 1 332 } 333 line[W] = 10 as u8 334 sys_write(1, line, W + 1) 335 py = py + 1 336 } 337 return 0 338} 339 340func main(argc: i64, argv: *i64) -> i64 { 341 if argc >= 2 { 342 let verb: *u8 = argv[1] as *u8 343 let vout: *i64 = sys_mmap(16) as *i64 344 let pend: *i64 = sys_mmap(16) as *i64 345 if tl_eq(verb, "preview" as *u8) == 1 { 346 var W: i64 = 78 347 var H: i64 = 30 348 if argc >= 4 { 349 sb_pint(argv[2] as *u8, fa_len(argv[2] as *u8), 0, vout, pend); W = vout[0] 350 sb_pint(argv[3] as *u8, fa_len(argv[3] as *u8), 0, vout, pend); H = vout[0] 351 } 352 return tl_preview(W, H) 353 } 354 if tl_eq(verb, "render" as *u8) == 1 { 355 if argc < 7 { tl_puts("usage: nx_swarm_tile render <W> <H> <ntiles> <tile_id> <outdir>\n" as *u8); return 2 } 356 sb_pint(argv[2] as *u8, fa_len(argv[2] as *u8), 0, vout, pend); let W: i64 = vout[0] 357 sb_pint(argv[3] as *u8, fa_len(argv[3] as *u8), 0, vout, pend); let H: i64 = vout[0] 358 sb_pint(argv[4] as *u8, fa_len(argv[4] as *u8), 0, vout, pend); let NT: i64 = vout[0] 359 sb_pint(argv[5] as *u8, fa_len(argv[5] as *u8), 0, vout, pend); let TID: i64 = vout[0] 360 let dir: *u8 = argv[6] as *u8 361 if tl_dir_ok(dir) == 0 { tl_puts("SWARMTILE render REFUSED (dir law)\n" as *u8); return 3 } 362 let r: i64 = tl_render(W, H, NT, TID, dir) 363 if r < 0 { tl_puts("SWARMTILE render IO-FAIL\n" as *u8); return 4 } 364 let t: *u8 = sys_mmap(96) 365 var o: i64 = fa_cat(t, 0, "SWARMTILE rendered tile=" as *u8) 366 o = fa_catn(t, o, TID); o = fa_cat(t, o, " bytes=" as *u8); o = fa_catn(t, o, r); o = fa_cat(t, o, "\n" as *u8) 367 sys_write(1, t, o) 368 return 0 369 } 370 if tl_eq(verb, "assemble" as *u8) == 1 { 371 if argc < 7 { tl_puts("usage: nx_swarm_tile assemble <W> <H> <ntiles> <outdir> <out.ppm>\n" as *u8); return 2 } 372 sb_pint(argv[2] as *u8, fa_len(argv[2] as *u8), 0, vout, pend); let W: i64 = vout[0] 373 sb_pint(argv[3] as *u8, fa_len(argv[3] as *u8), 0, vout, pend); let H: i64 = vout[0] 374 sb_pint(argv[4] as *u8, fa_len(argv[4] as *u8), 0, vout, pend); let NT: i64 = vout[0] 375 let dir: *u8 = argv[5] as *u8 376 if tl_dir_ok(dir) == 0 { tl_puts("SWARMTILE assemble REFUSED (dir law)\n" as *u8); return 3 } 377 let r: i64 = tl_assemble(W, H, NT, dir, argv[6] as *u8) 378 if r < 0 { tl_puts("SWARMTILE assemble IO-FAIL\n" as *u8); return 4 } 379 let t: *u8 = sys_mmap(96) 380 var o: i64 = fa_cat(t, 0, "SWARMTILE assembled bytes=" as *u8) 381 o = fa_catn(t, o, r); o = fa_cat(t, o, "\n" as *u8) 382 sys_write(1, t, o) 383 return 0 384 } 385 } 386 return tl_gate() 387}