blob: f20881fc315bec878d7e95e28752fce205a1220f [file]
/****************************************************************************
* libs/libdsp/lib_matrix.c
*
* SPDX-License-Identifier: Apache-2.0
*
* From: Djordje Vulovic's Extended-Kalman-Filter for STM32
* Licensed as Apache 2.0 to be included on NuttX:
* https://github.com/DjVul/Extended-Kalman-Filter---STM32/issues/1
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <dsp.h>
#include <math.h>
#include <string.h>
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: matrix_add
*
* Description:
* Matrix addition
*
* C (m x n) = A (m x n) + B (m x n)
*
* A Pointer to the first matrix (m x n)
* B Pointer to the second matrix (m x n)
* C Pointer to the result matrix (m x n)
* m Number of rows
* n Number of columns
*
****************************************************************************/
void matrix_add(const float *A, const float *B, float *C,
uint8_t m, uint8_t n)
{
for (uint8_t i = 0; i < m; i++)
{
for (uint8_t j = 0; j < n; j++)
{
C[i * n + j] = A[i * n + j] + B[i * n + j];
}
}
}
/****************************************************************************
* Name: matrix_sub
*
* Description:
* Matrix subtraction
* C (m x n) = A (m x n) - B (m x n)
*
* A Pointer to the first matrix (m x n)
* B Pointer to the second matrix (m x n)
* C Pointer to the result matrix (m x n)
* m Number of rows
* n Number of columns
*
****************************************************************************/
void matrix_sub(const float *A, const float *B, float *C,
uint8_t m, uint8_t n)
{
for (uint8_t i = 0; i < m; i++)
{
for (uint8_t j = 0; j < n; j++)
{
C[i * n + j] = A[i * n + j] - B[i * n + j];
}
}
}
/****************************************************************************
* Name: matrix_mul
*
* Description:
* Matrix multiplication
*
* C (m x n) = A (m x n) * B (m x n)
*
* A Pointer to the first matrix (m x n)
* B Pointer to the second matrix (m x n)
* C Pointer to the result matrix (m x n)
* m Number of rows
* n Number of columns
*
****************************************************************************/
void matrix_mul(const float *A, const float *B, float *C,
uint8_t m, uint8_t n, uint8_t p)
{
for (uint8_t i = 0; i < m; i++)
{
for (uint8_t j = 0; j < p; j++)
{
C[i * p + j] = 0.0f;
for (uint8_t k = 0; k < n; k++)
{
C[i * p + j] += A[i * n + k] * B[k * p + j];
}
}
}
}
/****************************************************************************
* Name: matrix_mul_transpose
*
* Description:
* Matrix multiplication with a transposed matrix
*
* C (m x n) = A (m x n) * B (p x n)^T
*
* A Pointer to the first matrix (m x n)
* B Pointer to the second matrix (p x n) - will be transposed
* C Pointer to the result matrix (m x p)
* m Number of rows in matrix A
* n Number of columns in matrices A and B
* p Number of rows in matrix B (becomes the number of columns
* in the result)
*
****************************************************************************/
void matrix_mul_transpose(const float *A, const float *B, float *C,
uint8_t m, uint8_t n, uint8_t p)
{
for (uint8_t i = 0; i < m; i++)
{
for (uint8_t j = 0; j < p; j++)
{
C[i * p + j] = 0.0f;
for (uint8_t k = 0; k < n; k++)
{
/* B^T is B[j][k] */
C[i * p + j] += A[i * n + k] * B[j * n + k];
}
}
}
}
/****************************************************************************
* Name: matrix_transpose
*
* Description:
* Matrix transposed
*
* B (m x n) = A^T (m x n)^T
*
* A Pointer to the input matrix (m x n)
* B Pointer to the output matrix (n x m)
* m Number of rows in the input matrix
* n Number of columns in the input matrix
*
****************************************************************************/
void matrix_transpose(const float *A, float *B, uint8_t m, uint8_t n)
{
for (uint8_t i = 0; i < m; i++)
{
for (uint8_t j = 0; j < n; j++)
{
B[j * m + i] = A[i * n + j];
}
}
}
/****************************************************************************
* Name: matrix_scalar_mul
*
* Description:
* Matrix-scalar multiplication
*
* B (m x n) = A (m x n) * s
*
* A Pointer to the input matrix (m x n)
* s Scalar value (float)
* B Pointer to the output matrix (m x n)
* m Number of rows
* n Number of columns
*
****************************************************************************/
void matrix_scalar_mul(const float *A, float s, float *B,
uint8_t m, uint8_t n)
{
uint16_t total = (uint16_t) m * n;
uint16_t i;
for (i = 0; i < total; i++)
{
B[i] = A[i] * s;
}
}
/****************************************************************************
* Name: matrix_copy
*
* Description:
* Matrix copy
*
* B (m x n) = A (m x n)
*
* A Pointer to the source matrix (m x n)
* B Pointer to the destination matrix (m x n)
* m Number of rows
* n Number of columns
*
****************************************************************************/
void matrix_copy(const float *A, float *B, uint8_t m, uint8_t n)
{
uint16_t total = (uint16_t) m * n;
memcpy(B, A, total * sizeof(float));
}
/****************************************************************************
* Name: matrix_inv_3x3
*
* Description:
* 3x3 matrix inversion
*
* inv (3x3) = A^-1 (3x3)
*
* A Input matrix (3x3)
* inv Output matrix (3x3) - inverse matrix
*
* Returns:
* 1 if the inversion was successful,
* 0 if the matrix is singular.
*
****************************************************************************/
uint8_t matrix_inv_3x3(const float A[3][3], float inv[3][3])
{
float det = A[0][0] * (A[1][1] * A[2][2] - A[1][2] * A[2][1])
- A[0][1] * (A[1][0] * A[2][2] - A[1][2] * A[2][0])
+ A[0][2] * (A[1][0] * A[2][1] - A[1][1] * A[2][0]);
float inv_det = 1.0f / det;
/* Check whether the matrix is singular */
if (fabsf(det) < 1e-10f)
{
return 0;
}
inv[0][0] = (A[1][1] * A[2][2] - A[1][2] * A[2][1]) * inv_det;
inv[0][1] = (A[0][2] * A[2][1] - A[0][1] * A[2][2]) * inv_det;
inv[0][2] = (A[0][1] * A[1][2] - A[0][2] * A[1][1]) * inv_det;
inv[1][0] = (A[1][2] * A[2][0] - A[1][0] * A[2][2]) * inv_det;
inv[1][1] = (A[0][0] * A[2][2] - A[0][2] * A[2][0]) * inv_det;
inv[1][2] = (A[0][2] * A[1][0] - A[0][0] * A[1][2]) * inv_det;
inv[2][0] = (A[1][0] * A[2][1] - A[1][1] * A[2][0]) * inv_det;
inv[2][1] = (A[0][1] * A[2][0] - A[0][0] * A[2][1]) * inv_det;
inv[2][2] = (A[0][0] * A[1][1] - A[0][1] * A[1][0]) * inv_det;
return 1;
}