1 /*
2  * Copyright (c) 2019-2020 Kevin Townsend (KTOWN)
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @defgroup MATRICES Matrices
9  *
10  * @brief Various mxn matrices functions.
11  *
12  * TODO: Expand with examples, better high-level documentation, etc.
13  */
14 
15 /**
16  * @file
17  * @brief API header file for matrices in zscilib.
18  *
19  * This file contains the zscilib matrix APIs
20  */
21 
22 #ifndef ZEPHYR_INCLUDE_ZSL_MATRICES_H_
23 #define ZEPHYR_INCLUDE_ZSL_MATRICES_H_
24 
25 #include <zsl/zsl.h>
26 #include <zsl/vectors.h>
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 
32 /**
33  * @addtogroup MTX_STRUCTS Structs and Macros
34  *
35  * @brief Common structs and macros for working with matrices.
36  *
37  * @ingroup MATRICES
38  *  @{ */
39 
40 /** Error: The number of eigenvectors is less than the matrice's dimension. */
41 #define EEIGENSIZE   (100)
42 /** Error: Occurs when the input matrix has complex eigenvalues. */
43 #define ECOMPLEXVAL  (101)
44 
45 /** @brief Represents a m x n matrix, with data stored in row-major order. */
46 struct zsl_mtx {
47 	/** The number of rows in the matrix (typically denoted as 'm'). */
48 	size_t sz_rows;
49 	/** The number of columns in the matrix (typically denoted as 'n'). */
50 	size_t sz_cols;
51 	/** Data assigned to the matrix, in row-major order (left to right). */
52 	zsl_real_t *data;
53 };
54 
55 /**
56  * Macro to declare a matrix of shape m*n.
57  *
58  * Be sure to also call 'zsl_mtx_init' on the matrix after this macro, since
59  * matrices declared on the stack may have non-zero values by default!
60  */
61 #define ZSL_MATRIX_DEF(name, m, n);	\
62 	zsl_real_t name ## _mtx[m * n];	\
63 	struct zsl_mtx name = {		\
64 		.sz_rows = m,		\
65 		.sz_cols = n,		\
66 		.data = name ## _mtx	\
67 	}
68 
69 /** @} */ /* End of MTX_STRUCTS group */
70 
71 /**
72  * @addtogroup MTX_OPERANDS Operands
73  *
74  * @brief Unary and binary operands that can be performed on matrix
75  *        coefficients.
76  *
77  * @ingroup MATRICES
78  *  @{ */
79 
80 /** @brief Component-wise unary operations. */
81 typedef enum zsl_mtx_unary_op {
82 	ZSL_MTX_UNARY_OP_INCREMENT,             /**< ++ */
83 	ZSL_MTX_UNARY_OP_DECREMENT,             /**< -- */
84 	ZSL_MTX_UNARY_OP_NEGATIVE,
85 	ZSL_MTX_UNARY_OP_ROUND,
86 	ZSL_MTX_UNARY_OP_ABS,
87 	ZSL_MTX_UNARY_OP_FLOOR,
88 	ZSL_MTX_UNARY_OP_CEIL,
89 	ZSL_MTX_UNARY_OP_EXP,
90 	ZSL_MTX_UNARY_OP_LOG,
91 	ZSL_MTX_UNARY_OP_LOG10,
92 	ZSL_MTX_UNARY_OP_SQRT,
93 	ZSL_MTX_UNARY_OP_SIN,
94 	ZSL_MTX_UNARY_OP_COS,
95 	ZSL_MTX_UNARY_OP_TAN,
96 	ZSL_MTX_UNARY_OP_ASIN,
97 	ZSL_MTX_UNARY_OP_ACOS,
98 	ZSL_MTX_UNARY_OP_ATAN,
99 	ZSL_MTX_UNARY_OP_SINH,
100 	ZSL_MTX_UNARY_OP_COSH,
101 	ZSL_MTX_UNARY_OP_TANH,
102 } zsl_mtx_unary_op_t;
103 
104 /** @brief Component-wise binary operations. */
105 typedef enum zsl_mtx_binary_op {
106 	ZSL_MTX_BINARY_OP_ADD,                  /**< a + b */
107 	ZSL_MTX_BINARY_OP_SUB,                  /**< a - b */
108 	ZSL_MTX_BINARY_OP_MULT,                 /**< a * b */
109 	ZSL_MTX_BINARY_OP_DIV,                  /**< a / b */
110 	ZSL_MTX_BINARY_OP_MEAN,                 /**< mean(a, b) */
111 	ZSL_MTX_BINARY_OP_EXPON,                /**< a ^ b */
112 	ZSL_MTX_BINARY_OP_MIN,                  /**< min(a, b) */
113 	ZSL_MTX_BINARY_OP_MAX,                  /**< max(a, b) */
114 	ZSL_MTX_BINARY_OP_EQUAL,                /**< a == b */
115 	ZSL_MTX_BINARY_OP_NEQUAL,               /**< a != b */
116 	ZSL_MTX_BINARY_OP_LESS,                 /**< a < b */
117 	ZSL_MTX_BINARY_OP_GREAT,                /**< a > b */
118 	ZSL_MTX_BINARY_OP_LEQ,                  /**< a <= b */
119 	ZSL_MTX_BINARY_OP_GEQ,                  /**< a >= b */
120 } zsl_mtx_binary_op_t;
121 
122 /** @} */ /* End of MTX_OPERANDS group */
123 
124 /**
125  * @addtogroup MTX_INIT Initialisation
126  *
127  * @brief Functions used to initialise matrices.
128  *
129  * @ingroup MATRICES
130  *  @{ */
131 
132 /**
133  * @brief Function prototype called when applying a set of component-wise unary
134  * operations to a matrix via `zsl_mtx_unary_func`.
135  *
136  * @param m     Pointer to the zsl_mtx to use.
137  * @param i     The row number to write (0-based).
138  * @param j     The column number to write (0-based).
139  *
140  * @return 0 on success, and non-zero error code on failure
141  */
142 typedef int (*zsl_mtx_unary_fn_t)(struct zsl_mtx *m, size_t i, size_t j);
143 
144 /**
145  * @brief Function prototype called when applying a set of component-wise binary
146  * operations using a pair of symmetrical matrices via `zsl_mtx_binary_func`.
147  *
148  * @param ma    Pointer to first zsl_mtx to use in the binary operation.
149  * @param mb    Pointer to second zsl_mtx to use in the binary operation.
150  * @param mc    Pointer to output zsl_mtx used to store results.
151  * @param i     The row number to write (0-based).
152  * @param j     The column number to write (0-based).
153  *
154  * @return 0 on success, and non-zero error code on failure
155  */
156 typedef int (*zsl_mtx_binary_fn_t)(struct zsl_mtx *ma, struct zsl_mtx *mb,
157 				   struct zsl_mtx *mc, size_t i, size_t j);
158 
159 /**
160  * @brief Function prototype called when populating a matrix via `zsl_mtx_init`.
161  *
162  * @param m     Pointer to the zsl_mtx to use.
163  * @param i     The row number to write (0-based).
164  * @param j     The column number to write (0-based).
165  *
166  * @return 0 on success, and non-zero error code on failure
167  */
168 typedef int (*zsl_mtx_init_entry_fn_t)(struct zsl_mtx *m, size_t i, size_t j);
169 
170 /**
171  * @brief Assigns a zero-value to all entries in the matrix.
172  *
173  * @param m     Pointer to the zsl_mtx to use.
174  * @param i     The row number to write (0-based).
175  * @param j     The column number to write (0-based).
176  *
177  * @return 0 on success, and non-zero error code on failure
178  */
179 int zsl_mtx_entry_fn_empty(struct zsl_mtx *m, size_t i, size_t j);
180 
181 /**
182  * @brief Sets the value to '1.0' if the entry is on the diagonal (row=col),
183  * otherwise '0.0'.
184  *
185  * @param m     Pointer to the zsl_mtx to use.
186  * @param i     The row number to write (0-based).
187  * @param j     The column number to write (0-based).
188  *
189  * @return 0 on success, and non-zero error code on failure
190  */
191 int zsl_mtx_entry_fn_identity(struct zsl_mtx *m, size_t i, size_t j);
192 
193 /**
194  * @brief Sets the value to a random number between -1.0 and 1.0.
195  *
196  * @param m     Pointer to the zsl_mtx to use.
197  * @param i     The row number to write (0-based).
198  * @param j     The column number to write (0-based).
199  *
200  * @return 0 on success, and non-zero error code on failure
201  */
202 int zsl_mtx_entry_fn_random(struct zsl_mtx *m, size_t i, size_t j);
203 
204 /**
205  * @brief Initialises matrix 'm' using the specified entry function to
206  * assign values.
207  *
208  * @param m         Pointer to the zsl_mtx to use.
209  * @param entry_fn  The zsl_mtx_init_entry_fn_t instance to call. If this
210  *                  is set to NULL 'zsl_mtx_entry_fn_empty' will be called.
211  *
212  * @return 0 on success, and non-zero error code on failure
213  */
214 int zsl_mtx_init(struct zsl_mtx *m, zsl_mtx_init_entry_fn_t entry_fn);
215 
216 /**
217  * @brief Converts an array of values into a matrix.
218  *
219  * The number of elements in array 'a' must match the number of elements in
220  * matrix 'm' (m.sz_rows * m.sz_cols). As such, 'm' should be a previously
221  * initialised matrix with appropriate values assigned to m.sz_rows and
222  * m.sz_cols. Assumes array values are in row-major order.
223  *
224  * @param m The matrix that the contents of array 'a' should be assigned to.
225  *          The m.sz_rows and m.sz_cols dimensions must match the number of
226  *          elements in 'a', meaning that the matrix should be initialised
227  *          before being passed in to this function.
228  * @param a Pointer to the array containing the values to assign to 'm' in
229  *          row-major order (left-to-right, top-to-bottom). The array will be
230  *          read m.sz_rows * m.sz_cols elements deep.
231  *
232  * @return 0 on success, and non-zero error code on failure
233  */
234 int zsl_mtx_from_arr(struct zsl_mtx *m, zsl_real_t *a);
235 
236 /**
237  * @brief Copies the contents of matrix 'msrc' into matrix 'mdest'.
238  *
239  * @param mdest Pointer to the destination matrix data will be copied to.
240  * @param msrc  Pointer to the source matrix data will be copied from.
241  *
242  * @return 0 on success, and non-zero error code on failure
243  */
244 int zsl_mtx_copy(struct zsl_mtx *mdest, struct zsl_mtx *msrc);
245 
246 /** @} */ /* End of MTX_INIT group */
247 
248 /**
249  * @addtogroup MTX_DATACCESS Data Access
250  *
251  * @brief Functions used to access or modify matrix rows, columns or
252  *        coefficients.
253  *
254  * @ingroup MATRICES
255  *  @{ */
256 
257 /**
258  * @brief Gets a single value from the specified row (i) and column (j).
259  *
260  * @param m     Pointer to the zsl_mtx to use.
261  * @param i     The row number to read (0-based).
262  * @param j     The column number to read (0-based).
263  * @param x     Pointer to where the value should be stored.
264  *
265  * @return  0 if everything executed correctly, or -EINVAL on an out of
266  *          bounds error.
267  */
268 int zsl_mtx_get(struct zsl_mtx *m, size_t i, size_t j, zsl_real_t *x);
269 
270 /**
271  * @brief Sets a single value at the specified row (i) and column (j).
272  *
273  * @param m     Pointer to the zsl_mtx to use.
274  * @param i     The row number to update (0-based).
275  * @param j     The column number to update (0-based).
276  * @param x     The value to assign.
277  *
278  * @return  0 if everything executed correctly, or -EINVAL on an out of
279  *          bounds error.
280  */
281 int zsl_mtx_set(struct zsl_mtx *m, size_t i, size_t j, zsl_real_t x);
282 
283 /**
284  * @brief Gets the contents of row 'i' from matrix 'm', assigning the array
285  *        of data to 'v'.
286  *
287  * @param m     Pointer to the zsl_mtx to use.
288  * @param i     The row number to read (0-based).
289  * @param v     Pointer to the array where the row vector should be written.
290  *              Must be at least m->sz_cols elements long!
291  *
292  * @return  0 if everything executed correctly, otherwise an appropriate
293  *          error code.
294  */
295 int zsl_mtx_get_row(struct zsl_mtx *m, size_t i, zsl_real_t *v);
296 
297 /**
298  * @brief Sets the contents of row 'i' in matrix 'm', assigning the values
299  *        found in array 'v'.
300  *
301  * @param m     Pointer to the zsl_mtx to use.
302  * @param i     The row number to write to (0-based).
303  * @param v     Pointer to the array where the row vector data is stored.
304  *              Must be at least m->sz_cols elements long!
305  *
306  * @return  0 if everything executed correctly, otherwise an appropriate
307  *          error code.
308  */
309 int zsl_mtx_set_row(struct zsl_mtx *m, size_t i, zsl_real_t *v);
310 
311 /**
312  * @brief Gets the contents of column 'j' from matrix 'm', assigning the array
313  *        of data to 'v'.
314  *
315  * @param m     Pointer to the zsl_mtx to use.
316  * @param j     The column number to read (0-based).
317  * @param v     Pointer to the array where the column vector should be written.
318  *              Must be at least m->sz_rows elements long!
319  *
320  * @return  0 if everything executed correctly, otherwise an appropriate
321  *          error code.
322  */
323 int zsl_mtx_get_col(struct zsl_mtx *m, size_t j, zsl_real_t *v);
324 
325 /**
326  * @brief Sets the contents of column 'j' in matrix 'm', assigning the values
327  *        found in array 'v'.
328  *
329  * @param m     Pointer to the zsl_mtx to use.
330  * @param j     The column number to write to (0-based).
331  * @param v     Pointer to the array where the column vector data is stored.
332  *              Must be at least m->sz_rows elements long!
333  *
334  * @return  0 if everything executed correctly, otherwise an appropriate
335  *          error code.
336  */
337 int zsl_mtx_set_col(struct zsl_mtx *m, size_t j, zsl_real_t *v);
338 
339 /** @} */ /* End of MTX_DATAACCESS group */
340 
341 /**
342  * @ingroup MTX_OPERANDS
343  *  @{ */
344 
345 /**
346  * @brief Applies a unary operand on every coefficient in matrix 'm'.
347  *
348  * @param m         Pointer to the zsl_mtx to use.
349  * @param op        The unary operation to apply to each coefficient.
350  *
351  * @return 0 on success, and non-zero error code on failure
352  */
353 int zsl_mtx_unary_op(struct zsl_mtx *m, zsl_mtx_unary_op_t op);
354 
355 /**
356  * @brief Applies a unary function on every coefficient in matrix 'm', using the
357  * specified 'zsl_mtx_apply_unary_fn_t' instance.
358  *
359  * @param m         Pointer to the zsl_mtx to use.
360  * @param fn        The zsl_mtx_unary_fn_t instance to call.
361  *
362  * @return 0 on success, and non-zero error code on failure
363  */
364 int zsl_mtx_unary_func(struct zsl_mtx *m, zsl_mtx_unary_fn_t fn);
365 
366 /**
367  * @brief Applies a component-wise binary operation on every coefficient in
368  * symmetrical matrices 'ma' and 'mb', with the results being stored in the
369  * identically shaped `mc` matrix.
370  *
371  * @param ma        Pointer to first zsl_mtx to use in the binary operation.
372  * @param mb        Pointer to second zsl_mtx to use in the binary operation.
373  * @param mc        Pointer to output zsl_mtx used to store results.
374  * @param op        The binary operation to apply to each coefficient.
375  *
376  * @return 0 on success, and non-zero error code on failure
377  */
378 int zsl_mtx_binary_op(struct zsl_mtx *ma, struct zsl_mtx *mb,
379 		      struct zsl_mtx *mc, zsl_mtx_binary_op_t op);
380 
381 /**
382  * @brief Applies a component-wise binary operztion on every coefficient in
383  * symmetrical matrices 'ma' and 'mb', with the results  being stored in the
384  * identically shaped 'mc' matrix. The actual binary operation is executed
385  * using the specified 'zsl_mtx_binary_fn_t' callback.
386  *
387  * @param ma        Pointer to first zsl_mtx to use in the binary operation.
388  * @param mb        Pointer to second zsl_mtx to use in the binary operation.
389  * @param mc        Pointer to output zsl_mtx used to store results.
390  * @param fn        The zsl_mtx_binary_fn_t instance to call.
391  *
392  * @return 0 on success, and non-zero error code on failure
393  */
394 int zsl_mtx_binary_func(struct zsl_mtx *ma, struct zsl_mtx *mb,
395 			struct zsl_mtx *mc, zsl_mtx_binary_fn_t fn);
396 
397 /** @} */ /* End of MTX_OPERANDS group */
398 
399 /**
400  * @addtogroup MTX_BASICMATH Basic Math
401  *
402  * @brief Basic mathematical operations for matrices (add, substract, etc.).
403  *
404  * @ingroup MATRICES
405  *  @{ */
406 
407 /**
408  * @brief Adds matrices 'ma' and 'mb', assigning the output to 'mc'.
409  *        Matrices 'ma', 'mb' and 'mc' must all be identically shaped.
410  *
411  * @param ma    Pointer to the first input zsl_mtx.
412  * @param mb    Pointer to the second input zsl_mtx.
413  * @param mc    Pointer to the output zsl_mtx.
414  *
415  * @return  0 if everything executed correctly, or -EINVAL if the three
416  *          matrices are not all identically shaped.
417  */
418 int zsl_mtx_add(struct zsl_mtx *ma, struct zsl_mtx *mb, struct zsl_mtx *mc);
419 
420 /**
421  * @brief Adds matrices 'ma' and 'mb', assigning the output to 'ma'.
422  *        Matrices 'ma', and 'mb' must be identically shaped.
423  *
424  * @param ma    Pointer to the first input zsl_mtx. This matrix will be
425  *              overwritten with the results of the addition operations!
426  * @param mb    Pointer to the second input zsl_mtx.
427  *
428  * @warning     This function is destructive to 'ma'!
429  *
430  * @return  0 if everything executed correctly, or -EINVAL if the two input
431  *          matrices are not identically shaped.
432  */
433 int zsl_mtx_add_d(struct zsl_mtx *ma, struct zsl_mtx *mb);
434 
435 /**
436  * @brief Adds the values of row 'j' to row 'i' in matrix 'm'. This operation
437  *        is destructive for row 'i'.
438  *
439  * @param m     Pointer to the zsl_mtx to use.
440  * @param i     The first row number to add (0-based).
441  * @param j     The second row number to add (0-based).
442  *
443  * @return  0 if everything executed correctly, or -EINVAL on an out of
444  *          bounds error.
445  */
446 int zsl_mtx_sum_rows_d(struct zsl_mtx *m, size_t i, size_t j);
447 
448 /**
449  * @brief This function takes the coefficients of row 'j' and multiplies them
450  *        by scalar 's', then adds the resulting coefficient to the parallel
451  *        element in row 'i'. Row 'i' will be modified in this operation.
452  *
453  * This function implements a key mechanism of Gauss–Jordan elimination, as can
454  * be seen in @ref zsl_mtx_gauss_elim.
455  *
456  * @param m     Pointer to the zsl_mtx to use.
457  * @param i     The row number to update (0-based).
458  * @param j     The row number to scale and then add to 'i' (0-based).
459  * @param s     The scalar value to apply to the values in row 'j'.
460  *
461  * @return  0 if everything executed correctly, otherwise an appropriate
462  *          error code.
463  */
464 int zsl_mtx_sum_rows_scaled_d(struct zsl_mtx *m, size_t i, size_t j,
465 			      zsl_real_t s);
466 
467 /**
468  * @brief Subtracts matrices 'mb' from 'ma', assigning the output to 'mc'.
469  *        Matrices 'ma', 'mb' and 'mc' must all be identically shaped.
470  *
471  * @param ma    Pointer to the first input zsl_mtx.
472  * @param mb    Pointer to the second input zsl_mtx.
473  * @param mc    Pointer to the output zsl_mtx.
474  *
475  * @return  0 if everything executed correctly, or -EINVAL if the three
476  *          matrices are not all identically shaped.
477  */
478 int zsl_mtx_sub(struct zsl_mtx *ma, struct zsl_mtx *mb, struct zsl_mtx *mc);
479 
480 /**
481  * @brief Subtracts matrix 'mb' from 'ma', assigning the output to 'ma'.
482  *        Matrices 'ma', and 'mb' must be identically shaped.
483  *
484  * @param ma    Pointer to the first input zsl_mtx. This matrix will be
485  *              overwritten with the results of the subtraction operations!
486  * @param mb    Pointer to the second input zsl_mtx.
487  *
488  * @warning     This function is destructive to 'ma'!
489  *
490  * @return  0 if everything executed correctly, or -EINVAL if the two input
491  *          matrices are not identically shaped.
492  */
493 int zsl_mtx_sub_d(struct zsl_mtx *ma, struct zsl_mtx *mb);
494 
495 /**
496  * @brief Multiplies matrix 'ma' by 'mb', assigning the output to 'mc'.
497  *        Matrices 'ma' and 'mb' must be compatibly shaped, meaning that
498  *        'ma' must have the same numbers of columns as there are rows
499  *        in 'mb'.
500  *
501  * @param ma    Pointer to the first input zsl_mtx.
502  * @param mb    Pointer to the second input zsl_mtx.
503  * @param mc    Pointer to the output zsl_mtx.
504  *
505  * @return  0 if everything executed correctly, or -EINVAL if the input
506  *          matrices are not compatibly shaped.
507  */
508 int zsl_mtx_mult(struct zsl_mtx *ma, struct zsl_mtx *mb, struct zsl_mtx *mc);
509 
510 /**
511  * @brief Multiplies matrix 'ma' by 'mb', assigning the output to 'ma'.
512  *        Matrices 'ma' and 'mb' must be compatibly shaped, meaning that
513  *        'ma' must have the same numbers of columns as there are rows
514  *        in 'mb'. To use this function, 'mb' must be a square matrix.
515  *        This function is destructive.
516  *
517  * @param ma    Pointer to the first input zsl_mtx.
518  * @param mb    Pointer to the second input zsl_mtx.
519  *
520  * @return  0 if everything executed correctly, or -EINVAL if the input
521  *          matrices are not compatibly shaped.
522  */
523 int zsl_mtx_mult_d(struct zsl_mtx *ma, struct zsl_mtx *mb);
524 
525 /**
526  * @brief Multiplies all elements in matrix 'm' by scalar value 's'.
527  *
528  * @param m     Pointer to the zsl_mtz to adjust.
529  * @param s     The scalar value to multiply elements in matrix 'm' with.
530  *
531  * @return  0 if everything executed correctly, otherwise an appropriate
532  *          error code.
533  */
534 int zsl_mtx_scalar_mult_d(struct zsl_mtx *m, zsl_real_t s);
535 
536 /**
537  * @brief Multiplies the elements of row 'i' in matrix 'm' by scalar 's'.
538  *
539  * @param m     Pointer to the zsl_mtx to use.
540  * @param i     The row number to multiply by scalar 's' (0-based).
541  * @param s     The scalar to use when multiplying elements of row 'i'.
542  *
543  * @return  0 if everything executed correctly, or -EINVAL on an out of
544  *          bounds error.
545  */
546 int zsl_mtx_scalar_mult_row_d(struct zsl_mtx *m, size_t i, zsl_real_t s);
547 
548 /** @} */ /* End of MTX_BASICMATH group */
549 
550 /**
551  * @addtogroup MTX_TRANSFORMATIONS Transformation
552  *
553  * @brief Transformation functions for matrices (transpose, inverse, guassian
554  *        elimination, etc.).
555  *
556  * @ingroup MATRICES
557  *  @{ */
558 
559 /**
560  * @brief Transposes the matrix 'ma' into matrix 'mb'. Note that output
561  *        matrix 'mb' must have 'ma->sz_rows' columns, and 'ma->sz_cols' rows.
562  *
563  * @param ma    Pointer to the input matrix to transpose.
564  * @param mb    Pointer to the output zsl_mtz.
565  *
566  * @return  0 if everything executed correctly, or -EINVAL if ma and mb are
567  *          not compatibly shaped.
568  */
569 int zsl_mtx_trans(struct zsl_mtx *ma, struct zsl_mtx *mb);
570 
571 /**
572  * @brief Calculates the ajoint matrix, based on the input 3x3 matrix 'm'.
573  *
574  * @param m     The input 3x3 square matrix to use.
575  * @param ma    The output 3x3 square matrix the adjoint values will be
576  *              assigned to.
577  *
578  * @return  0 if everything executed correctly, or -EINVAL if this isn't a
579  *          3x3 square matrix.
580  */
581 int zsl_mtx_adjoint_3x3(struct zsl_mtx *m, struct zsl_mtx *ma);
582 
583 /**
584  * @brief Calculates the ajoint matrix, based on the input square matrix 'm'.
585  *
586  * @param m     The input square matrix to use.
587  * @param ma    The output square matrix the adjoint values will be assigned to.
588  *
589  * @return  0 if everything executed correctly, or -EINVAL if this isn't a
590  *          square matrix.
591  */
592 int zsl_mtx_adjoint(struct zsl_mtx *m, struct zsl_mtx *ma);
593 
594 #ifndef CONFIG_ZSL_SINGLE_PRECISION
595 /**
596  * @brief Calculates the wedge product of n-1 vectors of size n, which are the
597  *        rows of the matrix 'm'. This n-1 vectors must be linearly independent.
598  *
599  * The wedge product is an extension of the cross product for dimension greater
600  * than 3. Given a set of n-1 vectors of size n, the wedge product calculates
601  * a n-dimensional vector that is perpendicular to all the others.
602  *
603  * @param m     The input (n-1) x n matrix, with n > 3, whose rows are the
604  *              linearly independent vectors to use in the wedge product.
605  * @param v     The output vector of dimension n, perpendicular to all the
606  *              input vectors.
607  *
608  * @return  0 if everything executed correctly, or -EINVAL if n > 3, or if
609  *          the input matrix isn't of the form (n-1) x n.
610  */
611 int zsl_mtx_vec_wedge(struct zsl_mtx *m, struct zsl_vec *v);
612 #endif
613 
614 /**
615  * @brief Removes row 'i' and column 'j' from square matrix 'm', assigning the
616  *        remaining elements in the matrix to 'mr'.
617  *
618  * @param m     The input nxn square matrix to use.
619  * @param mr    The output (n-1)x(n-1) square matrix.
620  * @param i     The row number to remove (0-based).
621  * @param j     The column number to remove (0-based).
622  *
623  * @return  0 if everything executed correctly, or -EINVAL if this isn't a
624  *          square matrix.
625  */
626 int zsl_mtx_reduce(struct zsl_mtx *m, struct zsl_mtx *mr, size_t i, size_t j);
627 
628 /* NOTE: This is used for household method/QR. Should it be in the main lib? */
629 /**
630  * @brief   Reduces the number of rows/columns in the input square matrix 'm'
631  *          to match the shape of 'mred', where mred < m. Rows/cols will be
632  *          removed starting on the left and upper vectors.
633  *
634  * @param m     Pointer to the input square matrix.
635  * @param mred  Pointer the the reduced output square matrix.
636  * @param place1 Pointer to first placeholder matrix, it must have same size of m.
637  * @param place2 Pointer to second placeholder matrix, it must have same size of m.
638  *
639  * @return  0 if everything executed correctly, otherwise -EAGAIN to instruct
640  * 			caller to call this method again because operation is not done yet
641  *
642  * @note this method should be called iteratively until it returns 0
643  */
644 int zsl_mtx_reduce_iter(struct zsl_mtx *m, struct zsl_mtx *mred,
645 				struct zsl_mtx *place1, struct zsl_mtx *place2);
646 
647 /* NOTE: This is used for household method/QR. Should it be in the main lib? */
648 /**
649  * @brief Augments the input square matrix with additional rows and columns,
650  *        based on the size 'diff' between m and maug (where maug > m). New rows
651  *        and columns are assigned values based on an identity matrix, meaning
652  *        1.0 on the new diagonal values and 0.0 above and below the diagonal.
653  *
654  * @param m     Pointer to the input square matrix.
655  * @param maug  Pointer the the augmented output square matrix.
656  *
657  * @return  0 if everything executed correctly, otherwise an appropriate
658  *          error code.
659  */
660 int zsl_mtx_augm_diag(struct zsl_mtx *m, struct zsl_mtx *maug);
661 
662 /**
663  * @brief Calculates the determinant of the input 3x3 matrix 'm'.
664  *
665  * @param m     The input 3x3 square matrix to use.
666  * @param d     The determinant of 3x3 square matrix m.
667  *
668  * @return  0 on success, or -EINVAL if this isn't a 3x3 square matrix.
669  */
670 int zsl_mtx_deter_3x3(struct zsl_mtx *m, zsl_real_t *d);
671 
672 /**
673  * @brief Calculates the determinant of the input square matrix 'm'.
674  *
675  * @param m     The input square matrix to use.
676  * @param d     The determinant of square matrix m.
677  *
678  * @return  0 if everything executed correctly, or -EINVAL if this isn't a
679  *          square matrix.
680  */
681 int zsl_mtx_deter(struct zsl_mtx *m, zsl_real_t *d);
682 
683 /**
684  * @brief Given the element (i,j) in matrix 'm', this function performs
685  *        gaussian elimination by adding row 'i' to the other rows until
686  *        all of the elements in column 'j' are equal to 0.0, aside from the
687  *        element at position (i, j). The result of this process will be
688  *        assigned to matrix 'mg'.
689  *
690  * @param m     Pointer to input zsl_mtx to use.
691  * @param mg    Pointer to gaussian form output matrix.
692  * @param mi    Pointer to the identity output matrix.
693  * @param i     The row number of the element to use (0-based).
694  * @param j     The column number of the element to use (0-based).
695  *
696  * @return 0 on success, and non-zero error code on failure
697  */
698 int zsl_mtx_gauss_elim(struct zsl_mtx *m, struct zsl_mtx *mg,
699 		       struct zsl_mtx *mi, size_t i, size_t j);
700 
701 /**
702  * @brief Given the element (i,j) in matrix 'm', this function performs
703  *        gaussian elimination by adding row 'i' to the other rows until
704  *        all of the elements in column 'j' are equal to 0.0, aside from the
705  *        element at position (i, j). This function is destructive and will
706  *        modify the contents of m.
707  *
708  * @param m     Pointer to zsl_mtx to use.
709  * @param mi    Pointer to the identity output matrix.
710  * @param i     The row number of the element to use (0-based).
711  * @param j     The column number of the element to use (0-based).
712  *
713  * @return 0 on success, and non-zero error code on failure
714  */
715 int zsl_mtx_gauss_elim_d(struct zsl_mtx *m, struct zsl_mtx *mi,
716 			 size_t i, size_t j);
717 
718 /**
719  * @brief Given matrix 'm', puts the matrix into echelon form using
720  *        Gauss-Jordan reduction.
721  *
722  * @param m     Pointer to the input square matrix to use.
723  * @param mi    Pointer to the identity output matrix.
724  * @param mg    Pointer to the output square matrix in echelon form.
725  *
726  * @return 0 on success, and non-zero error code on failure
727  */
728 int zsl_mtx_gauss_reduc(struct zsl_mtx *m, struct zsl_mtx *mi,
729 			struct zsl_mtx *mg);
730 
731 /**
732  * @brief Updates the values of every column vector in input matrix 'm' to have
733  *        unitary values.
734  *
735  * @param m      Pointer to the input matrix.
736  * @param mnorm  Pointer to the output matrix where the columns are unitary
737  *               vectors.
738  *
739  * @return  0 if everything executed correctly, otherwise an appropriate
740  *          error code.
741  */
742 int zsl_mtx_cols_norm(struct zsl_mtx *m, struct zsl_mtx *mnorm);
743 
744 /**
745  * @brief Performs the Gram-Schmidt algorithm on the set of column vectors in
746  *        matrix 'm'. This algorithm calculates a set of orthogonal vectors in
747  *        the same vectorial space as the original vectors.
748  *
749  * @param m     Pointer to the input matrix containing the vector data.
750  * @param mort  Pointer to the output matrix containing the orthogonal vector
751  *              data.
752  *
753  * @return  0 if everything executed correctly, otherwise an appropriate
754  *          error code.
755  */
756 int zsl_mtx_gram_schmidt(struct zsl_mtx *m, struct zsl_mtx *mort);
757 
758 /**
759  * @brief Normalises elements in matrix m such that the element at position
760  *        (i, j) is equal to 1.0.
761  *
762  * @param m     Pointer to input zsl_mtx to use.
763  * @param mn    Pointer to normalised output zsl_mtx.
764  * @param mi    Pointer to the output identity zsl_mtx.
765  * @param i     The row number of the element to use (0-based).
766  * @param j     The column number of the element to use (0-based).
767  *
768  * @return 0 on success, and non-zero error code on failure
769  */
770 int zsl_mtx_norm_elem(struct zsl_mtx *m, struct zsl_mtx *mn, struct zsl_mtx *mi,
771 		      size_t i, size_t j);
772 
773 /**
774  * @brief Normalises elements in matrix m such that the element at position
775  *        (i, j) is equal to 1.0. This function is destructive and will
776  *        modify the contents of m.
777  *
778  * @param m     Pointer to zsl_mtx to use.
779  * @param mi    Pointer to the output identity zsl_mtx.
780  * @param i     The row number of the element to use (0-based).
781  * @param j     The column number of the element to use (0-based).
782  *
783  * @return 0 on success, and non-zero error code on failure
784  */
785 int zsl_mtx_norm_elem_d(struct zsl_mtx *m, struct zsl_mtx *mi,
786 			size_t i, size_t j);
787 
788 /**
789  * @brief Calculates the inverse of 3x3 matrix 'm'. If the determinant of
790  *        'm' is zero, an identity matrix will be returned via 'mi'.
791  *
792  * @param m     The input 3x3 matrix to use.
793  * @param mi    The output inverse 3x3 matrix.
794  *
795  * @return  0 if everything executed correctly, or -EINVAL if this isn't a
796  *          3x3 matrix.
797  */
798 int zsl_mtx_inv_3x3(struct zsl_mtx *m, struct zsl_mtx *mi);
799 
800 /**
801  * @brief Calculates the inverse of square matrix 'm'.
802  *
803  * @param m     The input square matrix to use.
804  * @param mi    The output inverse square matrix.
805  *
806  * @return  0 if everything executed correctly, or -EINVAL if this isn't a
807  *          square matrix.
808  */
809 int zsl_mtx_inv(struct zsl_mtx *m, struct zsl_mtx *mi);
810 
811 /**
812  * @brief Calculates the Cholesky decomposition of a symmetric square matrix
813  *        using the Cholesky–Crout algorithm.
814  *
815  * Computing the Cholesky decomposition of a symmetric square matrix M consists
816  * in finding a matrix L such that M = L * Lt (L multiplied by its transpose).
817  *
818  * @param m     The input symmetric square matrix to use.
819  * @param l     The output lower triangular matrix.
820  *
821  * @return  0 if everything executed correctly, or -EINVAL if 'm' isn't a
822  *          symmetric square matrix.
823  */
824 int zsl_mtx_cholesky(struct zsl_mtx *m, struct zsl_mtx *l);
825 
826 /**
827  * @brief Balances the square matrix 'm', a process in which the eigenvalues of
828  *        the output matrix are the same as the eigenvalues of the input matrix.
829  *
830  * @param m     The input square matrix to use.
831  * @param mout  The output balanced matrix.
832  *
833  * @return  0 if everything executed correctly, otherwise an appropriate
834  *          error code.
835  */
836 int zsl_mtx_balance(struct zsl_mtx *m, struct zsl_mtx *mout);
837 
838 /**
839  * @brief Calculates the householder reflection of 'm'. Used as part of QR
840  *        decomposition. When 'hessenberg' is active, it calculates the
841  *        householder reflection but without using the first line of 'm'.
842  *
843  * @param m            Pointer to the input matrix to use.
844  * @param hessenberg   If set to true, the first line in 'm' is ignored.
845  * @param h            Pointer to the output square matrix where the
846  *                     values of the householder reflection should be assigned.
847  *
848  * @return  0 if everything executed correctly, otherwise an appropriate
849  *          error code.
850  */
851 int zsl_mtx_householder(struct zsl_mtx *m, struct zsl_mtx *h, bool hessenberg);
852 
853 /**
854  * @brief If 'hessenberg' is set to false, this function performs the QR
855  *        decomposition, which is a factorisation of matrix 'm' into an
856  *        orthogonal matrix (q) and an upper triangular matrix (r). If
857  *        'hessenberg' is set to true, this function puts the matrix 'm' into
858  *        hessenberg form. This function uses the householder reflections.
859  *
860  * One of the uses of this function is to make use of the householder method to
861  * perform the QR decomposition, which introduces the zeros below the diagonal
862  * of matrix 'r'. Other algorithms exist, such as the Gram-Schmidt process,
863  * but they tend to be less stable than the householder method for a similar
864  * computational cost.
865  *
866  * @param m     Pointer to the input square matrix.
867  * @param q     Pointer to the output orthoogonal square matrix.
868  * @param r     Pointer to the output upper triangular square matrix or
869  *              hessenberg matrix if set to true.
870  * @param hessenberg Sets the matrix to hessenberg format if 'true'.
871  *
872  * @return  0 if everything executed correctly, otherwise an appropriate
873  *          error code.
874  */
875 int zsl_mtx_qrd(struct zsl_mtx *m, struct zsl_mtx *q, struct zsl_mtx *r,
876 		bool hessenberg);
877 
878 #ifndef CONFIG_ZSL_SINGLE_PRECISION
879 /**
880  * @brief Computes recursively the QR decompisition method to put the input
881  *        square matrix into upper triangular form.
882  *
883  * @param m     The input square matrix to use when performing the QR
884  *              decomposition.
885  * @param mout  The output upper triangular square matrix where the results
886  *              should be stored.
887  * @param iter  The number of times that 'zsl_mtx_qrd' should be called.
888  *
889  * @return  0 if everything executed correctly, otherwise an appropriate
890  *          error code.
891  */
892 int zsl_mtx_qrd_iter(struct zsl_mtx *m, struct zsl_mtx *mout, size_t iter);
893 #endif
894 
895 #ifndef CONFIG_ZSL_SINGLE_PRECISION
896 /**
897  * @brief   Calculates the eigenvalues for input matrix 'm' using QR
898  *          decomposition recursively. The output vector will only contain real
899  *          eigenvalues, even if the input matrix has complex eigenvalues.
900  *
901  * @param m     The input square matrix to use.
902  * @param v     The placeholder for the output vector where the real eigenvalues
903  *              should be stored.
904  * @param iter  The number of times that 'zsl_mtx_qrd' should be called
905  *              during the QR decomposition phase.
906  *
907  * NOTE: Large values required more iterations to get precise results, and
908  * some trial and error may be required to find the right balance of
909  * iterations versus processing time.
910  *
911  * @return  0 if everything executed correctly, otherwise an appropriate
912  *          error code. If -ECOMPLEXVAL is returned, it means that complex
913  *          numbers were detected in the output eigenvalues.
914  */
915 int zsl_mtx_eigenvalues(struct zsl_mtx *m, struct zsl_vec *v, size_t iter);
916 #endif
917 
918 #ifndef CONFIG_ZSL_SINGLE_PRECISION
919 /**
920  * @brief Calcualtes the set of eigenvectors for input matrix 'm', using the
921  *        specified number of iterations to find a balance between precision and
922  *        processing effort. Optionally, the output eigenvectors can be
923  *        orthonormalised.
924  *
925  * @param m             The input square matrix to use.
926  * @param mev           The placeholder for the output square matrix where the
927  *                      eigenvectors should be stored as column vectors.
928  * @param iter          The number of times that 'zsl_mtx_qrd' should be called.
929  *                      during the QR decomposition phase.
930  * @param orthonormal   If set to true, the output matrix 'mev' will be
931  *                      orthonormalised.
932  *
933  * NOTE: Large values required more iterations to get precise results, and
934  * some trial and error may be required to find the right balance of
935  * iterations versus processing time.
936  *
937  * @return  0 if everything executed correctly, otherwise an appropriate
938  *          error code. If the number of calcualted eigenvectors is less
939  *          than the columns in 'm', EEIGENSIZE will be returned.
940  */
941 int zsl_mtx_eigenvectors(struct zsl_mtx *m, struct zsl_mtx *mev, size_t iter,
942 			 bool orthonormal);
943 #endif
944 
945 #ifndef CONFIG_ZSL_SINGLE_PRECISION
946 /**
947  * @brief Performs singular value decomposition, converting input matrix 'm'
948  *        into matrices 'u', 'e', and 'v'.
949  *
950  * @param m     The input mxn matrix to use.
951  * @param u     The placeholder for the output mxm matrix u.
952  * @param e     The placeholder for the output mxn matrix sigma.
953  * @param v     The placeholder for the output nxn matrix v.
954  * @param iter  The number of times that 'zsl_mtx_qrd' should be called.
955  *              during the QR decomposition phase.
956  *
957  * @return  0 if everything executed correctly, otherwise an appropriate
958  *          error code.
959  */
960 int zsl_mtx_svd(struct zsl_mtx *m, struct zsl_mtx *u, struct zsl_mtx *e,
961 		struct zsl_mtx *v, size_t iter);
962 #endif
963 
964 #ifndef CONFIG_ZSL_SINGLE_PRECISION
965 /**
966  * @brief   Performs the pseudo-inverse (aka pinv or Moore-Penrose inverse)
967  *          on input matrix 'm'.
968  *
969  * @param m     The input mxn matrix to use.
970  * @param pinv  The placeholder for the output pseudo inverse nxm matrix.
971  * @param iter  The number of times that 'zsl_mtx_qrd' should be called.
972  *              during the QR decomposition phase.
973  *
974  * @return  0 if everything executed correctly, otherwise an appropriate
975  *          error code.
976  */
977 int zsl_mtx_pinv(struct zsl_mtx *m, struct zsl_mtx *pinv, size_t iter);
978 #endif
979 
980 /** @} */ /* End of MTX_TRANSFORMATIONS group */
981 
982 /**
983  * @addtogroup MTX_LIMITS Limits
984  *
985  * @brief Min/max helpers to determine the range of the matrice's coefficients.
986  *
987  * @ingroup MATRICES
988  *  @{ */
989 
990 /**
991  * @brief Traverses the matrix elements to find the minimum element value.
992  *
993  * @param m     Pointer to the zsl_mtz to traverse.
994  * @param x     The minimum element value found in matrix 'm'.
995  *
996  * @return  0 if everything executed correctly, otherwise an appropriate
997  *          error code.
998  */
999 int zsl_mtx_min(struct zsl_mtx *m, zsl_real_t *x);
1000 
1001 /**
1002  * @brief Traverses the matrix elements to find the maximum element value.
1003  *
1004  * @param m     Pointer to the zsl_mtz to traverse.
1005  * @param x     The maximum element value found in matrix 'm'.
1006  *
1007  * @return  0 if everything executed correctly, otherwise an appropriate
1008  *          error code.
1009  */
1010 int zsl_mtx_max(struct zsl_mtx *m, zsl_real_t *x);
1011 
1012 /**
1013  * @brief Traverses the matrix elements to find the (i,j) index of the minimum
1014  *        element value. If multiple identical minimum values are founds,
1015  *        the (i, j) index values returned will refer to the first element.
1016  *
1017  * @param m     Pointer to the zsl_mtz to traverse.
1018  * @param i     Pointer to the row index of the minimum element value found
1019  *              in matrix 'm'.
1020  * @param j     Pointer to the column index of the minimum element value
1021  *              found in matrix 'm'.
1022  *
1023  * @return  0 if everything executed correctly, otherwise an appropriate
1024  *          error code.
1025  */
1026 int zsl_mtx_min_idx(struct zsl_mtx *m, size_t *i, size_t *j);
1027 
1028 /**
1029  * @brief Traverses the matrix elements to find the (i,j) index of the maximum
1030  *        element value. If multiple identical maximum values are founds,
1031  *        the (i, j) index values returned will refer to the first element.
1032  *
1033  * @param m     Pointer to the zsl_mtz to traverse.
1034  * @param i     Pointer to the row index of the maximum element value found
1035  *              in matrix 'm'.
1036  * @param j     Pointer to the column index of the maximum element value
1037  *              found in matrix 'm'.
1038  *
1039  * @return  0 if everything executed correctly, otherwise an appropriate
1040  *          error code.
1041  */
1042 int zsl_mtx_max_idx(struct zsl_mtx *m, size_t *i, size_t *j);
1043 
1044 /** @} */ /* End of MTX_LIMITS group */
1045 
1046 /**
1047  * @addtogroup MTX_COMPARISON Comparison
1048  *
1049  * @brief Functions used to compare or verify matrices.
1050  *
1051  * @ingroup MATRICES
1052  *  @{ */
1053 
1054 /**
1055  * @brief Checks if two matrices are identical in shape and content.
1056  *
1057  * @param ma The first matrix.
1058  * @param mb The second matrix.
1059  *
1060  * @return true if the two matrices have the same shape and values,
1061  *         otherwise false.
1062  */
1063 bool zsl_mtx_is_equal(struct zsl_mtx *ma, struct zsl_mtx *mb);
1064 
1065 /**
1066  * @brief Checks if all elements in matrix m are >= zero.
1067  *
1068  * @param m The matrix to check.
1069  *
1070  * @return true if the all matrix elements are zero or positive,
1071  *         otherwise false.
1072  */
1073 bool zsl_mtx_is_notneg(struct zsl_mtx *m);
1074 
1075 /**
1076  * @brief Checks if the square input matrix is symmetric.
1077  *
1078  * @param m The matrix to check.
1079  *
1080  * @return true if the matrix is symmetric, otherwise false.
1081  */
1082 bool zsl_mtx_is_sym(struct zsl_mtx *m);
1083 
1084 /** @} */ /* End of MTX_COMPARISON group */
1085 
1086 /**
1087  * @addtogroup MTX_DISPLAY Display
1088  *
1089  * @brief Functions used to present matrices in a user-friendly format.
1090  *
1091  * @ingroup MATRICES
1092  *  @{ */
1093 
1094 /**
1095  * @brief Printf the supplied matrix using printf in a human-readable manner.
1096  *
1097  * @param m     Pointer to the matrix to print.
1098  *
1099  * @return  0 if everything executed correctly, otherwise an appropriate
1100  *          error code.
1101  */
1102 int zsl_mtx_print(struct zsl_mtx *m);
1103 
1104 // int      zsl_mtx_fprint(FILE *stream, zsl_mtx *m);
1105 
1106 /** @} */ /* End of MTX_DISPLAY group */
1107 
1108 #ifdef __cplusplus
1109 }
1110 #endif
1111 
1112 #endif /* ZEPHYR_INCLUDE_ZSL_MATRICES_H_ */
1113 
1114 /** @} */ /* End of matrices group */
1115