code wiki / _hdl_build / nx_kind.nx

nx_kind.nx source

↩ module page · 586 lines · 25392 B

1// nx_kind.nx -- L0 OF THE SEMANTIC LADDER, OMNI EDITION (debts 1785954089 + 1785955711; operator 2// 2026-08-05: "animal, human, humanoid, real, fantasy, natural object, mechanical -- whatever fits the 3// ontological goal"). Successor to nx_bodyparts v1, which COMPILED IN "humanoid" and could therefore 4// only ever recognise one species -- the exact magic-number/spec-as-data violation the estate forbids. 5// 6// A KIND IS A ROW, NOT A FUNCTION. Schemas are predicates over a mesh's structural signature; the 7// organ evaluates a mesh against EVERY registered kind and reports the best match plus WHY each other 8// failed. Adding "quadruped" or "fastener" is an append, never a recompile. 9// 10// SIGNATURE (rig-free, works on any mesh soup): slice along the declared stack axis into bands; in each 11// band build a histogram over the declared cluster axis; count occupied runs (clusters) and the span 12// width. Triangle SPANS are rasterised, not vertices (a coarse box must occupy every band it crosses -- 13// a refusal from an empty measurement is not a refusal from a measurement). 14// 15// SCHEMA ROWS (plane knowledge/store/kind-, tab-separated, key-first; last-wins by convention): 16// <kind> stack <axis 0=x 1=y 2=z> <cluster-axis> -- declares the frame 17// <kind> band <lo> <hi> <minclust> <maxclust> <label> -- lo/hi are per-mille of extent 18// <kind> narrow <lo> <hi> <frac-permil-of-max> <label> -- a waist/neck: a width MINIMUM 19// Unknown verbs are IGNORED ADDITIVELY so new predicate kinds (radial-symmetry, periodicity, genus) 20// can be seeded before this organ learns to test them. 21// 22// nx_kind <mesh.nxmesh> [bands] (schemas from the plane) 23// nx_kind schema <file> <mesh.nxmesh> [bands] (schemas from a file -- offline/selftest) 24// nx_kind selftest 25// license_tier: ORIGINAL expect_exit: 0 26import "nx_syscalls.nx" 27import "nx_store_seed_lib.nx" 28const KD_MAGIC_65536: i64 = 65536 29const KD_MAGIC_1600: i64 = 1600 30const KD_MAGIC_262144: i64 = 262144 31const KD_MAGIC_1350: i64 = 1350 32const KD_MAGIC_1300: i64 = 1300 33const KD_MAGIC_1430: i64 = 1430 34const KD_MAGIC_1100: i64 = 1100 35 36const KD_CAP: i64 = 33554432 37const KD_SCAP: i64 = 262144 38const KD_MAXTRI: i64 = 400000 39const KD_MAXBAND: i64 = 256 40const KD_BINS: i64 = 128 41const KD_GAP: i64 = 2 42const KD_MAXTAX: i64 = 32 43const KD_MAXRULE: i64 = 256 44const KD_NAMECAP: i64 = 32 45const KD_M8388607: i64 = 8388607 46const KD_M8388608: i64 = 8388608 47const KD_BIG: i64 = 4611686018427387903 48const KD_TAB: i64 = 9 49const KD_NL: i64 = 10 50 51func hw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 52func pn(v: i64) -> i64 { let b: *u8=sys_mmap(32) as *u8; var x: i64=v; var ng: i64=0; if x<0{ng=1;x=0-x} var i: i64=31; if x==0{b[i]=48 as u8;i=i-1} while x>0{b[i]=(48+x%10) as u8;x=x/10;i=i-1} if ng==1{b[i]=45 as u8;i=i-1} sys_write(1,(b as i64+i+1) as *u8,31-i); return 0 } 53func kd_pr(b: *u8, a: i64, e: i64) -> i64 { if e > a { sys_write(1, ((b as i64)+a) as *u8, e-a) } return 0 } 54func kd_u32(b: *u8, o: i64) -> i64 { return (b[o] as i64) + ((b[o+1] as i64)<<8) + ((b[o+2] as i64)<<16) + ((b[o+3] as i64)<<24) } 55func kd_f32q(w: i64) -> i64 { 56 let sign: i64 = (w >> 31) & 1 57 let expo: i64 = (w >> 23) & 255 58 if expo == 0 { return 0 } 59 var mant: i64 = (w & KD_M8388607) | KD_M8388608 60 let sh: i64 = expo - 127 61 var v: i64 = 0 62 if sh >= 23 { if sh - 23 > 30 { return 0 } } 63 if sh >= 23 { v = mant * 100 * (1 << (sh - 23)) } 64 if sh < 23 { if 23 - sh > 62 { return 0 } } 65 if sh < 23 { v = (mant * 100) >> (23 - sh) } 66 if sign == 1 { return 0 - v } 67 return v 68} 69func kd_refuse(reason: *u8) -> i64 { hw("KIND REFUSED: " as *u8); hw(reason); hw("\n" as *u8); return 0 } 70 71func kd_load(path: *u8, vx: *i64) -> i64 { 72 let fd: i64 = sys_openat_rd(path) 73 if fd < 0 { return 0 - 1 } 74 let b: *u8 = sys_mmap(KD_CAP + 64) 75 var n: i64 = 0 76 var go: i64 = 1 77 while go == 1 { 78 let r: i64 = sys_read(fd, ((b as i64) + n) as *u8, KD_CAP - n) 79 if r <= 0 { go = 0 } else { n = n + r } 80 if n >= KD_CAP { go = 0 } 81 } 82 sys_close(fd) 83 if n < 44 { return 0 - 1 } 84 if b[0] != (78 as u8) { return 0 - 1 } 85 if b[5] != (50 as u8) { return 0 - 1 } 86 let nlay: i64 = kd_u32(b, 8) 87 let nt: i64 = kd_u32(b, 12) 88 if nt <= 0 { return 0 - 1 } 89 if nt > KD_MAXTRI { return 0 - 1 } 90 let hdr: i64 = 16 + nlay*24 91 if hdr + nt*84 > n { return 0 - 1 } 92 var t: i64 = 0 93 while t < nt { 94 var c: i64 = 0 95 while c < 9 { vx[t*9+c] = kd_f32q(kd_u32(b, hdr + t*84 + c*4)); c = c + 1 } 96 t = t + 1 97 } 98 return nt 99} 100func kd_readfile(path: *u8, buf: *u8, cap: i64) -> i64 { 101 let fd: i64 = sys_openat_rd(path) 102 if fd < 0 { return 0 - 1 } 103 var n: i64 = 0 104 var go: i64 = 1 105 while go == 1 { 106 let r: i64 = sys_read(fd, ((buf as i64) + n) as *u8, cap - n) 107 if r <= 0 { go = 0 } else { n = n + r } 108 if n >= cap { go = 0 } 109 } 110 sys_close(fd) 111 return n 112} 113 114// ---- signature: clusters + width per band, over declared axes ---- 115static KD_CL: i64 116static KD_WD: i64 117static KD_NB: i64 118func kd_clusters(occ: *i64) -> i64 { 119 var runs: i64 = 0 120 var inrun: i64 = 0 121 var empty: i64 = 0 122 var i: i64 = 0 123 while i < KD_BINS { 124 if occ[i] > 0 { 125 if inrun == 0 { runs = runs + 1; inrun = 1 } 126 empty = 0 127 } else { 128 empty = empty + 1 129 if empty >= KD_GAP { inrun = 0 } 130 } 131 i = i + 1 132 } 133 return runs 134} 135func kd_width(occ: *i64) -> i64 { 136 var lo: i64 = 0 - 1 137 var hi: i64 = 0 - 1 138 var i: i64 = 0 139 while i < KD_BINS { 140 if occ[i] > 0 { if lo < 0 { lo = i } hi = i } 141 i = i + 1 142 } 143 if lo < 0 { return 0 } 144 return hi - lo + 1 145} 146// ★A PREDICATE OVER A 2-AXIS PROJECTION MEASURES A SHADOW UNLESS IT WINDOWS THE THIRD AXIS 147// (found 2026-08-05 by the quadruped fixture: its barrel spans the same z as the legs beneath it, so 148// legs+barrel merged into ONE cluster and 'four legs' was untestable). wlo/whi are per-mille of the 149// THIRD axis extent (the one that is neither stack nor cluster); 0..1000 = no filter. 150func kd_sig(vx: *i64, nt: i64, nband: i64, sa: i64, ca: i64, wlo: i64, whi: i64) -> i64 { 151 var wa: i64 = 3 - sa - ca 152 var wmn: i64 = KD_BIG 153 var wmx: i64 = 0-KD_BIG 154 var tw: i64 = 0 155 while tw < nt { 156 var cw: i64 = 0 157 while cw < 3 { 158 let wv: i64 = vx[tw*9+cw*3+wa] 159 if wv < wmn { wmn = wv } 160 if wv > wmx { wmx = wv } 161 cw = cw + 1 162 } 163 tw = tw + 1 164 } 165 var wext: i64 = wmx - wmn 166 if wext < 1 { wext = 1 } 167 var smn: i64 = KD_BIG 168 var smx: i64 = 0-KD_BIG 169 var cmn: i64 = KD_BIG 170 var cmx: i64 = 0-KD_BIG 171 var t: i64 = 0 172 while t < nt { 173 var c: i64 = 0 174 while c < 3 { 175 let s: i64 = vx[t*9+c*3+sa] 176 let u: i64 = vx[t*9+c*3+ca] 177 if s < smn { smn = s } 178 if s > smx { smx = s } 179 if u < cmn { cmn = u } 180 if u > cmx { cmx = u } 181 c = c + 1 182 } 183 t = t + 1 184 } 185 var ext: i64 = smx - smn 186 if ext < 1 { return 0 - 1 } 187 var wid: i64 = cmx - cmn 188 if wid < 1 { wid = 1 } 189 let grid: *i64 = sys_mmap(KD_MAXBAND*KD_BINS*8 + 64) as *i64 190 var g: i64 = 0 191 while g < nband*KD_BINS { grid[g] = 0; g = g + 1 } 192 t = 0 193 while t < nt { 194 var slo: i64 = vx[t*9+sa] 195 var shi: i64 = slo 196 var ulo: i64 = vx[t*9+ca] 197 var uhi: i64 = ulo 198 var c2: i64 = 1 199 while c2 < 3 { 200 let ss: i64 = vx[t*9+c2*3+sa] 201 let uu: i64 = vx[t*9+c2*3+ca] 202 if ss < slo { slo = ss } 203 if ss > shi { shi = ss } 204 if uu < ulo { ulo = uu } 205 if uu > uhi { uhi = uu } 206 c2 = c2 + 1 207 } 208 // third-axis window filter (per-mille of that axis' extent) 209 var wc: i64 = (vx[t*9+wa] + vx[t*9+3+wa] + vx[t*9+6+wa])/3 210 var wpm: i64 = (wc - wmn)*1000/wext 211 var keep: i64 = 0 212 if wpm >= wlo { if wpm <= whi { keep = 1 } } 213 var b0: i64 = (slo - smn)*nband/ext 214 var b1: i64 = (shi - smn)*nband/ext 215 if b0 < 0 { b0 = 0 } 216 if b1 >= nband { b1 = nband-1 } 217 var i0: i64 = (ulo - cmn)*KD_BINS/wid 218 var i1: i64 = (uhi - cmn)*KD_BINS/wid 219 if i0 < 0 { i0 = 0 } 220 if i1 >= KD_BINS { i1 = KD_BINS-1 } 221 if keep == 1 { 222 var bb: i64 = b0 223 while bb <= b1 { 224 var ii: i64 = i0 225 while ii <= i1 { grid[bb*KD_BINS + ii] = grid[bb*KD_BINS + ii] + 1; ii = ii + 1 } 226 bb = bb + 1 227 } 228 } 229 t = t + 1 230 } 231 if KD_CL == 0 { KD_CL = sys_mmap(KD_MAXBAND*8) as i64; KD_WD = sys_mmap(KD_MAXBAND*8) as i64 } 232 let cl: *i64 = KD_CL as *i64 233 let wd: *i64 = KD_WD as *i64 234 var b3: i64 = 0 235 while b3 < nband { 236 cl[b3] = kd_clusters(((grid as i64) + b3*KD_BINS*8) as *i64) 237 wd[b3] = kd_width(((grid as i64) + b3*KD_BINS*8) as *i64) 238 b3 = b3 + 1 239 } 240 KD_NB = nband 241 return ext 242} 243 244// ---- schema parsing ---- 245func kd_eol(b: *u8, n: i64, i: i64) -> i64 { 246 var e: i64 = i 247 while e < n { if b[e] == (KD_NL as u8) { return e } else { e = e + 1 } } 248 return n 249} 250// fill col[0..2k] with start/end of up to maxc tab-separated fields in [ls,le) 251func kd_cols(b: *u8, ls: i64, le: i64, col: *i64, maxc: i64) -> i64 { 252 var c: i64 = 0 253 var p: i64 = ls 254 while c < maxc { 255 // ★A BREAK-BY-SENTINEL THAT OVERWRITES THE CURSOR DESTROYS THE POSITION IT EXISTS TO REPORT 256 // (banked law, re-broken here 2026-08-05 = 4th occurrence: q=le+le then q-le-le is 0, so every 257 // field parsed EMPTY and all 7 kinds came back nameless). Terminate with a FLAG, never the cursor. 258 var q: i64 = p 259 var fnd: i64 = 0 260 while fnd == 0 { 261 if q >= le { fnd = 1 } else { if b[q] == (KD_TAB as u8) { fnd = 1 } else { q = q + 1 } } 262 } 263 col[c*2] = p 264 col[c*2+1] = q 265 if q >= le { c = c + 1; while c < maxc { col[c*2] = le; col[c*2+1] = le; c = c + 1 } return c } 266 p = q + 1 267 c = c + 1 268 } 269 return c 270} 271func kd_int(b: *u8, a: i64, e: i64) -> i64 { 272 var v: i64 = 0 273 var neg: i64 = 0 274 var i: i64 = a 275 if i < e { if b[i] == (45 as u8) { neg = 1; i = i + 1 } } 276 while i < e { 277 let ch: i64 = b[i] as i64 278 if ch >= 48 { if ch <= 57 { v = v*10 + (ch-48) } } 279 i = i + 1 280 } 281 if neg == 1 { return 0 - v } 282 return v 283} 284func kd_same(b: *u8, a: i64, e: i64, lit: *u8) -> i64 { 285 var l: i64 = 0 286 while lit[l] != (0 as u8) { l = l + 1 } 287 if e - a != l { return 0 } 288 var i: i64 = 0 289 while i < l { if b[a+i] != lit[i] { return 0 } i = i + 1 } 290 return 1 291} 292func kd_streq(b: *u8, a1: i64, e1: i64, a2: i64, e2: i64) -> i64 { 293 if e1-a1 != e2-a2 { return 0 } 294 var i: i64 = 0 295 while i < e1-a1 { if b[a1+i] != b[a2+i] { return 0 } i = i + 1 } 296 return 1 297} 298 299func kd_run(meshp: *u8, sb: *u8, sn: i64, nband: i64) -> i64 { 300 let vx: *i64 = sys_mmap(KD_MAXTRI*9*8 + 64) as *i64 301 let nt: i64 = kd_load(meshp, vx) 302 if nt < 0 { kd_refuse("mesh unreadable or not NXMSH2" as *u8); return 3 } 303 if sn <= 0 { kd_refuse("no kind schemas (plane empty or file unreadable) -- refusing to guess an ontology" as *u8); return 4 } 304 // distinct kind names (first field of each row) 305 let tn0: *i64 = sys_mmap(KD_MAXTAX*8) as *i64 306 let tn1: *i64 = sys_mmap(KD_MAXTAX*8) as *i64 307 var ntax: i64 = 0 308 let col: *i64 = sys_mmap(24*2*8) as *i64 309 var i: i64 = 0 310 while i < sn { 311 let le: i64 = kd_eol(sb, sn, i) 312 if le > i { 313 kd_cols(sb, i, le, col, 10) 314 var seen: i64 = 0 315 var k: i64 = 0 316 while k < ntax { if kd_streq(sb, col[0], col[1], tn0[k], tn1[k]) == 1 { seen = 1; k = ntax } else { k = k + 1 } } 317 if seen == 0 { if ntax < KD_MAXTAX { tn0[ntax] = col[0]; tn1[ntax] = col[1]; ntax = ntax + 1 } } 318 } 319 i = le + 1 320 } 321 hw("{\x22organ\x22:\x22nx_kind\x22,\x22level\x22:\x22L0-kind\x22,\x22tris\x22:" as *u8); pn(nt) 322 hw(",\x22bands\x22:" as *u8); pn(nband) 323 hw(",\x22kinds_registered\x22:" as *u8); pn(ntax) 324 hw(",\x22results\x22:[" as *u8) 325 var best: i64 = 0 - 1 326 var best_rules: i64 = 0 327 var tix: i64 = 0 328 while tix < ntax { 329 // frame: default stack=y(1) cluster=x(0); a stack row overrides 330 var sa: i64 = 1 331 var ca: i64 = 0 332 i = 0 333 while i < sn { 334 let le2: i64 = kd_eol(sb, sn, i) 335 if le2 > i { 336 kd_cols(sb, i, le2, col, 8) 337 if kd_streq(sb, col[0], col[1], tn0[tix], tn1[tix]) == 1 { 338 if kd_same(sb, col[2], col[3], "stack" as *u8) == 1 { sa = kd_int(sb, col[4], col[5]); ca = kd_int(sb, col[6], col[7]) } 339 } 340 } 341 i = le2 + 1 342 } 343 if kd_sig(vx, nt, nband, sa, ca, 0, 1000) < 0 { kd_refuse("degenerate extent on the declared stack axis" as *u8); return 5 } 344 let cl: *i64 = KD_CL as *i64 345 let wd: *i64 = KD_WD as *i64 346 var wmax: i64 = 0 347 var b4: i64 = 0 348 while b4 < nband { if wd[b4] > wmax { wmax = wd[b4] } b4 = b4 + 1 } 349 var rules: i64 = 0 350 var passed: i64 = 0 351 var f0: i64 = 0 352 var f1: i64 = 0 353 i = 0 354 while i < sn { 355 let le3: i64 = kd_eol(sb, sn, i) 356 if le3 > i { 357 kd_cols(sb, i, le3, col, 10) 358 if kd_streq(sb, col[0], col[1], tn0[tix], tn1[tix]) == 1 { 359 if kd_same(sb, col[2], col[3], "band" as *u8) == 1 { 360 rules = rules + 1 361 let lo: i64 = kd_int(sb, col[4], col[5]) 362 let hi: i64 = kd_int(sb, col[6], col[7]) 363 let mnc: i64 = kd_int(sb, col[8], col[9]) 364 let mxc: i64 = kd_int(sb, col[10], col[11]) 365 // optional third-axis window in fields 7,8 (per-mille); absent = whole extent 366 var rwlo: i64 = 0 367 var rwhi: i64 = 1000 368 if col[15] > col[14] { rwlo = kd_int(sb, col[14], col[15]); rwhi = kd_int(sb, col[16], col[17]) } 369 if rwhi <= rwlo { rwlo = 0; rwhi = 1000 } 370 kd_sig(vx, nt, nband, sa, ca, rwlo, rwhi) 371 var got: i64 = 0 372 var b5: i64 = 0 373 while b5 < nband { 374 let pm: i64 = b5*1000/nband 375 if pm >= lo { if pm <= hi { if cl[b5] > got { got = cl[b5] } } } 376 b5 = b5 + 1 377 } 378 var ok: i64 = 0 379 if got >= mnc { if got <= mxc { ok = 1 } } 380 if ok == 1 { passed = passed + 1 } else { if f1 == 0 { f0 = col[12]; f1 = col[13] } } 381 kd_sig(vx, nt, nband, sa, ca, 0, 1000) 382 } 383 if kd_same(sb, col[2], col[3], "narrow" as *u8) == 1 { 384 rules = rules + 1 385 let lo2: i64 = kd_int(sb, col[4], col[5]) 386 let hi2: i64 = kd_int(sb, col[6], col[7]) 387 let frac: i64 = kd_int(sb, col[8], col[9]) 388 var wmin: i64 = KD_BIG 389 var b6: i64 = 0 390 while b6 < nband { 391 let pm2: i64 = b6*1000/nband 392 if pm2 >= lo2 { if pm2 <= hi2 { if wd[b6] > 0 { if wd[b6] < wmin { wmin = wd[b6] } } } } 393 b6 = b6 + 1 394 } 395 var ok2: i64 = 0 396 if wmin < KD_BIG { if wmax > 0 { if wmin*1000 <= wmax*frac { ok2 = 1 } } } 397 if ok2 == 1 { passed = passed + 1 } else { if f1 == 0 { f0 = col[10]; f1 = col[11] } } 398 } 399 } 400 } 401 i = le3 + 1 402 } 403 if tix > 0 { hw("," as *u8) } 404 hw("{\x22kind\x22:\x22" as *u8); kd_pr(sb, tn0[tix], tn1[tix]) 405 hw("\x22,\x22rules\x22:" as *u8); pn(rules) 406 hw(",\x22passed\x22:" as *u8); pn(passed) 407 if passed == rules { if rules > 0 { hw(",\x22match\x22:1" as *u8) } else { hw(",\x22match\x22:0" as *u8) } } else { hw(",\x22match\x22:0,\x22first_fail\x22:\x22" as *u8); kd_pr(sb, f0, f1); hw("\x22" as *u8) } 408 hw("}" as *u8) 409 if passed == rules { if rules > best_rules { best = tix; best_rules = rules } } 410 tix = tix + 1 411 } 412 hw("]" as *u8) 413 if best >= 0 { hw(",\x22verdict\x22:\x22" as *u8); kd_pr(sb, tn0[best], tn1[best]); hw("\x22,\x22matched_rules\x22:" as *u8); pn(best_rules) } else { hw(",\x22verdict\x22:\x22NO-KIND-MATCH\x22" as *u8) } 414 hw(",\x22note\x22:\x22kinds are DATA (plane rows); unknown verbs ignored additively so radial-symmetry/periodicity/genus can be seeded before they are testable\x22}\n" as *u8) 415 if best >= 0 { return 0 } 416 return 1 417} 418 419// ---- fixtures ---- 420func kd_encf(v: i64, scale: i64) -> i64 { 421 if v == 0 { return 0 } 422 var neg: i64 = 0 423 var m: i64 = v 424 if m < 0 { neg = 1; m = 0-m } 425 var e: i64 = 0 426 var num: i64 = m 427 var den: i64 = scale 428 while num >= den*2 { den = den*2; e = e+1 } 429 while num < den { num = num*2; e = e-1 } 430 let frac: i64 = ((num - den)*KD_M8388608)/den 431 var bits: i64 = ((e+127) << 23) | (frac & KD_M8388607) 432 if neg == 1 { bits = bits | (1<<31) } 433 return bits 434} 435func kd_w32(b: *u8, o: i64, v: i64) -> i64 { b[o]=(v&255) as u8; b[o+1]=((v>>8)&255) as u8; b[o+2]=((v>>16)&255) as u8; b[o+3]=((v>>24)&255) as u8; return 0 } 436func kd_tri(b: *u8, off: i64, x0: i64, y0: i64, z0: i64, x1: i64, y1: i64, z1: i64, x2: i64, y2: i64, z2: i64) -> i64 { 437 kd_w32(b, off, kd_encf(x0,1)); kd_w32(b, off+4, kd_encf(y0,1)); kd_w32(b, off+8, kd_encf(z0,1)) 438 kd_w32(b, off+12, kd_encf(x1,1)); kd_w32(b, off+16, kd_encf(y1,1)); kd_w32(b, off+20, kd_encf(z1,1)) 439 kd_w32(b, off+24, kd_encf(x2,1)); kd_w32(b, off+28, kd_encf(y2,1)); kd_w32(b, off+32, kd_encf(z2,1)) 440 var q: i64 = 36 441 while q < 84 { b[off+q] = 0 as u8; q = q + 1 } 442 return 0 443} 444func kd_box(b: *u8, off: i64, xlo: i64, xhi: i64, ylo: i64, yhi: i64, zlo: i64, zhi: i64) -> i64 { 445 var o: i64 = off 446 kd_tri(b, o, xlo,ylo,zlo, xhi,ylo,zlo, xhi,yhi,zlo); o = o + 84 447 kd_tri(b, o, xlo,ylo,zlo, xhi,yhi,zlo, xlo,yhi,zlo); o = o + 84 448 kd_tri(b, o, xlo,ylo,zhi, xhi,ylo,zhi, xhi,yhi,zhi); o = o + 84 449 kd_tri(b, o, xlo,ylo,zhi, xhi,yhi,zhi, xlo,yhi,zhi); o = o + 84 450 kd_tri(b, o, xlo,ylo,zlo, xlo,yhi,zlo, xlo,yhi,zhi); o = o + 84 451 kd_tri(b, o, xlo,ylo,zlo, xlo,yhi,zhi, xlo,ylo,zhi); o = o + 84 452 kd_tri(b, o, xhi,ylo,zlo, xhi,yhi,zlo, xhi,yhi,zhi); o = o + 84 453 kd_tri(b, o, xhi,ylo,zlo, xhi,yhi,zhi, xhi,ylo,zhi); o = o + 84 454 kd_tri(b, o, xlo,ylo,zlo, xhi,ylo,zlo, xhi,ylo,zhi); o = o + 84 455 kd_tri(b, o, xlo,ylo,zlo, xhi,ylo,zhi, xlo,ylo,zhi); o = o + 84 456 kd_tri(b, o, xlo,yhi,zlo, xhi,yhi,zlo, xhi,yhi,zhi); o = o + 84 457 kd_tri(b, o, xlo,yhi,zhi, xhi,yhi,zlo, xlo,yhi,zhi); o = o + 84 458 return 12 459} 460func kd_hdr(b: *u8, ntri: i64) -> i64 { 461 b[0]=78 as u8; b[1]=88 as u8; b[2]=77 as u8; b[3]=83 as u8 462 b[4]=72 as u8; b[5]=50 as u8; b[6]=0 as u8; b[7]=0 as u8 463 kd_w32(b, 8, 1); kd_w32(b, 12, ntri) 464 var q: i64 = 0 465 while q < 16 { b[16+q] = 0 as u8; q = q + 1 } 466 b[16]=115 as u8; b[17]=107 as u8; b[18]=105 as u8; b[19]=110 as u8 467 kd_w32(b, 32, 0); kd_w32(b, 36, ntri) 468 return 40 469} 470func kd_save(path: *u8, b: *u8, ntri: i64) -> i64 { 471 var z: i64 = 0 472 while z < ntri { kd_w32(b, 40 + ntri*84 + z*4, 0); z = z + 1 } 473 let fd: i64 = sys_openat_wr(path, 420) 474 if fd < 0 { return 0 - 1 } 475 sys_write(fd, b, 40 + ntri*84 + ntri*4) 476 sys_close(fd) 477 return 0 478} 479func kd_fix_blob(path: *u8) -> i64 { 480 let b: *u8 = sys_mmap(KD_MAGIC_65536) 481 kd_hdr(b, 12) 482 kd_box(b, 40, 0-150, 150, 0, KD_MAGIC_1600, 0-100, 100) 483 return kd_save(path, b, 12) 484} 485func kd_fix_human(path: *u8) -> i64 { 486 let b: *u8 = sys_mmap(KD_MAGIC_262144) 487 var o: i64 = 40 488 var n: i64 = 0 489 n = n + kd_box(b, o, 0-150, 150, 700, KD_MAGIC_1350, 0-100, 100); o = o + 12*84 490 n = n + kd_box(b, o, 0-450, 0-250, 1000, KD_MAGIC_1300, 0-60, 60); o = o + 12*84 491 n = n + kd_box(b, o, 250, 450, 1000, KD_MAGIC_1300, 0-60, 60); o = o + 12*84 492 n = n + kd_box(b, o, 0-140, 0-40, 60, 700, 0-80, 80); o = o + 12*84 493 n = n + kd_box(b, o, 40, 140, 60, 700, 0-80, 80); o = o + 12*84 494 n = n + kd_box(b, o, 0-60, 60, KD_MAGIC_1350, KD_MAGIC_1430, 0-60, 60); o = o + 12*84 495 n = n + kd_box(b, o, 0-110, 110, KD_MAGIC_1430, KD_MAGIC_1600, 0-110, 110); o = o + 12*84 496 kd_hdr(b, n) 497 return kd_save(path, b, n) 498} 499// a QUADRUPED: long horizontal body (x = long axis) on 4 legs -- proves the schema frame is data 500func kd_fix_quad(path: *u8) -> i64 { 501 let b: *u8 = sys_mmap(KD_MAGIC_262144) 502 var o: i64 = 40 503 var n: i64 = 0 504 n = n + kd_box(b, o, 0-600, 600, 700, 1000, 0-200, 200); o = o + 12*84 // barrel 505 n = n + kd_box(b, o, 0-560, 0-440, 0, 700, 0-180, 0-60); o = o + 12*84 // legs (4, split in z too) 506 n = n + kd_box(b, o, 0-560, 0-440, 0, 700, 60, 180); o = o + 12*84 507 n = n + kd_box(b, o, 440, 560, 0, 700, 0-180, 0-60); o = o + 12*84 508 n = n + kd_box(b, o, 440, 560, 0, 700, 60, 180); o = o + 12*84 509 n = n + kd_box(b, o, 600, 900, 900, KD_MAGIC_1100, 0-120, 120); o = o + 12*84 // head+neck forward 510 kd_hdr(b, n) 511 return kd_save(path, b, n) 512} 513func kd_wr(path: *u8, s: *u8) -> i64 { 514 var n: i64 = 0 515 while s[n] != (0 as u8) { n = n + 1 } 516 let fd: i64 = sys_openat_wr(path, 420) 517 if fd < 0 { return 0 - 1 } 518 sys_write(fd, s, n) 519 sys_close(fd) 520 return 0 521} 522func kd_selftest() -> i64 { 523 var fails: i64 = 0 524 kd_fix_blob("/tmp/kd_blob.nxmesh" as *u8) 525 kd_fix_human("/tmp/kd_human.nxmesh" as *u8) 526 kd_fix_quad("/tmp/kd_quad.nxmesh" as *u8) 527 kd_wr("/tmp/kd_schema.txt" as *u8, "humanoid\tstack\t1\t0\nhumanoid\tband\t550\t800\t3\t9\tarms-clear-of-torso\nhumanoid\tband\t80\t420\t2\t4\tlegs-separated\nhumanoid\tnarrow\t800\t920\t600\tneck-minimum\nquadruped\tstack\t0\t2\nquadruped\tband\t0\t1000\t2\t6\tlegs-along-length\t0\t450\nquadruped\tband\t100\t900\t1\t2\tbarrel-body\t500\t1000\n" as *u8) 528 let sb: *u8 = sys_mmap(KD_SCAP) 529 let sn: i64 = kd_readfile("/tmp/kd_schema.txt" as *u8, sb, KD_SCAP) 530 hw("T0 blob must match NO kind:\n" as *u8) 531 if kd_run("/tmp/kd_blob.nxmesh" as *u8, sb, sn, 64) == 0 { fails = fails + 1; hw("T0 FAIL blob matched a kind\n" as *u8) } else { hw("T0 PASS blob unmatched\n" as *u8) } 532 hw("T1 humanoid fixture must match humanoid:\n" as *u8) 533 if kd_run("/tmp/kd_human.nxmesh" as *u8, sb, sn, 64) != 0 { fails = fails + 1; hw("T1 FAIL humanoid unmatched\n" as *u8) } else { hw("T1 PASS\n" as *u8) } 534 hw("T2 quadruped fixture must match quadruped (proves the FRAME is data, not code):\n" as *u8) 535 if kd_run("/tmp/kd_quad.nxmesh" as *u8, sb, sn, 64) != 0 { fails = fails + 1; hw("T2 FAIL quadruped unmatched\n" as *u8) } else { hw("T2 PASS\n" as *u8) } 536 hw("T3 empty schema must REFUSE (never guess an ontology):\n" as *u8) 537 if kd_run("/tmp/kd_human.nxmesh" as *u8, sb, 0, 64) == 0 { fails = fails + 1; hw("T3 FAIL empty schema accepted\n" as *u8) } else { hw("T3 PASS refused\n" as *u8) } 538 if fails == 0 { hw("KIND-SELFTEST GREEN 4/4\n" as *u8); return 0 } 539 hw("KIND-SELFTEST RED fails=" as *u8); pn(fails); hw("\n" as *u8) 540 return 1 541} 542 543func main(argc: i64, argv: *i64) -> i64 { 544 if argc >= 2 { 545 let a1: *u8 = argv[1] as *u8 546 var m: i64 = 0 547 while a1[m] != (0 as u8) { m = m + 1 } 548 if m == 8 { 549 var ok: i64 = 1 550 let lit: *u8 = "selftest" as *u8 551 var i: i64 = 0 552 while i < 8 { if a1[i] != lit[i] { ok = 0; i = 8 } else { i = i + 1 } } 553 if ok == 1 { let rc: i64 = kd_selftest(); sys_exit(rc); return rc } 554 } 555 if m == 6 { 556 var ok2: i64 = 1 557 let lit2: *u8 = "schema" as *u8 558 var j: i64 = 0 559 while j < 6 { if a1[j] != lit2[j] { ok2 = 0; j = 6 } else { j = j + 1 } } 560 if ok2 == 1 { 561 if argc < 4 { hw("usage: nx_kind schema <file> <mesh.nxmesh> [bands]\n" as *u8); sys_exit(2); return 2 } 562 let sb2: *u8 = sys_mmap(KD_SCAP) 563 let sn2: i64 = kd_readfile(argv[2] as *u8, sb2, KD_SCAP) 564 var nb2: i64 = 64 565 let rc2: i64 = kd_run(argv[3] as *u8, sb2, sn2, nb2) 566 sys_exit(rc2) 567 return rc2 568 } 569 } 570 } 571 if argc < 2 { hw("usage: nx_kind <mesh.nxmesh> [bands] | schema <file> <mesh> | selftest\n" as *u8); sys_exit(2); return 2 } 572 let sb3: *u8 = sys_mmap(KD_SCAP) 573 let sn3: i64 = sts_load("knowledge/store/kind-" as *u8, sb3, KD_SCAP - 16) 574 var nb3: i64 = 64 575 if argc >= 3 { 576 let a2: *u8 = argv[2] as *u8 577 nb3 = 0 578 var q: i64 = 0 579 while a2[q] != (0 as u8) { nb3 = nb3*10 + ((a2[q] as i64) - 48); q = q + 1 } 580 if nb3 < 16 { nb3 = 16 } 581 if nb3 > KD_MAXBAND { nb3 = KD_MAXBAND } 582 } 583 let rc3: i64 = kd_run(argv[1] as *u8, sb3, sn3, nb3) 584 sys_exit(rc3) 585 return rc3 586}