code wiki / (root) / fx_gate.nx

fx_gate.nx source

↩ module page · 108 lines · 5222 B

1// fx_gate.nx -- the gate for the Q16.16 fixed-point math 49 modules import. 2// WHY: nx_gensota gen-3 worklist. This module exists for ONE reason -- bit-identical simulation 3// across machines (rollback netcode); IEEE-754 cannot deliver it. Its header numbers four 4// invariants FX1-FX4, and an invariant nothing checks is a wish. 5// ★SCOPE DECLARED HONESTLY: determinism has an IN-PROCESS half (same input -> same bits, every 6// call) and a CROSS-MACHINE half (same bits on every target). T9 proves the first. The second 7// CANNOT be proven from one host and is NOT claimed here -- it would need the same vectors run 8// on a second architecture and compared. Saying so beats a gate that implies coverage it lacks. 9// ⚠OPEN QUESTION FILED, NOT GUESSED (see debt): FX2 says fx_mul and fx_div "round toward zero 10// (arithmetic shift)" -- but an arithmetic right shift rounds toward NEGATIVE INFINITY on 11// negatives while integer division truncates toward ZERO, so the two may DISAGREE on negative 12// operands. Rather than pin a guessed direction, T5 asserts the property that is true either 13// way and matters to callers: the result is within ONE ULP of the exact product. 14// license_tier: ORIGINAL expect_exit: 0 No hw writes (Rule 26). 15import "nx_syscalls.nx" 16import "nx_gate_verdict.nx" 17import "fx.nx" 18 19func fxg_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v } 20 21func main() -> i64 { 22 let ctr: *i64 = gv_ctr() 23 gv_head("FX-GATE -- the Q16.16 determinism contract 49 modules import" as *u8) 24 25 var t1: i64 = 1 26 if FX_ONE != (1 << FX_SHIFT) { t1 = 0 } 27 if FX_HALF * 2 != FX_ONE { t1 = 0 } 28 if FX_FRAC_MASK != FX_ONE - 1 { t1 = 0 } 29 gv_check("T1 scale constants are mutually CONSISTENT (ONE, HALF, FRAC_MASK)" as *u8, t1, ctr) 30 31 var t2: i64 = 1 32 if fx_to_int(fx_from_int(0)) != 0 { t2 = 0 } 33 if fx_to_int(fx_from_int(7)) != 7 { t2 = 0 } 34 if fx_to_int(fx_from_int(32000)) != 32000 { t2 = 0 } 35 if fx_to_int(fx_from_int(0 - 7)) != (0 - 7) { t2 = 0 } 36 gv_check("T2 from_int/to_int ROUND-TRIPS incl. negative and near-range" as *u8, t2, ctr) 37 38 var t3: i64 = 1 39 if fx_mul(FX_ONE, FX_ONE) != FX_ONE { t3 = 0 } 40 if fx_mul(fx_from_int(5), FX_ONE) != fx_from_int(5) { t3 = 0 } 41 if fx_mul(fx_from_int(0 - 5), FX_ONE) != fx_from_int(0 - 5) { t3 = 0 } 42 if fx_mul(FX_HALF, fx_from_int(4)) != fx_from_int(2) { t3 = 0 } 43 gv_check("T3 mul: ONE is the identity (both signs); half x 4 == 2 exactly" as *u8, t3, ctr) 44 45 var t4: i64 = 1 46 if fx_div(FX_ONE, FX_ONE) != FX_ONE { t4 = 0 } 47 if fx_div(fx_from_int(9), FX_ONE) != fx_from_int(9) { t4 = 0 } 48 if fx_div(fx_from_int(0 - 9), FX_ONE) != fx_from_int(0 - 9) { t4 = 0 } 49 if fx_div(fx_from_int(6), fx_from_int(2)) != fx_from_int(3) { t4 = 0 } 50 gv_check("T4 div: ONE is the identity (both signs); 6/2 == 3 exactly" as *u8, t4, ctr) 51 52 // FX2 without guessing the rounding DIRECTION -- see header. 53 var t5: i64 = 1 54 var probe: i64 = 0 - 3 55 var iters: i64 = 0 56 while iters < 5 { 57 let a: i64 = probe 58 let b: i64 = FX_HALF + 7 59 let got: i64 = fx_mul(a, b) 60 let exact_num: i64 = a * b 61 let lo: i64 = got << FX_SHIFT 62 if fxg_abs(exact_num - lo) >= FX_ONE { t5 = 0 } 63 probe = probe * 11 + 13 64 iters = iters + 1 65 } 66 gv_check("T5 FX2: mul is within ONE ULP of the exact product (true for either rounding rule)" as *u8, t5, ctr) 67 68 var t6: i64 = 1 69 if fx_from_frac(1, 2) != FX_HALF { t6 = 0 } 70 if fx_from_frac(3, 1) != fx_from_int(3) { t6 = 0 } 71 if fx_from_frac(1, 4) != FX_HALF / 2 { t6 = 0 } 72 gv_check("T6 from_frac builds EXACT rationals (1/2, 3/1, 1/4)" as *u8, t6, ctr) 73 74 // the module's own stated exactness claim 75 var t7: i64 = 1 76 if fx_log2(FX_ONE) != 0 { t7 = 0 } 77 if fx_log2(FX_ONE << 1) != FX_ONE { t7 = 0 } 78 if fx_log2(FX_ONE << 3) != 3 * FX_ONE { t7 = 0 } 79 if fx_log2(FX_ONE << 10) != 10 * FX_ONE { t7 = 0 } 80 gv_check("T7 STATED CLAIM: log2 is EXACT on powers of two (2^0,2^1,2^3,2^10)" as *u8, t7, ctr) 81 82 // documented defensive boundary (Rule 12) 83 var t8: i64 = 1 84 if fx_log2(0) != 0 { t8 = 0 } 85 if fx_log2(0 - 5) != 0 { t8 = 0 } 86 gv_check("T8 log2 domain guard: <=0 returns 0, never a garbage value or a hang" as *u8, t8, ctr) 87 88 // FX1/FX3 raison d'etre: same input -> same bits, every call (IN-PROCESS half) 89 var t9: i64 = 1 90 var k: i64 = 0 91 while k < 4 { 92 let x: i64 = FX_ONE + k * 7919 93 if fx_log2(x) != fx_log2(x) { t9 = 0 } 94 if fx_mul(x, x) != fx_mul(x, x) { t9 = 0 } 95 if fx_div(x, FX_HALF) != fx_div(x, FX_HALF) { t9 = 0 } 96 k = k + 1 97 } 98 gv_check("T9 DETERMINISM (in-process): identical inputs give identical bits, 4 values" as *u8, t9, ctr) 99 100 // NEG-CONTROL: the comparators must be capable of failing. 101 var t10: i64 = 0 102 if fx_log2(FX_ONE << 1) != 3 * FX_ONE { if fx_mul(FX_ONE, FX_ONE) != 0 { if fx_from_int(1) != 1 { t10 = 1 } } } 103 gv_check("T10 NEG-CONTROL: wrong log2, wrong product and raw-int confusion all REJECT" as *u8, t10, ctr) 104 105 let rc: i64 = gv_verdict("FX-GATE" as *u8, ctr, "Q16.16 invariants checked; cross-machine half declared out of scope" as *u8) 106 sys_exit(rc) 107 return rc 108}