Re: Matrisberäkningar med för STM32?
Postat: 1 februari 2019, 18:36:05
Det jag försökte förklara är att GNU octave troligen använder den mer avancerad algoritm med bättre noggrannhet.
Svenskt forum för elektroniksnack.
https://elektronikforumet.com/forum/
Kod: Markera allt
#include <stdio.h>
#include <stdlib.h>
#include "LinearAlgebra/declareFunctions.h"
#include <time.h>
int main() {
clock_t start, end;
float cpu_time_used;
start = clock();
/*
* Create an empty initial matrix with 5 rows and 5 columns
*/
printf("Init a matrix\n");
matrix* A = (matrix*) malloc(sizeof(matrix)); // <--- kan man göra något här så man slipper "malloca" för varje matris?
init(A, 5,5);
/*
* Insert values in to the matrix
*/
float values[5][5] = { { 1, 76, 86, 1, 5 },
{ 1, 5, -6, 0, 3 },
{ -5, 7, 3, 87, 3 },
{ -8, 3, 1, 4, -1 },
{ 7, 9, 1, 28, 4 } };
printf("Create matrix\n");
insert(*values, A);
print(A);
end = clock();
cpu_time_used = ((float) (end - start)) / CLOCKS_PER_SEC;
printf("Total speed was %f,", cpu_time_used);
return EXIT_SUCCESS;
}
Kod: Markera allt
void init(matrix* a, int row, int column) {
a->column = column;
a->row = row;
a->data = (float*) malloc(sizeof(float) * column * row);
// Set all elements to 0
memset(a->data, 0, column * row * sizeof(float));
}
Kod: Markera allt
void insert(float* arr2D, matrix* a) {
int n = a->row;
int m = a->column;
float* ptr = a->data;
// Insert all values
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
*(ptr++) = *((arr2D + i * m) + j);
}
}
}
Kod: Markera allt
void print(matrix* a) {
float* ptr = a->data;
for (int i = 0; i < a->row; i++) {
for (int j = 0; j < a->column; j++) {
printf(" %9.6f", *(ptr++));
}
printf("\n");
}
printf("\n"); // Default new row
}
Kod: Markera allt
matrix* initMatrix(int row, int column) {
matrix* out = (matrix*) malloc(sizeof(matrix));
out->column = column;
out->row = row;
out->data = (float*) malloc(sizeof(float) * column * row);
memset(out->data, 0.0, column * row * sizeof(float));
return out;
}
Kod: Markera allt
float det_cofact_internal();
void cofact(matrix* a, matrix* co) {
int n = a->row;
float* minor_a = a->data;
float* minor_co = co->data;
// Create the minor matrix - Always one size smaller
float minor[(n-1)*(n-1)];
// Starting position
int row = 0;
int column = 0;
int minorCellposition = 0;
// What we do is to create sub matrices for every cell. 3x3 means 9 sub matrices
for (int k = 0; k < n * n; k++) {
// Loop rows
for (int i = 0; i < n; i++) {
// Loop columns
for (int j = 0; j < n; j++) {
// Check if we are not on the "forbidden" row and column
if (i != row && j != column) {
// Insert
minor[minorCellposition] = *((minor_a + i * n) + j);
minorCellposition++; // Next cell
}
}
}
// Insert in our output
*(minor_co++) = pow(-1, row+column)* det_cofact_internal(minor, n-1); //pow is needed because turning minor matrix to cofactor matrix
// Update - Remember n-1 is due to indexing from zero
if(column < n-1){
column++; // Next column
}else{
column = 0;
row++; // Next row
}
// Reset the minor matrix and jump back to cell position 0
memset(minor, 0, sizeof(minor));
minorCellposition = 0;
}
}
/*
* This is the same as det function, but the argument is diffrent!
*/
float det_cofact_internal(float* minor, int n) {
if (n == 1) {
// 1x1 "matrix" - Just return the value
return *(minor);
} else if (n == 2) {
// 2x2 matrix - Easy
return *(minor + 0) * *(minor + 3) - *(minor + 1) * *(minor + 2);
} else if (n == 3) {
// Don't change this! It works fine for 3x3 - Took me long time to write this
return (*(minor + 0)) * (*(minor + 4)) * (*(minor + 8))
+ (*(minor + 1)) * (*(minor + 5)) * (*(minor + 6))
+ (*(minor + 2)) * (*(minor + 3)) * (*(minor + 7)) -
(*(minor + 6)) * (*(minor + 4)) * (*(minor + 2))
- (*(minor + 7)) * (*(minor + 5)) * (*(minor + 0))
- (*(minor + 8)) * (*(minor + 3)) * (*(minor + 1));
} else {
float ratio;
float determinant = 1; // Initial det value
// Gauss Elimination Easy and fast algorithm to find the determinant of a nxn matrix
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (j > i) {
// We cannot divide with zero
if (*((minor + i * n) + i) == 0){
*((minor + i * n) + i) = pow(2.2204, -16); // Same as MATLAB command eps
}
ratio = *((minor + j * n) + i)/ (*((minor + i * n) + i));
for (int k = 0; k < n; k++) {
*((minor + j * n) + k) -= ratio * (*((minor + i * n) + k));
}
}
}
}
// Find det
for (int i = 0; i < n; i++) {
determinant *= *((minor + i * n) + i);
}
return determinant;
}
}
Kod: Markera allt
function cof = cof(a);
[r c] = size(a); %determine size of input
m = ones(r,c); %preallocate r x c cofactor matrix
a_temp=a; %create temporary matrix equal to input
for i = 1:r
for k = 1:c
a_temp([i],:)=[]; %remove ith row
a_temp(:,[k])=[]; %remove kth row
m(i,k) = ((-1)^(i+k))*det(a_temp); %compute cofactor element
a_temp=a; %reset elements of temporary matrix to input elements
end
end
cof=m; %return cofactor matrix as output variable
end