nx_colorsci_gate.nx
buildroot/runtime/nx_colorsci_gate.nx
about
nx_colorsci_gate.nx -- THE GATE FOR THE COLOUR-SCIENCE RULER (nx_colorsci_lib + nx_fixq30_lib), 2026-08-24.
SUBJECT: the libs in-process (they have no main; the ruler IS the code under test). Teeth, in order:
T1 the DERIVED constants against their published digits -- pi (Machin) and e to 1e-7, and the identities
sqrt(2)^2 = 2, atan2(0,-1) = pi, sin(pi/2) = 1, cos(pi/3) = 1/2, cbrt(27) = 3, ln(exp(3)) = 3. A CORDIC
whose table was mistyped cannot pass these; a series that stopped early cannot either.
T2 CIEDE2000 against Sharma-Wu-Dalal 2005 Table I: ALL 34 pairs (gv_subjects binds the denominator), both
directions (the formula is symmetric by construction, and pairs 7/8 exist to prove it), and the table's
h_bar_prime column (the arctangent branch handling pairs 9-16 exist to trap).
T3 NEG-CONTROL: pair 1 against a WRONG expectation (+0.5 dE00) must FAIL the tolerance -- a tolerance so
wide that anything passes would read green on every KAT row and prove nothing.
T4 ICC: the mirrored sRGB2014.icc (color.org) parses; rXYZ+gXYZ+bXYZ sum to wtpt within s15Fixed16
resolution (an ICC structural invariant, not a typed expectation); white reads L=100 a=b=0; black L=0;
EVERY one of the 256 greys reads a=b=0 (the whole population, not a sample); rgb->lab->rgb round-trips
within one code over all greys and the eight cube corners.
T5 the gamut descriptor: derived from the profile at the conf's sampling; every sample it was built from
reads INSIDE; a chroma no display reaches reads OUTSIDE; bite-proven both ways; chroma clipping brings
the outside probe inside at the same L and hue.
Thresholds: the KAT tolerance is the half-ulp of a four-decimal table plus Q30 headroom; everything else is a
structural identity. license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
dependencies 3 imports · 0 importers
imports: nx_syscalls.nxnx_gate_verdict.nxnx_colorsci_lib.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 25 | const CG_KAT_PATH: *u8 = "knowledge/colorsci_ciede2000_kat.tsv" |
| 26 | const CG_PROFILE: *u8 = "knowledge/fetched/cmp_phototwin_srgb2014.b64" // base64 transport of sRGB2014.icc (Google skcms mirror of color.org) |
| 27 | const CG_CONF: *u8 = "knowledge/colorsci.conf" |
| 28 | const CG_KAT_ROWS: i64 = 34 // Table I declares 34 pairs; another count is a partial table, refused |
| 29 | const CG_KAT_FIELDS: i64 = 9 |
| 30 | const CG_F_L1: i64 = 1 |
| 31 | const CG_F_A1: i64 = 2 |
| 32 | const CG_F_B1: i64 = 3 |
| 33 | const CG_F_L2: i64 = 4 |
| 34 | const CG_F_A2: i64 = 5 |
| 35 | const CG_F_B2: i64 = 6 |
| 36 | const CG_F_HBAR: i64 = 7 |
| 37 | const CG_F_DE: i64 = 8 |
| 38 | const CG_DE_TOL_MICRO: i64 = 60 // half-ulp of a 4-decimal table (50) + Q30 arithmetic headroom (10) |
| 39 | const CG_H_TOL_MICRO: i64 = 1000 // MEASURED 2026-08-24: the table's h' column is NOT four-decimal exact -- pair 21's own printed |
| 42 | const CG_NANO: i64 = 1000000000 |
| 43 | const CG_PI_NANO: i64 = 3141592654 // pi, published digits (the KAT oracle for the Machin derivation) |
| 44 | const CG_E_NANO: i64 = 2718281828 // e, published digits |
| 45 | const CG_NANO_TOL: i64 = 100 // 1e-7: the Q30 series accumulate ~4e-8, doubled |
| 46 | const CG_THREE: i64 = 3 |
| 47 | const CG_TWO: i64 = 2 |
| 48 | const CG_SQRT_ARG: i64 = 2 |
| 49 | const CG_CBRT_ARG: i64 = 27 |
| 50 | const CG_LN_ARG: i64 = 3 |
| 57 | const CG_WHITE_TOL_MICRO: i64 = 50000 |
| 58 | const CG_L_WHITE: i64 = 100 |
| 59 | const CG_S15_SUM_TOL_Q30: i64 = 262144 |
| 60 | const CG_GREYS: i64 = 256 |
| 61 | const CG_CODE_MAX: i64 = 255 |
| 62 | const CG_CODE_TOL: i64 = 1 |
| 63 | const CG_CORNERS: i64 = 8 |
| 64 | const CG_TAB: i64 = 9 |
| 65 | const CG_NL: i64 = 10 |
| 66 | const CG_HASH: i64 = 35 |
| 67 | const CG_ROW_SLOTS: i64 = 16 |
| 68 | const CG_BITE_DE_OFFSET_MICRO: i64 = 500000 // the planted-wrong expectation: +0.5 dE00 |
| 69 | const CG_OUT_L: i64 = 50 |
| 70 | const CG_OUT_A: i64 = 150 // a chroma of 150 at L=50: outside every display-class gamut |
| 71 | const CG_GREY_MID: i64 = 128 // a mid grey: strictly inside on every channel |
| 72 | const CG_BOUNDARY_SLACK_PERMIL: i64 = 1 // a cube-face sample sits ON the boundary: 1000 permil plus/minus one unit of Q30 rounding |
| 73 | const CG_PERMIL: i64 = 1000 |
| 74 | const CG_SLOT: i64 = 8 |
| 75 | const CG_KAT_CAP: i64 = 65536 |
functions
| 77 | func cg_nano(x: i64) -> i64 { if x >= 0 { return (x * CG_NANO) >> FQ_SHIFT } return 0 - (((0 - x) * CG_NANO) >> FQ_SHIFT) } called by 1: main |
| 78 | func cg_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v } |
| 80 | func cg_field(buf: *u8, s: i64, e: i64, idx: i64, box: *i64) -> i64 |
| 100 | func cg_fld_q30(buf: *u8, s: i64, e: i64, idx: i64, box: *i64) -> i64 |
| 104 | func cg_within(x: i64, y: i64, tol_micro: i64) -> i64 |
| 109 | func main(argc: i64, argv: *i64) -> i64 |