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

                Example 5  (pthreads_InfinityNorm_Row.c)

Objective             : To calculate the Infinity Norm of a matrix.
                        Uses Row 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_norm = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t CurRow_norm = PTHREAD_MUTEX_INITIALIZER;
int             Norm = 0;
int             row, col, **Mat;
int             CurRow;		/* Which row to operate on. */

void           *
doMyWork(int myId)
{

	int             cRow, cCol, rowSum = 0;
 
       while (1){
	pthread_mutex_lock(&CurRow_norm);
	{
		if (CurRow >= row) {
			pthread_mutex_unlock(&CurRow_norm);
			return;
		}
		cRow = CurRow;
		CurRow++;
	}
	pthread_mutex_unlock(&CurRow_norm);

	rowSum = 0;
	for (cCol = 0; cCol < col; cCol++)
		rowSum += abs(Mat[cRow][cCol]);
	pthread_mutex_lock(&mutex_norm);
	{
		if (Norm < rowSum)
			Norm = rowSum;
	}
	pthread_mutex_unlock(&mutex_norm);
        }
}


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

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

	if (argc != 2) {

		printf(" Missing Arguments: Number of Threads.\n");
		return;
	}
	fp = fopen("Norm_Data.dat", "r");

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

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

	NumThreads = atoi(argv[1]);

	if (NumThreads < 1) {

		printf("\n Number of threads must be greater than zero. Aborting ...\n");
		return;
	}
	threads = (pthread_t *) malloc(sizeof(pthread_t) * NumThreads);

	Mat = (int **) malloc(sizeof(int) * row);

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

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

	CurRow = 0;

	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);

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

}
