void merge_rec(long n, T left[n], T right[n], T result[n*2], long start, long length) {
	if (length <= MIN_MERGE_SIZE) {
		// Base case
		merge_task(n, (T *) left, (T *) right, (T *)result, start, length);
	} else {
		merge_rec(n, (T *) left, (T *) right, (T *) result, start, length/2);
		merge_rec(n, (T *) left, (T *) right, (T *) result, start + length/2, length/2);
	}
}
void merge_sort_rec(int * arr, int n) {
    if (n < 2)
        return;
    int m = n / 2;
    merge_sort_rec(arr, m);
    merge_sort_rec(arr + m, n - m);
    merge_rec(arr, n, m);
}
void multisort(long n, T data[n], T tmp[n]) {
	if (n >= MIN_SORT_SIZE*4L) {
		// Recursive decomposition
		multisort(n/4L, (T *) &data[0], (T *) &tmp[0]);
		multisort(n/4L, (T *) &data[n/4L], (T *) &tmp[n/4L]);
		multisort(n/4L, (T *) &data[n/2L], (T *) &tmp[n/2L]);
		multisort(n/4L, (T *) &data[3L*n/4L], (T *) &tmp[3L*n/4L]);   
        
		merge_rec(n/4L, (T *) &data[0], (T *) &data[n/4L], (T *) &tmp[0], 0, n/2L);
		merge_rec(n/4L, (T *) &data[n/2L], (T *) &data[3L*n/4L], (T *) &tmp[n/2L], 0, n/2L);
        
		merge_rec(n/2L, (T *) &tmp[0], (T *) &tmp[n/2L], (T *) &data[0], 0, n);
        
    } else {
		// base case
		basicsort(n, (T *) &data[0]);
    }
}