nx_linalg.nx source
↩ module page · 154 lines · 4530 B
1// nx_linalg.nx -- vector + matrix engine.
2//
3// Native NishiLang linear algebra over integer (Q-format) and real
4// elements. Vectors and matrices stored as flat arrays for tight
5// memory + cache behaviour. Engine-style: dimensions are runtime
6// parameters, not types -- one set of functions handles any size.
7
8// nx_safety_envelope:
9// intended_use: AUTO_APPLIED -- primitive-specific tuning queued
10// sil_target: SIL1
11// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail]
12// verdict: NOT_YET_EVALUATED
13
14import "nx_kernel_v2.nx"
15
16// ===== Vector =======================================================
17// flat array of nx_int (Q10 fixed point or raw int -- caller decides
18// the meaning; the engine just does arithmetic).
19struct Vec {
20 data: *nx_int,
21 n: nx_int,
22}
23const NX_VEC_BYTES: nx_int = 16
24
25func nx_vec_new(n: nx_int) -> *Vec {
26 let v: *Vec = (sys_mmap(NX_VEC_BYTES as i64)) as *Vec
27 v.data = (sys_mmap((n * 8) as i64)) as *nx_int
28 v.n = n
29 return v
30}
31
32func nx_vec_set(v: *Vec, i: nx_int, x: nx_int) -> nx_int {
33 let p: *nx_int = ((v.data as nx_int) + (i * 8)) as *nx_int
34 p[0] = x
35 return x
36}
37
38func nx_vec_get(v: *Vec, i: nx_int) -> nx_int {
39 let p: *nx_int = ((v.data as nx_int) + (i * 8)) as *nx_int
40 return p[0]
41}
42
43func nx_vec_add(a: *Vec, b: *Vec) -> *Vec {
44 let n: nx_int = a.n
45 let r: *Vec = nx_vec_new(n)
46 var i: nx_int = 0
47 while i < n {
48 let _s: nx_int = nx_vec_set(r, i, nx_vec_get(a, i) + nx_vec_get(b, i))
49 i = i + 1
50 }
51 return r
52}
53
54func nx_vec_scale(a: *Vec, k: nx_int) -> *Vec {
55 let r: *Vec = nx_vec_new(a.n)
56 var i: nx_int = 0
57 while i < a.n {
58 let _s: nx_int = nx_vec_set(r, i, nx_vec_get(a, i) * k)
59 i = i + 1
60 }
61 return r
62}
63
64func nx_vec_dot(a: *Vec, b: *Vec) -> nx_int {
65 var sum: nx_int = 0
66 var i: nx_int = 0
67 while i < a.n {
68 sum = sum + (nx_vec_get(a, i) * nx_vec_get(b, i))
69 i = i + 1
70 }
71 return sum
72}
73
74func nx_vec_norm_sq(a: *Vec) -> nx_int {
75 return nx_vec_dot(a, a)
76}
77
78// ===== Matrix (row-major) ==========================================
79struct Mat {
80 data: *nx_int,
81 rows: nx_int,
82 cols: nx_int,
83}
84const NX_MAT_BYTES: nx_int = 24
85
86func nx_mat_new(rows: nx_int, cols: nx_int) -> *Mat {
87 let m: *Mat = (sys_mmap(NX_MAT_BYTES as i64)) as *Mat
88 m.data = (sys_mmap((rows * cols * 8) as i64)) as *nx_int
89 m.rows = rows; m.cols = cols
90 return m
91}
92
93func nx_mat_set(m: *Mat, r: nx_int, c: nx_int, x: nx_int) -> nx_int {
94 let p: *nx_int = ((m.data as nx_int) + ((r * m.cols + c) * 8)) as *nx_int
95 p[0] = x
96 return x
97}
98
99func nx_mat_get(m: *Mat, r: nx_int, c: nx_int) -> nx_int {
100 let p: *nx_int = ((m.data as nx_int) + ((r * m.cols + c) * 8)) as *nx_int
101 return p[0]
102}
103
104// matmul: A is (n x m), B is (m x p) -> result is (n x p).
105func nx_mat_mul(a: *Mat, b: *Mat) -> *Mat {
106 let r: *Mat = nx_mat_new(a.rows, b.cols)
107 var i: nx_int = 0
108 while i < a.rows {
109 var j: nx_int = 0
110 while j < b.cols {
111 var sum: nx_int = 0
112 var k: nx_int = 0
113 while k < a.cols {
114 sum = sum + (nx_mat_get(a, i, k) * nx_mat_get(b, k, j))
115 k = k + 1
116 }
117 let _s: nx_int = nx_mat_set(r, i, j, sum)
118 j = j + 1
119 }
120 i = i + 1
121 }
122 return r
123}
124
125// 2x2 determinant -- exact integer arithmetic.
126func nx_mat_det2(m: *Mat) -> nx_int {
127 return nx_mat_get(m, 0, 0) * nx_mat_get(m, 1, 1) - nx_mat_get(m, 0, 1) * nx_mat_get(m, 1, 0)
128}
129
130// 3x3 determinant via cofactor expansion along row 0.
131func nx_mat_det3(m: *Mat) -> nx_int {
132 let a: nx_int = nx_mat_get(m, 0, 0)
133 let b: nx_int = nx_mat_get(m, 0, 1)
134 let c: nx_int = nx_mat_get(m, 0, 2)
135 let d: nx_int = nx_mat_get(m, 1, 0) * nx_mat_get(m, 2, 1) - nx_mat_get(m, 1, 1) * nx_mat_get(m, 2, 0)
136 let e: nx_int = nx_mat_get(m, 1, 0) * nx_mat_get(m, 2, 2) - nx_mat_get(m, 1, 2) * nx_mat_get(m, 2, 0)
137 let f: nx_int = nx_mat_get(m, 1, 1) * nx_mat_get(m, 2, 2) - nx_mat_get(m, 1, 2) * nx_mat_get(m, 2, 1)
138 return a * f - b * e + c * d
139}
140
141// Transpose of an (r x c) matrix gives (c x r).
142func nx_mat_transpose(m: *Mat) -> *Mat {
143 let t: *Mat = nx_mat_new(m.cols, m.rows)
144 var i: nx_int = 0
145 while i < m.rows {
146 var j: nx_int = 0
147 while j < m.cols {
148 let _s: nx_int = nx_mat_set(t, j, i, nx_mat_get(m, i, j))
149 j = j + 1
150 }
151 i = i + 1
152 }
153 return t
154}