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

             Example 4  (pthreads_VectorVector_BlockStriped.c)

Objective                 : To compute the vector-vector multiplication
                            with pthreads using block-striped partitioning
                            for uniform data distribution . Assume that
                            the vectors are of size n and p is number of
                            processors used and n is a multiple of p.

Input                     : Vector Size, Number of Threads. Threads must be a 
                            factor of vector size.

Output                    : Dot product of the vectors.

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


 /* Uses Uniform Data Distribution. */ 

#include <pthread.h>

pthread_mutex_t mutex_sum = PTHREAD_MUTEX_INITIALIZER;


int            *VecA, *VecB, sum = 0;


int             dist;



void           *
doMyWork(int myId)
{
	
	
	int             counter, mySum = 0;
	
		
		printf("\n %d: I am taking the interval: %d - %d.", myId, ((myId - 1) * dist), ((myId * dist) - 1));
	
		
		for (counter = ((myId - 1) * dist); counter <= ((myId * dist) - 1); counter++)
		
			mySum += VecA[counter] * VecB[counter];
	
		
		printf("\n %d: My Local Sum: %d.", myId, mySum);
	
		
		pthread_mutex_lock(&mutex_sum);
	
		sum += mySum;
	
		pthread_mutex_unlock(&mutex_sum);
	
		
		return;
	
} 

main(int argc, char *argv[])
{
	
		
		pthread_t * threads;
	
		
		int             counter, NumThreads, VecSize;
	
		
		if (argc != 3) {
		
			printf(" Missing Arguments: exe VectorSize NumThreads \n");
		
			return;
		
	} 
		
		NumThreads = abs(atoi(argv[2]));
	
		VecSize = abs(atoi(argv[1]));
	
		
		if (VecSize == 0)
		
			VecSize = 100;
	
		if (NumThreads == 0)
		
			NumThreads = 10;
	
		
		printf("\n Size of Vector: %d.", VecSize);
	
		printf("\n Number of Threads: %d.", NumThreads);
	
		
		if (VecSize % NumThreads != 0) {
		
			printf("\n Number of threads not a factor of vector size. Aborting.\n");
		
			return ;
		
	} 
		
		VecA = (int *) malloc(sizeof(int) * VecSize);
	
		VecB = (int *) malloc(sizeof(int) * VecSize);
	
		
		threads = (pthread_t *) malloc(sizeof(pthread_t) * NumThreads);
	
		
		dist = VecSize / NumThreads;
	
		
		for (counter = 0; counter < VecSize; counter++) {
		
			VecA[counter] = 1;
		
			VecB[counter] = 1;
		
	} 
		
		for (counter = 0; counter < NumThreads; counter++)
		
			
			pthread_create(&threads[counter], NULL, (void *(*) (void *)) doMyWork, (void *) (counter + 1));
	
		
		for (counter = 0; counter < NumThreads; counter++)
		
			
			pthread_join(threads[counter], NULL);
	
		
		printf("\n The Sum is: %d.\n", sum);
	
		return;
	
} 
