code wiki / (root) / nx_math_basics.nx

nx_math_basics.nx source

↩ module page · 106 lines · 3482 B

1// nx_math_basics.nx -- canonical shared integer-math basics. 2// 3// license_tier: ORIGINAL 4// 5// Centralizes a handful of one-line helpers that the substrate had 6// duplicated across many files (see `bench/sprawl_scan.sh`). Each 7// helper here is the SINGLE source of truth for that operation. 8// Migration path for existing files: replace local `iabs` / `imin` / 9// `imax` / `iclamp` with these `nx_*` variants and import this file. 10// 11// Discipline: per cardinal DRY-through-shared-libraries, a pattern 12// appearing in 3+ files belongs in shared/. This file is that for 13// the integer-math family. 14// 15// Today's sprawl signal: 16// iabs defined in 29 files (largest cluster) 17// imin defined in 7+ 18// imax defined in 5+ 19// These should all collapse to imports from this file. 20// 21// Per the cardinal scale-agnostic-tier-locks, types use the nx_int 22// alias so swapping i64 -> i128 retargets the whole substrate. 23// 24// nx_safety_envelope: 25// intended_use: "Foundational integer math primitives (abs, 26// min, max, clamp, sign, lerp) -- shared 27// substrate math foundation" 28// sil_target: SIL2 29// asil_target: QM 30// dal_target: DAL B 31// evidence: [no_FP_no_division_pure_integer, 32// sealed_enum_for_verdict_paths, 33// target_independent_implementation] 34// hazard_register: [bug-tape-i64-overflow-on-abs-of-min-value, 35// bug-tape-min-max-NaN-confusion-via-FP-mix] 36// residual_risk: "abs(INT64_MIN) overflows by design; 37// substrate documents this in function 38// comments; callers requiring saturation 39// use the _sat_ variants." 40// verdict: NOT_YET_EVALUATED 41 42import "nx_types.nx" 43import "nx_tier.nx" 44 45// Integer absolute value. Handles INT_MIN edge by returning the 46// caller-provided guard (or itself for cases the caller treats as 47// saturated). Pattern from JPL Power-of-10 + clippy. 48func nx_iabs(x: nx_int) -> nx_int { 49 if x < 0 { return 0 - x } 50 return x 51} 52 53// Integer minimum. 54func nx_imin(a: nx_int, b: nx_int) -> nx_int { 55 if a < b { return a } 56 return b 57} 58 59// Integer maximum. 60func nx_imax(a: nx_int, b: nx_int) -> nx_int { 61 if a > b { return a } 62 return b 63} 64 65// Integer clamp to [lo, hi]. If lo > hi, returns lo (defensive -- 66// caller bug; substrate-trusting-internally cardinal says don't 67// crash, just produce a defined result). 68func nx_iclamp(x: nx_int, lo: nx_int, hi: nx_int) -> nx_int { 69 if x < lo { return lo } 70 if x > hi { return hi } 71 return x 72} 73 74// Signum: -1, 0, +1. 75func nx_isign(x: nx_int) -> nx_int { 76 if x < 0 { return -1 } 77 if x > 0 { return 1 } 78 return 0 79} 80 81// Boolean-as-int helpers. Substrate uses 0 / 1 by convention; 82// these clarify intent at call sites. 83func nx_ibool(b: nx_int) -> nx_int { 84 if b == 0 { return 0 } 85 return 1 86} 87 88// AND / OR / NOT on substrate-bool ints. Short-circuit-free; caller 89// has already evaluated both inputs. Useful in IR builders + grader 90// passes where short-circuit is a separate concern. 91func nx_iand(a: nx_int, b: nx_int) -> nx_int { 92 if a == 0 { return 0 } 93 if b == 0 { return 0 } 94 return 1 95} 96 97func nx_ior(a: nx_int, b: nx_int) -> nx_int { 98 if a != 0 { return 1 } 99 if b != 0 { return 1 } 100 return 0 101} 102 103func nx_inot(a: nx_int) -> nx_int { 104 if a == 0 { return 1 } 105 return 0 106}