#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>

#define NUMBER_OF_THREADS 5
#define VECTOR_SIZE 100

int fibo[VECTOR_SIZE];

struct Parameters
{
	int inicial;
	int final;
};

void *calcula_fibo(void *);

int main (int argc, char** argv){
	int i;
	int operations_per_thread;
	unsigned long long int uinicial,ufinal;
	struct Parameters* parameter;
	pthread_t thread[NUMBER_OF_THREADS];
	struct timeval inicial, final;
	
	gettimeofday(&inicial,NULL);
	operations_per_thread = VECTOR_SIZE/NUMBER_OF_THREADS;
	
	for(i=0;i<NUMBER_OF_THREADS;i++){
		parameter = (struct Parameters *)malloc(sizeof(struct Parameters));
		parameter->inicial = i*operations_per_thread;
		parameter->final = parameter->inicial+operations_per_thread;
		
		pthread_create(&thread[i],NULL,calcula_fibo,parameter);
	}
	
	for(i=0;i<NUMBER_OF_THREADS;i++){
		pthread_join(thread[i],NULL);
	}
	gettimeofday(&final,NULL);
	
	uinicial = inicial.tv_sec*1000000 + inicial.tv_usec;
	ufinal = final.tv_sec*1000000 + final.tv_usec;
	fprintf(stdout, "Tempo de execução: %llu us\n",((ufinal-uinicial)));
	
	return 0;
}

void *calcula_fibo(void *arg){
	unsigned long long int* result = malloc(sizeof(long int));
	struct Parameters* parameter;	
	int i;
	int work;
	unsigned long long int last;
	unsigned long long int lastlast;
	
	parameter = (struct Parameters *) arg;
	
	fprintf(stdout,"Thread %ld - min=%d - max=%d\n",pthread_self,parameter->inicial,parameter->final);
	for(work=parameter->inicial;work<parameter->final;work++){
		last = 1;
		lastlast=0;
		*result = 1;
		
		for(i=1;i<work+1;i++){
			*result += lastlast;
			lastlast = last;
			last = *result;
		}		
		fibo[work] = *result;
		fprintf(stdout,"Fibonacci(%d)=%llu\n",work+1,*result);

		
	}
	free(result);
	free(parameter);
	
	return NULL;
}

