
You can now raise a matrix to a negative power and store the resulting matrixes from an operation with a scalar in another matrix
248 lines
7.1 KiB
C
248 lines
7.1 KiB
C
#include "matrix-operations.h"
|
|
|
|
|
|
matrix_t matrixError(error_t error){
|
|
switch(error){
|
|
case NOT_EQUAL:
|
|
perror("Matrices are not of the same dimensions\n");
|
|
break;
|
|
case NOT_MULTIPLIABLE:
|
|
perror("Matrix A's number of columns is different to matrix B's number of rows\n");
|
|
break;
|
|
case NOT_SQUARE:
|
|
perror("Matrix is not square");
|
|
break;
|
|
case ZERO_DET:
|
|
perror("Determinant of the matrix should be 0\n");
|
|
break;
|
|
case UNKNOWN:
|
|
default:
|
|
perror("Unknown error\n");
|
|
}
|
|
return createMatrix(0, 0);
|
|
}
|
|
|
|
// Creates a rows x columns matrix;
|
|
matrix_t createMatrix(size_t rows, size_t columns){
|
|
matrix_t newmatrix;
|
|
newmatrix.rows = rows;
|
|
newmatrix.columns = columns;
|
|
newmatrix.matrix = malloc(rows*sizeof(float*));
|
|
for(size_t i = 0; i < rows; ++i)
|
|
newmatrix.matrix[i] = calloc(columns,sizeof(float));
|
|
return newmatrix;
|
|
}
|
|
|
|
// Fills the matrix with values provided by the user
|
|
void initializeMatrix(matrix_t *m){
|
|
printf("Initializing %dx%d matrix\n", m->rows, m->columns);
|
|
for(size_t r = 0; r < m->rows; ++r){
|
|
printf("Please insert %d numbers for each of the columns of the %d%s row\n",
|
|
m->columns, r+1, (r+1==1)?("st"):((r+1==2)?("nd"):((r+1==3)?("rd"):("th"))));
|
|
for(size_t c = 0; c < m->columns; ++c){
|
|
scanf("%f", &m->matrix[r][c]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Returns true if the matrix is square, false otherwise
|
|
int isSquare(matrix_t m){
|
|
return m.rows == m.columns;
|
|
}
|
|
|
|
// Displays the given matrix
|
|
void displayMatrix(matrix_t m){
|
|
for(size_t r = 0; r < m.rows; ++r){
|
|
for(size_t c = 0; c < m.columns; ++c)
|
|
printf("%3.3g ", m.matrix[r][c]);
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
// Returns the identity matrix n x n
|
|
matrix_t identityMatrix(size_t n){
|
|
matrix_t identityMatrix = createMatrix(n, n);
|
|
for(size_t r = 0; r < n; ++r)
|
|
for(size_t c = 0; c < n; ++c)
|
|
if(r == c)
|
|
identityMatrix.matrix[r][c] = 1;
|
|
return identityMatrix;
|
|
}
|
|
|
|
// Returns a matrix of the same size as "m" filled with the number "n"
|
|
matrix_t fillN(matrix_t m, float n){
|
|
matrix_t filledmatrix = createMatrix(m.rows, m.columns);
|
|
for(size_t r = 0; r < m.rows; ++r)
|
|
for(size_t c = 0; c < m.columns; ++c)
|
|
filledmatrix.matrix[r][c] = n;
|
|
return filledmatrix;
|
|
}
|
|
|
|
// Adds a number to all the positions of the matrix and returns the result
|
|
matrix_t addN(matrix_t m, float n){
|
|
matrix_t addedmatrix = createMatrix(m.rows, m.columns);
|
|
for(size_t r = 0; r < m.rows; ++r)
|
|
for(size_t c = 0; c < m.columns; ++c)
|
|
addedmatrix.matrix[r][c] = m.matrix[r][c]+n;
|
|
return addedmatrix;
|
|
}
|
|
|
|
// Substracts a number from all the positions of the matrix and returns the result
|
|
matrix_t substractN(matrix_t m, float n){
|
|
matrix_t substractedmatrix = createMatrix(m.rows, m.columns);
|
|
for(size_t r = 0; r < m.rows; ++r)
|
|
for(size_t c = 0; c < m.columns; ++c)
|
|
substractedmatrix.matrix[r][c] = m.matrix[r][c]-n;
|
|
return substractedmatrix;
|
|
}
|
|
|
|
// Adds two matrices together and returns the result
|
|
matrix_t addMatrices(matrix_t a, matrix_t b){
|
|
if(a.rows != b.rows || a.columns != b.columns)
|
|
return matrixError(NOT_EQUAL);
|
|
matrix_t addedmatrices = createMatrix(a.rows, b.columns);
|
|
for(size_t r = 0; r < a.rows; ++r)
|
|
for(size_t c = 0; c < a.columns; ++c)
|
|
addedmatrices.matrix[r][c] = a.matrix[r][c] + b.matrix[r][c];
|
|
return addedmatrices;
|
|
}
|
|
|
|
// Negates all of the positions of the matrix and returns the result
|
|
matrix_t negateMatrix(matrix_t m){
|
|
matrix_t negatedmatrix = createMatrix(m.rows, m.columns);
|
|
for(size_t r = 0; r < m.rows; ++r)
|
|
for(size_t c = 0; c < m.columns; ++c)
|
|
negatedmatrix.matrix[r][c] = -m.matrix[r][c];
|
|
return negatedmatrix;
|
|
}
|
|
|
|
// Substracts matrix "b" from "a" and returns the result
|
|
matrix_t substractMatrices(matrix_t a, matrix_t b){
|
|
return addMatrices(a, negateMatrix(b));
|
|
}
|
|
|
|
// Multiplies all of the positions of the matrix by "n" and returns the result
|
|
matrix_t multiplyByN(matrix_t m, float n){
|
|
matrix_t multipliedmatrix = createMatrix(m.rows, m.columns);
|
|
for(size_t r = 0; r < m.rows; ++r)
|
|
for(size_t c = 0; c < m.columns; ++c)
|
|
multipliedmatrix.matrix[r][c] = m.matrix[r][c]*n;
|
|
return multipliedmatrix;
|
|
}
|
|
|
|
// Divides all of the positions of the matrix by "n" and returns the result
|
|
matrix_t divideByN(matrix_t m, float n){
|
|
return multiplyByN(m, (float)1/n);
|
|
}
|
|
|
|
// Multiplies matrix "a" by "b" and returns the result
|
|
matrix_t multiplyMatrices(matrix_t a, matrix_t b){
|
|
if(a.columns != b.rows)
|
|
return matrixError(NOT_MULTIPLIABLE);
|
|
matrix_t multipliedmatrices = createMatrix(a.rows, b.columns);
|
|
for(size_t r = 0; r < multipliedmatrices.rows; ++r)
|
|
for(size_t c = 0; c < multipliedmatrices.columns; ++c)
|
|
for(size_t n = 0; n < a.columns; ++n)
|
|
multipliedmatrices.matrix[r][c] += a.matrix[r][n]*b.matrix[n][c];
|
|
return multipliedmatrices;
|
|
}
|
|
|
|
// Divides matrix "a" by "b" and returns the result
|
|
matrix_t divideMatrices(matrix_t a, matrix_t b){
|
|
return multiplyMatrices(a, inverse(b));
|
|
}
|
|
|
|
// Raises the matrix to the nth power and returns the result
|
|
matrix_t raiseMatrixToN(matrix_t m, int n){
|
|
if(!isSquare(m))
|
|
return matrixError(NOT_SQUARE);
|
|
matrix_t raisedmatrix = identityMatrix(m.rows);
|
|
if(n < 0){
|
|
m = inverse(m);
|
|
n = -n;
|
|
}
|
|
for(int i = 0; i < n; ++i)
|
|
raisedmatrix = multiplyMatrices(raisedmatrix, m);
|
|
return raisedmatrix;
|
|
}
|
|
|
|
// Creates a submatrix from "matrix" without the column "column" and row "row" of "matrix"
|
|
matrix_t createSubmatrix(matrix_t m, size_t row, size_t column){
|
|
// TODO: not remove any
|
|
int mod = m.rows, nmod = mod-1, sr = 0, sc = 0;
|
|
matrix_t submatrix = createMatrix(nmod, nmod);
|
|
for(size_t r = 0; r < mod; ++r){
|
|
sc = 0;
|
|
if(r != row){
|
|
for(size_t c = 0; c < mod; ++c){
|
|
if(c != column){
|
|
submatrix.matrix[sr][sc] = m.matrix[r][c];
|
|
++sc;
|
|
}
|
|
}
|
|
++sr;
|
|
}
|
|
}
|
|
return submatrix;
|
|
}
|
|
|
|
// Returns the determinant of the given (square) matrix
|
|
int determinant(matrix_t m){
|
|
if(!isSquare(m)){
|
|
matrixError(NOT_SQUARE);
|
|
return (int)NULL;
|
|
}
|
|
int det = 0;
|
|
if(m.rows == 1)
|
|
return m.matrix[0][0];
|
|
else{
|
|
int count = 0, nmod = m.rows-1;
|
|
for(size_t r = 0; r < m.rows; ++r){
|
|
matrix_t submatrix = createSubmatrix(m, 0, r);
|
|
int subdeterminant = determinant(submatrix);
|
|
int step = m.matrix[0][r]*subdeterminant;
|
|
if((count++)%2 == 0)
|
|
det += step;
|
|
else
|
|
det -= step;
|
|
}
|
|
return det;
|
|
}
|
|
}
|
|
|
|
// Returns the cofactor matrix of the given matrix
|
|
matrix_t cofactor(matrix_t m){
|
|
if(!isSquare(m))
|
|
return matrixError(NOT_SQUARE);
|
|
matrix_t cofactormatrix = createMatrix(m.rows, m.columns);
|
|
for(size_t r = 0; r < m.rows; ++r){
|
|
for(size_t c = 0; c < m.columns; ++c){
|
|
matrix_t submatrix = createSubmatrix(m, r, c);
|
|
int d = determinant(submatrix);
|
|
cofactormatrix.matrix[r][c] = (r+c)%2?-d:d;
|
|
}
|
|
}
|
|
return cofactormatrix;
|
|
}
|
|
|
|
// Returns the transpose matrix of the given matrix
|
|
matrix_t transpose(matrix_t m){
|
|
matrix_t transposematrix = createMatrix(m.columns, m.rows);
|
|
for(size_t r = 0; r < m.columns; ++r)
|
|
for(size_t c = 0; c < m.rows; ++c)
|
|
transposematrix.matrix[r][c] = m.matrix[c][r];
|
|
return transposematrix;
|
|
}
|
|
|
|
// Returns the adjugate matrix of the given matrix
|
|
matrix_t adjugate(matrix_t m){
|
|
return transpose(cofactor(m));
|
|
}
|
|
|
|
// Returns the inverse matrix of the given matrix
|
|
matrix_t inverse(matrix_t m){
|
|
int det = determinant(m);
|
|
if(det == 0)
|
|
return matrixError(ZERO_DET);
|
|
return divideByN(adjugate(m), det);
|
|
} |