Himanshu Sourav
Himanshu Sourav

Reputation: 710

Matrix Multiplication for any proper order with dynamic memory allocation

I am trying to perform matrix multiplication(dynamic memory allocation) where that the user can enter any valid order for matrix multiplication (i.e. column1=row2). The output for same orders (2x2 or 3x3) for both matrices result in proper computation, but the orders like mat1 2x3 & mat2 3x2..give segmentation fault. I am not able to ascertain how am I accessing any illegal memory when I am doing the memory allocation beforehand.

kindly advise, pls forgive me if I am making some silly mistake...

following is the complete code:

#include<stdio.h>
#include<stdlib.h>


main(){
int **mat1, **mat2,**res,i,j,r1,c1,r2,c2;

printf("\nEnter the Order of the First matrix...\n");
scanf("%d %d",&r1,&c1);
printf("\nEnter the Order of the Second matrix...\n");
scanf("%d %d",&r2,&c2);

if(c1!=r2){
    printf("Invalid Order of matrix");
    exit(EXIT_SUCCESS);
}

mat1= (int**) malloc(r1*sizeof(int*));

for(i=0;i<c1;i++)
    mat1[i]=(int*)malloc(c1*sizeof(int));

mat2= (int**) malloc(r2*sizeof(int*));

for(i=0;i<c2;i++)
    mat2[i]=(int*)malloc(c2*sizeof(int));

res=(int**)calloc(r1,sizeof(int*));

for(i=0;i<c2;i++)
    res[i]=(int*)calloc(c2,sizeof(int));

//Input Matrix1
    for(i=0;i<r1;i++)
        for(j=0;j<c1;j++)
            scanf("%d",&mat1[i][j]);
//Input Matrix2
    for(i=0;i<r2;i++)
        for(j=0;j<c2;j++)
            scanf("%d",&mat2[i][j]);

//Printing Input Matrix 1 and 2

printf("\n Entered Matrix 1: \n");
for(i=0;i<r1;i++){
    for(j=0;j<c1;j++)
        printf("%d ",mat1[i][j]);
    printf("\n");
}

printf("\n Entered Matrix 2: \n");
for(i=0;i<r2;i++){
    for(j=0;j<c2;j++)
        printf("%d ",mat2[i][j]);
    printf("\n");
}       

//Computation


//Multiplication

    for(i=0;i<r1;i++){
        for(j=0;j<c2;j++){
                res[i][j]=0;
                for(k=0;k<c1;k++)
                    res[i][j]+= mat1[i][k]*mat2[k][j];

        }
        printf("\n");
    }


   printf("\nThe Multiplication of two matrix is\n");
   for(i=0;i<r1;i++){
       printf("\n");
       for(j=0;j<c2;j++)
            printf("%d\t",res[i][j]);   
   }
    printf("\n");

/*  Addition
for(i=0;i<r1;i++)
        for(j=0;j<c2;j++)
                res[i][j]=mat1[i][j]+mat2[i][j];


printf("\nThe Addition of two matrix is\n");
   for(i=0;i<r1;i++){
       printf("\n");
       for(j=0;j<c2;j++)
            printf("%d\t",res[i][j]);
    }
*/


return 0;}

Upvotes: 0

Views: 40241

Answers (4)

Aindrila Indra
Aindrila Indra

Reputation: 1

While computing the matrix multiplication you have to run the k loop from 0 to c2, and not from 0 to c1.

Upvotes: 0

Andrei
Andrei

Reputation: 599

I attached bellow the code for Matrix Multiplication for any proper order with dynamic memory allocation

For completeness I used 3 different methods for matrix multiplication: one function double** multMatrixpf (see equivalent function Fortran/Pascal) and two subroutine/procedure(Fortran/Pascal like), where by first void multMatrixp you need to allocate_mem(&c,ro1,co2) outside and in second subroutine void multMatrixpp the matrix c1 is allocated inside the subroutine. All of these three methods give the same result.

As well I used different methods for initialising arrays.

#include <stdio.h>
#include <stdlib.h>
void allocate_mem(double*** arr, int rows, int cols);
void deallocate_mem(double*** arr, int n);
double** readMatrixf(int rows, int cols);
void readMatrix(double ***a, int rows,int cols);
void printMatrix(double** a, int rows, int cols);
void printMatrixE(double** a, int rows, int cols);
void multMatrixp(double **A, double **B, double **C,int r1,int c1,int r2,int c2);
void multMatrixpp(double **A, double **B, double ***C,int ro1,int co1,int ro2,int co2);
double** multMatrixpf(double **A, double **B, int ro1,int co1,int ro2,int co2);

//______________________________________________________________________________

int main()
{
   int ro1, co1, ro2, co2;
   double **a1, **b1, **c1;    

ro1=2; co1=3;
ro2=3; co2=4;

printf("Ex1:__________________________________________________"
    "__________________________ \n");


double (*(a[])) = {
(double[]) { 1, 3, 5},
(double[]) {2, 4, 0}};


double (*(b[])) = {
(double[]) {6, 2, 4, 8},
(double[]) {1, 7, 0, 9},
(double[]) {0, 3, 5, 1}};


printMatrix(a,ro1,co1);    
printMatrix(b,ro2,co2);


printf("MatMult \n");
double **c;
allocate_mem(&c,ro1,co2);
multMatrixp(a, b, c, ro1, co1, ro2, co2);  
printMatrix(c,ro1,co2);        
printMatrixE(c,ro1,co2);      

deallocate_mem(&c,ro1);  


printf("Ex2:__________________________________________________"
    "__________________________ \n");

scanf("%d%d", &ro1, &co1);
readMatrix(&a1,ro1,co1);
printMatrix(a1,ro1,co1); 
//deallocate_mem(&a1,ro1); 
//printMatrix(a1,ro1,co1); 


scanf("%d%d", &ro2, &co2);
readMatrix(&b1,ro2,co2);
printMatrix(b1,ro2,co2);

printf("MatMult \n");
multMatrixpp(a1, b1, &c1, ro1, co1, ro2, co2);  
printMatrix(c1,ro1,co2); 
printMatrixE(c1,ro1,co2);      

deallocate_mem(&a1,ro1); 
deallocate_mem(&b1,ro2);
deallocate_mem(&c1,ro1);  


printf("Ex3:__________________________________________________"
    "__________________________ \n");

scanf("%d%d", &ro1, &co1);
a1=readMatrixf(ro1,co1);
printMatrix(a1,ro1,co1); 
//deallocate_mem(&a1,ro1); 
//printMatrix(a1,ro1,co1); 


scanf("%d%d", &ro2, &co2);
b1=readMatrixf(ro2,co2);
printMatrix(b1,ro2,co2);

printf("MatMult \n");
c1=multMatrixpf(a1, b1, ro1, co1, ro2, co2);  
printMatrix(c1,ro1,co2); 
printMatrixE(c1,ro1,co2);      

deallocate_mem(&a1,ro1); 
deallocate_mem(&b1,ro2);
deallocate_mem(&c1,ro1);  



    return 0;
}

//______________________________________________________________________________
void allocate_mem(double*** arr, int rows, int cols)
{
  int i;
  *arr = (double**)malloc(rows*sizeof(double*));
  for( i=0; i<rows; i++)
    (*arr)[i] = (double*)malloc(cols*sizeof(double));
} 

//______________________________________________________________________________
void deallocate_mem(double*** arr, int rows){
 int i;
    for (i = 0; i < rows; i++)
        free((*arr)[i]);
    free(*arr); 
}

//______________________________________________________________________________
double** readMatrixf(int rows, int cols)
{
double    **a; // Define a local pointer to keep rest of the code intact
int i, j;

a= (double**) malloc(rows*sizeof(double*));
for(i=0;i<rows;i++)
a[i]=(double*)malloc(cols*sizeof(double));

    for(i=0;i<rows;i++)
        for(j=0;j<cols;j++)
            scanf("%lf",&a[i][j]);
   return a;            

}

//______________________________________________________________________________

void readMatrix(double ***a, int rows,int cols)
{
   int i, j;

*a= (double**) malloc(rows*sizeof(double*));
for(i=0;i<rows;i++)
(*a)[i]=(double*)malloc(cols*sizeof(double));
    for(i=0;i<rows;i++)
        for(j=0;j<cols;j++)
            scanf("%lf",&(*a)[i][j]);
}

//______________________________________________________________________________
void printMatrix(double** a, int rows, int cols)
{
    int i, j;
   printf("Matrix[%d][%d]\n",rows,cols);    
   for(i=0;i<rows;i++){
      for(j=0;j<cols;j++)
      printf("%8.3lf ",a[i][j]);
      printf("\n");
   }
   printf("\n");   
}

//______________________________________________________________________________
void printMatrixE(double** a, int rows, int cols)
{
    int i, j;
   printf("Matrix[%d][%d]\n",rows,cols);    
   for(i=0;i<rows;i++){
      for(j=0;j<cols;j++)
      printf("%9.2e ",a[i][j]);
      printf("\n");
   } 
   printf("\n");     
}


//______________________________________________________________________________

void multMatrixp(double **A, double **B, double **C,int ro1,int co1,int ro2,int co2)
{
    int i, j, k;
    for(i = 0; i < ro1; i++) {
        for(j = 0; j < co2; j++) {
            C[i][j] = 0;
            for(k = 0; k < co1; k++) {
                C[i][j] += A[i][k] * B[k][j];
            }
        }
    }
}

//______________________________________________________________________________

void multMatrixpp(double **A, double **B, double ***C,int ro1,int co1,int ro2,int co2)
{
    int i, j, k;
*C= (double**) malloc(ro1*sizeof(double*));
for(i=0;i<ro1;i++)
(*C)[i]=(double*)malloc(co2*sizeof(double));

    for(i = 0; i < ro1; i++) {
        for(j = 0; j < co2; j++) {
            (*C)[i][j] = 0.0;
            for(k = 0; k < co1; k++) {
                (*C)[i][j] += A[i][k] * B[k][j];
            }
        }
    }
}


//______________________________________________________________________________

double** multMatrixpf(double **A, double **B, int ro1,int co1,int ro2,int co2)
{
    int i, j, k;
    double **C;
C= (double**) malloc(ro1*sizeof(double*));
for(i=0;i<ro1;i++)
C[i]=(double*)malloc(co2*sizeof(double));

    for(i = 0; i < ro1; i++) {
        for(j = 0; j < co2; j++) {
            C[i][j] = 0.0;
            for(k = 0; k < co1; k++) {
                C[i][j] += A[i][k] * B[k][j];
            }
        }
    }
     return C;              
}

where as input matrix we have in.txt

4 4
1 1 1 1
2 4 8 16
3 9 27 81
4 16 64 256
4 3
4.0 -3.0 4.0
-13.0 19.0 -7.0
3.0 -2.0 7.0
-1.0 1.0 -1.0
3 4
1 2 -2 0
-3 4 7 2
6 0 3 1
4 2
-1 3
0 9
1 -11
4 -5

in unix like cmmd line execute the command:

$ time ./Matmult < in.txt > out.txt

and you get the output

out.txt

Ex1:____________________________________________________________________________ 
Matrix[2][3]
   1.000    3.000    5.000 
   2.000    4.000    0.000 

Matrix[3][4]
   6.000    2.000    4.000    8.000 
   1.000    7.000    0.000    9.000 
   0.000    3.000    5.000    1.000 

MatMult 
Matrix[2][4]
   9.000   38.000   29.000   40.000 
  16.000   32.000    8.000   52.000 

Matrix[2][4]
 9.00e+00  3.80e+01  2.90e+01  4.00e+01 
 1.60e+01  3.20e+01  8.00e+00  5.20e+01 

Ex2:____________________________________________________________________________ 
Matrix[4][4]
   1.000    1.000    1.000    1.000 
   2.000    4.000    8.000   16.000 
   3.000    9.000   27.000   81.000 
   4.000   16.000   64.000  256.000 

Matrix[4][3]
   4.000   -3.000    4.000 
 -13.000   19.000   -7.000 
   3.000   -2.000    7.000 
  -1.000    1.000   -1.000 

MatMult 
Matrix[4][3]
  -7.000   15.000    3.000 
 -36.000   70.000   20.000 
-105.000  189.000   57.000 
-256.000  420.000   96.000 

Matrix[4][3]
-7.00e+00  1.50e+01  3.00e+00 
-3.60e+01  7.00e+01  2.00e+01 
-1.05e+02  1.89e+02  5.70e+01 
-2.56e+02  4.20e+02  9.60e+01 

Ex3:____________________________________________________________________________ 
Matrix[3][4]
   1.000    2.000   -2.000    0.000 
  -3.000    4.000    7.000    2.000 
   6.000    0.000    3.000    1.000 

Matrix[4][2]
  -1.000    3.000 
   0.000    9.000 
   1.000  -11.000 
   4.000   -5.000 

MatMult 
Matrix[3][2]
  -3.000   43.000 
  18.000  -60.000 
   1.000  -20.000 

Matrix[3][2]
-3.00e+00  4.30e+01 
 1.80e+01 -6.00e+01 
 1.00e+00 -2.00e+01 

Upvotes: 1

shahrukh
shahrukh

Reputation: 11

Here is the code for any valid matrix multiplication.... feel free for "Queries"....

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>

int main()
{

        int *ans,*first,*second;
        int *A,*B,*C;
        int i,j,k=0;
        int rowA,colA,sizeA,sizeB,sizeC;
        int rowB,colB;

        printf("Enter the row's and column of 1st matrix\n");
        scanf("%d%d",&rowA,&colA);


        printf("Enter the row's and column of 2nd matrix\n");
        scanf("%d%d",&rowB,&colB);

        if(colA!=rowB)
        {
            printf("Error => colA must be equal to rowB\n");
            getch();
            exit(EXIT_SUCCESS);
        }


        sizeC = rowA*colB;
        sizeA = rowA*colA;
        sizeB = rowB*colB;

        A  = (int *)malloc(sizeA*sizeof(int *));
        first = A;

        B = (int *)malloc(sizeB*sizeof(int *));
        second = B;

        C    = (int *)malloc(sizeC*sizeof(int *));
        ans = C;


        printf("Enter the elements of the first matrix A\n");

        for(i=0;i<sizeA;i++,first++)
        scanf("%d",first);

        printf("Enter the elements of the second matrix B\n");

        for(i=0;i<sizeB;i++,second++)
        scanf("%d",second);

        first=A;        
        second= B;      

        if(rowA==1 && colB==1)
        {
            for(i=0;i<rowA;i++)
            {
                for(j=0;j<colB;j++)
                {
                *ans=0;
                for(k=0;k<rowB;k++)
                    *ans = *ans + (*(first + (k + i*colA))) * (*(second + (j+k*colB)));
                ans++;
                }//j
            }//i
        }//if

    else
    {
        for(i=0;i<rowA;i++)
        {
        for(j=0;j<colB;j++)
        {
            *ans=0;
            for(k=0;k<rowB;k++)
                *ans = *ans + (*(first + (k + i*colA))) * (*(second + (j+k*rowB)));
            ans++;
        }//j
        }//i

        }

        printf("\nThe value of matrix 'C' = \n");

        ans = C;

        for(i=0;i<rowA;i++)
        {
         printf("\n");
         for(j=0;j<colB;j++,ans++)
         printf("%d\t",*ans);
         }

        free(A);
        free(B);
        free(C);
        getch();
    }

Upvotes: 1

Taiki
Taiki

Reputation: 639

mat1= (int**) malloc(r1*sizeof(int*));

for(i=0;i<c1;i++)  < c1 instead of r1
    mat1[i]=(int*)malloc(c1*sizeof(int));

mat2= (int**) malloc(r2*sizeof(int*));

for(i=0;i<c2;i++)   < c2 instead of r2
    mat2[i]=(int*)malloc(c2*sizeof(int));

You use c1/2 in your for instead of r1/2.

If r1 < c1, you end up outside of the memory you allocated.

If r1 > c1, you end up with uninitialized pointers.

Not related to the issue but you should write int main() instead of main(), the second one is accepted but the first one easier to read.

Upvotes: 2

Related Questions