nx_matrix_test.nx source
↩ module page · 148 lines · 6433 B
1// nx_matrix_test.nx -- smoke for matrix algebra.
2
3import "syscalls.nx"
4import "nx_matrix.nx"
5
6func main() -> i64 {
7 // === Test 1: alloc + set + get ===
8 let m: *Matrix = nx_matrix_alloc(2, 3)
9 if m.rows != 2 { return 1 }
10 if m.cols != 3 { return 2 }
11 nx_matrix_set(m, 0, 0, 10)
12 nx_matrix_set(m, 1, 2, 99)
13 if nx_matrix_get(m, 0, 0) != 10 { return 3 }
14 if nx_matrix_get(m, 1, 2) != 99 { return 4 }
15 if nx_matrix_get(m, 0, 1) != 0 { return 5 } // zeroed
16
17 // === Test 2: identity ===
18 let id: *Matrix = nx_matrix_alloc(3, 3)
19 nx_matrix_identity(id, 1)
20 if nx_matrix_get(id, 0, 0) != 1 { return 10 }
21 if nx_matrix_get(id, 1, 1) != 1 { return 11 }
22 if nx_matrix_get(id, 2, 2) != 1 { return 12 }
23 if nx_matrix_get(id, 0, 1) != 0 { return 13 }
24 if nx_matrix_get(id, 1, 0) != 0 { return 14 }
25
26 // === Test 3: transpose ===
27 let a: *Matrix = nx_matrix_alloc(2, 3)
28 nx_matrix_set(a, 0, 0, 1); nx_matrix_set(a, 0, 1, 2); nx_matrix_set(a, 0, 2, 3)
29 nx_matrix_set(a, 1, 0, 4); nx_matrix_set(a, 1, 1, 5); nx_matrix_set(a, 1, 2, 6)
30 let at: *Matrix = nx_matrix_transpose(a)
31 if at.rows != 3 { return 20 }
32 if at.cols != 2 { return 21 }
33 if nx_matrix_get(at, 0, 0) != 1 { return 22 }
34 if nx_matrix_get(at, 1, 0) != 2 { return 23 }
35 if nx_matrix_get(at, 2, 0) != 3 { return 24 }
36 if nx_matrix_get(at, 0, 1) != 4 { return 25 }
37 if nx_matrix_get(at, 1, 1) != 5 { return 26 }
38 if nx_matrix_get(at, 2, 1) != 6 { return 27 }
39
40 // === Test 4: multiply 2x3 * 3x2 = 2x2 ===
41 // A = [[1,2,3],[4,5,6]]
42 // B = [[7,8],[9,10],[11,12]]
43 // AB = [[58,64],[139,154]]
44 let b: *Matrix = nx_matrix_alloc(3, 2)
45 nx_matrix_set(b, 0, 0, 7); nx_matrix_set(b, 0, 1, 8)
46 nx_matrix_set(b, 1, 0, 9); nx_matrix_set(b, 1, 1, 10)
47 nx_matrix_set(b, 2, 0, 11); nx_matrix_set(b, 2, 1, 12)
48 let c: *Matrix = nx_matrix_alloc(2, 2)
49 if nx_matrix_multiply(a, b, c) != 0 { return 30 }
50 if nx_matrix_get(c, 0, 0) != 58 { return 31 }
51 if nx_matrix_get(c, 0, 1) != 64 { return 32 }
52 if nx_matrix_get(c, 1, 0) != 139 { return 33 }
53 if nx_matrix_get(c, 1, 1) != 154 { return 34 }
54
55 // === Test 5: multiply identity * A = A ===
56 let id2: *Matrix = nx_matrix_alloc(2, 2)
57 nx_matrix_identity(id2, 1)
58 let a2: *Matrix = nx_matrix_alloc(2, 2)
59 nx_matrix_set(a2, 0, 0, 5); nx_matrix_set(a2, 0, 1, 7)
60 nx_matrix_set(a2, 1, 0, 9); nx_matrix_set(a2, 1, 1, 11)
61 let prod: *Matrix = nx_matrix_alloc(2, 2)
62 nx_matrix_multiply(id2, a2, prod)
63 if nx_matrix_get(prod, 0, 0) != 5 { return 40 }
64 if nx_matrix_get(prod, 0, 1) != 7 { return 41 }
65 if nx_matrix_get(prod, 1, 0) != 9 { return 42 }
66 if nx_matrix_get(prod, 1, 1) != 11 { return 43 }
67
68 // === Test 6: multiply shape mismatch returns -1 ===
69 let bad: *Matrix = nx_matrix_alloc(3, 3)
70 if nx_matrix_multiply(a2, bad, prod) != -1 { return 50 }
71
72 // === Test 7: 2x2 determinant ===
73 // [[3,8],[4,6]] -> det = 18 - 32 = -14
74 let d2: *Matrix = nx_matrix_alloc(2, 2)
75 nx_matrix_set(d2, 0, 0, 3); nx_matrix_set(d2, 0, 1, 8)
76 nx_matrix_set(d2, 1, 0, 4); nx_matrix_set(d2, 1, 1, 6)
77 if nx_matrix_det_2x2(d2) != -14 { return 60 }
78
79 // === Test 8: 2x2 inverse ===
80 // Inverse of [[3,8],[4,6]] is (1/-14) * [[6,-8],[-4,3]]
81 // In Q14: [[6*16384/-14, -8*16384/-14], [-4*16384/-14, 3*16384/-14]]
82 // = [[-7021, 9362], [4681, -3510]]
83 let d2_inv: *Matrix = nx_matrix_alloc(2, 2)
84 if nx_matrix_inv_2x2(d2, d2_inv) != 0 { return 70 }
85 // Approximate check
86 let i00: i64 = nx_matrix_get(d2_inv, 0, 0)
87 let d00: i64 = i00 - (-7021)
88 var ad00: i64 = d00
89 if ad00 < 0 { ad00 = -ad00 }
90 if ad00 > 5 { return 71 }
91
92 // === Test 9: 2x2 inverse: M * inv_M = I (in Q14) ===
93 // M * inv_M should give Q14 identity (entries 16384 on diag, 0 off).
94 let id_q14: *Matrix = nx_matrix_alloc(2, 2)
95 nx_matrix_multiply(d2, d2_inv, id_q14)
96 // diagonal should be ~Q14 = 16384
97 let d_00: i64 = nx_matrix_get(id_q14, 0, 0) - 16384
98 var ad_00: i64 = d_00
99 if ad_00 < 0 { ad_00 = -ad_00 }
100 if ad_00 > 20 { return 80 }
101 let d_11: i64 = nx_matrix_get(id_q14, 1, 1) - 16384
102 var ad_11: i64 = d_11
103 if ad_11 < 0 { ad_11 = -ad_11 }
104 if ad_11 > 20 { return 81 }
105 // off-diagonal should be ~0
106 var d_01: i64 = nx_matrix_get(id_q14, 0, 1)
107 if d_01 < 0 { d_01 = -d_01 }
108 if d_01 > 20 { return 82 }
109
110 // === Test 10: 3x3 determinant ===
111 // [[1,2,3],[4,5,6],[7,8,10]] -> det = 1*(50-48) - 2*(40-42) + 3*(32-35)
112 // = 2 + 4 - 9 = -3
113 let d3: *Matrix = nx_matrix_alloc(3, 3)
114 nx_matrix_set(d3, 0, 0, 1); nx_matrix_set(d3, 0, 1, 2); nx_matrix_set(d3, 0, 2, 3)
115 nx_matrix_set(d3, 1, 0, 4); nx_matrix_set(d3, 1, 1, 5); nx_matrix_set(d3, 1, 2, 6)
116 nx_matrix_set(d3, 2, 0, 7); nx_matrix_set(d3, 2, 1, 8); nx_matrix_set(d3, 2, 2, 10)
117 if nx_matrix_det_3x3(d3) != -3 { return 90 }
118
119 // === Test 11: 3x3 singular matrix det = 0 ===
120 let sing: *Matrix = nx_matrix_alloc(3, 3)
121 nx_matrix_set(sing, 0, 0, 1); nx_matrix_set(sing, 0, 1, 2); nx_matrix_set(sing, 0, 2, 3)
122 nx_matrix_set(sing, 1, 0, 2); nx_matrix_set(sing, 1, 1, 4); nx_matrix_set(sing, 1, 2, 6)
123 nx_matrix_set(sing, 2, 0, 3); nx_matrix_set(sing, 2, 1, 6); nx_matrix_set(sing, 2, 2, 9)
124 if nx_matrix_det_3x3(sing) != 0 { return 100 }
125 // Inverse should fail
126 let bad_inv: *Matrix = nx_matrix_alloc(3, 3)
127 if nx_matrix_inv_3x3(sing, bad_inv) != -1 { return 101 }
128
129 // === Test 12: 3x3 inverse: M * inv_M = Q14 identity ===
130 let d3_inv: *Matrix = nx_matrix_alloc(3, 3)
131 if nx_matrix_inv_3x3(d3, d3_inv) != 0 { return 110 }
132 let r3: *Matrix = nx_matrix_alloc(3, 3)
133 nx_matrix_multiply(d3, d3_inv, r3)
134 var dd_00: i64 = nx_matrix_get(r3, 0, 0) - 16384
135 if dd_00 < 0 { dd_00 = -dd_00 }
136 if dd_00 > 100 { return 111 }
137 var dd_11: i64 = nx_matrix_get(r3, 1, 1) - 16384
138 if dd_11 < 0 { dd_11 = -dd_11 }
139 if dd_11 > 100 { return 112 }
140 var dd_22: i64 = nx_matrix_get(r3, 2, 2) - 16384
141 if dd_22 < 0 { dd_22 = -dd_22 }
142 if dd_22 > 100 { return 113 }
143 var dd_01: i64 = nx_matrix_get(r3, 0, 1)
144 if dd_01 < 0 { dd_01 = -dd_01 }
145 if dd_01 > 100 { return 114 }
146
147 return 0
148}