/* 
   matrix2.c - Matrix Multiplication
               matrix stored as array of vectors

   compile: gcc -Wall -O -o matrix2 matrix2.c
   run:     ./matrix2 file
*/

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

double startTime, stopTime;

/* Timing ------------------------------------------------------- */
void showElapsed(int id, char * m)
{  printf("%d: %s %f secs\n",id,m,(clock()-startTime)/CLOCKS_PER_SEC);
}

/* Aux fcts ------------------------------------------------------- */
int * allocVector(int n)
{
  return (int *)malloc(n*sizeof(int));
}

int ** allocMatrix(int m, int n)
{
  int ** newM = (int **)malloc(m*sizeof(int *));
  int i;
  for (i=0; i<m; i++)
    newM[i] = allocVector(n);
  return newM;
}

/* read a matrix M, with m rows and n columns, from a stream fin */
void readMatrix(fin,M,m,n)
FILE * fin;  /* input stream */
int ** M;    /* matrix to store values in */
int m,n;     /* number of rows and columns*/
{  int i,j;

  for(i=0; i<m; i++)   /* iterate over all rows */
    for(j=0; j<n; j++) /* iterate over all columns */ 
      fscanf(fin,"%d",&(M[i][j]));  /* read data */
}

/* write a matrix M, with m rows and n columns, to a stream fout */
void writeMatrix(fout,M,m,n)
FILE * fout; /* output stream */
int ** M;    /* matrix to read values from */
int m,n;     /* number of rows and columns*/
{  int i,j;

  for(i=0; i<m; i++)      /* iterate over all rows */
   {  for(j=0; j<n; j++)  /* iterate over all columns */ 
       fprintf(fout,"%d ",M[i][j]); /* write data */
      putc('\n',fout);
   }
}

/* matrix product of M1 (m row, n columns) with M2, with result in M3 */
void matrixProd(M1,M2,M3,m,n)
int **M1,**M2,**M3;
int m,n;
{  int i,j,k;
   
   for(i=0; i<m; i++)  /* iterate over all rows */
    for(j=0; j<m; j++) /* iterate over all columns */ 
    { M3[i][j]=0;
      for(k=0; k<n; k++) /* compute dot product */
        M3[i][j] = M3[i][j]+M1[i][k]*M2[k][j];
    }
}

int main(argc,argv)
int argc;
char ** argv;
{  FILE * fin;
   FILE * fout;
   int ** M1;
   int ** M2;
   int ** M3;
   int m,n;

   fin = fopen(argv[1],"r");
   fscanf(fin,"%d %d",&m,&n);
   M1 = allocMatrix(m,n);
   readMatrix(fin,M1,m,n);
   M2 = allocMatrix(n,m);
   readMatrix(fin,M2,n,m);
   fclose(fin);
   // Print input:
   /*
   writeMatrix(stdout,M1,m,n);
   putchar('\n');
   writeMatrix(stdout,M2,n,m);
   putchar('\n');
   */
   M3 = allocMatrix(m,m);
   startTime = clock();
   matrixProd(M1,M2,M3,m,n);
   stopTime = clock();
   printf("%d * %d; SEQUENTIAL; %f secs\n",
	  m,n, (stopTime-startTime)/CLOCKS_PER_SEC);
   // Print output:
   fout = fopen("/dev/null", "w");
   // writeMatrix(stdout,M3,m,m);
   /*
   fout = fopen("MRESULT_SEQ","w");
   writeMatrix(fout,M3,m,m);
   fclose(fout);
   */

   return 0;
}
