1use crate::types::*;
4
5#[derive(Debug, Clone, Copy)]
7pub struct MatrixInstance<'a, T> {
8 pub num_rows: u16,
9 pub num_cols: u16,
10 pub data: &'a [T],
11}
12
13impl<'a, T> MatrixInstance<'a, T> {
14 pub fn new(num_rows: u16, num_cols: u16, data: &'a [T]) -> Self {
15 Self {
16 num_rows,
17 num_cols,
18 data,
19 }
20 }
21}
22
23#[derive(Debug)]
25pub struct MatrixInstanceMut<'a, T> {
26 pub num_rows: u16,
27 pub num_cols: u16,
28 pub data: &'a mut [T],
29}
30
31impl<'a, T> MatrixInstanceMut<'a, T> {
32 pub fn new(num_rows: u16, num_cols: u16, data: &'a mut [T]) -> Self {
33 Self {
34 num_rows,
35 num_cols,
36 data,
37 }
38 }
39}
40
41pub fn mat_add_f32(
44 a: &MatrixInstance<f32>,
45 b: &MatrixInstance<f32>,
46 out: &mut MatrixInstanceMut<f32>,
47) -> Status {
48 if a.num_rows != b.num_rows
49 || a.num_cols != b.num_cols
50 || a.num_rows != out.num_rows
51 || a.num_cols != out.num_cols
52 {
53 return Status::SizeMismatch;
54 }
55 let total = (a.num_rows as usize) * (a.num_cols as usize);
56 if a.data.len() < total || b.data.len() < total || out.data.len() < total {
57 return Status::LengthError;
58 }
59 for i in 0..total {
60 out.data[i] = a.data[i] + b.data[i];
61 }
62 Status::Success
63}
64
65pub fn mat_add_q31(
66 a: &MatrixInstance<q31>,
67 b: &MatrixInstance<q31>,
68 out: &mut MatrixInstanceMut<q31>,
69) -> Status {
70 if a.num_rows != b.num_rows
71 || a.num_cols != b.num_cols
72 || a.num_rows != out.num_rows
73 || a.num_cols != out.num_cols
74 {
75 return Status::SizeMismatch;
76 }
77 let total = (a.num_rows as usize) * (a.num_cols as usize);
78 if a.data.len() < total || b.data.len() < total || out.data.len() < total {
79 return Status::LengthError;
80 }
81 for i in 0..total {
82 out.data[i] = a.data[i].saturating_add(b.data[i]);
83 }
84 Status::Success
85}
86
87pub fn mat_add_q15(
88 a: &MatrixInstance<q15>,
89 b: &MatrixInstance<q15>,
90 out: &mut MatrixInstanceMut<q15>,
91) -> Status {
92 if a.num_rows != b.num_rows
93 || a.num_cols != b.num_cols
94 || a.num_rows != out.num_rows
95 || a.num_cols != out.num_cols
96 {
97 return Status::SizeMismatch;
98 }
99 let total = (a.num_rows as usize) * (a.num_cols as usize);
100 if a.data.len() < total || b.data.len() < total || out.data.len() < total {
101 return Status::LengthError;
102 }
103 for i in 0..total {
104 out.data[i] = a.data[i].saturating_add(b.data[i]);
105 }
106 Status::Success
107}
108
109pub fn mat_sub_f32(
112 a: &MatrixInstance<f32>,
113 b: &MatrixInstance<f32>,
114 out: &mut MatrixInstanceMut<f32>,
115) -> Status {
116 if a.num_rows != b.num_rows
117 || a.num_cols != b.num_cols
118 || a.num_rows != out.num_rows
119 || a.num_cols != out.num_cols
120 {
121 return Status::SizeMismatch;
122 }
123 let total = (a.num_rows as usize) * (a.num_cols as usize);
124 if a.data.len() < total || b.data.len() < total || out.data.len() < total {
125 return Status::LengthError;
126 }
127 for i in 0..total {
128 out.data[i] = a.data[i] - b.data[i];
129 }
130 Status::Success
131}
132
133pub fn mat_sub_q31(
134 a: &MatrixInstance<q31>,
135 b: &MatrixInstance<q31>,
136 out: &mut MatrixInstanceMut<q31>,
137) -> Status {
138 if a.num_rows != b.num_rows
139 || a.num_cols != b.num_cols
140 || a.num_rows != out.num_rows
141 || a.num_cols != out.num_cols
142 {
143 return Status::SizeMismatch;
144 }
145 let total = (a.num_rows as usize) * (a.num_cols as usize);
146 if a.data.len() < total || b.data.len() < total || out.data.len() < total {
147 return Status::LengthError;
148 }
149 for i in 0..total {
150 out.data[i] = a.data[i].saturating_sub(b.data[i]);
151 }
152 Status::Success
153}
154
155pub fn mat_sub_q15(
156 a: &MatrixInstance<q15>,
157 b: &MatrixInstance<q15>,
158 out: &mut MatrixInstanceMut<q15>,
159) -> Status {
160 if a.num_rows != b.num_rows
161 || a.num_cols != b.num_cols
162 || a.num_rows != out.num_rows
163 || a.num_cols != out.num_cols
164 {
165 return Status::SizeMismatch;
166 }
167 let total = (a.num_rows as usize) * (a.num_cols as usize);
168 if a.data.len() < total || b.data.len() < total || out.data.len() < total {
169 return Status::LengthError;
170 }
171 for i in 0..total {
172 out.data[i] = a.data[i].saturating_sub(b.data[i]);
173 }
174 Status::Success
175}
176
177pub fn mat_mult_f32(
180 a: &MatrixInstance<f32>,
181 b: &MatrixInstance<f32>,
182 out: &mut MatrixInstanceMut<f32>,
183) -> Status {
184 if a.num_cols != b.num_rows || a.num_rows != out.num_rows || b.num_cols != out.num_cols {
185 return Status::SizeMismatch;
186 }
187 let rows_a = a.num_rows as usize;
188 let cols_a = a.num_cols as usize;
189 let cols_b = b.num_cols as usize;
190
191 for r in 0..rows_a {
192 for c in 0..cols_b {
193 let mut sum = 0.0f32;
194 for k in 0..cols_a {
195 sum += a.data[r * cols_a + k] * b.data[k * cols_b + c];
196 }
197 out.data[r * cols_b + c] = sum;
198 }
199 }
200 Status::Success
201}
202
203pub fn mat_mult_q31(
204 a: &MatrixInstance<q31>,
205 b: &MatrixInstance<q31>,
206 out: &mut MatrixInstanceMut<q31>,
207) -> Status {
208 if a.num_cols != b.num_rows || a.num_rows != out.num_rows || b.num_cols != out.num_cols {
209 return Status::SizeMismatch;
210 }
211 let rows_a = a.num_rows as usize;
212 let cols_a = a.num_cols as usize;
213 let cols_b = b.num_cols as usize;
214
215 for r in 0..rows_a {
216 for c in 0..cols_b {
217 let mut sum: i64 = 0;
218 for k in 0..cols_a {
219 sum += (a.data[r * cols_a + k] as i64 * b.data[k * cols_b + c] as i64) >> 31;
220 }
221 out.data[r * cols_b + c] = sum.clamp(i32::MIN as i64, i32::MAX as i64) as q31;
222 }
223 }
224 Status::Success
225}
226
227pub fn mat_mult_q15(
228 a: &MatrixInstance<q15>,
229 b: &MatrixInstance<q15>,
230 out: &mut MatrixInstanceMut<q15>,
231) -> Status {
232 if a.num_cols != b.num_rows || a.num_rows != out.num_rows || b.num_cols != out.num_cols {
233 return Status::SizeMismatch;
234 }
235 let rows_a = a.num_rows as usize;
236 let cols_a = a.num_cols as usize;
237 let cols_b = b.num_cols as usize;
238
239 for r in 0..rows_a {
240 for c in 0..cols_b {
241 let mut sum: i32 = 0;
242 for k in 0..cols_a {
243 sum += (a.data[r * cols_a + k] as i32 * b.data[k * cols_b + c] as i32) >> 15;
244 }
245 out.data[r * cols_b + c] = sum.clamp(i16::MIN as i32, i16::MAX as i32) as q15;
246 }
247 }
248 Status::Success
249}
250
251pub fn mat_scale_f32(
254 src: &MatrixInstance<f32>,
255 scale: f32,
256 out: &mut MatrixInstanceMut<f32>,
257) -> Status {
258 if src.num_rows != out.num_rows || src.num_cols != out.num_cols {
259 return Status::SizeMismatch;
260 }
261 let total = (src.num_rows as usize) * (src.num_cols as usize);
262 for i in 0..total {
263 out.data[i] = src.data[i] * scale;
264 }
265 Status::Success
266}
267
268pub fn mat_scale_q31(
269 src: &MatrixInstance<q31>,
270 scale_fract: q31,
271 shift: i8,
272 out: &mut MatrixInstanceMut<q31>,
273) -> Status {
274 if src.num_rows != out.num_rows || src.num_cols != out.num_cols {
275 return Status::SizeMismatch;
276 }
277 let total = (src.num_rows as usize) * (src.num_cols as usize);
278 crate::basic_math::scale_q31(
279 &src.data[..total],
280 scale_fract,
281 shift,
282 &mut out.data[..total],
283 );
284 Status::Success
285}
286
287pub fn mat_scale_q15(
288 src: &MatrixInstance<q15>,
289 scale_fract: q15,
290 shift: i8,
291 out: &mut MatrixInstanceMut<q15>,
292) -> Status {
293 if src.num_rows != out.num_rows || src.num_cols != out.num_cols {
294 return Status::SizeMismatch;
295 }
296 let total = (src.num_rows as usize) * (src.num_cols as usize);
297 crate::basic_math::scale_q15(
298 &src.data[..total],
299 scale_fract,
300 shift,
301 &mut out.data[..total],
302 );
303 Status::Success
304}
305
306pub fn mat_trans_f32(src: &MatrixInstance<f32>, out: &mut MatrixInstanceMut<f32>) -> Status {
309 if src.num_rows != out.num_cols || src.num_cols != out.num_rows {
310 return Status::SizeMismatch;
311 }
312 let rows = src.num_rows as usize;
313 let cols = src.num_cols as usize;
314
315 for r in 0..rows {
316 for c in 0..cols {
317 out.data[c * rows + r] = src.data[r * cols + c];
318 }
319 }
320 Status::Success
321}
322
323pub fn mat_trans_q31(src: &MatrixInstance<q31>, out: &mut MatrixInstanceMut<q31>) -> Status {
324 if src.num_rows != out.num_cols || src.num_cols != out.num_rows {
325 return Status::SizeMismatch;
326 }
327 let rows = src.num_rows as usize;
328 let cols = src.num_cols as usize;
329
330 for r in 0..rows {
331 for c in 0..cols {
332 out.data[c * rows + r] = src.data[r * cols + c];
333 }
334 }
335 Status::Success
336}
337
338pub fn mat_trans_q15(src: &MatrixInstance<q15>, out: &mut MatrixInstanceMut<q15>) -> Status {
339 if src.num_rows != out.num_cols || src.num_cols != out.num_rows {
340 return Status::SizeMismatch;
341 }
342 let rows = src.num_rows as usize;
343 let cols = src.num_cols as usize;
344
345 for r in 0..rows {
346 for c in 0..cols {
347 out.data[c * rows + r] = src.data[r * cols + c];
348 }
349 }
350 Status::Success
351}
352
353pub fn mat_inverse_f32(src: &MatrixInstance<f32>, out: &mut MatrixInstanceMut<f32>) -> Status {
356 if src.num_rows != src.num_cols || out.num_rows != out.num_cols || src.num_rows != out.num_rows
357 {
358 return Status::SizeMismatch;
359 }
360 let n = src.num_rows as usize;
361 if n == 0 {
362 return Status::SizeMismatch;
363 }
364
365 let mut aug = [0.0f32; 16 * 32];
368 if n > 16 {
369 return Status::ArgumentError; }
371
372 for r in 0..n {
373 for c in 0..n {
374 aug[r * 2 * n + c] = src.data[r * n + c];
375 aug[r * 2 * n + n + c] = if r == c { 1.0 } else { 0.0 };
376 }
377 }
378
379 for i in 0..n {
380 let mut max_row = i;
382 let mut max_val = aug[i * 2 * n + i].abs();
383 for r in (i + 1)..n {
384 let val = aug[r * 2 * n + i].abs();
385 if val > max_val {
386 max_val = val;
387 max_row = r;
388 }
389 }
390
391 if max_val < 1e-12 {
392 return Status::Singular;
393 }
394
395 if max_row != i {
397 for c in 0..(2 * n) {
398 aug.swap(i * 2 * n + c, max_row * 2 * n + c);
399 }
400 }
401
402 let pivot = aug[i * 2 * n + i];
403 for c in 0..(2 * n) {
404 aug[i * 2 * n + c] /= pivot;
405 }
406
407 for r in 0..n {
408 if r != i {
409 let factor = aug[r * 2 * n + i];
410 for c in 0..(2 * n) {
411 let sub = factor * aug[i * 2 * n + c];
412 aug[r * 2 * n + c] -= sub;
413 }
414 }
415 }
416 }
417
418 for r in 0..n {
419 for c in 0..n {
420 out.data[r * n + c] = aug[r * 2 * n + n + c];
421 }
422 }
423
424 Status::Success
425}