From 0a564486f54fef4ae3300de5afa35cf2c68e774d Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Wed, 4 Sep 2019 23:21:52 +0300 Subject: [PATCH 01/28] automatic indent indent -nbad -bap -nbc -bbo -hnl -br -brs -c33 -cd33 -ncdb -ce -ci4 -cli0 -d0 -di1 -nfc1 -i4 -ip0 -l80 -lp -npcs -nprs -npsl -sai -saf -saw -ncs -nsc -sob -nfca -cp33 -ss -ts4 -il1 -nut Signed-off-by: Yauheni Kaliuta --- calculate.c | 159 +++++++++++++++++++++++++------------------------- determinant.c | 55 +++++++++-------- functions.c | 100 ++++++++++++++++--------------- functions.h | 6 +- inverse.c | 34 ++++++----- main.c | 15 ++--- read.c | 135 +++++++++++++++++++++--------------------- 7 files changed, 254 insertions(+), 250 deletions(-) diff --git a/calculate.c b/calculate.c index e430d64..bb4063e 100644 --- a/calculate.c +++ b/calculate.c @@ -1,97 +1,98 @@ #include "functions.h" -void calculate(struct m *matrix, int nop, int id, char *op){ - +void calculate(struct m *matrix, int nop, int id, char *op) +{ + int i; - - for(i=0; i < nop; i++){ + + for (i = 0; i < nop; i++) { /*Transpose the matrices */ - if(op[i] == 't' || op[i] == 'T') + if (op[i] == 't' || op[i] == 'T') transpose(&matrix[0]); - - else if(op[i]=='d'){ + + else if (op[i] == 'd') { matrix[i].data[0] = determinant(matrix[i].row, &matrix[i]); matrix[i].row = 1; matrix[i].col = 1; } - - if(op[i] == 'i'){ - if(matrix[0].row != matrix[0].col) - printf("Error: You can only calculate the inverse of square matrices\n"); + + if (op[i] == 'i') { + if (matrix[0].row != matrix[0].col) + printf + ("Error: You can only calculate the inverse of square matrices\n"); inverse(matrix[0].row, &matrix[0]); - } + } } - - for(i=0; i <= nop; i+=2) - { - if (op[i] == '+' && op[i+1] == '?'){ - struct m tmp = add(&matrix[i],&matrix[i+1],+1); - free(matrix[i+1].data); - matrix[i+1] = tmp; + + for (i = 0; i <= nop; i += 2) { + if (op[i] == '+' && op[i + 1] == '?') { + struct m tmp = add(&matrix[i], &matrix[i + 1], +1); + free(matrix[i + 1].data); + matrix[i + 1] = tmp; break; - } - - else if(op[i] == '*' && op[i+1] == '?'){ - if (matrix[i].row == 1 && matrix[i].col == 1) - scalar_product(matrix[i].data[0], &matrix[i+1]); //Multiplication of Scalar per matrix - else{ - struct m tmp = multiply(&matrix[i], &matrix[i+1]); - free(matrix[i+1].data); - matrix[i+1] = tmp; - } - break; - } - - else if (op[i] == '-' && op[i+1] == '?'){ - struct m tmp = add(&matrix[i],&matrix[i+1],-1); - free(matrix[i+1].data); - matrix[i+1] = tmp; + } + + else if (op[i] == '*' && op[i + 1] == '?') { + if (matrix[i].row == 1 && matrix[i].col == 1) + scalar_product(matrix[i].data[0], &matrix[i + 1]); //Multiplication of Scalar per matrix + else { + struct m tmp = multiply(&matrix[i], &matrix[i + 1]); + free(matrix[i + 1].data); + matrix[i + 1] = tmp; + } + break; + } + + else if (op[i] == '-' && op[i + 1] == '?') { + struct m tmp = add(&matrix[i], &matrix[i + 1], -1); + free(matrix[i + 1].data); + matrix[i + 1] = tmp; break; - } - - else if(op[i] == '*' && op[i+1] == '+'){ - if (matrix[i].row == 1 && matrix[i].col == 1) - scalar_product(matrix[i].data[0],&matrix[i+1]); //Multiplication of Scalar per matrix - else{ - matrix[i+1] = multiply(&matrix[i],&matrix[i+1]); - matrix[i+2] = add(&matrix[i+1],&matrix[i+2],+1); - } } - - else if (op[i] == '+' && op[i+1] == '*'){ - struct m tmp = multiply(&matrix[i+1], &matrix[i+2]); - free(matrix[i+1].data); - matrix[i+1] = tmp; - - tmp = add(&matrix[i],&matrix[i+1],+1); - free(matrix[i+2].data); - matrix[i+2] = tmp; - } - - else if (op[i] == '+' && op[i+1] == '+'){ - struct m tmp = add(&matrix[i],&matrix[i+1],+1); - free(matrix[i+1].data); - matrix[i+1] = tmp; - - tmp = add(&matrix[i],&matrix[i+2],+1); - free(matrix[i+2].data); - matrix[i+2] = tmp; - } - - else if (op[i] == '-' && op[i+1] == '*'){ - struct m tmp = multiply(&matrix[i+1], &matrix[i+2]); - free(matrix[i+1].data); - matrix[i+1] = tmp; - - tmp = add(&matrix[i],&matrix[i+1],-1); - free(matrix[i+2].data); - matrix[i+2] = tmp; - } + + else if (op[i] == '*' && op[i + 1] == '+') { + if (matrix[i].row == 1 && matrix[i].col == 1) + scalar_product(matrix[i].data[0], &matrix[i + 1]); //Multiplication of Scalar per matrix + else { + matrix[i + 1] = multiply(&matrix[i], &matrix[i + 1]); + matrix[i + 2] = add(&matrix[i + 1], &matrix[i + 2], +1); + } + } + + else if (op[i] == '+' && op[i + 1] == '*') { + struct m tmp = multiply(&matrix[i + 1], &matrix[i + 2]); + free(matrix[i + 1].data); + matrix[i + 1] = tmp; + + tmp = add(&matrix[i], &matrix[i + 1], +1); + free(matrix[i + 2].data); + matrix[i + 2] = tmp; + } + + else if (op[i] == '+' && op[i + 1] == '+') { + struct m tmp = add(&matrix[i], &matrix[i + 1], +1); + free(matrix[i + 1].data); + matrix[i + 1] = tmp; + + tmp = add(&matrix[i], &matrix[i + 2], +1); + free(matrix[i + 2].data); + matrix[i + 2] = tmp; + } + + else if (op[i] == '-' && op[i + 1] == '*') { + struct m tmp = multiply(&matrix[i + 1], &matrix[i + 2]); + free(matrix[i + 1].data); + matrix[i + 1] = tmp; + + tmp = add(&matrix[i], &matrix[i + 1], -1); + free(matrix[i + 2].data); + matrix[i + 2] = tmp; + } } - + printf("=\n"); - print_matrix(&matrix[id]); /*Print the result */ - for(i=0; i <= id; i++) - free(matrix[i].data); + print_matrix(&matrix[id]); /*Print the result */ + for (i = 0; i <= id; i++) + free(matrix[i].data); free(matrix); } diff --git a/determinant.c b/determinant.c index 306bf00..2239c73 100644 --- a/determinant.c +++ b/determinant.c @@ -4,46 +4,45 @@ #include "functions.h" double determinant(size_t n, struct m *A) -{ - size_t i,j,i_count,j_count, count=0; - +{ + size_t i, j, i_count, j_count, count = 0; + double det = 0; - - if(n < 1) - { + + if (n < 1) { printf("Error\n"); exit(1); } - - else if(n==1) return A->data[0]; - - else if(n==2) return (A->data[0]* A->data[1 * A->col + 1] - A->data[0 + 1] * A->data[1*A->col + 0]); - - else{ + + else if (n == 1) + return A->data[0]; + + else if (n == 2) + return (A->data[0] * A->data[1 * A->col + 1] - + A->data[0 + 1] * A->data[1 * A->col + 0]); + + else { struct m C; - - C.row = A->row-1; - C.col = A->col-1; - - C.data = malloc(sizeof(double) * (A->row-1) * (A->col-1)); - - for(count=0; count < n; count++) - { + + C.row = A->row - 1; + C.col = A->col - 1; + + C.data = malloc(sizeof(double) * (A->row - 1) * (A->col - 1)); + + for (count = 0; count < n; count++) { //Creating array of Minors i_count = 0; - for(i = 1; i < n; i++) - { - j_count=0; - for(j = 0; j < n; j++) - { - if(j == count) - continue; // don't copy the minor column element + for (i = 1; i < n; i++) { + j_count = 0; + for (j = 0; j < n; j++) { + if (j == count) + continue; // don't copy the minor column element C.data[i_count * C.col + j_count] = A->data[i * A->col + j]; j_count++; } i_count++; } - det += pow(-1, count) * A->data[count] * determinant(n-1,&C);//Recursive call + det += pow(-1, count) * A->data[count] * determinant(n - 1, &C); //Recursive call } free(C.data); return det; diff --git a/functions.c b/functions.c index b62b04b..3cf1586 100644 --- a/functions.c +++ b/functions.c @@ -4,70 +4,74 @@ #include #include "functions.h" -struct m multiply(const struct m *A, const struct m *B) -{ +struct m multiply(const struct m *A, const struct m *B) +{ size_t i, j, k; struct m C; C.data = malloc(sizeof(double) * A->row * B->col); - + C.row = A->row; C.col = B->col; - - for (i=0; i< C.row; i++) - for (j=0; j < C.col; j++) + + for (i = 0; i < C.row; i++) + for (j = 0; j < C.col; j++) C.data[i * C.col + j] = 0; - + // Multiplying matrix A and B and storing in C. - for(i = 0; i < A->row; ++i) - for(j = 0; j < B->col; ++j) - for(k=0; k < A->col; ++k) - C.data[i * C.col + j] += A->data[i * A->col + k] * B->data[k * B->col + j]; - + for (i = 0; i < A->row; ++i) + for (j = 0; j < B->col; ++j) + for (k = 0; k < A->col; ++k) + C.data[i * C.col + j] += + A->data[i * A->col + k] * B->data[k * B->col + j]; + return C; } -struct m add(const struct m *A, const struct m *B, double n) -{ - if ( (A->row != B->row) || (A->col != B->col) ){ +struct m add(const struct m *A, const struct m *B, double n) +{ + if ((A->row != B->row) || (A->col != B->col)) { printf("Error: You can't sum up matrix of different dimension\n"); exit(1); - } - + } + size_t i, j; - + struct m C; C.data = malloc(sizeof(double) * A->row * B->col); C.row = A->row; C.col = A->col; - - for (i=0; i< C.row; i++) - for (j=0; j < C.col; j++) - C.data[i * C.col + j] = A->data[i * A->col + j] + n *B->data[i * B->col + j]; - + + for (i = 0; i < C.row; i++) + for (j = 0; j < C.col; j++) + C.data[i * C.col + j] = + A->data[i * A->col + j] + n * B->data[i * B->col + j]; + return C; } void f(double x) { - double i,f= modf(x,&i); - - if(f<.00001) - printf("%.f ",i); - - else printf("%f ",x); + double i, f = modf(x, &i); + + if (f < .00001) + printf("%.f ", i); + + else + printf("%f ", x); } /*printing a Matrix*/ -void print_matrix(struct m *A){ - - size_t i,j; +void print_matrix(struct m *A) +{ + + size_t i, j; + + double *tmp = A->data; - double *tmp = A->data; - - for(i=0; i < A->row; i++){ - for(j=0; j < A->col; j++){ - f(*(tmp++)); + for (i = 0; i < A->row; i++) { + for (j = 0; j < A->col; j++) { + f(*(tmp++)); } putchar('\n'); } @@ -75,24 +79,24 @@ void print_matrix(struct m *A){ void scalar_product(double scalar, struct m *B) { - size_t i,j; - - for(i=0; i < B->row; i++) - for(j=0; j < B->col; j++) - B->data[i * B->col + j] = scalar * B->data[i * B->col + j]; + size_t i, j; + + for (i = 0; i < B->row; i++) + for (j = 0; j < B->col; j++) + B->data[i * B->col + j] = scalar * B->data[i * B->col + j]; } void transpose(struct m *A) -{ +{ struct m C; C.data = malloc(sizeof(double) * A->row * A->col); - + C.row = A->col; C.col = A->row; - size_t i, j; - for (i = 0; i < C.row; i++) - for (j = 0; j < C.col; j++) - C.data[i * C.col + j] = A->data[j * A->col + i]; + size_t i, j; + for (i = 0; i < C.row; i++) + for (j = 0; j < C.col; j++) + C.data[i * C.col + j] = A->data[j * A->col + i]; *A = C; } diff --git a/functions.h b/functions.h index 551eaa2..4bfbcae 100644 --- a/functions.h +++ b/functions.h @@ -1,9 +1,9 @@ #include #include -#define MAXNOP 20 /*Max number of operations allowed */ +#define MAXNOP 20 /*Max number of operations allowed */ -struct m{ +struct m { size_t row; size_t col; double *data; @@ -17,5 +17,5 @@ void transpose(struct m *A); double determinant(size_t n, struct m *A); void scalar_product(double scalar, struct m *B); void inverse(size_t n, struct m *A); -void read_file(int maxc, FILE *fp); +void read_file(int maxc, FILE * fp); void calculate(struct m *matrix, int nop, int id, char op[MAXNOP]); diff --git a/inverse.c b/inverse.c index cc8e3d2..84127c1 100644 --- a/inverse.c +++ b/inverse.c @@ -1,38 +1,40 @@ #include -#include "functions.h" +#include "functions.h" /*Calculate the inverse of a matrix */ -void inverse(size_t n, struct m *A) +void inverse(size_t n, struct m *A) { double det; - if( (det = determinant(n, A)) == 0 ){ + if ((det = determinant(n, A)) == 0) { printf("The matrix is singular\n"); exit(1); } - - size_t i,j,i_count,j_count, count=0; - struct m C; /*The Adjoint matrix */ + size_t i, j, i_count, j_count, count = 0; + + struct m C; /*The Adjoint matrix */ C.data = malloc(sizeof(double) * n * n); C.row = n; - C.col = n; - double Rdata[(n-1)*(n-1)]; // remaining data values - struct m R = { n-1, n-1, Rdata }; // matrix structure for them - for (count = 0; count < n*n; count++) // Create n*n Matrix of Minors + C.col = n; + double Rdata[(n - 1) * (n - 1)]; // remaining data values + struct m R = { n - 1, n - 1, Rdata }; // matrix structure for them + for (count = 0; count < n * n; count++) // Create n*n Matrix of Minors { - int row = count/n, col = count%n; + int row = count / n, col = count % n; for (i_count = i = 0; i < n; i++) - if (i != row) // don't copy the current row + if (i != row) // don't copy the current row { for (j_count = j = 0; j < n; j++) - if (j != col) // don't copy the current column - Rdata[i_count*R.col+j_count++] = A->data[i*A->col+j]; + if (j != col) // don't copy the current column + Rdata[i_count * R.col + j_count++] = + A->data[i * A->col + j]; i_count++; } // transpose by swapping row and column - C.data[col*C.col+row] = pow(-1, (row&1) ^ (col&1)) * determinant(n-1, &R) / det; + C.data[col * C.col + row] = + pow(-1, (row & 1) ^ (col & 1)) * determinant(n - 1, &R) / det; } - *A=C; + *A = C; } diff --git a/main.c b/main.c index 236c90b..77becc8 100644 --- a/main.c +++ b/main.c @@ -27,14 +27,15 @@ #include #include "functions.h" -int main(int argc, char *argv[]){ - +int main(int argc, char *argv[]) +{ + FILE *file = argc > 1 ? fopen(argv[1], "rb") : stdin; - + /*define max dimension of a matrix */ - int maxc = argc>2?atoi(argv[2])*atoi(argv[2]):100; - - read_file(maxc, file); - + int maxc = argc > 2 ? atoi(argv[2]) * atoi(argv[2]) : 100; + + read_file(maxc, file); + return 0; } diff --git a/read.c b/read.c index 71fbc1a..fd62759 100644 --- a/read.c +++ b/read.c @@ -2,59 +2,58 @@ #include #include -#define MAXNOP 20 /*Max number of operations allowed */ -#define MAXNMATR 40 /*Max number of matrices */ -#define MAXLINE 500 /*Max lenght of a line */ +#define MAXNOP 20 /*Max number of operations allowed */ +#define MAXNMATR 40 /*Max number of matrices */ +#define MAXLINE 500 /*Max lenght of a line */ -void read_file(int maxc, FILE *fp) +void read_file(int maxc, FILE * fp) { struct m *matrix; - int id = 0; /* id of a matrix */ - size_t ncol,nrow; /* No of columns of a matrix*/ + int id = 0; /* id of a matrix */ + size_t ncol, nrow; /* No of columns of a matrix */ ncol = nrow = 0; - int nop = 0; /*No of operators*/ + int nop = 0; /*No of operators */ int off = 0; int i; int n; double *d; - char buf[MAXLINE]; /*to store each lines of file */ + char buf[MAXLINE]; /*to store each lines of file */ char *p = buf; char op[MAXNOP]; - - for (i=0; i < MAXNOP; i++) - op[i]='?'; - - if (!(matrix = malloc(MAXNMATR*sizeof *(matrix)))) { - perror ("malloc-matrix"); - exit(1); + + for (i = 0; i < MAXNOP; i++) + op[i] = '?'; + + if (!(matrix = malloc(MAXNMATR * sizeof *(matrix)))) { + perror("malloc-matrix"); + exit(1); } - + /*Read file line by line */ - while (fgets (buf, MAXLINE, fp)){ - - if (nrow == 0){ + while (fgets(buf, MAXLINE, fp)) { + + if (nrow == 0) { /* allocate/validate max no. of matrix */ d = matrix[id].data = malloc(sizeof(double) * maxc); } - - if (strcmp(buf, "^-1\n") == 0){ - op[nop++] = 'i'; /* matrix inverse operation */ - continue; + + if (strcmp(buf, "^-1\n") == 0) { + op[nop++] = 'i'; /* matrix inverse operation */ + continue; } - - if (strcmp(buf, "^T\n") == 0 || strcmp(buf, "^t\n") == 0){ - op[nop++] = 't'; /* matrix inverse operation */ - continue; + + if (strcmp(buf, "^T\n") == 0 || strcmp(buf, "^t\n") == 0) { + op[nop++] = 't'; /* matrix inverse operation */ + continue; } - - else if (strcmp(buf, "det\n") == 0){ - op[nop++] = 'd'; /* determinant operation */ - continue; + + else if (strcmp(buf, "det\n") == 0) { + op[nop++] = 'd'; /* determinant operation */ + continue; } - + /*check if line contains operator */ - else if ( (!isdigit(*buf) && buf[1] =='\n')) - { + else if ((!isdigit(*buf) && buf[1] == '\n')) { op[nop++] = *buf; matrix[id].col = ncol; matrix[id].row = nrow; @@ -62,66 +61,64 @@ void read_file(int maxc, FILE *fp) id++; continue; } - - else /* read integers in a line into d */ - { - while (sscanf (p + off, "%lf%n", d, &n) == 1) { + + else { /* read integers in a line into d */ + while (sscanf(p + off, "%lf%n", d, &n) == 1) { d++; - if(nrow == 0) + if (nrow == 0) ncol++; off += n; } nrow++; off = 0; } - } /*end of while fgets cycle */ + } /*end of while fgets cycle */ + + fclose(fp); - fclose(fp); - /*Assign last matrix No of columns and rows */ matrix[id].col = ncol; matrix[id].row = nrow; - - if (nop == 0){ + + if (nop == 0) { printf("Nothing to do\n"); exit(1); - } - + } + /*Printing the matrices and operations */ - for(i=0; i <= id; i++){ - - if(op[i] == 'd'){ + for (i = 0; i <= id; i++) { + + if (op[i] == 'd') { printf("det\n"); print_matrix(&matrix[i]); } - - else if (op[i] == '*' || op[i] == '-' || op[i] =='+') - { + + else if (op[i] == '*' || op[i] == '-' || op[i] == '+') { print_matrix(&matrix[i]); - if(op[i-1] == 'i' || op[i-1] == 'T' || op[i-1] == 't') + if (op[i - 1] == 'i' || op[i - 1] == 'T' || op[i - 1] == 't') continue; else printf("%c\n", op[i]); } - - else if (op[i] == 't' || op[i] == 'T'){ - print_matrix(&matrix[i]); - printf("^T\n"); - if(op[i+1] != '?') - printf("%c\n",op[i+1]); + + else if (op[i] == 't' || op[i] == 'T') { + print_matrix(&matrix[i]); + printf("^T\n"); + if (op[i + 1] != '?') + printf("%c\n", op[i + 1]); } - - else if (op[i] == 'i'){ + + else if (op[i] == 'i') { + print_matrix(&matrix[i]); + printf("^-1\n"); /* matrix inverse operation */ + if (op[i + 1] != '?') + printf("%c\n", op[i + 1]); + } + + else if (op[i] == '?') { print_matrix(&matrix[i]); - printf("^-1\n"); /* matrix inverse operation */ - if(op[i+1] != '?') - printf("%c\n",op[i+1]); } - - else if(op[i] == '?'){ - print_matrix(&matrix[i]); - } } - + calculate(matrix, nop, id, op); } From b38c9aa4717184c6ecae8f9ff6a893adbf76ae77 Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Wed, 4 Sep 2019 23:32:02 +0300 Subject: [PATCH 02/28] main: add error checking Add error checking and polish the style: - alphabet order of includes; - define default values. Signed-off-by: Yauheni Kaliuta --- main.c | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/main.c b/main.c index 77becc8..2c8c1ac 100644 --- a/main.c +++ b/main.c @@ -21,19 +21,44 @@ * USA */ -#include -#include +#include "functions.h" + #include +#include #include -#include "functions.h" +#include +#include +#include + +#define DEFAULT_FILE stdin +#define DEFAULT_DIMENSION 100 int main(int argc, char *argv[]) { - FILE *file = argc > 1 ? fopen(argv[1], "rb") : stdin; + FILE *file = DEFAULT_FILE; + int maxc = DEFAULT_DIMENSION; + + if (argc > 1) { + file = fopen(argv[1], "rb"); + if (file == NULL) { + fprintf(stderr, "Could not open input file %s: %s\n", + argv[1], strerror(errno)); + return 1; + } + } + + if (argc > 2) { + int tmp; - /*define max dimension of a matrix */ - int maxc = argc > 2 ? atoi(argv[2]) * atoi(argv[2]) : 100; + tmp = atoi(argv[2]); + if (tmp == 0) { + fprintf(stderr, "Wrong dimension %s\n", argv[2]); + fclose(file); + return 1; + } + maxc = tmp; + } read_file(maxc, file); From e4138036bdb2371cfe593ebb053c762c4d2e0e7c Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Wed, 4 Sep 2019 23:48:34 +0300 Subject: [PATCH 03/28] read.c: minor style changes Unify if-else style (use continue always); init loop variables right before the loop; unify spaces in comments. Signed-off-by: Yauheni Kaliuta --- read.c | 69 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/read.c b/read.c index fd62759..4c14f4a 100644 --- a/read.c +++ b/read.c @@ -2,23 +2,22 @@ #include #include -#define MAXNOP 20 /*Max number of operations allowed */ -#define MAXNMATR 40 /*Max number of matrices */ -#define MAXLINE 500 /*Max lenght of a line */ +#define MAXNOP 20 /* Max number of operations allowed */ +#define MAXNMATR 40 /* Max number of matrices */ +#define MAXLINE 500 /* Max lenght of a line */ -void read_file(int maxc, FILE * fp) +void read_file(int maxc, FILE *fp) { struct m *matrix; - int id = 0; /* id of a matrix */ + int id; /* id of a matrix */ size_t ncol, nrow; /* No of columns of a matrix */ - ncol = nrow = 0; - int nop = 0; /*No of operators */ + int nop = 0; /* No of operators */ int off = 0; int i; int n; double *d; - char buf[MAXLINE]; /*to store each lines of file */ - char *p = buf; + char buf[MAXLINE]; /* to store each lines of file */ + char *p; char op[MAXNOP]; for (i = 0; i < MAXNOP; i++) @@ -29,7 +28,11 @@ void read_file(int maxc, FILE * fp) exit(1); } - /*Read file line by line */ + ncol = 0; + nrow = 0; + id = 0; + p = buf; + while (fgets(buf, MAXLINE, fp)) { if (nrow == 0) { @@ -47,13 +50,13 @@ void read_file(int maxc, FILE * fp) continue; } - else if (strcmp(buf, "det\n") == 0) { + if (strcmp(buf, "det\n") == 0) { op[nop++] = 'd'; /* determinant operation */ continue; } - /*check if line contains operator */ - else if ((!isdigit(*buf) && buf[1] == '\n')) { + /* check if line contains operator */ + if ((!isdigit(*buf) && buf[1] == '\n')) { op[nop++] = *buf; matrix[id].col = ncol; matrix[id].row = nrow; @@ -62,60 +65,64 @@ void read_file(int maxc, FILE * fp) continue; } - else { /* read integers in a line into d */ - while (sscanf(p + off, "%lf%n", d, &n) == 1) { - d++; - if (nrow == 0) - ncol++; - off += n; - } - nrow++; - off = 0; - } - } /*end of while fgets cycle */ + /* read integers in a line into d */ + while (sscanf(p + off, "%lf%n", d, &n) == 1) { + d++; + if (nrow == 0) + ncol++; + off += n; + } + + nrow++; + off = 0; + } /* end of while fgets cycle */ fclose(fp); - /*Assign last matrix No of columns and rows */ + /* Assign last matrix No of columns and rows */ matrix[id].col = ncol; matrix[id].row = nrow; if (nop == 0) { - printf("Nothing to do\n"); + fprintf(stderr, "Nothing to do\n"); exit(1); } - /*Printing the matrices and operations */ + /* Printing the matrices and operations */ for (i = 0; i <= id; i++) { if (op[i] == 'd') { printf("det\n"); print_matrix(&matrix[i]); + continue; } - else if (op[i] == '*' || op[i] == '-' || op[i] == '+') { + if (op[i] == '*' || op[i] == '-' || op[i] == '+') { print_matrix(&matrix[i]); if (op[i - 1] == 'i' || op[i - 1] == 'T' || op[i - 1] == 't') continue; else printf("%c\n", op[i]); + continue; } - else if (op[i] == 't' || op[i] == 'T') { + if (op[i] == 't' || op[i] == 'T') { print_matrix(&matrix[i]); printf("^T\n"); if (op[i + 1] != '?') printf("%c\n", op[i + 1]); + continue; } - else if (op[i] == 'i') { + if (op[i] == 'i') { print_matrix(&matrix[i]); printf("^-1\n"); /* matrix inverse operation */ if (op[i + 1] != '?') printf("%c\n", op[i + 1]); + continue; } - else if (op[i] == '?') { + if (op[i] == '?') { print_matrix(&matrix[i]); } } From fccc61d66a64b51eec850498f97e39bfb5651076 Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Thu, 5 Sep 2019 00:06:27 +0300 Subject: [PATCH 04/28] read.c: remove rudiment p and fix comment There is no point to duplicate buffer address to p variable, it's not changing, instead offset is used, remove it. Also sscanf is actually scans doubles (%lf), not integers, fix the comment. Signed-off-by: Yauheni Kaliuta --- read.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/read.c b/read.c index 4c14f4a..dbbff18 100644 --- a/read.c +++ b/read.c @@ -17,7 +17,6 @@ void read_file(int maxc, FILE *fp) int n; double *d; char buf[MAXLINE]; /* to store each lines of file */ - char *p; char op[MAXNOP]; for (i = 0; i < MAXNOP; i++) @@ -31,7 +30,6 @@ void read_file(int maxc, FILE *fp) ncol = 0; nrow = 0; id = 0; - p = buf; while (fgets(buf, MAXLINE, fp)) { @@ -65,8 +63,8 @@ void read_file(int maxc, FILE *fp) continue; } - /* read integers in a line into d */ - while (sscanf(p + off, "%lf%n", d, &n) == 1) { + /* read numbers in a line into d */ + while (sscanf(buf + off, "%lf%n", d, &n) == 1) { d++; if (nrow == 0) ncol++; From 6df63786d2ead911362653c7622c0c2f45abec63 Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Thu, 5 Sep 2019 00:57:54 +0300 Subject: [PATCH 05/28] inverse: fix memory leak Source data should be freed before overwriting. Signed-off-by: Yauheni Kaliuta --- inverse.c | 1 + 1 file changed, 1 insertion(+) diff --git a/inverse.c b/inverse.c index 84127c1..2421f1b 100644 --- a/inverse.c +++ b/inverse.c @@ -36,5 +36,6 @@ void inverse(size_t n, struct m *A) C.data[col * C.col + row] = pow(-1, (row & 1) ^ (col & 1)) * determinant(n - 1, &R) / det; } + free(A->data); *A = C; } From 8928d36cccd70f864cc0d1852587719e71728a17 Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Thu, 5 Sep 2019 01:19:02 +0300 Subject: [PATCH 06/28] Reorganize files There is no big point to split the functionality into such tiny pieces: put all matrix specific operations into matrix.c module; put main processing into processing.c module (it is just 2 functions at the moment, read_file() and calculate()). No funtional changes. Signed-off-by: Yauheni Kaliuta --- Makefile | 2 +- calculate.c | 98 --------------------- determinant.c | 50 ----------- freelab | Bin 36784 -> 0 bytes functions.c | 102 ---------------------- inverse.c | 41 --------- main.c | 4 +- matrix.c | 187 ++++++++++++++++++++++++++++++++++++++++ functions.h => matrix.h | 11 ++- read.c => processing.c | 101 +++++++++++++++++++++- processing.h | 8 ++ 11 files changed, 302 insertions(+), 302 deletions(-) delete mode 100644 calculate.c delete mode 100644 determinant.c delete mode 100644 freelab delete mode 100644 functions.c delete mode 100644 inverse.c create mode 100644 matrix.c rename functions.h => matrix.h (65%) rename read.c => processing.c (50%) create mode 100644 processing.h diff --git a/Makefile b/Makefile index 69a2d55..363fb2b 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ CC = gcc CFLAGS = -Wall -g -Wshadow -pedantic LDFLAGS = -lm -OBJFILES = main.o functions.o determinant.o inverse.o read.o calculate.o +OBJFILES = main.o processing.o matrix.o TARGET = freelab all: $(TARGET) diff --git a/calculate.c b/calculate.c deleted file mode 100644 index bb4063e..0000000 --- a/calculate.c +++ /dev/null @@ -1,98 +0,0 @@ -#include "functions.h" - -void calculate(struct m *matrix, int nop, int id, char *op) -{ - - int i; - - for (i = 0; i < nop; i++) { - /*Transpose the matrices */ - if (op[i] == 't' || op[i] == 'T') - transpose(&matrix[0]); - - else if (op[i] == 'd') { - matrix[i].data[0] = determinant(matrix[i].row, &matrix[i]); - matrix[i].row = 1; - matrix[i].col = 1; - } - - if (op[i] == 'i') { - if (matrix[0].row != matrix[0].col) - printf - ("Error: You can only calculate the inverse of square matrices\n"); - inverse(matrix[0].row, &matrix[0]); - } - } - - for (i = 0; i <= nop; i += 2) { - if (op[i] == '+' && op[i + 1] == '?') { - struct m tmp = add(&matrix[i], &matrix[i + 1], +1); - free(matrix[i + 1].data); - matrix[i + 1] = tmp; - break; - } - - else if (op[i] == '*' && op[i + 1] == '?') { - if (matrix[i].row == 1 && matrix[i].col == 1) - scalar_product(matrix[i].data[0], &matrix[i + 1]); //Multiplication of Scalar per matrix - else { - struct m tmp = multiply(&matrix[i], &matrix[i + 1]); - free(matrix[i + 1].data); - matrix[i + 1] = tmp; - } - break; - } - - else if (op[i] == '-' && op[i + 1] == '?') { - struct m tmp = add(&matrix[i], &matrix[i + 1], -1); - free(matrix[i + 1].data); - matrix[i + 1] = tmp; - break; - } - - else if (op[i] == '*' && op[i + 1] == '+') { - if (matrix[i].row == 1 && matrix[i].col == 1) - scalar_product(matrix[i].data[0], &matrix[i + 1]); //Multiplication of Scalar per matrix - else { - matrix[i + 1] = multiply(&matrix[i], &matrix[i + 1]); - matrix[i + 2] = add(&matrix[i + 1], &matrix[i + 2], +1); - } - } - - else if (op[i] == '+' && op[i + 1] == '*') { - struct m tmp = multiply(&matrix[i + 1], &matrix[i + 2]); - free(matrix[i + 1].data); - matrix[i + 1] = tmp; - - tmp = add(&matrix[i], &matrix[i + 1], +1); - free(matrix[i + 2].data); - matrix[i + 2] = tmp; - } - - else if (op[i] == '+' && op[i + 1] == '+') { - struct m tmp = add(&matrix[i], &matrix[i + 1], +1); - free(matrix[i + 1].data); - matrix[i + 1] = tmp; - - tmp = add(&matrix[i], &matrix[i + 2], +1); - free(matrix[i + 2].data); - matrix[i + 2] = tmp; - } - - else if (op[i] == '-' && op[i + 1] == '*') { - struct m tmp = multiply(&matrix[i + 1], &matrix[i + 2]); - free(matrix[i + 1].data); - matrix[i + 1] = tmp; - - tmp = add(&matrix[i], &matrix[i + 1], -1); - free(matrix[i + 2].data); - matrix[i + 2] = tmp; - } - } - - printf("=\n"); - print_matrix(&matrix[id]); /*Print the result */ - for (i = 0; i <= id; i++) - free(matrix[i].data); - free(matrix); -} diff --git a/determinant.c b/determinant.c deleted file mode 100644 index 2239c73..0000000 --- a/determinant.c +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include -#include -#include "functions.h" - -double determinant(size_t n, struct m *A) -{ - size_t i, j, i_count, j_count, count = 0; - - double det = 0; - - if (n < 1) { - printf("Error\n"); - exit(1); - } - - else if (n == 1) - return A->data[0]; - - else if (n == 2) - return (A->data[0] * A->data[1 * A->col + 1] - - A->data[0 + 1] * A->data[1 * A->col + 0]); - - else { - struct m C; - - C.row = A->row - 1; - C.col = A->col - 1; - - C.data = malloc(sizeof(double) * (A->row - 1) * (A->col - 1)); - - for (count = 0; count < n; count++) { - //Creating array of Minors - i_count = 0; - for (i = 1; i < n; i++) { - j_count = 0; - for (j = 0; j < n; j++) { - if (j == count) - continue; // don't copy the minor column element - C.data[i_count * C.col + j_count] = A->data[i * A->col + j]; - j_count++; - } - i_count++; - } - det += pow(-1, count) * A->data[count] * determinant(n - 1, &C); //Recursive call - } - free(C.data); - return det; - } -} diff --git a/freelab b/freelab deleted file mode 100644 index 36aab668e9136b9281518f9eb34c5972c1b01b0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36784 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 diff --git a/functions.c b/functions.c deleted file mode 100644 index 3cf1586..0000000 --- a/functions.c +++ /dev/null @@ -1,102 +0,0 @@ -#include -#include -#include -#include -#include "functions.h" - -struct m multiply(const struct m *A, const struct m *B) -{ - size_t i, j, k; - struct m C; - C.data = malloc(sizeof(double) * A->row * B->col); - - C.row = A->row; - C.col = B->col; - - for (i = 0; i < C.row; i++) - for (j = 0; j < C.col; j++) - C.data[i * C.col + j] = 0; - - // Multiplying matrix A and B and storing in C. - for (i = 0; i < A->row; ++i) - for (j = 0; j < B->col; ++j) - for (k = 0; k < A->col; ++k) - C.data[i * C.col + j] += - A->data[i * A->col + k] * B->data[k * B->col + j]; - - return C; -} - -struct m add(const struct m *A, const struct m *B, double n) -{ - if ((A->row != B->row) || (A->col != B->col)) { - printf("Error: You can't sum up matrix of different dimension\n"); - exit(1); - } - - size_t i, j; - - struct m C; - C.data = malloc(sizeof(double) * A->row * B->col); - C.row = A->row; - C.col = A->col; - - for (i = 0; i < C.row; i++) - for (j = 0; j < C.col; j++) - C.data[i * C.col + j] = - A->data[i * A->col + j] + n * B->data[i * B->col + j]; - - return C; -} - -void f(double x) -{ - double i, f = modf(x, &i); - - if (f < .00001) - printf("%.f ", i); - - else - printf("%f ", x); -} - -/*printing a Matrix*/ - -void print_matrix(struct m *A) -{ - - size_t i, j; - - double *tmp = A->data; - - for (i = 0; i < A->row; i++) { - for (j = 0; j < A->col; j++) { - f(*(tmp++)); - } - putchar('\n'); - } -} - -void scalar_product(double scalar, struct m *B) -{ - size_t i, j; - - for (i = 0; i < B->row; i++) - for (j = 0; j < B->col; j++) - B->data[i * B->col + j] = scalar * B->data[i * B->col + j]; -} - -void transpose(struct m *A) -{ - struct m C; - C.data = malloc(sizeof(double) * A->row * A->col); - - C.row = A->col; - C.col = A->row; - - size_t i, j; - for (i = 0; i < C.row; i++) - for (j = 0; j < C.col; j++) - C.data[i * C.col + j] = A->data[j * A->col + i]; - *A = C; -} diff --git a/inverse.c b/inverse.c deleted file mode 100644 index 2421f1b..0000000 --- a/inverse.c +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include "functions.h" - -/*Calculate the inverse of a matrix */ - -void inverse(size_t n, struct m *A) -{ - double det; - if ((det = determinant(n, A)) == 0) { - printf("The matrix is singular\n"); - exit(1); - } - - size_t i, j, i_count, j_count, count = 0; - - struct m C; /*The Adjoint matrix */ - C.data = malloc(sizeof(double) * n * n); - - C.row = n; - C.col = n; - double Rdata[(n - 1) * (n - 1)]; // remaining data values - struct m R = { n - 1, n - 1, Rdata }; // matrix structure for them - for (count = 0; count < n * n; count++) // Create n*n Matrix of Minors - { - int row = count / n, col = count % n; - for (i_count = i = 0; i < n; i++) - if (i != row) // don't copy the current row - { - for (j_count = j = 0; j < n; j++) - if (j != col) // don't copy the current column - Rdata[i_count * R.col + j_count++] = - A->data[i * A->col + j]; - i_count++; - } - // transpose by swapping row and column - C.data[col * C.col + row] = - pow(-1, (row & 1) ^ (col & 1)) * determinant(n - 1, &R) / det; - } - free(A->data); - *A = C; -} diff --git a/main.c b/main.c index 2c8c1ac..e99523b 100644 --- a/main.c +++ b/main.c @@ -21,11 +21,9 @@ * USA */ -#include "functions.h" +#include "processing.h" -#include #include -#include #include #include #include diff --git a/matrix.c b/matrix.c new file mode 100644 index 0000000..3832af2 --- /dev/null +++ b/matrix.c @@ -0,0 +1,187 @@ +#include "matrix.h" + +#include +#include +#include + +/*Calculate the inverse of a matrix */ + +void inverse(size_t n, struct m *A) +{ + double det; + if ((det = determinant(n, A)) == 0) { + printf("The matrix is singular\n"); + exit(1); + } + + size_t i, j, i_count, j_count, count = 0; + + struct m C; /*The Adjoint matrix */ + C.data = malloc(sizeof(double) * n * n); + + C.row = n; + C.col = n; + double Rdata[(n - 1) * (n - 1)]; // remaining data values + struct m R = { n - 1, n - 1, Rdata }; // matrix structure for them + for (count = 0; count < n * n; count++) // Create n*n Matrix of Minors + { + int row = count / n, col = count % n; + for (i_count = i = 0; i < n; i++) + if (i != row) // don't copy the current row + { + for (j_count = j = 0; j < n; j++) + if (j != col) // don't copy the current column + Rdata[i_count * R.col + j_count++] = + A->data[i * A->col + j]; + i_count++; + } + // transpose by swapping row and column + C.data[col * C.col + row] = + pow(-1, (row & 1) ^ (col & 1)) * determinant(n - 1, &R) / det; + } + free(A->data); + *A = C; +} + +double determinant(size_t n, struct m *A) +{ + size_t i, j, i_count, j_count, count = 0; + + double det = 0; + + if (n < 1) { + printf("Error\n"); + exit(1); + } + + else if (n == 1) + return A->data[0]; + + else if (n == 2) + return (A->data[0] * A->data[1 * A->col + 1] - + A->data[0 + 1] * A->data[1 * A->col + 0]); + + else { + struct m C; + + C.row = A->row - 1; + C.col = A->col - 1; + + C.data = malloc(sizeof(double) * (A->row - 1) * (A->col - 1)); + + for (count = 0; count < n; count++) { + //Creating array of Minors + i_count = 0; + for (i = 1; i < n; i++) { + j_count = 0; + for (j = 0; j < n; j++) { + if (j == count) + continue; // don't copy the minor column element + C.data[i_count * C.col + j_count] = A->data[i * A->col + j]; + j_count++; + } + i_count++; + } + det += pow(-1, count) * A->data[count] * determinant(n - 1, &C); //Recursive call + } + free(C.data); + return det; + } +} + +struct m multiply(const struct m *A, const struct m *B) +{ + size_t i, j, k; + struct m C; + C.data = malloc(sizeof(double) * A->row * B->col); + + C.row = A->row; + C.col = B->col; + + for (i = 0; i < C.row; i++) + for (j = 0; j < C.col; j++) + C.data[i * C.col + j] = 0; + + // Multiplying matrix A and B and storing in C. + for (i = 0; i < A->row; ++i) + for (j = 0; j < B->col; ++j) + for (k = 0; k < A->col; ++k) + C.data[i * C.col + j] += + A->data[i * A->col + k] * B->data[k * B->col + j]; + + return C; +} + +struct m add(const struct m *A, const struct m *B, double n) +{ + if ((A->row != B->row) || (A->col != B->col)) { + printf("Error: You can't sum up matrix of different dimension\n"); + exit(1); + } + + size_t i, j; + + struct m C; + C.data = malloc(sizeof(double) * A->row * B->col); + C.row = A->row; + C.col = A->col; + + for (i = 0; i < C.row; i++) + for (j = 0; j < C.col; j++) + C.data[i * C.col + j] = + A->data[i * A->col + j] + n * B->data[i * B->col + j]; + + return C; +} + +void f(double x) +{ + double i, f = modf(x, &i); + + if (f < .00001) + printf("%.f ", i); + + else + printf("%f ", x); +} + +/*printing a Matrix*/ + +void print_matrix(struct m *A) +{ + + size_t i, j; + + double *tmp = A->data; + + for (i = 0; i < A->row; i++) { + for (j = 0; j < A->col; j++) { + f(*(tmp++)); + } + putchar('\n'); + } +} + +void scalar_product(double scalar, struct m *B) +{ + size_t i, j; + + for (i = 0; i < B->row; i++) + for (j = 0; j < B->col; j++) + B->data[i * B->col + j] = scalar * B->data[i * B->col + j]; +} + +void transpose(struct m *A) +{ + struct m C; + C.data = malloc(sizeof(double) * A->row * A->col); + + C.row = A->col; + C.col = A->row; + + size_t i, j; + for (i = 0; i < C.row; i++) + for (j = 0; j < C.col; j++) + C.data[i * C.col + j] = A->data[j * A->col + i]; + *A = C; +} diff --git a/functions.h b/matrix.h similarity index 65% rename from functions.h rename to matrix.h index 4bfbcae..54d0155 100644 --- a/functions.h +++ b/matrix.h @@ -1,7 +1,7 @@ -#include -#include +#ifndef _MATRIXLAB_MATRIX_H_ +#define _MATRIXLAB_MATRIX_H_ -#define MAXNOP 20 /*Max number of operations allowed */ +#include struct m { size_t row; @@ -11,11 +11,10 @@ struct m { struct m add(const struct m *A, const struct m *B, double n); struct m multiply(const struct m *A, const struct m *B); -void f(double x); void print_matrix(struct m *A); void transpose(struct m *A); double determinant(size_t n, struct m *A); void scalar_product(double scalar, struct m *B); void inverse(size_t n, struct m *A); -void read_file(int maxc, FILE * fp); -void calculate(struct m *matrix, int nop, int id, char op[MAXNOP]); + +#endif /* _MATRIXLAB_MATRIX_H_ */ diff --git a/read.c b/processing.c similarity index 50% rename from read.c rename to processing.c index dbbff18..9ee7267 100644 --- a/read.c +++ b/processing.c @@ -1,11 +1,110 @@ -#include "functions.h" +#include "matrix.h" + #include +#include #include #define MAXNOP 20 /* Max number of operations allowed */ #define MAXNMATR 40 /* Max number of matrices */ #define MAXLINE 500 /* Max lenght of a line */ +void calculate(struct m *matrix, int nop, int id, char *op) +{ + + int i; + + for (i = 0; i < nop; i++) { + /*Transpose the matrices */ + if (op[i] == 't' || op[i] == 'T') + transpose(&matrix[0]); + + else if (op[i] == 'd') { + matrix[i].data[0] = determinant(matrix[i].row, &matrix[i]); + matrix[i].row = 1; + matrix[i].col = 1; + } + + if (op[i] == 'i') { + if (matrix[0].row != matrix[0].col) + printf + ("Error: You can only calculate the inverse of square matrices\n"); + inverse(matrix[0].row, &matrix[0]); + } + } + + for (i = 0; i <= nop; i += 2) { + if (op[i] == '+' && op[i + 1] == '?') { + struct m tmp = add(&matrix[i], &matrix[i + 1], +1); + free(matrix[i + 1].data); + matrix[i + 1] = tmp; + break; + } + + else if (op[i] == '*' && op[i + 1] == '?') { + if (matrix[i].row == 1 && matrix[i].col == 1) + scalar_product(matrix[i].data[0], &matrix[i + 1]); //Multiplication of Scalar per matrix + else { + struct m tmp = multiply(&matrix[i], &matrix[i + 1]); + free(matrix[i + 1].data); + matrix[i + 1] = tmp; + } + break; + } + + else if (op[i] == '-' && op[i + 1] == '?') { + struct m tmp = add(&matrix[i], &matrix[i + 1], -1); + free(matrix[i + 1].data); + matrix[i + 1] = tmp; + break; + } + + else if (op[i] == '*' && op[i + 1] == '+') { + if (matrix[i].row == 1 && matrix[i].col == 1) + scalar_product(matrix[i].data[0], &matrix[i + 1]); //Multiplication of Scalar per matrix + else { + matrix[i + 1] = multiply(&matrix[i], &matrix[i + 1]); + matrix[i + 2] = add(&matrix[i + 1], &matrix[i + 2], +1); + } + } + + else if (op[i] == '+' && op[i + 1] == '*') { + struct m tmp = multiply(&matrix[i + 1], &matrix[i + 2]); + free(matrix[i + 1].data); + matrix[i + 1] = tmp; + + tmp = add(&matrix[i], &matrix[i + 1], +1); + free(matrix[i + 2].data); + matrix[i + 2] = tmp; + } + + else if (op[i] == '+' && op[i + 1] == '+') { + struct m tmp = add(&matrix[i], &matrix[i + 1], +1); + free(matrix[i + 1].data); + matrix[i + 1] = tmp; + + tmp = add(&matrix[i], &matrix[i + 2], +1); + free(matrix[i + 2].data); + matrix[i + 2] = tmp; + } + + else if (op[i] == '-' && op[i + 1] == '*') { + struct m tmp = multiply(&matrix[i + 1], &matrix[i + 2]); + free(matrix[i + 1].data); + matrix[i + 1] = tmp; + + tmp = add(&matrix[i], &matrix[i + 1], -1); + free(matrix[i + 2].data); + matrix[i + 2] = tmp; + } + } + + printf("=\n"); + print_matrix(&matrix[id]); /*Print the result */ + for (i = 0; i <= id; i++) + free(matrix[i].data); + free(matrix); +} + void read_file(int maxc, FILE *fp) { struct m *matrix; diff --git a/processing.h b/processing.h new file mode 100644 index 0000000..8cb51b9 --- /dev/null +++ b/processing.h @@ -0,0 +1,8 @@ +#ifndef _MATRIXLAB_PROCESSING_H_ +#define _MATRIXLAB_PROCESSING_H_ + +#include + +void read_file(int maxc, FILE *fp); + +#endif /* _MATRIXLAB_PROCESSING_H_ */ From 05f70c8120c92bfb31f2701877e9ca0f1a98cac3 Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Thu, 5 Sep 2019 01:24:25 +0300 Subject: [PATCH 07/28] declare local functions static --- matrix.c | 2 +- processing.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/matrix.c b/matrix.c index 3832af2..6d48aca 100644 --- a/matrix.c +++ b/matrix.c @@ -134,7 +134,7 @@ struct m add(const struct m *A, const struct m *B, double n) return C; } -void f(double x) +static void f(double x) { double i, f = modf(x, &i); diff --git a/processing.c b/processing.c index 9ee7267..2bb9c11 100644 --- a/processing.c +++ b/processing.c @@ -8,7 +8,7 @@ #define MAXNMATR 40 /* Max number of matrices */ #define MAXLINE 500 /* Max lenght of a line */ -void calculate(struct m *matrix, int nop, int id, char *op) +static void calculate(struct m *matrix, int nop, int id, char *op) { int i; From 65a8d7f1754158f95d3cb937ffcbf6187640114e Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Thu, 5 Sep 2019 01:38:56 +0300 Subject: [PATCH 08/28] matrix: add manipulation methods Add set of methods to create, access and free matrix object. Also matrix_is_square() predicate. At the moment new/free doesn't really allocate the objects to be compatible with the current codebase. Signed-off-by: Yauheni Kaliuta --- matrix.h | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/matrix.h b/matrix.h index 54d0155..826f962 100644 --- a/matrix.h +++ b/matrix.h @@ -1,6 +1,7 @@ #ifndef _MATRIXLAB_MATRIX_H_ #define _MATRIXLAB_MATRIX_H_ +#include #include struct m { @@ -9,6 +10,57 @@ struct m { double *data; }; +static inline struct m *matrix_new(struct m *M, size_t r, size_t c) +{ + double *t; + + t = malloc(sizeof(double) * r * c); + if (t == NULL) + abort(); + + M->data = t; + M->row = r; + M->col = c; + + return M; +} + +static inline void matrix_free(struct m *M) +{ + free(M->data); +} + +static inline size_t matrix_rows(struct m *M) +{ + return M->row; +} + +static inline size_t matrix_cols(struct m *M) +{ + return M->col; +} + +static inline double matrix_get(struct m *M, size_t r, size_t c) +{ + if (r >= M->row || c >= M->col) + abort(); + + return M->data[r * M->col + c]; +} + +static inline void matrix_set(struct m *M, size_t r, size_t c, double v) +{ + if (r >= M->row || c >= M->col) + abort(); + + M->data[r * M->col + c] = v; +} + +static inline bool matrix_is_square(struct m *M) +{ + return M->row == M->col; +} + struct m add(const struct m *A, const struct m *B, double n); struct m multiply(const struct m *A, const struct m *B); void print_matrix(struct m *A); From 3fe7cb313f0d2e606ff4723faef847f34ab44994 Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Thu, 5 Sep 2019 01:58:47 +0300 Subject: [PATCH 09/28] matrix: refactor inverse() to use new interface Use wrappers to access matrix. Fix C++ comments. Change the signature -- there is no point to pass the size, the only user of the function passed .row field. Output error message to stdout. Signed-off-by: Yauheni Kaliuta --- matrix.c | 63 +++++++++++++++++++++++++++++----------------------- matrix.h | 2 +- processing.c | 2 +- 3 files changed, 37 insertions(+), 30 deletions(-) diff --git a/matrix.c b/matrix.c index 6d48aca..bbf6b5d 100644 --- a/matrix.c +++ b/matrix.c @@ -4,42 +4,49 @@ #include #include -/*Calculate the inverse of a matrix */ - -void inverse(size_t n, struct m *A) +void inverse(struct m *A) { double det; - if ((det = determinant(n, A)) == 0) { - printf("The matrix is singular\n"); + size_t n = matrix_rows(A); + struct m C; /*The Adjoint matrix */ + struct m R; + size_t i, j, i_count, j_count, count; + int row; + int col; + double t; + + det = determinant(n, A); + if (det == 0) { + fprintf(stderr, "The matrix is singular\n"); exit(1); } - size_t i, j, i_count, j_count, count = 0; - - struct m C; /*The Adjoint matrix */ - C.data = malloc(sizeof(double) * n * n); - - C.row = n; - C.col = n; - double Rdata[(n - 1) * (n - 1)]; // remaining data values - struct m R = { n - 1, n - 1, Rdata }; // matrix structure for them - for (count = 0; count < n * n; count++) // Create n*n Matrix of Minors - { - int row = count / n, col = count % n; - for (i_count = i = 0; i < n; i++) - if (i != row) // don't copy the current row - { - for (j_count = j = 0; j < n; j++) - if (j != col) // don't copy the current column - Rdata[i_count * R.col + j_count++] = - A->data[i * A->col + j]; + matrix_new(&C, n, n); + matrix_new(&R, n - 1, n - 1); + /* Create n*n Matrix of Minors */ + for (count = 0; count < n * n; count++) { + row = count / n; + col = count % n; + + for (i_count = i = 0; i < n; i++) { + /* don't copy the current row */ + if (i != row) { + for (j_count = j = 0; j < n; j++) { + /* don't copy the current column */ + if (j != col) { + t = matrix_get(A, i, j); + matrix_set(&R, i_count, j_count++, t); + } + } i_count++; } - // transpose by swapping row and column - C.data[col * C.col + row] = - pow(-1, (row & 1) ^ (col & 1)) * determinant(n - 1, &R) / det; + } + /* transpose by swapping row and column */ + t = pow(-1, (row & 1) ^ (col & 1)) * determinant(n - 1, &R) / det; + matrix_set(&C, col, row, t); } - free(A->data); + matrix_free(&R); + matrix_free(A); *A = C; } diff --git a/matrix.h b/matrix.h index 826f962..4518b0c 100644 --- a/matrix.h +++ b/matrix.h @@ -67,6 +67,6 @@ void print_matrix(struct m *A); void transpose(struct m *A); double determinant(size_t n, struct m *A); void scalar_product(double scalar, struct m *B); -void inverse(size_t n, struct m *A); +void inverse(struct m *A); #endif /* _MATRIXLAB_MATRIX_H_ */ diff --git a/processing.c b/processing.c index 2bb9c11..ced516f 100644 --- a/processing.c +++ b/processing.c @@ -28,7 +28,7 @@ static void calculate(struct m *matrix, int nop, int id, char *op) if (matrix[0].row != matrix[0].col) printf ("Error: You can only calculate the inverse of square matrices\n"); - inverse(matrix[0].row, &matrix[0]); + inverse(&matrix[0]); } } From 02b8727c309806a036f47236cdc4e2840815069f Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Thu, 5 Sep 2019 02:18:53 +0300 Subject: [PATCH 10/28] matrix: refactor determinant Unify if-else-return. Change signature: remove n argument, there is no sense, it's a number of rows of the matrix. Use wrappers to access matrix object. Output error to stderr. More verbose message. Fix C++ comments. Signed-off-by: Yauheni Kaliuta --- matrix.c | 72 ++++++++++++++++++++++++++-------------------------- matrix.h | 2 +- processing.c | 2 +- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/matrix.c b/matrix.c index bbf6b5d..9da3102 100644 --- a/matrix.c +++ b/matrix.c @@ -15,7 +15,7 @@ void inverse(struct m *A) int col; double t; - det = determinant(n, A); + det = determinant(A); if (det == 0) { fprintf(stderr, "The matrix is singular\n"); exit(1); @@ -42,7 +42,7 @@ void inverse(struct m *A) } } /* transpose by swapping row and column */ - t = pow(-1, (row & 1) ^ (col & 1)) * determinant(n - 1, &R) / det; + t = pow(-1, (row & 1) ^ (col & 1)) * determinant(&R) / det; matrix_set(&C, col, row, t); } matrix_free(&R); @@ -50,50 +50,50 @@ void inverse(struct m *A) *A = C; } -double determinant(size_t n, struct m *A) +double determinant(struct m *A) { - size_t i, j, i_count, j_count, count = 0; - + size_t i, j, i_count, j_count, count; double det = 0; + double t; + struct m C; + size_t n = matrix_rows(A); if (n < 1) { - printf("Error\n"); + fprintf(stderr, "Error, matrix size < 1\n"); exit(1); } - else if (n == 1) - return A->data[0]; - - else if (n == 2) - return (A->data[0] * A->data[1 * A->col + 1] - - A->data[0 + 1] * A->data[1 * A->col + 0]); - - else { - struct m C; + if (n == 1) + return matrix_get(A, 0, 0); - C.row = A->row - 1; - C.col = A->col - 1; - - C.data = malloc(sizeof(double) * (A->row - 1) * (A->col - 1)); + if (n == 2) { + t = matrix_get(A, 0, 0) * matrix_get(A, 1, 1) + - matrix_get(A, 0, 1) * matrix_get(A, 1, 0); + return t; + } - for (count = 0; count < n; count++) { - //Creating array of Minors - i_count = 0; - for (i = 1; i < n; i++) { - j_count = 0; - for (j = 0; j < n; j++) { - if (j == count) - continue; // don't copy the minor column element - C.data[i_count * C.col + j_count] = A->data[i * A->col + j]; - j_count++; - } - i_count++; - } - det += pow(-1, count) * A->data[count] * determinant(n - 1, &C); //Recursive call - } - free(C.data); - return det; + matrix_new(&C, matrix_cols(A) - 1, matrix_rows(A) - 1); + + for (count = 0; count < n; count++) { + /* Creating array of Minors */ + i_count = 0; + for (i = 1; i < n; i++) { + j_count = 0; + for (j = 0; j < n; j++) { + if (j == count) + /* don't copy the minor column element */ + continue; + + t = matrix_get(A, i, j); + matrix_set(&C, i_count, j_count, t); + j_count++; + } + i_count++; + } + det += pow(-1, count) * matrix_get(A, count, 1) * determinant(&C); /* Recursive call */ } + matrix_free(&C); + return det; } struct m multiply(const struct m *A, const struct m *B) diff --git a/matrix.h b/matrix.h index 4518b0c..74c8e2d 100644 --- a/matrix.h +++ b/matrix.h @@ -65,7 +65,7 @@ struct m add(const struct m *A, const struct m *B, double n); struct m multiply(const struct m *A, const struct m *B); void print_matrix(struct m *A); void transpose(struct m *A); -double determinant(size_t n, struct m *A); +double determinant(struct m *A); void scalar_product(double scalar, struct m *B); void inverse(struct m *A); diff --git a/processing.c b/processing.c index ced516f..2ca8892 100644 --- a/processing.c +++ b/processing.c @@ -19,7 +19,7 @@ static void calculate(struct m *matrix, int nop, int id, char *op) transpose(&matrix[0]); else if (op[i] == 'd') { - matrix[i].data[0] = determinant(matrix[i].row, &matrix[i]); + matrix[i].data[0] = determinant(&matrix[i]); matrix[i].row = 1; matrix[i].col = 1; } From ddf980fe742af80f7deb5b9ae6586a2a1f9cf8d5 Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Thu, 5 Sep 2019 08:44:20 +0300 Subject: [PATCH 11/28] matrix: refactor multiply and add const to wrappers Use wrappers to access object. Move memory initialization to matrix_new(). It slow down execution a bit and not necessary for all operations, but looks as a proper responsibility split. Fix C++ comments. Fix wrappers to respect the const modifier. Signed-off-by: Yauheni Kaliuta --- matrix.c | 28 +++++++++++++++------------- matrix.h | 14 +++++++++----- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/matrix.c b/matrix.c index 9da3102..f896429 100644 --- a/matrix.c +++ b/matrix.c @@ -100,21 +100,23 @@ struct m multiply(const struct m *A, const struct m *B) { size_t i, j, k; struct m C; - C.data = malloc(sizeof(double) * A->row * B->col); + size_t row, col; + double t1, t2; - C.row = A->row; - C.col = B->col; + row = matrix_rows(A); + col = matrix_cols(B); - for (i = 0; i < C.row; i++) - for (j = 0; j < C.col; j++) - C.data[i * C.col + j] = 0; - - // Multiplying matrix A and B and storing in C. - for (i = 0; i < A->row; ++i) - for (j = 0; j < B->col; ++j) - for (k = 0; k < A->col; ++k) - C.data[i * C.col + j] += - A->data[i * A->col + k] * B->data[k * B->col + j]; + matrix_new(&C, col, row); + + /* Multiplying matrix A and B and storing in C */ + for (i = 0; i < row; ++i) + for (j = 0; j < col; ++j) + for (k = 0; k < matrix_cols(A); ++k) { + + t1 = matrix_get(A, i, k) * matrix_get(B, k, j); + t2 = matrix_get(&C, i, j); + matrix_set(&C, i, j, t1 + t2); + } return C; } diff --git a/matrix.h b/matrix.h index 74c8e2d..e95ac75 100644 --- a/matrix.h +++ b/matrix.h @@ -3,6 +3,7 @@ #include #include +#include struct m { size_t row; @@ -13,11 +14,14 @@ struct m { static inline struct m *matrix_new(struct m *M, size_t r, size_t c) { double *t; + size_t size = sizeof(double) * r * c; - t = malloc(sizeof(double) * r * c); + t = malloc(size); if (t == NULL) abort(); + memset(t, 0, size); + M->data = t; M->row = r; M->col = c; @@ -30,17 +34,17 @@ static inline void matrix_free(struct m *M) free(M->data); } -static inline size_t matrix_rows(struct m *M) +static inline size_t matrix_rows(const struct m *M) { return M->row; } -static inline size_t matrix_cols(struct m *M) +static inline size_t matrix_cols(const struct m *M) { return M->col; } -static inline double matrix_get(struct m *M, size_t r, size_t c) +static inline double matrix_get(const struct m *M, size_t r, size_t c) { if (r >= M->row || c >= M->col) abort(); @@ -56,7 +60,7 @@ static inline void matrix_set(struct m *M, size_t r, size_t c, double v) M->data[r * M->col + c] = v; } -static inline bool matrix_is_square(struct m *M) +static inline bool matrix_is_square(const struct m *M) { return M->row == M->col; } From bd4ce3018d9b3692687f4fdbeb1bb6bab202b186 Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Thu, 5 Sep 2019 08:08:34 +0300 Subject: [PATCH 12/28] matrix: add matrix_is_same_size predicate. Will be used in add() check instead of direct access. Signed-off-by: Yauheni Kaliuta --- matrix.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/matrix.h b/matrix.h index e95ac75..2d8aca5 100644 --- a/matrix.h +++ b/matrix.h @@ -65,6 +65,12 @@ static inline bool matrix_is_square(const struct m *M) return M->row == M->col; } +static inline bool matrix_is_same_size(const struct m *M1, + const struct m *M2) +{ + return (M1->row == M2->row) && (M1->col == M2->col); +} + struct m add(const struct m *A, const struct m *B, double n); struct m multiply(const struct m *A, const struct m *B); void print_matrix(struct m *A); From 9297411fd7fa3759b5eb24dd2b532260d8656d7a Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Thu, 5 Sep 2019 08:14:42 +0300 Subject: [PATCH 13/28] matrix: refactor add Use wrappers to access matrices. Output error message to stderr. Signed-off-by: Yauheni Kaliuta --- matrix.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/matrix.c b/matrix.c index f896429..a9d6303 100644 --- a/matrix.c +++ b/matrix.c @@ -123,22 +123,28 @@ struct m multiply(const struct m *A, const struct m *B) struct m add(const struct m *A, const struct m *B, double n) { - if ((A->row != B->row) || (A->col != B->col)) { - printf("Error: You can't sum up matrix of different dimension\n"); + size_t i, j; + struct m C; + size_t col, row; + double t; + + if (!matrix_is_same_size(A, B)) { + fprintf(stderr, + "Error: You can't sum up matrix of different dimension\n"); exit(1); } - size_t i, j; + col = matrix_cols(A); + row = matrix_rows(A); - struct m C; - C.data = malloc(sizeof(double) * A->row * B->col); - C.row = A->row; - C.col = A->col; + matrix_new(&C, col, row); - for (i = 0; i < C.row; i++) - for (j = 0; j < C.col; j++) - C.data[i * C.col + j] = - A->data[i * A->col + j] + n * B->data[i * B->col + j]; + for (i = 0; i < row; i++) { + for (j = 0; j < col; j++) { + t = matrix_get(A, i, j) + (n * matrix_get(B, i, j)); + matrix_set(&C, i, j, t); + } + } return C; } From 5d7c837979804d0d3dc1e4fac90b30de4dc948db Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Thu, 5 Sep 2019 08:20:43 +0300 Subject: [PATCH 14/28] matrix: refactor print_matrix Use wrapper to access the matrix. Rename helper to print_elem. Remove extra blank lines. Use const modifier. Signed-off-by: Yauheni Kaliuta --- matrix.c | 18 +++++++----------- matrix.h | 2 +- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/matrix.c b/matrix.c index a9d6303..df1f7e1 100644 --- a/matrix.c +++ b/matrix.c @@ -149,29 +149,25 @@ struct m add(const struct m *A, const struct m *B, double n) return C; } -static void f(double x) +static void print_elem(double x) { double i, f = modf(x, &i); if (f < .00001) printf("%.f ", i); - else printf("%f ", x); } -/*printing a Matrix*/ - -void print_matrix(struct m *A) +void print_matrix(const struct m *A) { - size_t i, j; + size_t row = matrix_rows(A); + size_t col = matrix_cols(A); - double *tmp = A->data; - - for (i = 0; i < A->row; i++) { - for (j = 0; j < A->col; j++) { - f(*(tmp++)); + for (i = 0; i < row; i++) { + for (j = 0; j < col; j++) { + print_elem(matrix_get(A, i, j)); } putchar('\n'); } diff --git a/matrix.h b/matrix.h index 2d8aca5..1dc984e 100644 --- a/matrix.h +++ b/matrix.h @@ -73,7 +73,7 @@ static inline bool matrix_is_same_size(const struct m *M1, struct m add(const struct m *A, const struct m *B, double n); struct m multiply(const struct m *A, const struct m *B); -void print_matrix(struct m *A); +void print_matrix(const struct m *A); void transpose(struct m *A); double determinant(struct m *A); void scalar_product(double scalar, struct m *B); From 29a0666af406636fc05c51a44eef52964e9d5862 Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Thu, 5 Sep 2019 08:51:02 +0300 Subject: [PATCH 15/28] matrix: refactor scalar_product Use wrappers to access matrix. Change signature to take matrix as the first argument. Signed-off-by: Yauheni Kaliuta --- matrix.c | 12 ++++++++---- matrix.h | 2 +- processing.c | 4 ++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/matrix.c b/matrix.c index df1f7e1..a8ad175 100644 --- a/matrix.c +++ b/matrix.c @@ -173,13 +173,17 @@ void print_matrix(const struct m *A) } } -void scalar_product(double scalar, struct m *B) +void scalar_product(struct m *A, double scalar) { size_t i, j; + double t; - for (i = 0; i < B->row; i++) - for (j = 0; j < B->col; j++) - B->data[i * B->col + j] = scalar * B->data[i * B->col + j]; + for (i = 0; i < matrix_rows(A); i++) { + for (j = 0; j < matrix_cols(A); j++) { + t = scalar * matrix_get(A, i, j); + matrix_set(A, i, j, t); + } + } } void transpose(struct m *A) diff --git a/matrix.h b/matrix.h index 1dc984e..0ed664c 100644 --- a/matrix.h +++ b/matrix.h @@ -76,7 +76,7 @@ struct m multiply(const struct m *A, const struct m *B); void print_matrix(const struct m *A); void transpose(struct m *A); double determinant(struct m *A); -void scalar_product(double scalar, struct m *B); +void scalar_product(struct m *A, double scalar); void inverse(struct m *A); #endif /* _MATRIXLAB_MATRIX_H_ */ diff --git a/processing.c b/processing.c index 2ca8892..9183d77 100644 --- a/processing.c +++ b/processing.c @@ -42,7 +42,7 @@ static void calculate(struct m *matrix, int nop, int id, char *op) else if (op[i] == '*' && op[i + 1] == '?') { if (matrix[i].row == 1 && matrix[i].col == 1) - scalar_product(matrix[i].data[0], &matrix[i + 1]); //Multiplication of Scalar per matrix + scalar_product(&matrix[i + 1], matrix[i].data[0]); //Multiplication of Scalar per matrix else { struct m tmp = multiply(&matrix[i], &matrix[i + 1]); free(matrix[i + 1].data); @@ -60,7 +60,7 @@ static void calculate(struct m *matrix, int nop, int id, char *op) else if (op[i] == '*' && op[i + 1] == '+') { if (matrix[i].row == 1 && matrix[i].col == 1) - scalar_product(matrix[i].data[0], &matrix[i + 1]); //Multiplication of Scalar per matrix + scalar_product(&matrix[i + 1], matrix[i].data[0]); //Multiplication of Scalar per matrix else { matrix[i + 1] = multiply(&matrix[i], &matrix[i + 1]); matrix[i + 2] = add(&matrix[i + 1], &matrix[i + 2], +1); From 5ed93bb3dcdd94ef70a5c1fedcbce122ecbc5f77 Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Thu, 5 Sep 2019 08:55:17 +0300 Subject: [PATCH 16/28] matrix: refactor transpose Use wrappers to access matrix. Free source matrix before overwriting to fix memory leak. Signed-off-by: Yauheni Kaliuta --- matrix.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/matrix.c b/matrix.c index a8ad175..832487d 100644 --- a/matrix.c +++ b/matrix.c @@ -189,14 +189,22 @@ void scalar_product(struct m *A, double scalar) void transpose(struct m *A) { struct m C; - C.data = malloc(sizeof(double) * A->row * A->col); + size_t i, j; + size_t row, col; + double t; - C.row = A->col; - C.col = A->row; + /* transpose, so opposite order */ + row = matrix_cols(A); + col = matrix_rows(A); - size_t i, j; - for (i = 0; i < C.row; i++) - for (j = 0; j < C.col; j++) - C.data[i * C.col + j] = A->data[j * A->col + i]; + matrix_new(&C, row, col); + + for (i = 0; i < row; i++) { + for (j = 0; j < col; j++) { + t = matrix_get(A, j, i); + matrix_set(&C, i, j, t); + } + } + matrix_free(A); *A = C; } From e7708055cf0242729f2160548b5580a9bf86bbf6 Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Thu, 5 Sep 2019 09:09:34 +0300 Subject: [PATCH 17/28] matrix: unify API All the operations return a new matrix and do not change arguments. That will make memory management for easier and consistent. Signed-off-by: Yauheni Kaliuta --- matrix.c | 30 +++++++++++++++++++----------- matrix.h | 8 ++++---- processing.c | 35 +++++++++++++++++++++++++---------- 3 files changed, 48 insertions(+), 25 deletions(-) diff --git a/matrix.c b/matrix.c index 832487d..9857d93 100644 --- a/matrix.c +++ b/matrix.c @@ -4,7 +4,7 @@ #include #include -void inverse(struct m *A) +struct m inverse(const struct m *A) { double det; size_t n = matrix_rows(A); @@ -45,12 +45,12 @@ void inverse(struct m *A) t = pow(-1, (row & 1) ^ (col & 1)) * determinant(&R) / det; matrix_set(&C, col, row, t); } + matrix_free(&R); - matrix_free(A); - *A = C; + return C; } -double determinant(struct m *A) +double determinant(const struct m *A) { size_t i, j, i_count, j_count, count; double det = 0; @@ -173,20 +173,28 @@ void print_matrix(const struct m *A) } } -void scalar_product(struct m *A, double scalar) +struct m scalar_product(const struct m *A, double scalar) { size_t i, j; double t; + struct m R; + size_t row, col; - for (i = 0; i < matrix_rows(A); i++) { - for (j = 0; j < matrix_cols(A); j++) { + row = matrix_rows(A); + col = matrix_cols(A); + + matrix_new(&R, row, col); + + for (i = 0; i < row; i++) { + for (j = 0; j < col; j++) { t = scalar * matrix_get(A, i, j); - matrix_set(A, i, j, t); + matrix_set(&R, i, j, t); } } + return R; } -void transpose(struct m *A) +struct m transpose(const struct m *A) { struct m C; size_t i, j; @@ -205,6 +213,6 @@ void transpose(struct m *A) matrix_set(&C, i, j, t); } } - matrix_free(A); - *A = C; + + return C; } diff --git a/matrix.h b/matrix.h index 0ed664c..6087161 100644 --- a/matrix.h +++ b/matrix.h @@ -74,9 +74,9 @@ static inline bool matrix_is_same_size(const struct m *M1, struct m add(const struct m *A, const struct m *B, double n); struct m multiply(const struct m *A, const struct m *B); void print_matrix(const struct m *A); -void transpose(struct m *A); -double determinant(struct m *A); -void scalar_product(struct m *A, double scalar); -void inverse(struct m *A); +struct m transpose(const struct m *A); +double determinant(const struct m *A); +struct m scalar_product(const struct m *A, double scalar); +struct m inverse(const struct m *A); #endif /* _MATRIXLAB_MATRIX_H_ */ diff --git a/processing.c b/processing.c index 9183d77..9cb5d2e 100644 --- a/processing.c +++ b/processing.c @@ -8,15 +8,28 @@ #define MAXNMATR 40 /* Max number of matrices */ #define MAXLINE 500 /* Max lenght of a line */ +#define IN_PLACE(op, pelem) do { \ + tmp = op(pelem); \ + matrix_free(pelem); \ + *pelem = tmp; \ + } while (0) + +#define IN_PLACE_1(op, pelem, arg) do { \ + tmp = op(pelem, arg); \ + matrix_free(pelem); \ + *pelem = tmp; \ + } while (0) + static void calculate(struct m *matrix, int nop, int id, char *op) { int i; + struct m tmp; for (i = 0; i < nop; i++) { /*Transpose the matrices */ if (op[i] == 't' || op[i] == 'T') - transpose(&matrix[0]); + IN_PLACE(transpose, &matrix[0]); else if (op[i] == 'd') { matrix[i].data[0] = determinant(&matrix[i]); @@ -28,13 +41,13 @@ static void calculate(struct m *matrix, int nop, int id, char *op) if (matrix[0].row != matrix[0].col) printf ("Error: You can only calculate the inverse of square matrices\n"); - inverse(&matrix[0]); + IN_PLACE(inverse, &matrix[0]); } } for (i = 0; i <= nop; i += 2) { if (op[i] == '+' && op[i + 1] == '?') { - struct m tmp = add(&matrix[i], &matrix[i + 1], +1); + tmp = add(&matrix[i], &matrix[i + 1], +1); free(matrix[i + 1].data); matrix[i + 1] = tmp; break; @@ -42,9 +55,10 @@ static void calculate(struct m *matrix, int nop, int id, char *op) else if (op[i] == '*' && op[i + 1] == '?') { if (matrix[i].row == 1 && matrix[i].col == 1) - scalar_product(&matrix[i + 1], matrix[i].data[0]); //Multiplication of Scalar per matrix + /* Multiplication of Scalar per matrix */ + IN_PLACE_1(scalar_product, &matrix[i + 1], matrix[i].data[0]); else { - struct m tmp = multiply(&matrix[i], &matrix[i + 1]); + tmp = multiply(&matrix[i], &matrix[i + 1]); free(matrix[i + 1].data); matrix[i + 1] = tmp; } @@ -52,7 +66,7 @@ static void calculate(struct m *matrix, int nop, int id, char *op) } else if (op[i] == '-' && op[i + 1] == '?') { - struct m tmp = add(&matrix[i], &matrix[i + 1], -1); + tmp = add(&matrix[i], &matrix[i + 1], -1); free(matrix[i + 1].data); matrix[i + 1] = tmp; break; @@ -60,7 +74,8 @@ static void calculate(struct m *matrix, int nop, int id, char *op) else if (op[i] == '*' && op[i + 1] == '+') { if (matrix[i].row == 1 && matrix[i].col == 1) - scalar_product(&matrix[i + 1], matrix[i].data[0]); //Multiplication of Scalar per matrix + /* Multiplication of Scalar per matrix */ + IN_PLACE_1(scalar_product, &matrix[i + 1], matrix[i].data[0]); else { matrix[i + 1] = multiply(&matrix[i], &matrix[i + 1]); matrix[i + 2] = add(&matrix[i + 1], &matrix[i + 2], +1); @@ -68,7 +83,7 @@ static void calculate(struct m *matrix, int nop, int id, char *op) } else if (op[i] == '+' && op[i + 1] == '*') { - struct m tmp = multiply(&matrix[i + 1], &matrix[i + 2]); + tmp = multiply(&matrix[i + 1], &matrix[i + 2]); free(matrix[i + 1].data); matrix[i + 1] = tmp; @@ -78,7 +93,7 @@ static void calculate(struct m *matrix, int nop, int id, char *op) } else if (op[i] == '+' && op[i + 1] == '+') { - struct m tmp = add(&matrix[i], &matrix[i + 1], +1); + tmp = add(&matrix[i], &matrix[i + 1], +1); free(matrix[i + 1].data); matrix[i + 1] = tmp; @@ -88,7 +103,7 @@ static void calculate(struct m *matrix, int nop, int id, char *op) } else if (op[i] == '-' && op[i + 1] == '*') { - struct m tmp = multiply(&matrix[i + 1], &matrix[i + 2]); + tmp = multiply(&matrix[i + 1], &matrix[i + 2]); free(matrix[i + 1].data); matrix[i + 1] = tmp; From 9dfefe93ac301241997bd0cc0b8cfef11c3e046e Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Thu, 5 Sep 2019 09:11:58 +0300 Subject: [PATCH 18/28] processing: move freeing array to read_file That makes allocation and cleaning on the same level. Signed-off-by: Yauheni Kaliuta --- processing.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/processing.c b/processing.c index 9cb5d2e..11be6df 100644 --- a/processing.c +++ b/processing.c @@ -115,9 +115,6 @@ static void calculate(struct m *matrix, int nop, int id, char *op) printf("=\n"); print_matrix(&matrix[id]); /*Print the result */ - for (i = 0; i <= id; i++) - free(matrix[i].data); - free(matrix); } void read_file(int maxc, FILE *fp) @@ -240,4 +237,8 @@ void read_file(int maxc, FILE *fp) } calculate(matrix, nop, id, op); + + for (i = 0; i <= id; i++) + free(matrix[i].data); + free(matrix); } From ffdfd726b3365e5b20c93d3587653daf593cbe0d Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Thu, 5 Sep 2019 09:18:31 +0300 Subject: [PATCH 19/28] processing: do not allocate matrix array dynamically There is no big point to allocate it dynamically, the size is known in advance. It can be better to make it static to save some stack, or change the logic for dynamic allocation but with automatic extending on demand. Signed-off-by: Yauheni Kaliuta --- processing.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/processing.c b/processing.c index 11be6df..8030ec6 100644 --- a/processing.c +++ b/processing.c @@ -119,7 +119,7 @@ static void calculate(struct m *matrix, int nop, int id, char *op) void read_file(int maxc, FILE *fp) { - struct m *matrix; + struct m matrix[MAXNMATR]; int id; /* id of a matrix */ size_t ncol, nrow; /* No of columns of a matrix */ int nop = 0; /* No of operators */ @@ -133,11 +133,6 @@ void read_file(int maxc, FILE *fp) for (i = 0; i < MAXNOP; i++) op[i] = '?'; - if (!(matrix = malloc(MAXNMATR * sizeof *(matrix)))) { - perror("malloc-matrix"); - exit(1); - } - ncol = 0; nrow = 0; id = 0; @@ -240,5 +235,4 @@ void read_file(int maxc, FILE *fp) for (i = 0; i <= id; i++) free(matrix[i].data); - free(matrix); } From 9edb9576c0610c5795bbe37bb11f64b31220005e Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Thu, 5 Sep 2019 11:36:40 +0300 Subject: [PATCH 20/28] processing: fix memory leak on mult and sum The overwritten objects must be freed. Signed-off-by: Yauheni Kaliuta --- processing.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/processing.c b/processing.c index 8030ec6..e1058de 100644 --- a/processing.c +++ b/processing.c @@ -77,8 +77,13 @@ static void calculate(struct m *matrix, int nop, int id, char *op) /* Multiplication of Scalar per matrix */ IN_PLACE_1(scalar_product, &matrix[i + 1], matrix[i].data[0]); else { + tmp = matrix[i + 1]; matrix[i + 1] = multiply(&matrix[i], &matrix[i + 1]); + free(tmp.data); + + tmp = matrix[i + 2]; matrix[i + 2] = add(&matrix[i + 1], &matrix[i + 2], +1); + free(tmp.data); } } From 1b88733da4c026f603d0c206fd420a30f8fe1429 Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Thu, 5 Sep 2019 12:32:19 +0300 Subject: [PATCH 21/28] processing: factor out matrix parsing logic Separate processing of file and creating of matrix. Signed-off-by: Yauheni Kaliuta --- matrix.h | 8 ++++ processing.c | 121 ++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 98 insertions(+), 31 deletions(-) diff --git a/matrix.h b/matrix.h index 6087161..8620749 100644 --- a/matrix.h +++ b/matrix.h @@ -29,6 +29,14 @@ static inline struct m *matrix_new(struct m *M, size_t r, size_t c) return M; } +static inline struct m *matrix_new_data(struct m *M, size_t r, size_t c, + double *data) +{ + matrix_new(M, r, c); + memcpy(M->data, data, sizeof(*M->data) * r * c); + return M; +} + static inline void matrix_free(struct m *M) { free(M->data); diff --git a/processing.c b/processing.c index e1058de..ad67dae 100644 --- a/processing.c +++ b/processing.c @@ -1,6 +1,7 @@ #include "matrix.h" #include +#include #include #include @@ -122,32 +123,101 @@ static void calculate(struct m *matrix, int nop, int id, char *op) print_matrix(&matrix[id]); /*Print the result */ } +struct matrix_state { + double *buf; + size_t row; + size_t col; + size_t pos; + bool started; /* matrix parsing started */ +}; + + +static void matrix_parse_init(struct matrix_state *s, int maxc) +{ + s->started = false; + s->buf = malloc(sizeof(*s->buf) * maxc); + if (s->buf == NULL) + abort(); +} + +static void matrix_parse_row(struct matrix_state *s, char *str) +{ + size_t off = 0; + int n; + + /* read numbers in a line into s->buf */ + while (sscanf(str + off, "%lf%n", &s->buf[s->pos], &n) == 1) { + s->pos++; + if (s->row == 0) + s->col++; + off += n; + } + + s->row++; +} + +static void matrix_parse_start(struct matrix_state *s, char *str) +{ + s->row = 0; + s->col = 0; + s->pos = 0; + s->started = true; +} + +static void matrix_parse_line(struct matrix_state *s, char *str) +{ + if (!s->started) + matrix_parse_start(s, str); + matrix_parse_row(s, str); +} + +static bool matrix_parse_end(struct matrix_state *s, struct m *M) +{ + if (!s->started) + return false; + + matrix_new_data(M, s->row, s->col, s->buf); + s->started = false; + return true; +} + +static bool matrix_parse_end_all(struct matrix_state *s, struct m *M) +{ + bool rc; + + rc = matrix_parse_end(s, M); + free(s->buf); + + return rc; +} + +static bool is_operator_line(char *buf) +{ + return !isdigit(*buf) && buf[1] == '\n'; +} + void read_file(int maxc, FILE *fp) { struct m matrix[MAXNMATR]; int id; /* id of a matrix */ - size_t ncol, nrow; /* No of columns of a matrix */ int nop = 0; /* No of operators */ - int off = 0; int i; - int n; - double *d; char buf[MAXLINE]; /* to store each lines of file */ char op[MAXNOP]; + struct matrix_state parse_state; + struct m tmp; for (i = 0; i < MAXNOP; i++) op[i] = '?'; - ncol = 0; - nrow = 0; + matrix_parse_init(&parse_state, maxc); id = 0; while (fgets(buf, MAXLINE, fp)) { - - if (nrow == 0) { - /* allocate/validate max no. of matrix */ - d = matrix[id].data = malloc(sizeof(double) * maxc); - } + if (id >= MAXNMATR) { + fprintf(stderr, "Too much matrices, max is %d\n", MAXNMATR); + abort(); + } if (strcmp(buf, "^-1\n") == 0) { op[nop++] = 'i'; /* matrix inverse operation */ @@ -164,33 +234,22 @@ void read_file(int maxc, FILE *fp) continue; } - /* check if line contains operator */ - if ((!isdigit(*buf) && buf[1] == '\n')) { - op[nop++] = *buf; - matrix[id].col = ncol; - matrix[id].row = nrow; - nrow = ncol = 0; - id++; + if (!is_operator_line(buf)) { + matrix_parse_line(&parse_state, buf); + } else { + if (matrix_parse_end(&parse_state, &tmp)) + matrix[id++] = tmp; + + op[nop++] = *buf; continue; } - /* read numbers in a line into d */ - while (sscanf(buf + off, "%lf%n", d, &n) == 1) { - d++; - if (nrow == 0) - ncol++; - off += n; - } - - nrow++; - off = 0; } /* end of while fgets cycle */ fclose(fp); - /* Assign last matrix No of columns and rows */ - matrix[id].col = ncol; - matrix[id].row = nrow; + if (matrix_parse_end_all(&parse_state, &tmp)) + matrix[id] = tmp; if (nop == 0) { fprintf(stderr, "Nothing to do\n"); From 5b5c5ed9d53c97998ab842338d6a9b504c892069 Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Thu, 5 Sep 2019 12:36:32 +0300 Subject: [PATCH 22/28] processing: fix lookup of -1 index of op array Signed-off-by: Yauheni Kaliuta --- processing.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/processing.c b/processing.c index ad67dae..79233bc 100644 --- a/processing.c +++ b/processing.c @@ -267,7 +267,8 @@ void read_file(int maxc, FILE *fp) if (op[i] == '*' || op[i] == '-' || op[i] == '+') { print_matrix(&matrix[i]); - if (op[i - 1] == 'i' || op[i - 1] == 'T' || op[i - 1] == 't') + if (i > 0 && + (op[i - 1] == 'i' || op[i - 1] == 'T' || op[i - 1] == 't')) continue; else printf("%c\n", op[i]); From 125380458105adb97becf9f4610491c02d7b9d27 Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Thu, 5 Sep 2019 12:41:40 +0300 Subject: [PATCH 23/28] processing: use variadic macro for IN_PLACE Signed-off-by: Yauheni Kaliuta --- processing.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/processing.c b/processing.c index 79233bc..13181c2 100644 --- a/processing.c +++ b/processing.c @@ -9,14 +9,8 @@ #define MAXNMATR 40 /* Max number of matrices */ #define MAXLINE 500 /* Max lenght of a line */ -#define IN_PLACE(op, pelem) do { \ - tmp = op(pelem); \ - matrix_free(pelem); \ - *pelem = tmp; \ - } while (0) - -#define IN_PLACE_1(op, pelem, arg) do { \ - tmp = op(pelem, arg); \ +#define IN_PLACE(op, pelem, ...) do { \ + tmp = op(pelem, ## __VA_ARGS__); \ matrix_free(pelem); \ *pelem = tmp; \ } while (0) @@ -57,7 +51,7 @@ static void calculate(struct m *matrix, int nop, int id, char *op) else if (op[i] == '*' && op[i + 1] == '?') { if (matrix[i].row == 1 && matrix[i].col == 1) /* Multiplication of Scalar per matrix */ - IN_PLACE_1(scalar_product, &matrix[i + 1], matrix[i].data[0]); + IN_PLACE(scalar_product, &matrix[i + 1], matrix[i].data[0]); else { tmp = multiply(&matrix[i], &matrix[i + 1]); free(matrix[i + 1].data); @@ -76,7 +70,7 @@ static void calculate(struct m *matrix, int nop, int id, char *op) else if (op[i] == '*' && op[i + 1] == '+') { if (matrix[i].row == 1 && matrix[i].col == 1) /* Multiplication of Scalar per matrix */ - IN_PLACE_1(scalar_product, &matrix[i + 1], matrix[i].data[0]); + IN_PLACE(scalar_product, &matrix[i + 1], matrix[i].data[0]); else { tmp = matrix[i + 1]; matrix[i + 1] = multiply(&matrix[i], &matrix[i + 1]); From a2d35d086cf263b7d1742c6e5470e94f6a989e53 Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Thu, 5 Sep 2019 12:49:50 +0300 Subject: [PATCH 24/28] processing: use wrappers Finish migrating to the public matrix API. Adds one more wrapper matrix_is_scalar(). Signed-off-by: Yauheni Kaliuta --- matrix.h | 5 +++++ processing.c | 44 ++++++++++++++++++++++++-------------------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/matrix.h b/matrix.h index 8620749..dbfeec9 100644 --- a/matrix.h +++ b/matrix.h @@ -79,6 +79,11 @@ static inline bool matrix_is_same_size(const struct m *M1, return (M1->row == M2->row) && (M1->col == M2->col); } +static inline bool matrix_is_scalar(const struct m *M) +{ + return M->col == 1 && M->row == 1; +} + struct m add(const struct m *A, const struct m *B, double n); struct m multiply(const struct m *A, const struct m *B); void print_matrix(const struct m *A); diff --git a/processing.c b/processing.c index 13181c2..a6cefce 100644 --- a/processing.c +++ b/processing.c @@ -20,6 +20,7 @@ static void calculate(struct m *matrix, int nop, int id, char *op) int i; struct m tmp; + double d; for (i = 0; i < nop; i++) { /*Transpose the matrices */ @@ -27,15 +28,16 @@ static void calculate(struct m *matrix, int nop, int id, char *op) IN_PLACE(transpose, &matrix[0]); else if (op[i] == 'd') { - matrix[i].data[0] = determinant(&matrix[i]); - matrix[i].row = 1; - matrix[i].col = 1; + d = determinant(&matrix[i]); + matrix_new_data(&matrix[i], 1, 1, &d); } if (op[i] == 'i') { - if (matrix[0].row != matrix[0].col) - printf - ("Error: You can only calculate the inverse of square matrices\n"); + if (matrix_is_square(&matrix[0])) { + fprintf(stderr, + "Error: You can only calculate the inverse of square matrices\n"); + abort(); + } IN_PLACE(inverse, &matrix[0]); } } @@ -43,7 +45,7 @@ static void calculate(struct m *matrix, int nop, int id, char *op) for (i = 0; i <= nop; i += 2) { if (op[i] == '+' && op[i + 1] == '?') { tmp = add(&matrix[i], &matrix[i + 1], +1); - free(matrix[i + 1].data); + matrix_free(&matrix[i + 1]); matrix[i + 1] = tmp; break; } @@ -54,7 +56,7 @@ static void calculate(struct m *matrix, int nop, int id, char *op) IN_PLACE(scalar_product, &matrix[i + 1], matrix[i].data[0]); else { tmp = multiply(&matrix[i], &matrix[i + 1]); - free(matrix[i + 1].data); + matrix_free(&matrix[i + 1]); matrix[i + 1] = tmp; } break; @@ -62,53 +64,55 @@ static void calculate(struct m *matrix, int nop, int id, char *op) else if (op[i] == '-' && op[i + 1] == '?') { tmp = add(&matrix[i], &matrix[i + 1], -1); - free(matrix[i + 1].data); + matrix_free(&matrix[i + 1]); matrix[i + 1] = tmp; break; } else if (op[i] == '*' && op[i + 1] == '+') { - if (matrix[i].row == 1 && matrix[i].col == 1) + if (matrix_is_scalar(&matrix[i])) /* Multiplication of Scalar per matrix */ - IN_PLACE(scalar_product, &matrix[i + 1], matrix[i].data[0]); + IN_PLACE(scalar_product, + &matrix[i + 1], + matrix_get(&matrix[i], 0, 0)); else { tmp = matrix[i + 1]; matrix[i + 1] = multiply(&matrix[i], &matrix[i + 1]); - free(tmp.data); + matrix_free(&tmp); tmp = matrix[i + 2]; matrix[i + 2] = add(&matrix[i + 1], &matrix[i + 2], +1); - free(tmp.data); + matrix_free(&tmp); } } else if (op[i] == '+' && op[i + 1] == '*') { tmp = multiply(&matrix[i + 1], &matrix[i + 2]); - free(matrix[i + 1].data); + matrix_free(&matrix[i + 1]); matrix[i + 1] = tmp; tmp = add(&matrix[i], &matrix[i + 1], +1); - free(matrix[i + 2].data); + matrix_free(&matrix[i + 2]); matrix[i + 2] = tmp; } else if (op[i] == '+' && op[i + 1] == '+') { tmp = add(&matrix[i], &matrix[i + 1], +1); - free(matrix[i + 1].data); + matrix_free(&matrix[i + 1]); matrix[i + 1] = tmp; tmp = add(&matrix[i], &matrix[i + 2], +1); - free(matrix[i + 2].data); + matrix_free(&matrix[i + 2]); matrix[i + 2] = tmp; } else if (op[i] == '-' && op[i + 1] == '*') { tmp = multiply(&matrix[i + 1], &matrix[i + 2]); - free(matrix[i + 1].data); + matrix_free(&matrix[i + 1]); matrix[i + 1] = tmp; tmp = add(&matrix[i], &matrix[i + 1], -1); - free(matrix[i + 2].data); + matrix_free(&matrix[i + 2]); matrix[i + 2] = tmp; } } @@ -293,5 +297,5 @@ void read_file(int maxc, FILE *fp) calculate(matrix, nop, id, op); for (i = 0; i <= id; i++) - free(matrix[i].data); + matrix_free(&matrix[i]); } From de202326e6cae388cc9469d6c85acfdaa3b02b6d Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Thu, 5 Sep 2019 13:14:56 +0300 Subject: [PATCH 25/28] switch to array of pointers Signed-off-by: Yauheni Kaliuta --- matrix.c | 62 ++++++++++++++-------------- matrix.h | 36 +++++++++-------- processing.c | 111 +++++++++++++++++++++++++++------------------------ 3 files changed, 109 insertions(+), 100 deletions(-) diff --git a/matrix.c b/matrix.c index 9857d93..26ac0fd 100644 --- a/matrix.c +++ b/matrix.c @@ -4,12 +4,12 @@ #include #include -struct m inverse(const struct m *A) +struct m *inverse(const struct m *A) { double det; size_t n = matrix_rows(A); - struct m C; /*The Adjoint matrix */ - struct m R; + struct m *C; /*The Adjoint matrix */ + struct m *R; size_t i, j, i_count, j_count, count; int row; int col; @@ -21,8 +21,8 @@ struct m inverse(const struct m *A) exit(1); } - matrix_new(&C, n, n); - matrix_new(&R, n - 1, n - 1); + C = matrix_new(n, n); + R = matrix_new(n - 1, n - 1); /* Create n*n Matrix of Minors */ for (count = 0; count < n * n; count++) { row = count / n; @@ -35,18 +35,18 @@ struct m inverse(const struct m *A) /* don't copy the current column */ if (j != col) { t = matrix_get(A, i, j); - matrix_set(&R, i_count, j_count++, t); + matrix_set(R, i_count, j_count++, t); } } i_count++; } } /* transpose by swapping row and column */ - t = pow(-1, (row & 1) ^ (col & 1)) * determinant(&R) / det; - matrix_set(&C, col, row, t); + t = pow(-1, (row & 1) ^ (col & 1)) * determinant(R) / det; + matrix_set(C, col, row, t); } - matrix_free(&R); + matrix_free(R); return C; } @@ -55,7 +55,7 @@ double determinant(const struct m *A) size_t i, j, i_count, j_count, count; double det = 0; double t; - struct m C; + struct m *C; size_t n = matrix_rows(A); if (n < 1) { @@ -72,7 +72,7 @@ double determinant(const struct m *A) return t; } - matrix_new(&C, matrix_cols(A) - 1, matrix_rows(A) - 1); + C = matrix_new(matrix_cols(A) - 1, matrix_rows(A) - 1); for (count = 0; count < n; count++) { /* Creating array of Minors */ @@ -85,28 +85,28 @@ double determinant(const struct m *A) continue; t = matrix_get(A, i, j); - matrix_set(&C, i_count, j_count, t); + matrix_set(C, i_count, j_count, t); j_count++; } i_count++; } - det += pow(-1, count) * matrix_get(A, count, 1) * determinant(&C); /* Recursive call */ + det += pow(-1, count) * matrix_get(A, count, 1) * determinant(C); /* Recursive call */ } - matrix_free(&C); + matrix_free(C); return det; } -struct m multiply(const struct m *A, const struct m *B) +struct m *multiply(const struct m *A, const struct m *B) { size_t i, j, k; - struct m C; + struct m *C; size_t row, col; double t1, t2; row = matrix_rows(A); col = matrix_cols(B); - matrix_new(&C, col, row); + C = matrix_new(col, row); /* Multiplying matrix A and B and storing in C */ for (i = 0; i < row; ++i) @@ -114,17 +114,17 @@ struct m multiply(const struct m *A, const struct m *B) for (k = 0; k < matrix_cols(A); ++k) { t1 = matrix_get(A, i, k) * matrix_get(B, k, j); - t2 = matrix_get(&C, i, j); - matrix_set(&C, i, j, t1 + t2); + t2 = matrix_get(C, i, j); + matrix_set(C, i, j, t1 + t2); } return C; } -struct m add(const struct m *A, const struct m *B, double n) +struct m *add(const struct m *A, const struct m *B, double n) { size_t i, j; - struct m C; + struct m *C; size_t col, row; double t; @@ -137,12 +137,12 @@ struct m add(const struct m *A, const struct m *B, double n) col = matrix_cols(A); row = matrix_rows(A); - matrix_new(&C, col, row); + C = matrix_new(col, row); for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { t = matrix_get(A, i, j) + (n * matrix_get(B, i, j)); - matrix_set(&C, i, j, t); + matrix_set(C, i, j, t); } } @@ -173,30 +173,30 @@ void print_matrix(const struct m *A) } } -struct m scalar_product(const struct m *A, double scalar) +struct m *scalar_product(const struct m *A, double scalar) { size_t i, j; double t; - struct m R; + struct m *R; size_t row, col; row = matrix_rows(A); col = matrix_cols(A); - matrix_new(&R, row, col); + R = matrix_new(row, col); for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { t = scalar * matrix_get(A, i, j); - matrix_set(&R, i, j, t); + matrix_set(R, i, j, t); } } return R; } -struct m transpose(const struct m *A) +struct m *transpose(const struct m *A) { - struct m C; + struct m *C; size_t i, j; size_t row, col; double t; @@ -205,12 +205,12 @@ struct m transpose(const struct m *A) row = matrix_cols(A); col = matrix_rows(A); - matrix_new(&C, row, col); + C = matrix_new(row, col); for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { t = matrix_get(A, j, i); - matrix_set(&C, i, j, t); + matrix_set(C, i, j, t); } } diff --git a/matrix.h b/matrix.h index dbfeec9..9e6ee4c 100644 --- a/matrix.h +++ b/matrix.h @@ -8,38 +8,40 @@ struct m { size_t row; size_t col; - double *data; + double data[]; }; -static inline struct m *matrix_new(struct m *M, size_t r, size_t c) +static inline struct m *matrix_new(size_t r, size_t c) { - double *t; - size_t size = sizeof(double) * r * c; + struct m *M; + size_t data_size = sizeof(M->data[0]) * r * c; - t = malloc(size); - if (t == NULL) + M = malloc(sizeof(*M) + data_size); + if (M == NULL) abort(); - memset(t, 0, size); + memset(M->data, 0, data_size); - M->data = t; M->row = r; M->col = c; return M; } -static inline struct m *matrix_new_data(struct m *M, size_t r, size_t c, - double *data) +static inline struct m *matrix_new_data(size_t r, size_t c, double *data) { - matrix_new(M, r, c); + struct m *M; + + M = matrix_new(r, c); memcpy(M->data, data, sizeof(*M->data) * r * c); return M; } static inline void matrix_free(struct m *M) { - free(M->data); + if (M == NULL) + return; + free(M); } static inline size_t matrix_rows(const struct m *M) @@ -84,12 +86,12 @@ static inline bool matrix_is_scalar(const struct m *M) return M->col == 1 && M->row == 1; } -struct m add(const struct m *A, const struct m *B, double n); -struct m multiply(const struct m *A, const struct m *B); +struct m *add(const struct m *A, const struct m *B, double n); +struct m *multiply(const struct m *A, const struct m *B); void print_matrix(const struct m *A); -struct m transpose(const struct m *A); +struct m *transpose(const struct m *A); double determinant(const struct m *A); -struct m scalar_product(const struct m *A, double scalar); -struct m inverse(const struct m *A); +struct m *scalar_product(const struct m *A, double scalar); +struct m *inverse(const struct m *A); #endif /* _MATRIXLAB_MATRIX_H_ */ diff --git a/processing.c b/processing.c index a6cefce..e569406 100644 --- a/processing.c +++ b/processing.c @@ -9,116 +9,120 @@ #define MAXNMATR 40 /* Max number of matrices */ #define MAXLINE 500 /* Max lenght of a line */ -#define IN_PLACE(op, pelem, ...) do { \ - tmp = op(pelem, ## __VA_ARGS__); \ - matrix_free(pelem); \ - *pelem = tmp; \ +#define IN_PLACE(op, elem, ...) do { \ + tmp = op(elem, ## __VA_ARGS__); \ + matrix_free(elem); \ + elem = tmp; \ } while (0) -static void calculate(struct m *matrix, int nop, int id, char *op) +static void calculate(struct m *matrix[], int nop, int id, char *op) { int i; - struct m tmp; + struct m *tmp; double d; for (i = 0; i < nop; i++) { /*Transpose the matrices */ if (op[i] == 't' || op[i] == 'T') - IN_PLACE(transpose, &matrix[0]); + IN_PLACE(transpose, matrix[0]); else if (op[i] == 'd') { - d = determinant(&matrix[i]); - matrix_new_data(&matrix[i], 1, 1, &d); + d = determinant(matrix[i]); + tmp = matrix[i]; + matrix[i] = matrix_new_data(1, 1, &d); + matrix_free(tmp); } if (op[i] == 'i') { - if (matrix_is_square(&matrix[0])) { + if (matrix_is_square(matrix[0])) { fprintf(stderr, "Error: You can only calculate the inverse of square matrices\n"); abort(); } - IN_PLACE(inverse, &matrix[0]); + IN_PLACE(inverse, matrix[0]); } } for (i = 0; i <= nop; i += 2) { if (op[i] == '+' && op[i + 1] == '?') { - tmp = add(&matrix[i], &matrix[i + 1], +1); - matrix_free(&matrix[i + 1]); + tmp = add(matrix[i], matrix[i + 1], +1); + matrix_free(matrix[i + 1]); matrix[i + 1] = tmp; break; } else if (op[i] == '*' && op[i + 1] == '?') { - if (matrix[i].row == 1 && matrix[i].col == 1) + if (matrix_is_scalar(matrix[i])) /* Multiplication of Scalar per matrix */ - IN_PLACE(scalar_product, &matrix[i + 1], matrix[i].data[0]); + IN_PLACE(scalar_product, + matrix[i + 1], + matrix_get(matrix[i], 0, 0)); else { - tmp = multiply(&matrix[i], &matrix[i + 1]); - matrix_free(&matrix[i + 1]); + tmp = multiply(matrix[i], matrix[i + 1]); + matrix_free(matrix[i + 1]); matrix[i + 1] = tmp; } break; } else if (op[i] == '-' && op[i + 1] == '?') { - tmp = add(&matrix[i], &matrix[i + 1], -1); - matrix_free(&matrix[i + 1]); + tmp = add(matrix[i], matrix[i + 1], -1); + matrix_free(matrix[i + 1]); matrix[i + 1] = tmp; break; } else if (op[i] == '*' && op[i + 1] == '+') { - if (matrix_is_scalar(&matrix[i])) + if (matrix_is_scalar(matrix[i])) /* Multiplication of Scalar per matrix */ IN_PLACE(scalar_product, - &matrix[i + 1], - matrix_get(&matrix[i], 0, 0)); + matrix[i + 1], + matrix_get(matrix[i], 0, 0)); else { tmp = matrix[i + 1]; - matrix[i + 1] = multiply(&matrix[i], &matrix[i + 1]); - matrix_free(&tmp); + matrix[i + 1] = multiply(matrix[i], matrix[i + 1]); + matrix_free(tmp); tmp = matrix[i + 2]; - matrix[i + 2] = add(&matrix[i + 1], &matrix[i + 2], +1); - matrix_free(&tmp); + matrix[i + 2] = add(matrix[i + 1], matrix[i + 2], +1); + matrix_free(tmp); } } else if (op[i] == '+' && op[i + 1] == '*') { - tmp = multiply(&matrix[i + 1], &matrix[i + 2]); - matrix_free(&matrix[i + 1]); + tmp = multiply(matrix[i + 1], matrix[i + 2]); + matrix_free(matrix[i + 1]); matrix[i + 1] = tmp; - tmp = add(&matrix[i], &matrix[i + 1], +1); - matrix_free(&matrix[i + 2]); + tmp = add(matrix[i], matrix[i + 1], +1); + matrix_free(matrix[i + 2]); matrix[i + 2] = tmp; } else if (op[i] == '+' && op[i + 1] == '+') { - tmp = add(&matrix[i], &matrix[i + 1], +1); - matrix_free(&matrix[i + 1]); + tmp = add(matrix[i], matrix[i + 1], +1); + matrix_free(matrix[i + 1]); matrix[i + 1] = tmp; - tmp = add(&matrix[i], &matrix[i + 2], +1); - matrix_free(&matrix[i + 2]); + tmp = add(matrix[i], matrix[i + 2], +1); + matrix_free(matrix[i + 2]); matrix[i + 2] = tmp; } else if (op[i] == '-' && op[i + 1] == '*') { - tmp = multiply(&matrix[i + 1], &matrix[i + 2]); - matrix_free(&matrix[i + 1]); + tmp = multiply(matrix[i + 1], matrix[i + 2]); + matrix_free(matrix[i + 1]); matrix[i + 1] = tmp; - tmp = add(&matrix[i], &matrix[i + 1], -1); - matrix_free(&matrix[i + 2]); + tmp = add(matrix[i], matrix[i + 1], -1); + matrix_free(matrix[i + 2]); matrix[i + 2] = tmp; } } printf("=\n"); - print_matrix(&matrix[id]); /*Print the result */ + print_matrix(matrix[id]); /*Print the result */ } struct matrix_state { @@ -169,17 +173,20 @@ static void matrix_parse_line(struct matrix_state *s, char *str) matrix_parse_row(s, str); } -static bool matrix_parse_end(struct matrix_state *s, struct m *M) +static bool matrix_parse_end(struct matrix_state *s, struct m **M) { + struct m *m; + if (!s->started) return false; - matrix_new_data(M, s->row, s->col, s->buf); + m = matrix_new_data(s->row, s->col, s->buf); s->started = false; + *M = m; return true; } -static bool matrix_parse_end_all(struct matrix_state *s, struct m *M) +static bool matrix_parse_end_all(struct matrix_state *s, struct m **M) { bool rc; @@ -196,17 +203,17 @@ static bool is_operator_line(char *buf) void read_file(int maxc, FILE *fp) { - struct m matrix[MAXNMATR]; + struct m *matrix[MAXNMATR]; int id; /* id of a matrix */ int nop = 0; /* No of operators */ int i; char buf[MAXLINE]; /* to store each lines of file */ char op[MAXNOP]; struct matrix_state parse_state; - struct m tmp; + struct m *tmp; - for (i = 0; i < MAXNOP; i++) - op[i] = '?'; + memset(matrix, 0, sizeof(matrix)); + memset(op, '?', sizeof(op)); matrix_parse_init(&parse_state, maxc); id = 0; @@ -259,12 +266,12 @@ void read_file(int maxc, FILE *fp) if (op[i] == 'd') { printf("det\n"); - print_matrix(&matrix[i]); + print_matrix(matrix[i]); continue; } if (op[i] == '*' || op[i] == '-' || op[i] == '+') { - print_matrix(&matrix[i]); + print_matrix(matrix[i]); if (i > 0 && (op[i - 1] == 'i' || op[i - 1] == 'T' || op[i - 1] == 't')) continue; @@ -274,7 +281,7 @@ void read_file(int maxc, FILE *fp) } if (op[i] == 't' || op[i] == 'T') { - print_matrix(&matrix[i]); + print_matrix(matrix[i]); printf("^T\n"); if (op[i + 1] != '?') printf("%c\n", op[i + 1]); @@ -282,7 +289,7 @@ void read_file(int maxc, FILE *fp) } if (op[i] == 'i') { - print_matrix(&matrix[i]); + print_matrix(matrix[i]); printf("^-1\n"); /* matrix inverse operation */ if (op[i + 1] != '?') printf("%c\n", op[i + 1]); @@ -290,12 +297,12 @@ void read_file(int maxc, FILE *fp) } if (op[i] == '?') { - print_matrix(&matrix[i]); + print_matrix(matrix[i]); } } calculate(matrix, nop, id, op); for (i = 0; i <= id; i++) - matrix_free(&matrix[i]); + matrix_free(matrix[i]); } From 7a07e329b47c8b80c28539e61ffdb4633bc1b585 Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Thu, 5 Sep 2019 15:30:08 +0300 Subject: [PATCH 26/28] unify determinant API determninant returns double, but in the main code (processing) scalar value actually represented as 1x1 matrix. Return such a matrix instead of double, makes code more consistent. Signed-off-by: Yauheni Kaliuta --- matrix.c | 96 ++++++++++++++++++++++++++++------------------------ matrix.h | 2 +- processing.c | 6 +--- 3 files changed, 54 insertions(+), 50 deletions(-) diff --git a/matrix.c b/matrix.c index 26ac0fd..8bf63de 100644 --- a/matrix.c +++ b/matrix.c @@ -4,6 +4,52 @@ #include #include +static double determinant_int(const struct m *A) +{ + size_t i, j, i_count, j_count, count; + double det = 0; + double t; + struct m *C; + size_t n = matrix_rows(A); + + if (n < 1) { + fprintf(stderr, "Error, matrix size < 1\n"); + exit(1); + } + + if (n == 1) + return matrix_get(A, 0, 0); + + if (n == 2) { + t = matrix_get(A, 0, 0) * matrix_get(A, 1, 1) + - matrix_get(A, 0, 1) * matrix_get(A, 1, 0); + return t; + } + + C = matrix_new(matrix_cols(A) - 1, matrix_rows(A) - 1); + + for (count = 0; count < n; count++) { + /* Creating array of Minors */ + i_count = 0; + for (i = 1; i < n; i++) { + j_count = 0; + for (j = 0; j < n; j++) { + if (j == count) + /* don't copy the minor column element */ + continue; + + t = matrix_get(A, i, j); + matrix_set(C, i_count, j_count, t); + j_count++; + } + i_count++; + } + det += pow(-1, count) * matrix_get(A, count, 1) * determinant_int(C); /* Recursive call */ + } + matrix_free(C); + return det; +} + struct m *inverse(const struct m *A) { double det; @@ -15,7 +61,7 @@ struct m *inverse(const struct m *A) int col; double t; - det = determinant(A); + det = determinant_int(A); if (det == 0) { fprintf(stderr, "The matrix is singular\n"); exit(1); @@ -42,7 +88,7 @@ struct m *inverse(const struct m *A) } } /* transpose by swapping row and column */ - t = pow(-1, (row & 1) ^ (col & 1)) * determinant(R) / det; + t = pow(-1, (row & 1) ^ (col & 1)) * determinant_int(R) / det; matrix_set(C, col, row, t); } @@ -50,50 +96,12 @@ struct m *inverse(const struct m *A) return C; } -double determinant(const struct m *A) +struct m *determinant(const struct m *A) { - size_t i, j, i_count, j_count, count; - double det = 0; - double t; - struct m *C; - size_t n = matrix_rows(A); - - if (n < 1) { - fprintf(stderr, "Error, matrix size < 1\n"); - exit(1); - } - - if (n == 1) - return matrix_get(A, 0, 0); - - if (n == 2) { - t = matrix_get(A, 0, 0) * matrix_get(A, 1, 1) - - matrix_get(A, 0, 1) * matrix_get(A, 1, 0); - return t; - } + double t; - C = matrix_new(matrix_cols(A) - 1, matrix_rows(A) - 1); - - for (count = 0; count < n; count++) { - /* Creating array of Minors */ - i_count = 0; - for (i = 1; i < n; i++) { - j_count = 0; - for (j = 0; j < n; j++) { - if (j == count) - /* don't copy the minor column element */ - continue; - - t = matrix_get(A, i, j); - matrix_set(C, i_count, j_count, t); - j_count++; - } - i_count++; - } - det += pow(-1, count) * matrix_get(A, count, 1) * determinant(C); /* Recursive call */ - } - matrix_free(C); - return det; + t = determinant_int(A); + return matrix_new_data(1, 1, &t); } struct m *multiply(const struct m *A, const struct m *B) diff --git a/matrix.h b/matrix.h index 9e6ee4c..4b3320c 100644 --- a/matrix.h +++ b/matrix.h @@ -90,7 +90,7 @@ struct m *add(const struct m *A, const struct m *B, double n); struct m *multiply(const struct m *A, const struct m *B); void print_matrix(const struct m *A); struct m *transpose(const struct m *A); -double determinant(const struct m *A); +struct m *determinant(const struct m *A); struct m *scalar_product(const struct m *A, double scalar); struct m *inverse(const struct m *A); diff --git a/processing.c b/processing.c index e569406..ea921e2 100644 --- a/processing.c +++ b/processing.c @@ -20,7 +20,6 @@ static void calculate(struct m *matrix[], int nop, int id, char *op) int i; struct m *tmp; - double d; for (i = 0; i < nop; i++) { /*Transpose the matrices */ @@ -28,10 +27,7 @@ static void calculate(struct m *matrix[], int nop, int id, char *op) IN_PLACE(transpose, matrix[0]); else if (op[i] == 'd') { - d = determinant(matrix[i]); - tmp = matrix[i]; - matrix[i] = matrix_new_data(1, 1, &d); - matrix_free(tmp); + IN_PLACE(determinant, matrix[i]); } if (op[i] == 'i') { From 87bd2479d582cd95b340985977bb2dd36256a827 Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Thu, 5 Sep 2019 15:36:19 +0300 Subject: [PATCH 27/28] processing: factor out summary printing It's a pretty separate code, make a function for it. Signed-off-by: Yauheni Kaliuta --- processing.c | 84 ++++++++++++++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/processing.c b/processing.c index ea921e2..b62f2c7 100644 --- a/processing.c +++ b/processing.c @@ -121,6 +121,50 @@ static void calculate(struct m *matrix[], int nop, int id, char *op) print_matrix(matrix[id]); /*Print the result */ } +static void print_task(struct m *matrix[], size_t id, char *op) +{ + size_t i; + + for (i = 0; i <= id; i++) { + + if (op[i] == 'd') { + printf("det\n"); + print_matrix(matrix[i]); + continue; + } + + if (op[i] == '*' || op[i] == '-' || op[i] == '+') { + print_matrix(matrix[i]); + if (i > 0 && + (op[i - 1] == 'i' || op[i - 1] == 'T' || op[i - 1] == 't')) + continue; + else + printf("%c\n", op[i]); + continue; + } + + if (op[i] == 't' || op[i] == 'T') { + print_matrix(matrix[i]); + printf("^T\n"); + if (op[i + 1] != '?') + printf("%c\n", op[i + 1]); + continue; + } + + if (op[i] == 'i') { + print_matrix(matrix[i]); + printf("^-1\n"); /* matrix inverse operation */ + if (op[i + 1] != '?') + printf("%c\n", op[i + 1]); + continue; + } + + if (op[i] == '?') { + print_matrix(matrix[i]); + } + } +} + struct matrix_state { double *buf; size_t row; @@ -257,45 +301,7 @@ void read_file(int maxc, FILE *fp) exit(1); } - /* Printing the matrices and operations */ - for (i = 0; i <= id; i++) { - - if (op[i] == 'd') { - printf("det\n"); - print_matrix(matrix[i]); - continue; - } - - if (op[i] == '*' || op[i] == '-' || op[i] == '+') { - print_matrix(matrix[i]); - if (i > 0 && - (op[i - 1] == 'i' || op[i - 1] == 'T' || op[i - 1] == 't')) - continue; - else - printf("%c\n", op[i]); - continue; - } - - if (op[i] == 't' || op[i] == 'T') { - print_matrix(matrix[i]); - printf("^T\n"); - if (op[i + 1] != '?') - printf("%c\n", op[i + 1]); - continue; - } - - if (op[i] == 'i') { - print_matrix(matrix[i]); - printf("^-1\n"); /* matrix inverse operation */ - if (op[i + 1] != '?') - printf("%c\n", op[i + 1]); - continue; - } - - if (op[i] == '?') { - print_matrix(matrix[i]); - } - } + print_task(matrix, id, op); calculate(matrix, nop, id, op); From cfc101e44ffe9995f0b2a8b374ecb321f2c8fa01 Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Fri, 6 Sep 2019 13:44:30 +0300 Subject: [PATCH 28/28] matrix: determinant: fixing lookup of element data[count] is actually A[0][count], not [count][1] Signed-off-by: Yauheni Kaliuta --- matrix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix.c b/matrix.c index 8bf63de..df910b2 100644 --- a/matrix.c +++ b/matrix.c @@ -44,7 +44,7 @@ static double determinant_int(const struct m *A) } i_count++; } - det += pow(-1, count) * matrix_get(A, count, 1) * determinant_int(C); /* Recursive call */ + det += pow(-1, count) * matrix_get(A, 0, count) * determinant_int(C); /* Recursive call */ } matrix_free(C); return det;