code wiki / (root) / nx_dynaoracle_gate.nx

nx_dynaoracle_gate.nx source

↩ module page · 577 lines · 34713 B

1// nx_dynaoracle_gate.nx -- GATE for the shared ringdown estimator and the video oracle's derived 2// constants. 3// 4// WHY THE FIXTURE IS AN ANALYTIC OSCILLATOR AND NOT A VIDEO CLIP. A gate whose fixture is a real 5// clip can only assert that today's answer equals yesterday's answer -- it has no ground truth, so 6// it detects drift and CANNOT detect being wrong. Here the fixture is a mass-spring-damper the gate 7// integrates itself, so the TRUE natural frequency and damping ratio are known in closed form from 8// k and c: w0 = sqrt(k/m), zeta = c/(2*sqrt(k*m)), wd = w0*sqrt(1-zeta^2). The teeth then ask 9// whether rd_analyze RECOVERS numbers it was never told. That is an oracle, not a snapshot. 10// 11// EVERY TOLERANCE HERE IS DERIVED, NOT PICKED: 12// * FREQUENCY: rd_analyze times a period by counting whole SAMPLES between zero crossings, so a 13// plus-or-minus-one-sample error bounds the relative frequency error at 1/P where P is the 14// period in samples. The tooth computes that bound from the fixture's own period. 15// * DAMPING: rd_zeta_permil goes through rd_log2_q16, whose own header declares a worst error of 16// about 0.086 in log2 inside an octave. That propagates as ln-error 0.086*ln2 = 0.0596, and for 17// a lightly damped decay zeta is about delta/(2*pi), giving a bound near 9.5 permil. The tooth 18// computes that from the declared constant instead of hard-coding the answer. 19// A tolerance chosen after seeing the result is the defect this estate refuses; a tolerance derived 20// from a declared imprecision is a contract. 21// 22// license_tier: ORIGINAL 23import "nx_syscalls.nx" 24import "nx_gate_verdict.nx" 25import "nx_ringdown_lib.nx" 26import "nx_motion.nx" 27 28const DG_Q16: i64 = 65536 29const DG_PERMIL: i64 = 1000 30const DG_NSAMP: i64 = 512 31const DG_DT_US: i64 = 1000 32// THE DECLARED IMPRECISIONS NOW HAVE ONE OWNER AND IT IS THE LIBRARY. These used to be hand-copied 33// numbers with a comment asking the next reader to remember to re-derive them, and a tolerance that 34// depends on somebody remembering is the stale-bound defect with extra steps. They are now 35// DEFINITIONS of the library's own constants, so improving rd_log2_q16 moves this gate BY 36// CONSTRUCTION instead of leaving it quietly loose. 37const DG_LOG2_ERR_PERMIL: i64 = RD_LOG2_ERR_PERMIL 38const DG_LN2_PERMIL: i64 = RD_LN2_PERMIL 39const DG_TWOPI_PERMIL: i64 = RD_TWOPI_PERMIL 40 41// ---- THE DECLARED GRID ----------------------------------------------------------------------- 42// A remedy validated only on the case that motivated it is the vacuous-test defect, so the span 43// estimator is measured over a SURFACE: six injected damping ratios crossed with three stiffnesses, 44// every point integrated by this gate from k and c so the truth stays closed-form. The damping 45// values span AND EXCEED the tissue band knowledge/gamefeel_oracle.conf carries 46// (tissue_zeta_permil 350..600), because an estimator only shown correct inside the band it was 47// built for has not been shown correct at all. 48const DG_GRID_NSAMP: i64 = 16384 49// The step divisor is large so w0*dt stays small. The fixture is a semi-implicit Euler integration 50// and carries its OWN leading damping error of order c*dt/2 relative; holding w0*dt at or below 51// 0.016 keeps that below the estimator's published tolerance instead of hiding inside it -- and the 52// teeth add it explicitly rather than assuming it away. 53const DG_GRID_DT_DIV: i64 = 1000 54const DG_GRID_K0: i64 = 16 55const DG_GRID_K_STEP: i64 = 4 56const DG_GRID_NK: i64 = 3 57const DG_GRID_NZ: i64 = 6 58// THE FIXTURE'S OWN AMPLITUDE HEADROOM, AND WHY IT IS THIS LARGE. dg_sim carries x and v as Q16 59// INTEGERS, so every step truncates by up to one quantum and that truncation ACCUMULATES over the 60// thousands of steps a long span covers. MEASURED at the first attempt with x0 = 1000: three of the 61// eighteen video-sampling points missed their published tolerance, and the offender lines named the 62// cause -- the last analysed peak had decayed to 114 QUANTA, where the fixture's own arithmetic is 63// worth tens of permil of log-ratio and the estimator's is worth eight. The span estimator is the 64// most exposed to that BY DESIGN, because it deliberately reads the smallest peak it can still 65// admit. The remedy is to fix the FIXTURE rather than widen the estimator's bound: a thousand times 66// more headroom puts the fixture's quantum a thousand times below the peaks being read. A tooth 67// below asserts the resulting floor, so this can never silently regress into a tolerance excuse. 68const DG_GRID_X0: i64 = 1000000 69// The smallest peak any grid point may be judged on, in fixture quanta. One quantum on a peak of P 70// is 1/P relative, so a floor of DG_PERMIL quanta holds the fixture's amplitude contribution at or 71// below one permil of log-ratio -- an order of magnitude inside every tolerance published here. 72const DG_GRID_MIN_PEAK_QUANTA: i64 = 1000 73// AND THAT FLOOR IS THE DEADBAND, WHICH IS THE MECHANISM THE ANALYSER ALREADY HAS FOR IT. Raising 74// the fixture's headroom a thousandfold moved the worst video-sampling error from 7 permil to 3 but 75// did NOT stop the span estimator reading down to 239 quanta, and it never will: the estimator 76// extends until the record stops being periodic, so it will always walk into whatever noise floor 77// exists. rd_analyze's `quant` argument exists precisely to declare that floor, and its own header 78// says the caller must say where the number came from -- here it is the fixture's accumulated 79// integer-truncation noise, bounded by the same DG_PERMIL-quanta reasoning above. Passing 0, as the 80// primary fixture legitimately does for a short window, told the analyser to trust values one 81// quantum above zero. 82const DG_GRID_QUANT: i64 = DG_GRID_MIN_PEAK_QUANTA 83// A deadband can fail in the OTHER direction by eating the evidence, so the grid asserts that every 84// point still spans a full period of baseline after the floor is applied. 85const DG_GRID_MIN_HALVES: i64 = 2 86 87// ---- PROBES FOR THE RESPONSIVENESS OF THE PUBLISHED BOUND ------------------------------------- 88// Recomputing the published tolerance through the same function proves the SLOT carries that 89// function's answer; it cannot notice the FUNCTION being replaced by a constant. MEASURED by 90// mutation: a mutant returning a fixed 3 permil SURVIVED every tooth in this gate, because on this 91// grid the honest bound happens to land near 3 -- defence and vacuity looked identical from one 92// surviving mutant. What a constant cannot fake is RESPONSIVENESS: the bound carries a 2/halves 93// factor and a 1/peak factor, so halving the baseline must widen it and shrinking the final peak 94// must widen it. These probe values are chosen only to be far apart on each axis. 95const DG_TOL_PROBE_A: i64 = 1000000 96const DG_TOL_PROBE_B: i64 = 1000 97const DG_TOL_PROBE_B_SMALL: i64 = 10 98const DG_TOL_PROBE_HALVES_LONG: i64 = 16 99const DG_TOL_PROBE_HALVES_SHORT: i64 = 2 100// The six injected damping ratios in permil, each named for what it IS and never for its value. 101const DG_GRID_Z_LINEAR_LIMIT: i64 = 50 102const DG_GRID_Z_LIGHT: i64 = 100 103const DG_GRID_Z_VIDEO_FIXTURE: i64 = 200 104const DG_GRID_Z_TISSUE_BAND_LOW: i64 = 350 105const DG_GRID_Z_TISSUE_BAND_MID: i64 = 450 106const DG_GRID_Z_TISSUE_BAND_HIGH: i64 = 600 107// Leading semi-implicit Euler errors: damping c*dt/2 RELATIVE, period (w0*dt)^2/24 RELATIVE. Named 108// so a tooth can add the FIXTURE's imprecision to the ESTIMATOR's rather than charge it to the 109// estimator, which would read as the estimator being worse than it is. 110// THE SAMPLING RATIO IS A GRID DIMENSION, NOT A DETAIL. The fine pass above oversamples a period 111// by two orders of magnitude, and at that ratio BOTH estimators are limited only by rd_log2_q16 -- 112// so a grid built only from it cannot discriminate them and would understate the difference it was 113// built to measure. nx_dynaoracle works at fifteen samples per period: a 1960 mHz damped motion at 114// 30 fps is 15.3. The second pass DECIMATES the accurately integrated series to that ratio, which 115// changes the SAMPLING without touching the waveform, so the fixture's own integration error stays 116// negligible and the teeth measure the estimators rather than the integrator. 117const DG_GRID_TARGET_SPP: i64 = 15 118const DG_EULER_ZETA_DEN: i64 = 2 119const DG_EULER_PER_DEN: i64 = 24 120 121// ---- THE LOBE FIXTURE: a decay whose ONLY variable is the spacing of its crossings ------------ 122// Amplitude halves at every crossing in both variants, so the two-lobe decrement is equally happy 123// with either. Only the SPACING differs, which is what makes the aperiodic variant an anti-vacuity 124// control rather than merely another failing input. 125const DG_LOBE_N: i64 = 128 126const DG_LOBE_AMP0: i64 = 1024 127const DG_LOBE_DECAY_DIV: i64 = 2 128const DG_LOBE_HEAD: i64 = 8 // the truncated opening lobe, before the first crossing 129const DG_LOBE_LEN: i64 = 12 // the periodic half period 130const DG_LOBE_ODD: i64 = 20 // the intruder: eight samples off, far beyond a one-sample window 131 132func dg_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v } 133 134// Integrate a unit-mass damped oscillator in Q16 and write the displacement series. 135// x'' = -(k/m)x - (c/m)x' with m = 1, k and c supplied in Q16. 136func dg_sim(sig: *i64, n: i64, k_q16: i64, c_q16: i64, x0_q16: i64, dt_q16: i64) -> i64 { 137 var x: i64 = x0_q16 138 var v: i64 = 0 139 var i: i64 = 0 140 while i < n { 141 sig[i] = x 142 let a: i64 = (0 - k_q16) * x / DG_Q16 - c_q16 * v / DG_Q16 143 v = v + a * dt_q16 / DG_Q16 144 x = x + v * dt_q16 / DG_Q16 145 i = i + 1 146 } 147 return 0 148} 149 150// Build a DECAYING alternating-sign wave whose lobe LENGTHS are supplied. Amplitude halves at every 151// crossing, so the logarithmic decrement reads it happily; only the spacing differs between the two 152// fixtures this builds, which is exactly the discrimination under test. 153func dg_sim_lobes(sig: *i64, n: i64, l0: i64, l1: i64, l2: i64, l3: i64) -> i64 { 154 var amp: i64 = DG_LOBE_AMP0 155 var sign: i64 = 1 156 var remain: i64 = l0 157 var lob: i64 = 0 158 var i: i64 = 0 159 while i < n { 160 sig[i] = sign * amp 161 remain = remain - 1 162 if remain <= 0 { 163 sign = 0 - sign 164 amp = amp / DG_LOBE_DECAY_DIV 165 if amp < 1 { amp = 1 } 166 lob = lob + 1 167 if lob == 1 { remain = l1 } 168 else { if lob == 2 { remain = l2 } else { remain = l3 } } 169 } 170 i = i + 1 171 } 172 return 0 173} 174 175// A RIGID fixture: the anti-vacuity control. It cannot oscillate, so any organ that reports a 176// frequency for it is reporting one it invented. 177func dg_sim_rigid(sig: *i64, n: i64) -> i64 { 178 var i: i64 = 0 179 while i < n { sig[i] = 0; i = i + 1 } 180 return 0 181} 182 183func main(argc: i64, argv: *i64) -> i64 { 184 gv_head("NX-DYNAORACLE-GATE -- shared ringdown estimator + derived-constant binding" as *u8) 185 let ctr: *i64 = gv_ctr() 186 187 let sig: *i64 = (sys_mmap(DG_NSAMP * 8 + 16)) as *i64 188 let out: *i64 = (sys_mmap(RD_R_N * 8 + 16)) as *i64 189 190 // ---- FIXTURE 1: a known underdamped oscillator ---------------------------------------- 191 // k and c are chosen so the response is clearly underdamped and completes several periods 192 // inside the window; the TRUTH is then computed from them, never asserted. 193 let k_q16: i64 = 40 * DG_Q16 194 let c_q16: i64 = DG_Q16 195 let dt_q16: i64 = DG_Q16 / 100 196 dg_sim(sig, DG_NSAMP, k_q16, c_q16, 1000 * DG_Q16, dt_q16) 197 198 // ASSERT THE FIXTURE REACHED THE CONDITION BEFORE ASSERTING THE OUTCOME. A fixture that never 199 // actually oscillated would make every tooth below pass for the wrong reason. 200 var swings: i64 = 0 201 var prev: i64 = 0 202 var i: i64 = 0 203 while i < DG_NSAMP { 204 var s: i64 = 0 205 if sig[i] > 0 { s = 1 } 206 if sig[i] < 0 { s = 0 - 1 } 207 if s != 0 { if prev != 0 { if s != prev { swings = swings + 1 } } prev = s } 208 i = i + 1 209 } 210 gv_check("fixture-actually-oscillates" as *u8, swings >= 4, ctr) 211 var fixmax: i64 = 0 212 var m2: i64 = 0 213 while m2 < DG_NSAMP { if dg_abs(sig[m2]) > fixmax { fixmax = dg_abs(sig[m2]) } m2 = m2 + 1 } 214 gv_check("fixture-has-measurable-amplitude" as *u8, fixmax > 0, ctr) 215 216 // Deadband here is ZERO on purpose: this is an exact integer series with no measurement noise, 217 // so any non-zero deadband would be a number chosen to make the test pass. 218 let rc: i64 = rd_analyze(sig, DG_NSAMP, DG_DT_US, 0, out) 219 gv_check("analyze-returns-OK-on-a-clean-underdamped-signal" as *u8, rc == RD_OK, ctr) 220 gv_check("analyze-reports-a-period" as *u8, out[RD_R_PER_US] > 0, ctr) 221 gv_check("analyze-reports-a-frequency" as *u8, out[RD_R_FN_MHZ] > 0, ctr) 222 gv_check("analyze-reports-decay-A1-greater-than-A2" as *u8, out[RD_R_A1] > out[RD_R_A2], ctr) 223 224 // ---- TRUTH, computed from k and c ------------------------------------------------------ 225 // w0 = sqrt(k) with m = 1 (k in Q16 -> w0 in Q16 via the integer sqrt of k<<16). 226 let w0_q16: i64 = rd_isqrt(k_q16 * DG_Q16) 227 // zeta = c / (2*sqrt(k*m)) = c / (2*w0) 228 let zeta_true_permil: i64 = c_q16 * DG_PERMIL / (2 * w0_q16) 229 gv_check("truth-is-underdamped" as *u8, zeta_true_permil < DG_PERMIL, ctr) 230 231 // The DERIVED frequency tolerance: one sample of period-timing error. 232 let per_samples: i64 = out[RD_R_PER_US] / DG_DT_US 233 gv_check("period-spans-several-samples" as *u8, per_samples >= 4, ctr) 234 let fn_tol_permil: i64 = DG_PERMIL / per_samples + 1 235 236 // wd = w0 * sqrt(1 - zeta^2); fn_mhz = 1000 * wd / (2*pi) expressed against the sim's own clock. 237 // The simulation advances dt_q16/Q16 seconds of MODEL time per sample while rd_analyze was told 238 // DG_DT_US microseconds per sample, so the comparison is made in SAMPLES, which is the unit both 239 // sides actually share and therefore the only one that cannot hide a scale error. 240 let zsq_q16: i64 = zeta_true_permil * zeta_true_permil * DG_Q16 / (DG_PERMIL * DG_PERMIL) 241 let wd_q16: i64 = w0_q16 * rd_isqrt((DG_Q16 - zsq_q16) * DG_Q16) / DG_Q16 242 // period in samples = 2*pi / (wd * dt) 243 // period_samples = 2*pi / (wd * dt). With wd and dt both in Q16, wd*dt carries Q16 TWICE, so the 244 // numerator needs Q16^2 and the denominator must NOT divide by Q16 again. The first cut did, and 245 // this gate caught its own author: it reported 6,534,567 samples against a measured 100 while the 246 // estimator was right to within 0.3 percent. Printing the values beside the verdict is what made 247 // that one read instead of an investigation. 248 let per_true_samples: i64 = DG_TWOPI_PERMIL * DG_Q16 * DG_Q16 / (DG_PERMIL * wd_q16 * dt_q16) 249 let per_err: i64 = dg_abs(per_samples - per_true_samples) * DG_PERMIL / per_true_samples 250 gv_check("recovered-period-matches-closed-form-within-derived-sampling-bound" as *u8, 251 per_err <= fn_tol_permil * 2, ctr) 252 253 // The DERIVED damping tolerance, from rd_log2_q16's OWN declared imprecision. 254 let zeta_tol_permil: i64 = DG_LOG2_ERR_PERMIL * DG_LN2_PERMIL * DG_PERMIL 255 / (DG_PERMIL * DG_TWOPI_PERMIL) + 1 256 let zeta_err: i64 = dg_abs(out[RD_R_ZETA] - zeta_true_permil) 257 gv_check("recovered-zeta-matches-closed-form-within-declared-log2-imprecision" as *u8, 258 zeta_err <= zeta_tol_permil, ctr) 259 260 // ---- neg-control: A RIGID SUBJECT MUST NOT PRODUCE A FREQUENCY ------------------------- 261 // This is the anti-vacuity tooth. An estimator that always emits a plausible number passes 262 // every test above and fails this one. 263 dg_sim_rigid(sig, DG_NSAMP) 264 let out2: *i64 = (sys_mmap(RD_R_N * 8 + 16)) as *i64 265 let rc2: i64 = rd_analyze(sig, DG_NSAMP, DG_DT_US, 0, out2) 266 gv_check("neg-control-rigid-signal-refuses-with-a-named-third-state" as *u8, 267 rc2 == RD_UNOBS_NO_CROSSING, ctr) 268 gv_check("neg-control-rigid-signal-emits-no-frequency" as *u8, out2[RD_R_FN_MHZ] == 0, ctr) 269 270 // ---- neg-control: A DIFFERENT SUBJECT MUST PRODUCE A DIFFERENT ANSWER ------------------ 271 // Without this, a constant-returning stub passes both the truth tooth and the rigid tooth by 272 // luck of calibration. Stiffen the spring: the frequency MUST rise. 273 let out3: *i64 = (sys_mmap(RD_R_N * 8 + 16)) as *i64 274 dg_sim(sig, DG_NSAMP, k_q16 * 4, c_q16, 1000 * DG_Q16, dt_q16) 275 let rc3: i64 = rd_analyze(sig, DG_NSAMP, DG_DT_US, 0, out3) 276 gv_check("neg-control-stiffer-spring-is-measured-as-a-higher-frequency" as *u8, 277 rc3 == RD_OK, ctr) 278 gv_check("neg-control-frequency-actually-moved" as *u8, 279 out3[RD_R_FN_MHZ] > out[RD_R_FN_MHZ], ctr) 280 281 // ---- THE THIRD STATE IS DISTINGUISHABLE, NOT A ZERO ------------------------------------ 282 let out4: *i64 = (sys_mmap(RD_R_N * 8 + 16)) as *i64 283 let rc4: i64 = rd_analyze(sig, 0, DG_DT_US, 0, out4) 284 gv_check("empty-input-is-named-not-silently-zero" as *u8, rc4 == RD_UNOBS_NO_SAMPLES, ctr) 285 let rc5: i64 = rd_analyze(sig, DG_NSAMP, 0, 0, out4) 286 gv_check("zero-sample-period-is-named" as *u8, rc5 == RD_UNOBS_NO_SAMPLES, ctr) 287 288 // ---- DERIVED-CONSTANT BINDING ---------------------------------------------------------- 289 // nx_dynaoracle derives its minimum ROI from nx_motion's OWN integration window. This tooth is 290 // what stops the two drifting apart: it recomputes the derivation here and asserts it. If the 291 // LK window ever changes, this fires instead of the oracle silently accepting an empty region. 292 gv_check("min-roi-derivation-still-equals-lk-window-area" as *u8, 293 NX_MOTION_WIN * NX_MOTION_WIN == 25, ctr) 294 gv_check("flow-quantum-is-the-declared-Q8-base" as *u8, NX_MOTION_Q == 256, ctr) 295 296 // ==== THE PERIODIC-SPAN ESTIMATOR ========================================================== 297 // out[] still holds the ORIGINAL underdamped fixture's analysis, so the span rows are checked 298 // against the SAME closed form the two-lobe rows were, and inside the tolerance the ESTIMATOR 299 // ITSELF published for this record rather than one this gate invented. 300 gv_check("fixture-reached-the-condition-span-was-established" as *u8, 301 out[RD_R_SPAN_RC] == RD_OK, ctr) 302 gv_check("span-reports-at-least-one-half-period-of-baseline" as *u8, 303 out[RD_R_SPAN_HALVES] >= 1, ctr) 304 305 // The FIXTURE's own imprecision, added explicitly so it is never charged to the estimator: 306 // semi-implicit Euler damps by c*dt/2 relative and shifts the period by (w0*dt)^2/24 relative. 307 let cdt_permil: i64 = c_q16 * dt_q16 * DG_PERMIL / (DG_Q16 * DG_Q16) 308 let fx_zeta_err: i64 = zeta_true_permil * cdt_permil / (DG_EULER_ZETA_DEN * DG_PERMIL) 309 let w0dt_permil: i64 = w0_q16 * dt_q16 * DG_PERMIL / (DG_Q16 * DG_Q16) 310 let fx_per_err: i64 = w0dt_permil * w0dt_permil / (DG_EULER_PER_DEN * DG_PERMIL) 311 312 let span_zeta_err: i64 = dg_abs(out[RD_R_SPAN_ZETA] - zeta_true_permil) 313 gv_check("span-zeta-matches-closed-form-inside-its-OWN-published-tolerance" as *u8, 314 span_zeta_err <= out[RD_R_SPAN_ZETA_TOL] + fx_zeta_err, ctr) 315 316 let span_per_samples: i64 = out[RD_R_SPAN_PER_US] / DG_DT_US 317 let span_per_err: i64 = dg_abs(span_per_samples - per_true_samples) * DG_PERMIL / per_true_samples 318 gv_check("span-period-matches-closed-form-inside-its-OWN-published-tolerance" as *u8, 319 span_per_err <= out[RD_R_SPAN_FN_TOL] + fx_per_err, ctr) 320 321 // THE PUBLISHED TOLERANCE IS DERIVED, NOT STORED. Recomputing it here from the amplitudes and 322 // the span the estimator also published binds the number to its formula: a build that started 323 // returning a convenient constant would fail this tooth and nothing else. 324 let re_tol: i64 = rd_span_zeta_tol_permil(out[RD_R_SPAN_A], out[RD_R_SPAN_B], 325 out[RD_R_SPAN_HALVES]) 326 gv_check("published-zeta-tolerance-slot-carries-the-functions-own-answer" as *u8, 327 re_tol == out[RD_R_SPAN_ZETA_TOL], ctr) 328 329 // AND THE FUNCTION ITSELF IS A DERIVATION, NOT A STORED NUMBER. A shorter baseline MUST widen 330 // the bound and a smaller final peak MUST widen it; a constant answers the same to all three. 331 let tol_long: i64 = rd_span_zeta_tol_permil(DG_TOL_PROBE_A, DG_TOL_PROBE_B, 332 DG_TOL_PROBE_HALVES_LONG) 333 let tol_short: i64 = rd_span_zeta_tol_permil(DG_TOL_PROBE_A, DG_TOL_PROBE_B, 334 DG_TOL_PROBE_HALVES_SHORT) 335 let tol_noisy: i64 = rd_span_zeta_tol_permil(DG_TOL_PROBE_A, DG_TOL_PROBE_B_SMALL, 336 DG_TOL_PROBE_HALVES_LONG) 337 gv_check("neg-control-tolerance-WIDENS-when-the-baseline-shortens" as *u8, 338 tol_short > tol_long, ctr) 339 gv_check("neg-control-tolerance-WIDENS-when-the-final-peak-shrinks" as *u8, 340 tol_noisy > tol_long, ctr) 341 342 // THE GENERALISATION CONTAINS THE INCUMBENT. At a span of one period the two are the same 343 // identity, so this must hold EXACTLY and not approximately: if it ever stops holding, the span 344 // form has stopped being a generalisation and has become a second ruler. 345 var contains: i64 = 1 346 if rd_zeta_permil_span(out[RD_R_A1], out[RD_R_A2], RD_HALVES_PER_PERIOD) != rd_zeta_permil(out[RD_R_A1], out[RD_R_A2]) { contains = 0 } 347 if rd_zeta_permil_span(1000, 500, RD_HALVES_PER_PERIOD) != rd_zeta_permil(1000, 500) { contains = 0 } 348 if rd_zeta_permil_span(7, 3, RD_HALVES_PER_PERIOD) != rd_zeta_permil(7, 3) { contains = 0 } 349 gv_check("span-at-one-period-reproduces-the-incumbent-EXACTLY" as *u8, contains == 1, ctr) 350 351 // ---- neg-control: A DECAY WITH APERIODIC CROSSINGS MUST BE REFUSED ----------------------- 352 // The anti-vacuity tooth. This signal decays cleanly, so the two-lobe decrement accepts it and 353 // publishes a number; only an estimator that actually checks whether its crossings are 354 // half-period markers can refuse. A stub that always returns OK passes every tooth above and 355 // fails this one. 356 let lsig: *i64 = (sys_mmap(DG_LOBE_N * 8 + 16)) as *i64 357 let lout: *i64 = (sys_mmap(RD_R_N * 8 + 16)) as *i64 358 dg_sim_lobes(lsig, DG_LOBE_N, DG_LOBE_HEAD, DG_LOBE_ODD, DG_LOBE_LEN, DG_LOBE_LEN) 359 let lrc: i64 = rd_analyze(lsig, DG_LOBE_N, DG_DT_US, 0, lout) 360 gv_check("fixture-reached-the-condition-incumbent-ACCEPTS-the-aperiodic-decay" as *u8, 361 lrc == RD_OK, ctr) 362 gv_check("neg-control-aperiodic-crossings-are-refused-by-the-span-admission" as *u8, 363 lout[RD_R_SPAN_RC] == RD_UNOBS_NO_PERIODIC_SPAN, ctr) 364 gv_check("neg-control-a-refused-span-publishes-no-zeta" as *u8, 365 lout[RD_R_SPAN_ZETA] == 0, ctr) 366 367 // ---- POSITIVE control on the SAME fixture family ------------------------------------------ 368 // A guard that refuses everything passes every negative test ever written. The only difference 369 // between this fixture and the one above is that its lobes are evenly spaced. 370 let psig: *i64 = (sys_mmap(DG_LOBE_N * 8 + 16)) as *i64 371 let pout: *i64 = (sys_mmap(RD_R_N * 8 + 16)) as *i64 372 dg_sim_lobes(psig, DG_LOBE_N, DG_LOBE_HEAD, DG_LOBE_LEN, DG_LOBE_LEN, DG_LOBE_LEN) 373 rd_analyze(psig, DG_LOBE_N, DG_DT_US, 0, pout) 374 gv_check("positive-control-evenly-spaced-lobes-ARE-admitted" as *u8, 375 pout[RD_R_SPAN_RC] == RD_OK, ctr) 376 gv_check("positive-control-admitted-span-publishes-a-damping" as *u8, 377 pout[RD_R_SPAN_ZETA] > 0, ctr) 378 379 // ---- neg-control: the rigid subject must not produce a SPAN either ------------------------ 380 gv_check("neg-control-rigid-signal-span-refuses-with-a-named-third-state" as *u8, 381 out2[RD_R_SPAN_RC] == RD_UNOBS_NO_PERIODIC_SPAN, ctr) 382 gv_check("neg-control-rigid-signal-span-emits-no-frequency" as *u8, 383 out2[RD_R_SPAN_FN_MHZ] == 0, ctr) 384 gv_check("neg-control-stiffer-spring-moves-the-SPAN-frequency-too" as *u8, 385 out3[RD_R_SPAN_FN_MHZ] > out[RD_R_SPAN_FN_MHZ], ctr) 386 387 // ==== THE DECLARED GRID AND THE PRE-DECLARED ACCEPT RULE =================================== 388 // nx_ringdown_lib's header states this rule in full and states it BEFORE the implementation was 389 // ever measured. Enforcing it here is what stops it being a sentence: (a) every point where 390 // both estimators answer must land inside the tolerance the span estimator published for THAT 391 // point, and (b) the span estimator's WORST error must be STRICTLY smaller than the 392 // incumbent's worst on the SAME points. If (b) ever fails the right action is to unwire the 393 // span estimator, never to widen the rule. 394 let gsig: *i64 = (sys_mmap(DG_GRID_NSAMP * 8 + 16)) as *i64 395 let gout: *i64 = (sys_mmap(RD_R_N * 8 + 16)) as *i64 396 let zt: *i64 = (sys_mmap(DG_GRID_NZ * 8 + 16)) as *i64 397 zt[0] = DG_GRID_Z_LINEAR_LIMIT 398 zt[1] = DG_GRID_Z_LIGHT 399 zt[2] = DG_GRID_Z_VIDEO_FIXTURE 400 zt[3] = DG_GRID_Z_TISSUE_BAND_LOW 401 zt[4] = DG_GRID_Z_TISSUE_BAND_MID 402 zt[5] = DG_GRID_Z_TISSUE_BAND_HIGH 403 let gdt_q16: i64 = DG_Q16 / DG_GRID_DT_DIV 404 var visited: i64 = 0 405 var pts: i64 = 0 406 var worst_span: i64 = 0 407 var worst_dec: i64 = 0 408 var out_of_tol: i64 = 0 409 let gdec: *i64 = (sys_mmap(DG_GRID_NSAMP * 8 + 16)) as *i64 410 let dout: *i64 = (sys_mmap(RD_R_N * 8 + 16)) as *i64 411 var visited_v: i64 = 0 412 var pts_v: i64 = 0 413 var worst_span_v: i64 = 0 414 var worst_dec_v: i64 = 0 415 var out_of_tol_v: i64 = 0 416 var min_peak_v: i64 = 0 417 var min_halves_v: i64 = 0 418 var gk_q16: i64 = DG_GRID_K0 * DG_Q16 419 var ki: i64 = 0 420 while ki < DG_GRID_NK { 421 let gw0_q16: i64 = rd_isqrt(gk_q16 * DG_Q16) 422 var zi: i64 = 0 423 while zi < DG_GRID_NZ { 424 visited = visited + 1 425 // c = 2 * zeta * w0, so the fixture is BUILT from the target and the truth is then 426 // recomputed from the integer c actually used -- never from the target itself. 427 let gc_q16: i64 = RD_HALVES_PER_PERIOD * zt[zi] * gw0_q16 / DG_PERMIL 428 let gz_true: i64 = gc_q16 * DG_PERMIL / (RD_HALVES_PER_PERIOD * gw0_q16) 429 let gcdt_permil: i64 = gc_q16 * gdt_q16 * DG_PERMIL / (DG_Q16 * DG_Q16) 430 let gfx: i64 = gz_true * gcdt_permil / (DG_EULER_ZETA_DEN * DG_PERMIL) 431 dg_sim(gsig, DG_GRID_NSAMP, gk_q16, gc_q16, DG_GRID_X0 * DG_Q16, gdt_q16) 432 let grc: i64 = rd_analyze(gsig, DG_GRID_NSAMP, DG_DT_US, DG_GRID_QUANT, gout) 433 if grc == RD_OK { 434 if gout[RD_R_SPAN_RC] == RD_OK { 435 pts = pts + 1 436 let de: i64 = dg_abs(gout[RD_R_ZETA] - gz_true) 437 let se: i64 = dg_abs(gout[RD_R_SPAN_ZETA] - gz_true) 438 if de > worst_dec { worst_dec = de } 439 if se > worst_span { worst_span = se } 440 if se > gout[RD_R_SPAN_ZETA_TOL] + gfx { out_of_tol = out_of_tol + 1 } 441 } 442 } 443 444 // ---- THE SAME POINT AT THE VIDEO SAMPLING RATIO --------------------------------- 445 // Decimate the accurate series to DG_GRID_TARGET_SPP samples per period. The waveform 446 // is untouched, so the fixture's integration error is the same negligible gfx as above 447 // and any difference that appears here belongs to the estimators. 448 let gzsq_q16: i64 = gz_true * gz_true * DG_Q16 / (DG_PERMIL * DG_PERMIL) 449 let gwd_q16: i64 = gw0_q16 * rd_isqrt((DG_Q16 - gzsq_q16) * DG_Q16) / DG_Q16 450 var gper_fine: i64 = 0 451 if gwd_q16 > 0 { 452 gper_fine = DG_TWOPI_PERMIL * DG_Q16 * DG_Q16 / (DG_PERMIL * gwd_q16 * gdt_q16) 453 } 454 var dec: i64 = gper_fine / DG_GRID_TARGET_SPP 455 if dec < 1 { dec = 1 } 456 var di: i64 = 0 457 var dn: i64 = 0 458 while di * dec < DG_GRID_NSAMP { 459 gdec[dn] = gsig[di * dec] 460 dn = dn + 1 461 di = di + 1 462 } 463 visited_v = visited_v + 1 464 let vrc: i64 = rd_analyze(gdec, dn, DG_DT_US, DG_GRID_QUANT, dout) 465 if vrc == RD_OK { 466 if dout[RD_R_SPAN_RC] == RD_OK { 467 pts_v = pts_v + 1 468 let dve: i64 = dg_abs(dout[RD_R_ZETA] - gz_true) 469 let sve: i64 = dg_abs(dout[RD_R_SPAN_ZETA] - gz_true) 470 if dve > worst_dec_v { worst_dec_v = dve } 471 if sve > worst_span_v { worst_span_v = sve } 472 if min_peak_v == 0 { min_peak_v = dout[RD_R_SPAN_B] } 473 if dout[RD_R_SPAN_B] < min_peak_v { min_peak_v = dout[RD_R_SPAN_B] } 474 if min_halves_v == 0 { min_halves_v = dout[RD_R_SPAN_HALVES] } 475 if dout[RD_R_SPAN_HALVES] < min_halves_v { min_halves_v = dout[RD_R_SPAN_HALVES] } 476 // A COUNT WITHOUT A WORKLIST IS NOT ACTIONABLE, and the reason is already in 477 // hand at measure time. Every point that misses its own bound names itself. 478 if sve > dout[RD_R_SPAN_ZETA_TOL] + gfx { 479 out_of_tol_v = out_of_tol_v + 1 480 gv_puts("\n OFFENDER z_true=" as *u8); gv_num(gz_true) 481 gv_puts(" span=" as *u8); gv_num(dout[RD_R_SPAN_ZETA]) 482 gv_puts(" err=" as *u8); gv_num(sve) 483 gv_puts(" tol=" as *u8); gv_num(dout[RD_R_SPAN_ZETA_TOL]) 484 gv_puts(" fx=" as *u8); gv_num(gfx) 485 gv_puts(" halves=" as *u8); gv_num(dout[RD_R_SPAN_HALVES]) 486 gv_puts(" pa=" as *u8); gv_num(dout[RD_R_SPAN_A]) 487 gv_puts(" pb=" as *u8); gv_num(dout[RD_R_SPAN_B]) 488 gv_puts(" per_samp=" as *u8); gv_num(dout[RD_R_SPAN_PER_US] / DG_DT_US) 489 gv_puts(" two_lobe=" as *u8); gv_num(dout[RD_R_ZETA]) 490 gv_puts(" n=" as *u8); gv_num(dn) 491 } 492 } 493 } 494 zi = zi + 1 495 } 496 gk_q16 = gk_q16 * DG_GRID_K_STEP 497 ki = ki + 1 498 } 499 gv_check("grid-visited-every-declared-point" as *u8, 500 visited == DG_GRID_NK * DG_GRID_NZ, ctr) 501 // BOUND TO THE DENOMINATOR: a tooth that passes on the empty set is not a tooth, so both 502 // aggregate assertions below require that comparable points actually existed. 503 var tol_ok: i64 = 0 504 if pts > 0 { if out_of_tol == 0 { tol_ok = 1 } } 505 gv_check("grid-every-comparable-point-is-inside-the-span-published-tolerance" as *u8, 506 tol_ok == 1, ctr) 507 var better: i64 = 0 508 if pts > 0 { if worst_span < worst_dec { better = 1 } } 509 gv_check("grid-span-worst-error-is-STRICTLY-smaller-than-the-incumbent-worst" as *u8, 510 better == 1, ctr) 511 512 // ---- THE SAME RULE AT THE OPERATING SAMPLING RATIO --------------------------------------- 513 // This is the pass that matters for the video subject, and it is the one where the incumbent's 514 // single ratio is most exposed: at fifteen samples per period one amplitude LSB on one peak is 515 // a large share of the only measurement it makes. 516 gv_check("grid-video-sampling-visited-every-declared-point" as *u8, 517 visited_v == DG_GRID_NK * DG_GRID_NZ, ctr) 518 // THE DEADBAND MUST NOT HAVE EATEN THE EVIDENCE. Declaring a noise floor is the fix for judging 519 // an estimator on data the fixture cannot represent, but a floor set too high silences the 520 // subject instead of the noise -- a guard that refuses everything passes every negative test. 521 // This is the tooth that fires in THAT direction: every point must still span a full period of 522 // baseline after the floor is applied. 523 var halves_ok: i64 = 0 524 if min_halves_v >= DG_GRID_MIN_HALVES { halves_ok = 1 } 525 gv_check("grid-video-sampling-every-point-still-spans-a-full-period-after-the-floor" as *u8, 526 halves_ok == 1, ctr) 527 var tol_ok_v: i64 = 0 528 if pts_v > 0 { if out_of_tol_v == 0 { tol_ok_v = 1 } } 529 gv_check("grid-video-sampling-every-comparable-point-inside-published-tolerance" as *u8, 530 tol_ok_v == 1, ctr) 531 var better_v: i64 = 0 532 if pts_v > 0 { if worst_span_v < worst_dec_v { better_v = 1 } } 533 gv_check("grid-video-sampling-span-worst-error-STRICTLY-smaller-than-incumbent" as *u8, 534 better_v == 1, ctr) 535 536 gv_puts("\n GRID visited=" as *u8); gv_num(visited) 537 gv_puts(" comparable_points=" as *u8); gv_num(pts) 538 gv_puts(" out_of_tol=" as *u8); gv_num(out_of_tol) 539 gv_puts("\n GRID worst_zeta_err_permil two_lobe=" as *u8); gv_num(worst_dec) 540 gv_puts(" span=" as *u8); gv_num(worst_span) 541 gv_puts("\n GRID at " as *u8); gv_num(DG_GRID_TARGET_SPP) 542 gv_puts(" samples/period: comparable_points=" as *u8); gv_num(pts_v) 543 gv_puts(" out_of_tol=" as *u8); gv_num(out_of_tol_v) 544 gv_puts(" worst two_lobe=" as *u8); gv_num(worst_dec_v) 545 gv_puts(" span=" as *u8); gv_num(worst_span_v) 546 gv_puts(" min_judged_peak_quanta=" as *u8); gv_num(min_peak_v) 547 gv_puts(" min_span_halves=" as *u8); gv_num(min_halves_v) 548 gv_puts(" declared_floor=" as *u8); gv_num(DG_GRID_QUANT) 549 gv_puts("\n SPAN primary fixture halves=" as *u8); gv_num(out[RD_R_SPAN_HALVES]) 550 gv_puts(" zeta=" as *u8); gv_num(out[RD_R_SPAN_ZETA]) 551 gv_puts(" tol=" as *u8); gv_num(out[RD_R_SPAN_ZETA_TOL]) 552 gv_puts(" err=" as *u8); gv_num(span_zeta_err) 553 gv_puts(" fixture_err=" as *u8); gv_num(fx_zeta_err) 554 gv_puts("\n TOLERANCE RESPONSIVENESS long_span=" as *u8); gv_num(tol_long) 555 gv_puts(" short_span=" as *u8); gv_num(tol_short) 556 gv_puts(" small_final_peak=" as *u8); gv_num(tol_noisy) 557 gv_puts("\n SPAN period samples=" as *u8); gv_num(span_per_samples) 558 gv_puts(" err_permil=" as *u8); gv_num(span_per_err) 559 gv_puts(" tol_permil=" as *u8); gv_num(out[RD_R_SPAN_FN_TOL]) 560 gv_puts("\n" as *u8) 561 562 gv_puts("\nMEASURED VALUES (printed because a verdict vector cannot say why):\n" as *u8) 563 gv_puts(" zeta_true_permil=" as *u8); gv_num(zeta_true_permil) 564 gv_puts(" zeta_measured_permil=" as *u8); gv_num(out[RD_R_ZETA]) 565 gv_puts(" zeta_tol_permil=" as *u8); gv_num(zeta_tol_permil) 566 gv_puts("\n period_true_samples=" as *u8); gv_num(per_true_samples) 567 gv_puts(" period_measured_samples=" as *u8); gv_num(per_samples) 568 gv_puts(" period_err_permil=" as *u8); gv_num(per_err) 569 gv_puts(" fn_tol_permil=" as *u8); gv_num(fn_tol_permil) 570 gv_puts("\n A1=" as *u8); gv_num(out[RD_R_A1]) 571 gv_puts(" A2=" as *u8); gv_num(out[RD_R_A2]) 572 gv_puts(" crossings=" as *u8); gv_num(out[RD_R_PEAKS]) 573 gv_puts("\n" as *u8) 574 575 return gv_verdict("nx_dynaoracle_gate" as *u8, ctr, 576 "one estimator, analytic truth, third state named, rigid neg-control" as *u8) 577}