Download or See Image Here
The problem statement is that I need to perform dilation and erosion on a binary image and using a structure element of dimension given by the user typically a 1D or 2D array and it can be square matrix(n X n) or rectangle matrix (m X n) where m, n can be even or odd integers.
This is morphological image processing using C language.
I implemented the following code, but I am not getting output as expected. Can any one tell me my mistake?
I am taking origin as a // 2 and b // 2 of structuring element which is order of a X b.
The following is my main function in image processing.
#include "DEOC.h"
int main(int argc, char *argv[])<br>
{
FILE *fp, *op1, *op2, *op3, *op4;
fp = fopen(argv[1], "r");
op1 = fopen(argv[2], "wb");
op2 = fopen(argv[3], "wb");
op3 = fopen(argv[4], "wb");
op4 = fopen(argv[5], "wb");
if (fp == NULL)
{
printf("There is a problem in file opening!!! Please check again!!!");
exit(0);
}
int i, j, col, row, x, y, temp;
char ch1, ch2;
fscanf(fp, "%c%c", &ch1, &ch2);
fscanf(fp, "%d %d", &col, &row);
fprintf(op1, "%c%c\n", ch1, ch2);
fprintf(op1, "%d %d\n", col, row);
fprintf(op2, "%c%c\n", ch1, ch2);
fprintf(op2, "%d %d\n", col, row);
fprintf(op3, "%c%c\n", ch1, ch2);
fprintf(op3, "%d %d\n", col, row);
fprintf(op4, "%c%c\n", ch1, ch2);
fprintf(op4, "%d %d\n", col, row);
int *img, *dialated_img, *eroted_img, *opened, *closed, *structure;
img = (int *)malloc(row * col * sizeof(int));
dialated_img = (int *)malloc(row * col * sizeof(int));
eroted_img = (int *)malloc(row * col * sizeof(int));
opened = (int *)malloc(row * col * sizeof(int));
closed = (int *)malloc(row * col * sizeof(int));
printf("Enter x: - ");
scanf("%d", &x);
printf("Enter y: - ");
scanf("%d", &y);
structure = (int *)malloc(x * y * sizeof(int));
for (i = 0; i < x; i++)
{
for (j = 0; j < y; j++)
{
*(structure + i * y + j) = 1;
}
}
printf("Used Structure is: -\n");
for (i = 0; i < x; i++)
{
for (j = 0; j < y; j++)
{
printf("%d ", *(structure + i * y + j));
}
printf("\n");
}
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
fscanf(fp, "%d", &temp);
*(img + i * col + j) = temp;
*(dialated_img + i * col + j) = temp;
*(eroted_img + i * col + j) = temp;
*(opened + i * col + j) = temp;
*(closed + i * col + j) = temp;
}
}
dialation(img, dialated_img, structure, row, col, x, y);
erosion(img, eroted_img, structure, row, col, x, y);
opening(img, opened, structure, row, col, x, y);
closing(img, closed, structure, row, col, x, y);
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
fprintf(op1, "%d", *(dialated_img + i * col + j));
fprintf(op2, "%d", *(eroted_img + i * col + j));
fprintf(op3, "%d", *(opened + i * col + j));
fprintf(op4, "%d", *(closed + i * col + j));
}
fprintf(op1, "\n");
fprintf(op2, "\n");
fprintf(op3, "\n");
fprintf(op4, "\n");
}
fclose(fp);
fclose(op1);
fclose(op2);
fclose(op3);
fclose(op4);
return 0;
}
The DEOC.h file is
#include <stdio.h>
#include <stdlib.h>
void dialation(int *img, int *dialation_img, int *structure, int row, int col, int x, int y)
{
int s = x / 2;
int a = y / 2;
for (int i = s; i < row - s; i++)
{
for (int j = a; j < col - a; j++)
{
if (*(img + i * col + j) == 1)
{
continue;
}
else
{
for (int w = -1 * s; w <= s; w++)
{
for (int q = -1 * a; q <= a; q++)
{
if (*(structure + (w + s) * y + (q + a)) == 1)
{
if (*(img + (i + w) * col + (j + q)) == 1)
{
*(dialation_img + i * col + j) = 2;
continue;
}
}
}
}
}
}
}
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (*(dialation_img + i * col + j) == 2)
{
*(dialation_img + i * col + j) = 1;
}
}
}
}
void erosion(int *img, int *erosion_img, int *structure, int row, int col, int x, int y)
{
int s = x / 2;
int a = y / 2;
for (int i = s; i < row - s; i++)
{
for (int j = a; j < col - a; j++)
{
for (int w = -1 * s; w <= s; x++)
{
for (int q = -1 * a; q <= a; y++)
{
if (x == 0 && y == 0)
{
continue;
}
else
{
if (*(structure + (w + s) * y + (q + a)) == 1)
{
if (*(img + (i + w) * col + (j + q)) == 0)
{
*(erosion_img + i * col + j) = 2;
continue;
}
}
}
}
}
}
}
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (*(erosion_img + i * col + j) == 2)
{
*(erosion_img + i * col + j) = 0;
}
}
}
}
void opening(int *img, int *opened_img, int *structure, int row, int col, int x, int y)
{
erosion(img, opened_img, structure, row, col, x, y);
dialation(img, opened_img, structure, row, col, x, y);
}
void closing(int *img, int *closed_img, int *structure, int row, int col, int x, int y)
{
dialation(img, closed_img, structure, row, col, x, y);
erosion(img, closed_img, structure, row, col, x, y);
}
I am trying to use it but it is not executing properly.
Related
I'm trying to write a function that does naive matrix multiplication of two contiguous, row-major arrays. But when I attempt to print each value at the end I get garbage. I'm guessing it's because I've mixed up the proper iterations and scaling needed to jump rows/columns. Does anyone have any advice?
Full code necessary is below:
#include <stdio.h>
#include <stdlib.h>
void dmatmul(double *a, double *b, double *c, int astride, int bstride, int cdim_0, int cdim_1) {
int i, j, p;
for (i = 0; i < cdim_0; i++) {
for (j = 0; j < cdim_1; j++) {
c[i * cdim_1 + j] = 0.0;
for (p = 0; p < (astride); p++) {
c[i * cdim_1 + j] += a[i * (astride) + p] * b[p * (bstride) + j];
}
}
}
}
int main(void) {
double *x, *y, *z;
int xdim_0, xdim_1, ydim_0, ydim_1, zdim_0, zdim_1, i, j;
xdim_0 = 2;
xdim_1 = 4;
ydim_0 = 4;
ydim_1 = 2;
zdim_0 = 2;
zdim_1 = 2;
x = (double *) malloc (xdim_0 * xdim_1 * sizeof(double));
y = (double *) malloc (ydim_0 * ydim_1 * sizeof(double));
z = (double *) malloc (zdim_0 * zdim_1 * sizeof(double));
for (i = 0; i < xdim_0 * xdim_1; i++) {
x[i] = i + 1;
y[i] = 2 * (i + 1);
}
dmatmul(x, y, z, xdim_1, ydim_1, zdim_0, zdim_1);
printf("\nMatrix product of X and Y dimensions: (%d, %d)\n", zdim_0, zdim_1);
printf("Matrix product of X and Y values:");
for (i = 0; i < zdim_0; i++) {
printf("\n");
for (j = 0; j < zdim_1; i++) {
printf("\t%f", z[i * zdim_1 + j]);
}
}
return 0;
}
The primary problem is a typo in the inner for loop doing the printing. You have:
for (j = 0; j < zdim_1; i++)
but you ned to increment j, not i:
for (j = 0; j < zdim_1; j++)
Here's my code, which has an independent matrix printing function appropriate for the arrays you're using:
/* SO 7516-7451 */
#include <stdio.h>
#include <stdlib.h>
static void dmatmul(double *a, double *b, double *c, int astride, int bstride, int cdim_0, int cdim_1)
{
int i, j, p;
for (i = 0; i < cdim_0; i++)
{
for (j = 0; j < cdim_1; j++)
{
c[i * cdim_1 + j] = 0.0;
for (p = 0; p < (astride); p++)
{
c[i * cdim_1 + j] += a[i * (astride) + p] * b[p * (bstride) + j];
}
}
}
}
static void mat_print(const char *tag, int rows, int cols, double *matrix)
{
printf("%s (%dx%d):\n", tag, rows, cols);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
printf("%4.0f", matrix[i * cols + j]);
putchar('\n');
}
}
int main(void)
{
int xdim_0 = 2;
int xdim_1 = 4;
int ydim_0 = 4;
int ydim_1 = 2;
int zdim_0 = 2;
int zdim_1 = 2;
double *x = (double *)malloc(xdim_0 * xdim_1 * sizeof(double));
double *y = (double *)malloc(ydim_0 * ydim_1 * sizeof(double));
double *z = (double *)malloc(zdim_0 * zdim_1 * sizeof(double));
for (int i = 0; i < xdim_0 * xdim_1; i++)
{
x[i] = i + 1;
y[i] = 2 * (i + 1);
}
mat_print("X", xdim_0, xdim_1, x);
mat_print("Y", ydim_0, ydim_1, y);
dmatmul(x, y, z, xdim_1, ydim_1, zdim_0, zdim_1);
mat_print("Z", zdim_0, zdim_1, z);
printf("\nMatrix product of X and Y dimensions: (%d, %d)\n", zdim_0, zdim_1);
printf("Matrix product of X and Y values:\n");
for (int i = 0; i < zdim_0; i++)
{
for (int j = 0; j < zdim_1; j++)
printf("\t%f", z[i * zdim_1 + j]);
printf("\n");
}
return 0;
}
I've also initialized the variables as I declared them. The code should, but does not, check that the memory was allocated.
When I ran this code without your printing, I got the correct result, so then I took a good look at that and saw the problem.
X (2x4):
1 2 3 4
5 6 7 8
Y (4x2):
2 4
6 8
10 12
14 16
Z (2x2):
100 120
228 280
Matrix product of X and Y dimensions: (2, 2)
Matrix product of X and Y values:
100.000000 120.000000
228.000000 280.000000
I have a problem with increasing C[] array from 6 to 10 I've faced with heap corruption problem by realloc(). I have a following code of Big M metod:
#include <stdio.h>
#include <stdlib.h>
int * mnInit(FILE * );
double * * ReadA(FILE * , int, int);
double * ReadVector(FILE * , int);
int * condtxt(FILE *, int );
void Artif_counter(int* , int *, int);
void reallocationA(double**, int* , int , int);
void increaseA(int*, double**, int, int, int);
void increaseC(double *, int);
int main(int argc, char * argv[]) {
FILE * file1 = fopen("C.txt", "r");
FILE * file4 = fopen("A.txt", "r");
FILE * file5 = fopen("Agetmn.txt", "r");
FILE * file6 = fopen("cond.txt", "r");
int * ptr_mn;
ptr_mn = mnInit(file5);
int n = * (ptr_mn);
int m = * (ptr_mn + 1);
double * * A;
A = ReadA(file4, n, m);
double * C;
C = ReadVector(file1, n);
int * cond;
cond = condtxt(file6, m);
for(int i = 0; i < m; i++){
}
//--------------------------------------------------
int BAcounter = 0;
Artif_counter(cond, &BAcounter, m);
printf("\n Basys and Artifical variable = %d", BAcounter);
reallocationA(A, &n, m, BAcounter);
increaseA(cond, A, n, m, BAcounter);
this function dont't working
increaseC(C, n);
When I trying to print arrays: the A[][] was printed right while C[] array was printed by unknown numbers and after the program Mmetod.exe was closed with problem: A heap has been corrupted (parameters: 0x00007FFCA0C1F6B0).
// count of basys and artif
//------------------------------------------------After Adding a new columns:
printf("\n A[][] ARRAY:\n");
for (int i = 0; i < m; i++) {
printf("%d ", i);
for (int j = 0; j < n; j++) {
printf(" %.3f ", A[i][j]);
}
printf("\n");
}
printf("\n\tVECTOR C[]:\n");
for (int i = 0; i < n; i++) {
printf("%lf ", C[i]);
}
fclose(file1);
fclose(file4);
fclose(file5);
fclose(file6);
free(C);
for (int i = 0; i < m; i++) {
free(A[i]);
}
free(A);
printf("\n\n");
system("pause");
return 0;
}
int * mnInit(FILE * file) {
int c;
int digit = 0;
int column = 0;
int * mnArray = malloc(2 * sizeof( * mnArray));
if (file == NULL) perror("Warning!");
else {
while (!feof(file)) {
c = fgetc(file);
if (c == ';') {
column++;
}
if (c == ' ') {
digit++;
}
}
}
* (mnArray) = (digit / column) + 1; * (mnArray + 1) = column;
return mnArray;
}
double * * ReadA(FILE * file, int n, int m) {
double * * A = malloc(m * sizeof( * A));
for (int i = 0; i < m; i++) {
A[i] = malloc(n * sizeof( * A[i]));
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
//fscanf(file ,"%lf ", &(*(*(A + i) + j)));
fscanf(file, "%lf ", & A[i][j]);
}
fscanf(file, "\n");
}
return A;
}
double * ReadVector(FILE * file, int m) { // ++++
double * Vector = malloc(m * sizeof( * Vector));
for (int i = 0; i < m; i++) {
fscanf(file, "%lf ", Vector + i);
}
return Vector;
}
int* condtxt(FILE * file, int m){
int * condA = malloc(m * sizeof(*condA));
for(int i = 0; i < m; i++){
fscanf(file, "%d", &condA[i]);
}
return condA;
}
void Artif_counter(int * cond, int *k, int m){
for(int i = 0; i < m; i++){
if(cond[i] == -1){
(*k)++;
}
if(cond[i] == 0){
(*k)++;
}
if(cond[i] == 1){
*k = (*k) + 2;
}
}
}
void reallocationA(double** A, int* n, int m, int k){
double * tmp = NULL;
for(int i = 0; i < m; i++){
tmp = realloc(A[i], ((*n) + k)*sizeof(*A[i]));
if(tmp){
A[i] = tmp;
tmp = NULL;
} else{
printf("Error! Memory isn't reallocated'");
tmp = NULL;
}
}
(*n) = (*n) + k;
}
void increaseA(int* cond, double** A, int n, int m, int k){
int presentcol = n-k;
for(int i = 0; i < m; i++){
if(cond[i] == -1){
for(int j = 0; j < m; j++){
if(j == i){
A[j][presentcol] = 1;
} else {
A[j][presentcol] = 0;
}
}
presentcol++;
}
if(cond[i] == 0){
for(int j = 0; j < m; j++){
if(j == i){
A[j][presentcol] = 1;
} else {
A[j][presentcol] = 0;
}
}
presentcol++;
}
if(cond[i] == 1){
for(int j = 0; j < m; j++){
if(j == i){
A[j][presentcol] = 1;
A[j][presentcol + 1] = -1;
} else {
A[j][presentcol] = 0;
A[j][presentcol + 1] = 0;
}
}
presentcol = presentcol + 2;
}
}
}
When I wanted to increase an array in a simple code by this function it've done and I don't understand why(
A GNU debugger rewiev: 0 warning: Critical error detected c0000374
void increaseC(double * C, int n){
double * tmp;
tmp = realloc(C, (n)*sizeof(*C)); // found out that realloc function caused an error
if(!tmp){
printf("Error");
} else{
C = tmp;
}
tmp = NULL;
}
I have a program that:
given a sequence of numbers,
sorts even numbers in ascending order, and
sort odd numbers in descending order, and
adds the sorted even numbers to an array followed by the sorted odd numbers.
Example:
Input: 1, 2, 3, 4, 5, 6
Expected output: 2, 4, 6, 5, 3, 1
Actual output: 1578032, 0, 3, 6, 6487408, 0
here is my code:
#include < stdio.h >
int main() {
input();
}
int input() {
int n;
printf("Enter The Number Of Elements You Want To Enter : ");
scanf("%d", & n);
int * ptr, i, ev = 0, od = 0;
ptr = (int * ) calloc(n, sizeof(int));
for (i = 0; i < n; i++) {
printf("Enter Number : ");
scanf("%d", (ptr + i));
if ( * (ptr + i) % 2 == 0) {
ev++;
} else {
od++;
}
}
sorteven( & ptr, ev, od, n);
}
int sorteven(int * ptr, int ev, int od, int n) {
int i, j = 0, swap = 0, * ptreven;
ptreven = (int * ) calloc(ev, sizeof(int));
for (i = 0; i < n; i++) {
if ( * (ptr + i) % 2 == 0) { *
(ptreven + j) = * (ptr + i);
j++;
}
}
for (i = 0; i < ev - 1; i++) {
for (j = 0; j < ev - i - 1; j++) {
if ( * (ptreven + j) > * (ptreven + j + 1)) {
swap = * (ptreven + j); *
(ptreven + j) = * (ptreven + j + 1); *
(ptreven + j + 1) = swap;
}
}
}
sortodd( & ptr, ev, od, n, & ptreven);
}
int sortodd(int * ptr, int ev, int od, int n, int ptreven) {
int i, k = 0, swap = 0, * ptrodd, j;
ptrodd = (int * ) calloc(od, sizeof(int));
for (i = 0; i < n; i++) {
if ( * (ptr + i) % 2 != 0) { *
(ptrodd + k) = * (ptr + i);
k++;
}
}
for (i = 0; i < od - 1; i++) {
for (j = 0; j < od - i - 1; j++) {
if ( * (ptrodd + j) < * (ptrodd + j + 1)) {
swap = * (ptrodd + j); *
(ptrodd + j) = * (ptrodd + j + 1); *
(ptrodd + j + 1) = swap;
}
}
}
merge( & ptr, ev, od, n, & ptreven, & ptrodd);
}
int merge(int * ptr, int ev, int od, int n, int * ptreven, int * ptrodd) {
int * ptrmerge, i, j;
ptrmerge = (int * ) calloc(n, sizeof(int));
for (i = 0; i < ev; i++) { *
(ptrmerge + i) = * (ptreven + i);
}
for (i = ev, j = 0; i < n; i++, j++) { *
(ptrmerge + i) = * (ptrodd + j);
}
display( & ptrmerge, n);
}
int display(int * ptrmerge, int n) {
int i;
printf("OUTPUT : ");
for (i = 0; i < n; i++) {
printf(" %d ", * (ptrmerge + i));
}
}
like this
#include <stdio.h>
#include <stdlib.h>
void input(void);
int main(void){
input();
}
void sorteven(int *ptr, int n);
void sortodd(int *ptr, int n);
void display(int *ptt, int n);
void input(void){
int n;
printf("Enter The Number Of Elements You Want To Enter : ");fflush(stdout);
scanf("%d", &n);
int *ptr, i, ev = 0, od = 0;
if((ptr = calloc(n, sizeof(int)))==NULL){
perror("malloc");
exit(EXIT_FAILURE);
}
for (i = 0; i < n; i++){
int v;
printf("Enter Number : ");fflush(stdout);
scanf("%d", &v);
if(v % 2 == 0){
ptr[ev++] = v;
} else {
ptr[n - ++od] = v;
}
}
sorteven(ptr, ev);
sortodd(ptr + ev, od);
display(ptr, n);
free(ptr);
}
void sorteven(int *ptr, int n){
//sort to ascending order
int i, j, temp;
for (i = 0; i < n - 1; i++){
for (j = 0; j < n - i - 1; j++){
if(ptr[j] > ptr[j + 1]){
int temp = ptr[j];
ptr[j] = ptr[j + 1];
ptr[j + 1] = temp;
}
}
}
}
void sortodd(int *ptr, int n){
//sort to descending order
int i, j, temp;
for (i = 0; i < n - 1; i++){
for (j = 0; j < n - i - 1; j++){
if(ptr[j] < ptr[j + 1]){
int temp = ptr[j];
ptr[j] = ptr[j + 1];
ptr[j + 1] = temp;
}
}
}
}
void display(int *ptr, int n){
int i;
printf("\nOUTPUT : ");
for (i = 0; i < n; i++){
if(i)
putchar(' ');
printf("%d", ptr[i]);
}
putchar('\n');
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am a beginner in programming and just learned new concepts and started writing code for matrix multiplication but I got confused in pointers and others so I am uploading my code here in seek of guidelines.
#include <stdio.h>
#include <stdlib.h>
int **matrixMultiply(int A[][8], int B[][8], int row);
int main() {
int **A = allocate_matrix(A, 8, 8);
int **B = allocate_matrix(B, 8, 8);
int i, j;
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
A[i][j] = i + j;
A[i][j] = i + j;
}
}
int **C = allocate_matrix(C, 8, 8);
C = matrixMultiply(A, B, 8);
return 0;
}
int **matrixMultiply(int A[][8], int B[][8], int row) {
int **C = allocate_matrix(C, row, row);
if (row == 1) {
C[1][1] = A[1][1] * B[1][1];
} else {
int a11[row/2][row/2], a12[row/2][row/2], a21[row/2][row/2], a22[row/2][row/2];
int b11[row/2][row/2], b12[row/2][row/2], b21[row/2][row/2], b22[row/2][row/2];
int **c11 = allocate_matrix(c11, row/2, row/2);
int **c12 = allocate_matrix(c12, row/2, row/2);
int **c21 = allocate_matrix(c21, row/2, row/2);
int **c22 = allocate_matrix(c22, row/2, row/2);
int i, j;
for (i = 0; i < row/2; i++) {
for (j = 0; j < row/2; j++) {
a11[i][j] = A[i][j];
a12[i][j] = A[i][j + (row/2)];
a21[i][j] = A[i + (row/2)][j];
a22[i][j] = A[i + (row/2)][j + (row/2)];
b11[i][j] = B[i][j];
b12[i][j] = B[i][j + (row/2)];
b21[i][j] = B[i + (row/2)][j];
b22[i][j] = B[i + (row/2)][j + (row/2)];
c11[i][j] = C[i][j];
c12[i][j] = C[i][j + (row/2)];
c21[i][j] = C[i + (row/2)][j];
c22[i][j] = C[i + (row/2)][j + (row/2)];
}
}
c11 = addmatrix(matrixMultiply(a11, b11, row/2),
matrixMultiply(a12, b21, row/2), c11, row/2);
c12 = addmatrix(matrixMultiply(a11, b12, row/2),
matrixMultiply(a22, b22, row/2), c12, row/2);
c21 = addmatrix(matrixMultiply(a21, b11, row/2),
matrixMultiply(a22, b21, row/2), c21, row/2);
c22 = addmatrix(matrixMultiply(a21, b12, row/2),
matrixMultiply(a22, b22, row/2), c22, row/2);
// missing code???
return C;
}
}
int **allocate_matrix(int **matrix, int row, int column) {
matrix = (int **)malloc(row * sizeof(int*));
int i;
for (i = 0; i < row; i++) {
matrix[row] = (int *)malloc(row * sizeof(int));
}
return matrix;
}
void deallocate_matrix(int **matrix, int row) {
int i;
for (i = 0; i < row; i++) {
free(matrix[row]);
}
free(matrix);
}
int **addMatrix(int **a, int **b, int **c, int row) {
int i, j;
for (i = 0; i < row; i++) {
for (j = 0; j < row; j++) {
c[i][j] = a[i][j] + b[i][j];
}
}
return c;
}
I reformatted your code so I could analyze it. Indent consistently with 4 spaces, insert spaces around binary operators, after , and ; separators and between keywords and (, this improves readability a lot.
There seems to be missing code in the matrixMultiply function: you allocate the resulting matrix C but you use it as an input to initialize the intermediary matrices c11, c21, c21 and c22, and never actually store anything into C except for the trivial 1x1 case.
The matrix multiplication code seems broken beyond this, the function takes 2 arguments of type int A[][8], int B[][8], but you recursively call it with local arrays a11 to b22 defined as int a11[row/2][row/2]. These types are different, I do not know how the code even compiles.
In the matrix allocation code, you allocate rows with in incorrect size row instead of column. You should use calloc for this so the matrix is initialized to 0, plus you should not pass the initial argument at all:
int **allocate_matrix(int row, int column) {
int **matrix = malloc(row * sizeof(*matrix));
for (int i = 0; i < row; i++) {
matrix[i] = calloc(column, sizeof(*matrix[row]));
}
return matrix;
}
There is also a mistake for the second submatrix multiplication, it should be
c12 = addmatrix(matrixMultiply(a11, b12, row/2),
matrixMultiply(a12, b22, row/2), c12, row/2);
Furthermore, you never free the temporary matrices used for intermediary results. Unlike java, C does not have a garbage collector, you are responsible for releasing blocks of memory when you no longer need them, before they become inaccessible.
Here is a corrected version, with extra functions to print the matrix data and verify the matrix multiplication correctness. I added timings: the recursive method is much slower than the direct method, mostly because of all the extra allocation/deallocation for the intermediary results.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int **matrix_allocate(int row, int column) {
int **matrix = malloc(row * sizeof(*matrix));
for (int i = 0; i < row; i++) {
matrix[i] = calloc(column, sizeof(*matrix[i]));
}
return matrix;
}
void matrix_free(int **matrix, int row) {
for (int i = 0; i < row; i++) {
free(matrix[i]);
}
free(matrix);
}
void matrix_print(const char *str, int **a, int row) {
int min, max, w = 0, n1, n2, nw;
min = max = a[0][0];
for (int i = 0; i < row; i++) {
for (int j = 0; j < row; j++) {
if (min > a[i][j])
min = a[i][j];
if (max < a[i][j])
max = a[i][j];
}
}
n1 = snprintf(NULL, 0, "%d", min);
n2 = snprintf(NULL, 0, "%d", max);
nw = n1 > n2 ? n1 : n2;
for (int i = 0; i < row; i++) {
if (i == 0)
w = printf("%s = ", str);
else
printf("%*s", w, "");
for (int j = 0; j < row; j++) {
printf(" %*d", nw, a[i][j]);
}
printf("\n");
}
fflush(stdout);
}
int **matrix_add(int **a, int **b, int row, int deallocate) {
int **c = matrix_allocate(row, row);
for (int i = 0; i < row; i++) {
for (int j = 0; j < row; j++) {
c[i][j] = a[i][j] + b[i][j];
}
}
if (deallocate & 1) matrix_free(a, row);
if (deallocate & 2) matrix_free(b, row);
return c;
}
int **matrix_multiply(int **A, int **B, int row, int deallocate) {
int **C = matrix_allocate(row, row);
if (row == 1) {
C[0][0] = A[0][0] * B[0][0];
} else {
int row2 = row / 2;
int **a11 = matrix_allocate(row2, row2);
int **a12 = matrix_allocate(row2, row2);
int **a21 = matrix_allocate(row2, row2);
int **a22 = matrix_allocate(row2, row2);
int **b11 = matrix_allocate(row2, row2);
int **b12 = matrix_allocate(row2, row2);
int **b21 = matrix_allocate(row2, row2);
int **b22 = matrix_allocate(row2, row2);
for (int i = 0; i < row2; i++) {
for (int j = 0; j < row2; j++) {
a11[i][j] = A[i][j];
a12[i][j] = A[i][j + row2];
a21[i][j] = A[i + row2][j];
a22[i][j] = A[i + row2][j + row2];
b11[i][j] = B[i][j];
b12[i][j] = B[i][j + row2];
b21[i][j] = B[i + row2][j];
b22[i][j] = B[i + row2][j + row2];
}
}
int **c11 = matrix_add(matrix_multiply(a11, b11, row2, 0),
matrix_multiply(a12, b21, row2, 0), row2, 1+2);
int **c12 = matrix_add(matrix_multiply(a11, b12, row2, 1),
matrix_multiply(a12, b22, row2, 1), row2, 1+2);
int **c21 = matrix_add(matrix_multiply(a21, b11, row2, 2),
matrix_multiply(a22, b21, row2, 2), row2, 1+2);
int **c22 = matrix_add(matrix_multiply(a21, b12, row2, 1+2),
matrix_multiply(a22, b22, row2, 1+2), row2, 1+2);
for (int i = 0; i < row2; i++) {
for (int j = 0; j < row2; j++) {
C[i][j] = c11[i][j];
C[i][j + row2] = c12[i][j];
C[i + row2][j] = c21[i][j];
C[i + row2][j + row2] = c22[i][j];
}
}
matrix_free(c11, row2);
matrix_free(c12, row2);
matrix_free(c21, row2);
matrix_free(c22, row2);
}
if (deallocate & 1) matrix_free(A, row);
if (deallocate & 2) matrix_free(B, row);
return C;
}
int **matrix_multiply_direct(int **A, int **B, int row, int deallocate) {
int **C = matrix_allocate(row, row);
for (int i = 0; i < row; i++) {
for (int j = 0; j < row; j++) {
int x = 0;
for (int k = 0; k < row; k++) {
x += A[i][k] * B[k][j];
}
C[i][j] = x;
}
}
if (deallocate & 1) matrix_free(A, row);
if (deallocate & 2) matrix_free(B, row);
return C;
}
int main(int argc, char **argv) {
int n = argc < 2 ? 8 : atoi(argv[1]);
int **A = matrix_allocate(n, n);
int **B = matrix_allocate(n, n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
A[i][j] = i + j;
B[i][j] = i + j;
}
}
matrix_print("A", A, n);
matrix_print("B", B, n);
if ((n & (n - 1)) == 0) {
/* recursive method can be applied only to powers of 2 */
clock_t ticks = -clock();
int **C = matrix_multiply(A, B, n, 0);
ticks += clock();
matrix_print("C = A * B", C, n);
printf("%d ticks\n", ticks);
matrix_free(C, n);
}
clock_t ticks = -clock();
int **D = matrix_multiply_direct(A, B, n, 1+2);
ticks += clock();
matrix_print("D = A * B", D, n);
printf("%d ticks\n", ticks);
matrix_free(D, n);
return 0;
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Here is my code. It is a C program using Gauss Elimination Method and Partial Pivoting to solve systems of linear algebraic equations. Would you tell me when it is better to use pointers?
typedef double **Matrix;
typedef double *Row;
typedef double *Col;
typedef double Elem;
Matrix allocate_matrix(int n);
Col allocate_col(int n);
Row allocate_row(int n);
void free_matrix(Matrix M, int n);
void pivot_partial(Matrix A, Col S,Col B, int n);
void forward_elimination(Matrix A,Col B,int n);
Col back_substitution(Matrix A, Col B, int n);
Col scale_factor(Matrix A,int n);
void gauss(Matrix A, Col B, int n);
void swap_rows(Row *r1, Row*r2);
void print_matrix(Matrix M, int n, char * name);
void print_col(Col C, int n, char *name);
void print_row(Row R, int n, char *name);
int main(int argc, char *argv[])
{
FILE *ifp;
int n,i,j;
Matrix A;
Col B;
if(argc < 2)
{
printf("\nInput filename not passed \n");
exit(1);
}
ifp = fopen(argv[1],"r");
if(ifp == NULL)
{
printf("\nCould not open file %s\n",argv[1]);
exit(1);
}
fscanf(ifp,"%i",&n);
printf("A * X = B\n");
printf("\nDimension(A) = %i\n",n);
A = allocate_matrix(n);
for( i = 1; i <= n; ++i)
for(j = 1; j <= n; ++j)
fscanf(ifp,"%lf", &A[i][j]);
B = allocate_col(n);
for(j = 1; j <= n; ++j)
fscanf(ifp,"%lf",&B[j]);
fclose(ifp);
print_matrix(A,n,"A");
print_col(B,n,"B");
gauss(A,B,n);
free_matrix(A,n);
free(B + 1);
getchar();
return 0;
}
void print_matrix(Matrix M, int n, char * name)
{
int i,j;
printf("\n[%s] = ",name);
printf("\n\n");
for(i = 1; i <= n; i++)
{
for(j = 1; j <= n; ++j)
printf("%6lG ",M[i][j]);
printf("\n");
}
}
void print_col(Col C, int n, char * name)
{
int j;
printf("\n[%s] = ",name);
printf("\n\n");
for(j = 1; j <= n; ++j)
printf("%6lg\n",C[j]);
}
void print_row(Row R, int n, char * name)
{
int i;
printf("\n[%s] = ",name);
for(i = 1; i <= n; ++i)
printf("%6lg ",R[i]);
printf("\n");
}
Matrix allocate_matrix(int n)
{
Matrix A;
int i,j;
A = malloc(n * sizeof(Row));
if(!A)
{
printf("\nError : Could not allocate
memory for matrix\n");
exit(1);
}
--A;
for(i = 1; i <= n; ++i)
{
A[i] = malloc(n * sizeof(Elem));
if(!A[i])
{
printf("\nError : Could not allocate
memory for matrix\n");
exit(1);
}
--A[i];
}
return A;
}
void free_matrix(Matrix M, int n)
{
int i;
for(i = 1; i <= n; ++i)
free(M[i] + 1);
free(M + 1);
}
Col allocate_col(int n)
{
Col B;
B = malloc(n * sizeof(Elem));
if(!B)
{
printf("\nError : could not allocate
memory\n");
exit(1);
}
--B;
return B;
}
Row allocate_row(int n)
{
Row B;
B = malloc(n * sizeof(Elem));
if(!B)
{
printf("\nError : could not allocate
memory\n");
exit(1);
}
--B;
return B;
}
Col scale_factor(Matrix A, int n)
{
int i,j;
Col S ;
S = allocate_col(n);
for(i = 1; i <= n; ++i)
{
S[i] = A[i][1];
for(j = 2; j <= n; ++j)
{
if(S[i] < fabs(A[i][j]))
S[i] = fabs(A[i][j]);
}
}
return S;
}
void pivot_partial(Matrix A, Col S,Col B, int n)
{
int i,j;
Elem temp;
for(j = 1; j <= n; ++j)
{
for(i = j + 1; i <= n; ++i)
{
if(S[i] == 0)
{
if(B[i] == 0)
printf("\nSystem doesnt
have a unique solution");
else
printf("\nSystem is
inconsistent");
exit(1);
}
if(fabs(A[i][j]/S[i])>fabs(A[j][j]/S[j]))
{
swap_rows(&A[i],&A[j]);
temp = B[i];
B[i] = B[j];
B[j] = temp;
}
}
if(A[j][j] == 0)
{
printf("\nSingular System Detected\n");
exit(1);
}
}
}
void swap_rows(Row *r1, Row*r2)
{
Row temp;
temp = *r1;
*r1 = *r2;
*r2 = temp;
}
void forward_elimination(Matrix A,Col B,int n)
{
int i,j,k;
double m;
for(k = 1; k <= n-1; ++k)
{
for(i = k + 1; i <= n; ++i)
{
m = A[i][k] / A[k][k];
for(j = k + 1; j <= n; ++j)
{
A[i][j] -= m * A[k][j];
if(i == j && A[i][j] == 0)
{
printf("\nSingular
system detected");
exit(1);
}
}
B[i] -= m * B[k];
}
}
}
Col back_substitution(Matrix A, Col B, int n)
{
int i,j;
Elem sum;
Col X = allocate_col(n);
X[n] = B[n]/A[n][n];
for(i = n - 1; i >= 1; --i)
{
sum = 0;
for(j = i + 1; j <= n; ++j)
sum += A[i][j] * X[j];
X[i] = (B[i] - sum) / A[i][i];
}
return X;
}
void gauss(Matrix A, Col B, int n)
{
int i,j;
Col S, X;
S = scale_factor(A,n);
pivot_partial(A,S,B,n);
forward_elimination(A,B,n);
X = back_substitution(A,B,n);
print_col(X,n,"X");
free(S + 1);
free(X + 1);
}
If you don't know in advance the size of the array (Matrix), use pointers.
Arrays once declared with a particular size cannot grow or shrink.
But, pointers on the other hand, can be allocated memory (using malloc()), deallocated memory (using free()) and reallocated memory (using realloc()).
In your code, these lines
A = allocate_matrix(n);
for( i = 1; i <= n; ++i)
for(j = 1; j <= n; ++j)
fscanf(ifp,"%lf", &A[i][j]);
dynamically allocate a matrix A, after reading the size from file. This isn't possible in case of arrays.