/* file:		child3.c
 * author:		Robert S. Laramee
 * class:		cs720/820
 * date started:  	27 Jan 98
 * date finished:	3 Feb 98
 * project:		assignment 1
 * description:		This program opens the data file and reads the 
 * elements of the specified row of matrixA and the elements of matrixB.
 * It then computes the product of the specified row, and writes it to
 * output file product.out
 *
 *  argv[0] = child3    -name of executable (child3)
 *  argv[1] = mat.dat   -data filename
 *  argv[2] = x         -current row number
 *  argv[3] = x         -number of rows in matrix A
 *  argv[4] = x         -number of columns in matrix A
 *  argv[3] = x         -number of columns in matrix B
 */

#include       /* for printf(), scanf()       */
#include 	/* for malloc(), realloc()     */

void main(int argc, char *argv[]) {

   FILE *mat_ptr;       	/* pointer to mat.dat file      */
   FILE *product_ptr;       	/* pointer to product.out file      */
   int *array_ptr;		/* pointer to allocated ints	*/
   int i=0, j=0, k=0;
   int row, column, data, offset, first, second, difference, product = 0;	
   int row_num = atoi(argv[2]);
   int num_rowsA = atoi(argv[3]);
   int num_colsA = atoi(argv[4]);
   int num_colsB = atoi(argv[5]);

/*   printf("\n child process 3 with ID = %ld", (long)getpid()); */

   /* Start off by allocating storage for an arrays of 1 integer using 
    * malloc() and saving the returning addres in 'array_ptr' Check that
    * this has been done correctly with an 'if' test and a comparison
    * with the value NULL.
    */
   if ((array_ptr = malloc (sizeof(int))) == NULL) {
      printf("\n no memory for malloc() \n");
      exit(1);
   }   

   if ( (mat_ptr = fopen(argv[1], "r")) == NULL) {
      printf("\n Cannot open file mat.dat for reading \n");
      exit(1);
   }

   /*  read in the appropriate row:
    *  normally the offset is 
    *  4 * current_row * (number of columns in A + B)
    *  but when there are extra rows at the end, the offset is:
    *  4 * current_row * (number of columns in A + B) -
    *  4 * number of columns in B * (current row - number of columns in B)
    *  we'll use the fact the num_colsA = num_rowsB for multiplication
    */
   
   if ( (row_num - num_colsA) >= 1 ) {		/* abnormal offset  */

      offset = 4* row_num * (num_colsA + num_colsB) -
               4* num_colsB * (row_num - num_colsA);
      fseek(mat_ptr, offset, SEEK_SET);
   } else {						/* normal offset */
      offset = 4* row_num * (num_colsA + num_colsB);
      fseek(mat_ptr, offset, SEEK_SET);
   }

   for ( j=0; j < num_colsA; j++) {	/* read in the appropriate row */
      fscanf(mat_ptr, "%d ", &data);
      array_ptr[i++] = data;
      array_ptr = realloc(array_ptr, (i + 1) * sizeof(int));   
   }

   /* Now display the data in the dynamically allocated array before
    * releasing it back ot the heap using free().
    *
    * printf("\n the child3 row read in is: ");
    * for( j=0; j < num_colsA; j++) {
    *    printf("%d ", array_ptr[j]);
    * }
    * printf("\n");
    */

   /* for computing the product, the whole matrixB has to be read in	*/

   for ( j=0; j < num_colsB; j++) {	/* read in the appropriate columns */
      for (k=0; k < num_colsA; k++) {
         offset = (4*num_colsA) + (4*k*(num_colsA + num_colsB)) + 4*j;
         fseek(mat_ptr, offset, SEEK_SET);
         fscanf(mat_ptr, "%d ", &data);
         array_ptr[i++] = data;
         array_ptr = realloc(array_ptr, (i + 1) * sizeof(int));
     }
   }

   /* Now display the data in the dynamically allocated array before
    * releasing it back ot the heap using free().
    *
    *   printf("\n the child3 columns read in is: ");
    *   for( j = 0; j < num_rowsA + num_rowsA * num_colsB; j++) {
    *      printf("%d ", array_ptr[j]);
    *   }
    */

   if ( (product_ptr = fopen("product.out", "a+")) == NULL) {
      printf("\n Cannot open file product.out for reading/writing \n");
      exit(1);
   }

   /* compute the product
    * for the current row we're working on
    *   for each column in matrix B
    *      start product at zero
    *      for each column in matrix A
    *         add up the product of the corresponding elements
    */
   for (i=0; i< num_colsB; i++) {
      product = 0;

      for (j=0; j< num_colsA; j++) {
          product = product + array_ptr[j] *
                              array_ptr[j + num_colsA + i * num_colsA];      

      }
      fprintf(product_ptr, " %5d", product);
   }   
   fprintf(product_ptr,"\n");

   if (fclose(mat_ptr))
      printf("\n error closing mat.dat \n");
   if (fclose(product_ptr))
      printf("\n error closing add.out \n");
   free(array_ptr);		/* no memory leaks here */
   exit(0);
}