nx_mmdev.nx source
↩ module page · 58 lines · 3003 B
1// nx_mmdev.nx -- CLI for the millimetre surface-deviation ruler (PG4, procgen.plan, 2026-08-24).
2// nx_mmdev <ours.nxmesh> <reference.nxmesh> -> JSON, both directions, units are TENTHS of a millimetre.
3// Exit 0 measured / 2 usage / 3 unreadable / 4 REFUSED extent bound (a subject over 2.5 m would overflow
4// the integer point-triangle test, and the ruler declines rather than reporting garbage) / 5 empty mesh.
5// Thin main: every function lives in nx_mmdev_lib so nx_mmdev_gate composes it in-process.
6// license_tier: ORIGINAL
7
8import "nx_syscalls.nx"
9import "nx_itoa_lib.nx"
10import "nx_mmdev_lib.nx"
11
12func mm_w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
13func mm_kv(k: *u8, v: i64, last: i64) -> i64 {
14 mm_w("\x22" as *u8); mm_w(k); mm_w("\x22:" as *u8); nxi_out(v)
15 if last == 0 { mm_w("," as *u8) }
16 return 0
17}
18func mm_dir(tag: *u8, res: *i64) -> i64 {
19 mm_w("\x22" as *u8); mm_w(tag); mm_w("\x22:{" as *u8)
20 mm_kv("tri_verts" as *u8, res[MD_R_VERTS], 0)
21 mm_kv("ref_tris" as *u8, res[MD_R_TRIS_B], 0)
22 mm_kv("mean_x10mm" as *u8, md_mean(res), 0)
23 mm_kv("p95_x10mm" as *u8, res[MD_R_P95], 0)
24 mm_kv("max_x10mm" as *u8, res[MD_R_MAX], 0)
25 mm_kv("grid_cells_axis" as *u8, res[MD_R_CELLS_AXIS], 0)
26 mm_kv("hist_overflow" as *u8, res[MD_R_OVERFLOW_BIN], 1)
27 mm_w("}" as *u8)
28 return 0
29}
30
31func main(argc: i64, argv: *i64) -> i64 {
32 if argc < 3 {
33 mm_w("{\x22error\x22:\x22usage: nx_mmdev <ours.nxmesh> <reference.nxmesh> -- surface deviation in tenths of a millimetre, both directions, full population\x22}\n" as *u8)
34 return 2
35 }
36 let la: *i64 = sys_mmap(16) as *i64
37 let lb: *i64 = sys_mmap(16) as *i64
38 let ma: *u8 = sys_read_file(argv[1] as *u8, la)
39 let mb: *u8 = sys_read_file(argv[2] as *u8, lb)
40 if (ma as i64) == 0 { mm_w("{\x22error\x22:\x22cannot read ours\x22}\n" as *u8); return 3 }
41 if (mb as i64) == 0 { mm_w("{\x22error\x22:\x22cannot read reference\x22}\n" as *u8); return 3 }
42 let ab: *i64 = md_res()
43 let ba: *i64 = md_res()
44 let r1: i64 = md_measure(ma, mb, ab)
45 let r2: i64 = md_measure(mb, ma, ba)
46 if r1 == 1 { mm_w("{\x22error\x22:\x22REFUSED extent over 2.5 m -- integer point-triangle test would overflow; the ruler declines rather than reporting garbage\x22}\n" as *u8); return 4 }
47 if r2 == 1 { mm_w("{\x22error\x22:\x22REFUSED extent over 2.5 m on the reference\x22}\n" as *u8); return 4 }
48 if r1 == 3 { mm_w("{\x22error\x22:\x22empty mesh\x22}\n" as *u8); return 5 }
49 if r2 == 3 { mm_w("{\x22error\x22:\x22empty reference\x22}\n" as *u8); return 5 }
50 mm_w("{\x22unit\x22:\x22tenths-of-a-millimetre\x22,\x22sampled\x22:0," as *u8)
51 mm_dir("ours_to_ref" as *u8, ab); mm_w("," as *u8)
52 mm_dir("ref_to_ours" as *u8, ba); mm_w("," as *u8)
53 var sym: i64 = md_mean(ab)
54 if md_mean(ba) > sym { sym = md_mean(ba) }
55 mm_kv("symmetric_mean_x10mm" as *u8, sym, 1)
56 mm_w("}\n" as *u8)
57 return 0
58}