#include "mergeSort.h"

#include <stdlib.h>
#include <assert.h>
#include <pthread.h>

#define THREADS

pthread_t threads[THREADS];

void* merge_sort(void* args) {
	margs_t* f = (margs_t*) args;
	if(f->start < f->final) {
		pthread_t t1, t2;
		index middle = (f->start + f->final) / 2;

		margs_t args1 = {f->array, f->start, middle};
		assert(!pthread_create(&t1, NULL, merge_sort,  (void*) &args1));
		margs_t args2 = {f->array, middle+1, f->final};
		assert(!pthread_create(&t2, NULL, merge_sort,  (void*) &args2));

		assert(pthread_join(t1, NULL));
		assert(pthread_join(t2, NULL));
		merge(f->array, f->start, middle, f->final);
	}
	int *ret = 0;
	return ret;
}

void merge(int array[], index start, index middle, index final) {

	length countL = middle - start + 1;
	int *arrayL = malloc(countL * sizeof(int));
	for(index currentL = 0; currentL < countL; currentL ++)
		arrayL[currentL] = array[start + currentL ];

	length countR = final - middle;
	int* arrayR = malloc(countR * sizeof(int));
	for(index currentR = 0; currentR < countR; currentR ++)
		arrayR[currentR] = array[middle + 1 + currentR ];

	index currentL, currentR, current;
	for(currentL = 0, currentR = 0, current = start;
		 	current <= final && currentL < countL && currentR < countR;
		   	current ++) 
		if(arrayL[currentL] <= arrayR[currentR])
			array[current] = arrayL[currentL++];
		else
			array[current] = arrayR[currentR++];

	while(currentR < countR)
		array[current++] = arrayR[currentR++];
	while(currentL < countL)
		array[current++] = arrayL[currentL++];

	free(arrayL);
	free(arrayR);
}
