/* File: tweak_merge.c
   Tweaked Merge Sort for better performance
*/

#include <assert.h>
#include <stdio.h>
#include "sorting.h"

/* Global variable temp must be allocated the same
   amount of space as the array to be sorted
*/

static data *temp ;

void init_mergesort(index n) {

   temp = (data *) malloc(n * sizeof(data)) ;
   if (temp == NULL) {
      printf("Could allocate temporary space for merge\n") ;
      exit(1) ;
   }
}


void merge(data A[], index low1, index high1, index low2, index high2) {
   index t, i1, i2 ;

   /* Sanity check */
   assert(low2 == high1 + 1) ;
  
   /* while there are elements in both halves, copy the lowest one */
   i1 = low1 ;
   i2 = low2 ;
   t = 0 ;
   while (i1 <= high1 && i2 <= high2) {
      if (A[i1] < A[i2]) {
         temp[t] = A[i1] ;
         i1++ ;
         t++ ;
      } else {
         temp[t] = A[i2] ;
         i2++ ;
         t++ ;
      }
   }

   /* copy any remaining elements */
   while (i1 <= high1) {
    temp[t] = A[i1] ;
    t++ ;
    i1++ ;
   }
   while (i2 <= high2) {
     temp[t++] = A[i2++] ;
   }

   /* copy the now-sorted elements back into the original array */
   for (t = low1; t <= high2; t++) {
      A[t] = temp[t - low1] ;
   }
}

void mergesort(int A[], index low, index high) {
  index mid ;
  
  if (high - low <= 20) {
     insertion_sort(A, low, high) ;
     return ;
  }
  
   mid = (low + high)/2 ;
   mergesort(A, low, mid) ;
   mergesort(A, mid + 1, high) ;
   
   merge(A, low, mid, mid + 1, high) ;
}
