code wiki / (root) / nx_haircollide_gate.nx

nx_haircollide_gate.nx source

↩ module page · 139 lines · 8781 B

1// nx_haircollide_gate.nx -- THE TOOTH THE COLLIDER OWED. Subject: vm_capsule_push (nx_vecmath) and 2// hd_tick_collide (nx_hairdyn_lib), landed 2026-09-04 against the operator's REJECT row 3// beach-hair-colour-wind-0830: "hair clips the body and moves like a mop, not strand by strand". 4// 5// WHY IT EXISTS AS ITS OWN GATE. nx_hairdyn_gate's teeth measure hd_tick, which this change DELIBERATELY 6// left unchanged, so a GREEN from it would say nothing whatever about the collider -- the classic shape of 7// a gate that is counted as coverage while being structurally blind to the thing shipped beside it. 8// 9// * A COMPILING CAPABILITY IS NOT A PROVEN ONE. The lib built clean hours before this file existed, and a 10// clean build is exactly what an absent collider also produces, because absent code has no failure mode. 11// 12// THE ANTI-VACUITY TOOTH IS THE ncap=0 CONTROL: with no capsules the SAME seeded point must remain INSIDE 13// the region a capsule would have covered. Without it, a collider that silently did nothing would pass 14// every "is the point outside?" assertion whenever the seed happened to start outside, and a collider that 15// pushed EVERYTHING would pass them all too -- which is why a positive control (a point outside is left 16// ALONE) sits beside the deny tooth. A suite that only asks "was it pushed?" is blind in both directions. 17// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 18import "nx_syscalls.nx" 19import "nx_gate_verdict.nx" 20import "nx_vecmath.nx" 21import "nx_hairdyn_lib.nx" 22 23// One capsule, chosen so every number below is checkable by hand: axis up the y column from the origin, 24// radius 100. A reader can verify each expectation with arithmetic rather than by trusting the organ. 25const HG_AX: i64 = 0 26const HG_AY: i64 = 0 27const HG_AZ: i64 = 0 28const HG_BX: i64 = 0 29const HG_BY: i64 = 1000 30const HG_BZ: i64 = 0 31const HG_R: i64 = 100 32const HG_MID: i64 = 500 // a y strictly between the endpoints, so the closest point is ON the segment 33const HG_TOL: i64 = 2 // Q256 truncation band: three integer divides, each losing at most 1 unit 34 35func hg_dist_to_axis(px: i64, py: i64, pz: i64) -> i64 { 36 // the capsule axis is the y column, so the distance to it is the xz radius -- no projection needed, 37 // which is the point of choosing this axis: the ORACLE here is arithmetic the collider never runs. 38 return vm_isqrt(px*px + pz*pz) 39} 40 41func main() -> i64 { 42 let ctr: *i64 = gv_ctr() 43 gv_head("nx_haircollide_gate -- vm_capsule_push + hd_tick_collide" as *u8) 44 let o: *i64 = sys_mmap(24) as *i64 45 46 // ---- THE DENY DIRECTION: a point INSIDE is pushed to the surface --------------------------------- 47 let inside_r: i64 = vm_capsule_push(10, HG_MID, 0, HG_AX, HG_AY, HG_AZ, HG_BX, HG_BY, HG_BZ, HG_R, o) 48 gv_check_eq("a-point-INSIDE-reports-a-contact" as *u8, inside_r, 1, ctr) 49 let d_out: i64 = hg_dist_to_axis(o[0], o[1], o[2]) 50 gv_check_near("the-pushed-point-lands-ON-the-surface-not-merely-somewhere-else" as *u8, d_out, HG_R, HG_TOL, ctr) 51 gv_check_eq("the-push-is-PURELY-RADIAL-so-the-axial-coordinate-is-untouched" as *u8, o[1], HG_MID, ctr) 52 53 // ---- THE POSITIVE CONTROL: a point OUTSIDE must be LEFT ALONE ------------------------------------ 54 // Without this, a collider that pushed every point it was handed would pass every tooth above. 55 o[0] = 0-1; o[1] = 0-1; o[2] = 0-1 56 let outside_r: i64 = vm_capsule_push(500, HG_MID, 0, HG_AX, HG_AY, HG_AZ, HG_BX, HG_BY, HG_BZ, HG_R, o) 57 gv_check_eq("pos-control-a-point-OUTSIDE-reports-NO-contact" as *u8, outside_r, 0, ctr) 58 gv_check_eq("pos-control-a-point-OUTSIDE-leaves-the-out-buffer-UNWRITTEN" as *u8, o[0], 0-1, ctr) 59 60 // ---- THE DEGENERATE CASE IS DEFINED, NOT UNDEFINED ------------------------------------------------ 61 // A point exactly ON the axis has no direction to be pushed along. The lib documents that it takes +x. 62 // If this were left undefined the point would stay inside FOREVER -- the silent class the collider exists 63 // to remove -- so the behaviour is pinned here rather than left to whatever the arithmetic happens to do. 64 let axis_r: i64 = vm_capsule_push(0, HG_MID, 0, HG_AX, HG_AY, HG_AZ, HG_BX, HG_BY, HG_BZ, HG_R, o) 65 gv_check_eq("a-point-ON-the-axis-still-reports-a-contact" as *u8, axis_r, 1, ctr) 66 gv_check_eq("the-on-axis-degenerate-push-takes-the-DOCUMENTED-plus-x-direction" as *u8, o[0], HG_R, ctr) 67 68 // ---- BEYOND THE ENDPOINT: the closest point CLAMPS to the cap, it does not run off the axis -------- 69 // A segment-distance that forgot to clamp t would treat the infinite LINE as the subject and report this 70 // point as inside; that is the commonest way this arithmetic is written wrong. 71 let past_r: i64 = vm_capsule_push(0, HG_BY + 500, 0, HG_AX, HG_AY, HG_AZ, HG_BX, HG_BY, HG_BZ, HG_R, o) 72 gv_check_eq("neg-control-a-point-500-BEYOND-the-endpoint-is-OUTSIDE-the-capsule-not-inside-the-line" as *u8, 73 past_r, 0, ctr) 74 75 // ---- END TO END THROUGH THE CHAIN, AND ITS ANTI-VACUITY CONTROL ----------------------------------- 76 // hd_tick_collide is the shipping entry point; the teeth above prove the geometry, this proves the WIRING. 77 let caps: *i64 = sys_mmap(7*8) as *i64 78 caps[0] = HG_AX; caps[1] = HG_AY; caps[2] = HG_AZ 79 caps[3] = HG_BX; caps[4] = HG_BY; caps[5] = HG_BZ 80 caps[6] = HG_R 81 // Scratch for the collider, allocated ONCE here because the lib takes it as a parameter now -- see the 82 // hot-loop note in nx_hairdyn_lib. A gate that allocated per call would hide the exact property the 83 // parameter exists to guarantee, which is that the solver allocates nothing on the wasm tick path. 84 let hsc: *i64 = sys_mmap(24) as *i64 85 86 let n: i64 = 4 87 let seglen: i64 = 120 88 let st1: *i64 = hd_alloc(n) 89 hd_seat(st1, n, 0, HG_BY, 0, seglen) 90 let resolved: i64 = hd_tick_collide(st1, n, 0, HG_BY, 0, seglen, SB_K_HAIR, SB_C_HAIR, SB_MAXD_HAIR, caps, 1, hsc) 91 92 // THE ANTI-VACUITY CONTROL: the SAME seed and the SAME tick with ncap=0. If the collider were a no-op 93 // the two runs would agree, so this tooth is the one that can tell a working push from an absent one. 94 let st0: *i64 = hd_alloc(n) 95 hd_seat(st0, n, 0, HG_BY, 0, seglen) 96 let resolved0: i64 = hd_tick_collide(st0, n, 0, HG_BY, 0, seglen, SB_K_HAIR, SB_C_HAIR, SB_MAXD_HAIR, caps, 0, hsc) 97 gv_check_eq("neg-control-with-ncap-0-NOTHING-is-resolved" as *u8, resolved0, 0, ctr) 98 99 // count how many segments each run leaves inside the capsule's radius 100 var in1: i64 = 0 101 var in0: i64 = 0 102 var i: i64 = 0 103 while i < n { 104 let b: i64 = i*SD_STRIDE 105 if hg_dist_to_axis(st1[b], st1[b+1], st1[b+2]) < HG_R - HG_TOL { in1 = in1 + 1 } 106 if hg_dist_to_axis(st0[b], st0[b+1], st0[b+2]) < HG_R - HG_TOL { in0 = in0 + 1 } 107 i = i + 1 108 } 109 gv_check_eq("WITH-the-collider-NO-segment-is-left-inside-the-body-capsule" as *u8, in1, 0, ctr) 110 gv_check("neg-control-WITHOUT-the-collider-at-least-one-segment-IS-left-inside" as *u8, (in0 > 0) as i64, ctr) 111 gv_check("the-fixture-REACHED-the-condition-the-collider-had-something-to-resolve" as *u8, 112 (resolved > 0) as i64, ctr) 113 114 gv_values_head() 115 gv_kv("capsule_radius" as *u8, HG_R) 116 gv_kv("surface_tolerance_q256_band" as *u8, HG_TOL) 117 gv_kv("pushed_point_distance_to_axis" as *u8, d_out) 118 gv_kv("segments" as *u8, n) 119 gv_kv("contacts_RESOLVED_not_defects" as *u8, resolved) 120 gv_kv("segments_left_inside_WITH_collider" as *u8, in1) 121 gv_kv("segments_left_inside_WITHOUT_collider" as *u8, in0) 122 // WHY THE END-TO-END TOOTH FAILS MUST BE READABLE FROM THE GATE'S OWN OUTPUT, or the next reader 123 // re-derives it by hand exactly as I was about to. A verdict is not a diagnosis: 4-of-4-still-inside 124 // is consistent with the push never writing, with it writing the wrong slot, and with the fixture's 125 // segments never being where I assumed -- three causes with three different remedies. 126 gv_kv("seg0_x_after" as *u8, st1[0]) 127 gv_kv("seg0_y_after" as *u8, st1[1]) 128 gv_kv("seg0_z_after" as *u8, st1[2]) 129 gv_kv("seg0_dist_to_axis_after" as *u8, hg_dist_to_axis(st1[0], st1[1], st1[2])) 130 gv_kv("seg0_x_nocollider" as *u8, st0[0]) 131 gv_kv("seg0_y_nocollider" as *u8, st0[1]) 132 gv_kv("seg0_dist_to_axis_nocollider" as *u8, hg_dist_to_axis(st0[0], st0[1], st0[2])) 133 gv_kv("SD_STRIDE" as *u8, SD_STRIDE) 134 gv_kv("capsule_axis_y_span_lo" as *u8, HG_AY) 135 gv_kv("capsule_axis_y_span_hi" as *u8, HG_BY) 136 137 return gv_verdict("nx_haircollide_gate" as *u8, ctr, 138 "the collider pushes an entered point to the surface, leaves an outside point untouched, clamps at the endpoint, and the ncap=0 control proves the tooth can fail" as *u8) 139}