Matrix math#
The matrix math software module provides an easy way to use matrices.
It uses an opaque data type uz_matrix_t
that boxes important information about the matrix (e.g., number of rows and column) together with the data.
The module provides common functions, e.g., matrix multiplication, which are called with matrices of the data type uz_matrix_t
, allowing error checking regarding dimensions.
The module does not hold the data of the matrix internally but uses an pointer to the data instead to allow variable length of arrays with one data type without using flexible array member.
The variable holding the data as well as the struct uz_matrix_t
has to be initialized outside of the module since this module is not configured by the Global configuration.
float data[5]={0};
struct uz_matrix_t input_matrix = {0};
uz_matrix_t *input = uz_matrix_init(&input_matrix, data, UZ_MATRIX_SIZE(data), 1, 5);
Warning
Take the storage duration of variables into account for the array as well as the uz_matrix_t struct! Most of the time, use static
storage duration.
Warning
The data can be accessed directly in the array. Do not do this after a uz_matrix_t
instance is coupled with the array by initialization.
Note
The matrix software module has similarities to the Array module but features math functions instead of a box for arrays including their length for different data types.
Matrix definition#
The following matrix definition with the number of columns \(n\) and number of rows \(m\) is used:
Note
Keep in mind that in C everything is 0-indexed while the matrix definitions still use 1-based indexing to be consistent with common math conventions! Thus, \(a_{11}\) is the element with index \([0,0]\) in c-code!
Dimensions#
A pointer to the actual data array has to be supplied uz_matrix_init
.
The array has to be of length \(m \times n\).
The dimension \(n\) (columns
) can be one to generate a column vector \(m \times 1\).
The dimension \(n\) can be one to generate a row vector \(1 \times n\).
The provided array is always an vector with \(m \times n\) elements. The array is split up according to the provided dimensions. It is treated as an matrix in the following way (zero indexing internally):
Note
Keep this in mind when initializing the data array or initialize all elements of the array to zero and use the set functions.
Example#
Each matrix has to be initialized with uz_matrix_init
.
To initialize the following \(3 \times 3\) matrix:
// declare data array static outside of a function to ensure static storage duration and file scope.
static float mat[9]={1,2,3,4,5,6,7,8,9};
struct uz_matrix_t input_matrix = {0};
void uz_matrix_init_3_times_3_matrix(void){
int rows=3; // Row and columns can be automatic storage duration since they are not required after initialization (stored in the module)
int columns=3;
uz_matrix_t* my_matrix=uz_matrix_init(input_matrix,mat,UZ_MATRIX_SIZE(mat),rows,columns);
}
Reference#
-
typedef struct uz_matrix_t uz_matrix_t#
Typedef for uz_matrix_t struct.
-
uz_matrix_t *uz_matrix_init(uz_matrix_t *self, float *data, uint32_t length_of_data, uint32_t rows, uint32_t columns)#
Initialize an uz_matrix.
- Parameters:
self – Pointer to the instance
data – Pointer to the data
length_of_data – Number of data elements calculated by UZ_MATRIX_SIZE makro
rows – Number of rows
columns – Number of columns
- Returns:
uz_matrix_t* Returns an pointer to the instance that was passed
-
uint32_t uz_matrix_get_number_of_rows(uz_matrix_t const *const self)#
Returns the number of rows of the given uz_matrix.
- Parameters:
self – Pointer to a uz_matrix_t instance
- Returns:
uint32_t
-
uint32_t uz_matrix_get_number_of_columns(uz_matrix_t const *const self)#
Returns the number of columns of the given uz_matrix.
- Parameters:
self – Pointer to a uz_matrix_t instance
- Returns:
uint32_t
-
float uz_matrix_get_element_zero_based(uz_matrix_t const *const A, uint32_t row, uint32_t column)#
Get the element row x column of matrix A with zero based indexing.
- Parameters:
A – Matrix object, hast to be ready.
row – Row of element
column – Column of element
- Returns:
float
-
void uz_matrix_set_element_zero_based(uz_matrix_t *const A, float x, uint32_t row, uint32_t column)#
Set the element row x column of matrix A with zero based indexing.
- Parameters:
A – Matrix object
x – Value that the element is set to
row – Row of element to set
column – Column of element to set
-
void uz_matrix_add_scalar(uz_matrix_t *const A, float scalar)#
Adds a scalar to all elements of the matrix A.
- Parameters:
A –
scalar –
-
void uz_matrix_multiply_by_scalar(uz_matrix_t *const A, float scalar)#
Multiplies all elements of the matrix A by a scalar.
- Parameters:
A – Pointer to a uz_matrix_t instance
scalar – Scalar value with which each element of A is multiplied
-
void uz_matrix_apply_function_to_each_element(uz_matrix_t *const A, float (*f)(float))#
Applies a function f, that is passed as a function pointer, to each of the elements.
- Parameters:
A – Pointer to a uz_matrix_t instance
f – Function pointer, function has to accept one float as argument and return one float
-
float uz_matrix_get_max_value(uz_matrix_t const *const A)#
Retruns the value of the biggest element of the matrix.
- Parameters:
A – Pointer to a uz_matrix_t instance
- Returns:
float
-
uint32_t uz_matrix_get_max_index(uz_matrix_t const *const A)#
Returns the index at which position the biggest value is located in the matrix A.
- Parameters:
A – Pointer to a uz_matrix_t instance
- Returns:
uint32_t
-
void uz_matrix_transpose(uz_matrix_t *A)#
Transposes the matrix A.
- Parameters:
A – Pointer to a uz_matrix_t instance
Warning
uz_matrix_transpose uses a variable length array (VLA), which does not comply to the coding rules.
-
void uz_matrix_copy(uz_matrix_t const *const source, uz_matrix_t *const destination)#
Copies the matrix source into the matrix destination. Requires that source and destination have the same length. Rows, columns, and data will be overwritten by this function!
- Parameters:
source – Matrix to be copied
destination – Matrix where the data is copied to
Performance estimation#
The following performance is measured when the functions are called in the, expect for the test code and uz_SystemTime_ISR_Tic()
functions, empty ISR of the R5.
void ISR_Control(void *data)
{
uz_SystemTime_ISR_Tic();
for(uint32_t i=0U;i<10;i++){
function_under_test(A,B,C ); //
}
uz_SystemTime_ISR_Toc();
}
Testing is conducted with compiler optimization set to -O2.
Empty ISR: 2.7 us
Add a 3x3 matrix, code executed 10 times: 5.5 us
elementwise_product of two 10x10 matrix, code executed 10 times: 18 us
matrix_multiply 10x10 matrix, code executed 1 time: 23 us
matrix_multiply 3x3 matrix, code executed 10 times: 14 us
matrix_multiply 10x10 matrix with double data type (not implemented in the software module!), code executed 1 time: 52.8 us
Rough estimation:
Adding a 3x3 matrix takes 0.3 us
Multiplication of a 3x3 matrix takes 1us, of a 10x10 matrix 12 us.
Multiplication of a 10x10 matrix takes 12 us.