nx_units.nx source
↩ module page · 133 lines · 5835 B
1// nx_units.nx -- SI units + dimensional-analysis engine.
2//
3// Foundation for native physics primitives. Per user 2026-05-15:
4// "physics and chemistry and higher math".
5//
6// Patent-clean SI base + derived units. 7-D dimensional vector
7// (m, kg, s, A, K, mol, cd) tracks every quantity. nx_dim_check
8// validates equations: F = m * a is OK because [N] = [kg][m/s^2].
9
10// nx_safety_envelope:
11// intended_use: AUTO_APPLIED -- primitive-specific tuning queued
12// sil_target: SIL1
13// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail]
14// verdict: NOT_YET_EVALUATED
15
16import "nx_kernel_v2.nx"
17const NX_MAGIC_299792458: i64 = 299792458
18const NX_MAGIC_662607015: i64 = 662607015
19const NX_MAGIC_66743: i64 = 66743
20const NX_MAGIC_1602176634: i64 = 1602176634
21
22// ===== Sym IDs (units family 413xxx) ================================
23const NX_UNIT_SYM_METER: nx_int = 413001
24const NX_UNIT_SYM_KG: nx_int = 413002
25const NX_UNIT_SYM_SEC: nx_int = 413003
26const NX_UNIT_SYM_AMPERE: nx_int = 413004
27const NX_UNIT_SYM_KELVIN: nx_int = 413005
28const NX_UNIT_SYM_MOL: nx_int = 413006
29const NX_UNIT_SYM_CANDELA: nx_int = 413007
30const NX_UNIT_SYM_NEWTON: nx_int = 413008
31const NX_UNIT_SYM_JOULE: nx_int = 413009
32const NX_UNIT_SYM_WATT: nx_int = 413010
33const NX_UNIT_SYM_PASCAL: nx_int = 413011
34const NX_UNIT_SYM_HZ: nx_int = 413012
35const NX_UNIT_SYM_VOLT: nx_int = 413013
36const NX_UNIT_SYM_OHM: nx_int = 413014
37
38// ===== 7-D dimensional vector =======================================
39// Order: [meter, kg, sec, ampere, kelvin, mol, candela]
40// Each cell is the integer exponent. Dimensionless quantity = all zeros.
41struct Dim {
42 m: nx_int, kg: nx_int, s: nx_int, a: nx_int, k: nx_int, mol: nx_int, cd: nx_int,
43}
44const NX_DIM_BYTES: nx_int = 56
45
46func nx_dim_new(m: nx_int, kg: nx_int, s: nx_int, a: nx_int, k: nx_int, mol: nx_int, cd: nx_int) -> *Dim {
47 let d: *Dim = (sys_mmap(NX_DIM_BYTES as i64)) as *Dim
48 d.m = m; d.kg = kg; d.s = s; d.a = a; d.k = k; d.mol = mol; d.cd = cd
49 return d
50}
51
52func nx_dim_zero() -> *Dim { return nx_dim_new(0, 0, 0, 0, 0, 0, 0) }
53
54// SI base unit dim vectors
55func nx_dim_meter() -> *Dim { return nx_dim_new(1, 0, 0, 0, 0, 0, 0) }
56func nx_dim_kg() -> *Dim { return nx_dim_new(0, 1, 0, 0, 0, 0, 0) }
57func nx_dim_sec() -> *Dim { return nx_dim_new(0, 0, 1, 0, 0, 0, 0) }
58func nx_dim_ampere() -> *Dim { return nx_dim_new(0, 0, 0, 1, 0, 0, 0) }
59func nx_dim_kelvin() -> *Dim { return nx_dim_new(0, 0, 0, 0, 1, 0, 0) }
60func nx_dim_mol() -> *Dim { return nx_dim_new(0, 0, 0, 0, 0, 1, 0) }
61func nx_dim_candela() -> *Dim { return nx_dim_new(0, 0, 0, 0, 0, 0, 1) }
62
63// Derived units expressed as compound dims
64func nx_dim_newton() -> *Dim { return nx_dim_new(1, 1, 0 - 2, 0, 0, 0, 0) } // kg*m/s^2
65func nx_dim_joule() -> *Dim { return nx_dim_new(2, 1, 0 - 2, 0, 0, 0, 0) } // N*m
66func nx_dim_watt() -> *Dim { return nx_dim_new(2, 1, 0 - 3, 0, 0, 0, 0) } // J/s
67func nx_dim_pascal() -> *Dim { return nx_dim_new(0 - 1, 1, 0 - 2, 0, 0, 0, 0) } // N/m^2
68func nx_dim_hz() -> *Dim { return nx_dim_new(0, 0, 0 - 1, 0, 0, 0, 0) } // 1/s
69func nx_dim_volt() -> *Dim { return nx_dim_new(2, 1, 0 - 3, 0 - 1, 0, 0, 0) } // W/A
70func nx_dim_ohm() -> *Dim { return nx_dim_new(2, 1, 0 - 3, 0 - 2, 0, 0, 0) } // V/A
71func nx_dim_velocity() -> *Dim { return nx_dim_new(1, 0, 0 - 1, 0, 0, 0, 0) }
72func nx_dim_acceleration() -> *Dim { return nx_dim_new(1, 0, 0 - 2, 0, 0, 0, 0) }
73
74// Operators on dims: addition (multiplication of quantities multiplies
75// units => add exponents); negation (division => negate); scaling.
76func nx_dim_mul(a: *Dim, b: *Dim) -> *Dim {
77 return nx_dim_new(a.m + b.m, a.kg + b.kg, a.s + b.s,
78 a.a + b.a, a.k + b.k, a.mol + b.mol, a.cd + b.cd)
79}
80func nx_dim_div(a: *Dim, b: *Dim) -> *Dim {
81 return nx_dim_new(a.m - b.m, a.kg - b.kg, a.s - b.s,
82 a.a - b.a, a.k - b.k, a.mol - b.mol, a.cd - b.cd)
83}
84func nx_dim_pow(a: *Dim, n: nx_int) -> *Dim {
85 return nx_dim_new(a.m * n, a.kg * n, a.s * n,
86 a.a * n, a.k * n, a.mol * n, a.cd * n)
87}
88
89// Exact equality of dim vectors -- the dim-analysis check.
90func nx_dim_eq(a: *Dim, b: *Dim) -> nx_int {
91 if a.m != b.m { return 0 }
92 if a.kg != b.kg { return 0 }
93 if a.s != b.s { return 0 }
94 if a.a != b.a { return 0 }
95 if a.k != b.k { return 0 }
96 if a.mol != b.mol { return 0 }
97 if a.cd != b.cd { return 0 }
98 return 1
99}
100
101// ===== Physical constants (Q-format integer mantissa, dim attached) =
102// Speed of light c = 299_792_458 m/s. Stored as (mantissa, exp)
103// pair plus the dim vector, so numeric ops can stay integer.
104struct PhysConst {
105 mantissa: nx_int,
106 exp10: nx_int,
107 dim: *Dim,
108}
109const NX_PCONST_BYTES: nx_int = 24
110
111func nx_pconst(m: nx_int, e: nx_int, d: *Dim) -> *PhysConst {
112 let c: *PhysConst = (sys_mmap(NX_PCONST_BYTES as i64)) as *PhysConst
113 c.mantissa = m; c.exp10 = e; c.dim = d
114 return c
115}
116
117func nx_const_speed_of_light() -> *PhysConst {
118 return nx_pconst(NX_MAGIC_299792458, 0, nx_dim_velocity())
119}
120func nx_const_planck() -> *PhysConst {
121 // h = 6.62607015e-34 J*s. Mantissa 662607015, exp -42 (since J*s).
122 return nx_pconst(NX_MAGIC_662607015, 0 - 42, nx_dim_mul(nx_dim_joule(), nx_dim_sec()))
123}
124func nx_const_grav() -> *PhysConst {
125 // G = 6.6743e-11 m^3/(kg*s^2). Mantissa 66743, exp -15.
126 let dim_grav: *Dim = nx_dim_div(nx_dim_pow(nx_dim_meter(), 3),
127 nx_dim_mul(nx_dim_kg(), nx_dim_pow(nx_dim_sec(), 2)))
128 return nx_pconst(NX_MAGIC_66743, 0 - 15, dim_grav)
129}
130func nx_const_elementary_charge() -> *PhysConst {
131 // e = 1.602176634e-19 C = A*s
132 return nx_pconst(NX_MAGIC_1602176634, 0 - 28, nx_dim_mul(nx_dim_ampere(), nx_dim_sec()))
133}