/********************************************************************

               Example 6 (pthreads_InfinityNorm_Col.c)

Objective          : To calculate the Infinity Norm of a matrix.
                     Uses Column Wise Splitting.
                     Demonstrates use of:
                     pthread_create()
                     pthread_join()
                     pthread_mutex_t
                     pthread_mutex_lock()
                     pthread_mutex_unlock()

Input              : Input Matrix in the file Norm_data.dat. Number of threads
                     as command line parameters.

Output             : The Infinity Norm of the matrix.

********************************************************************/

#include<pthread.h>
#include<stdio.h>

pthread_mutex_t *mutex_Res;
pthread_mutex_t mutex_col;
int Norm = 0;
int row, col, **Mat, *Res;
int CurCol=0;

void *doMyWork(int myId){

     int cRow, cCol;

         while (1){

         pthread_mutex_lock(&mutex_col); {
             cCol=CurCol;
             if (CurCol >= col){
                pthread_mutex_unlock(&mutex_col);
                return;
                }
             CurCol++;
          }
          pthread_mutex_unlock(&mutex_col);

             for(cRow=0; cRow<row; cRow++){
                      pthread_mutex_lock(&mutex_Res[cRow]);
                               {
                               Res[cRow] += abs(Mat[cRow][cCol]);
                               }
                      pthread_mutex_unlock(&mutex_Res[cRow]);
                      }
          }

     }
    

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

     FILE* fp;
     pthread_t *threads;
     int counter, cRow, cCol, NumThreads;

     if (argc != 2 ){

             printf("\n Missing Arguments: Number of Threads.\n");
             return;
             }

     NumThreads = atoi(argv[1]);

     fp = fopen("Norm_Data.dat", "r");

     fscanf(fp, "%d", &row);
     fscanf(fp, "%d", &col);

     printf("\n Row:%d  Col:%d.", row, col);

     threads = (pthread_t*)malloc(sizeof(pthread_t)*NumThreads);

     Mat = (int**)malloc(sizeof(int)*row);
     Res = (int*)malloc(sizeof(int)*row);
     mutex_Res = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t)*row);

     for (counter=0; counter<row; counter++){
            Mat[counter]=(int*)malloc(sizeof(int)*col);
            Res[counter]=0;
            }

     for (cRow=0; cRow<row; cRow++)
            for (cCol=0; cCol<col; cCol++)
                   fscanf(fp, "%d", &Mat[cRow][cCol]);

     for (counter=0; counter<NumThreads; counter++)
            pthread_create(&threads[counter], NULL, (void*(*)(void*))doMyWork, (void*)(counter));

     for (counter=0; counter<NumThreads; counter++)
            pthread_join(threads[counter], NULL);

     for (cRow=0; cRow<row; cRow++)
           if (Res[cRow]>Norm)
                   Norm=Res[cRow];

     printf("\n Col Wise partitioning. Infinity Norm: %d.\n", Norm);
     
     return;
     }
