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