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}