code wiki / (root) / nx_linalg.nx

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}