merge.c
#include 
 
 
#define uint32 unsigned int
 
typedef int (*CMPFUN)(int, int);
 
 
 
#define INSERTION_SORT_BOUND 8 /* boundary point to use insertion sort */
 
void ArraySort(int This[], CMPFUN fun_ptr, uint32 the_len)
{
  uint32 span;
  uint32 median;
  uint32 lb;
  uint32 ub;
  uint32 indx;
  uint32 indx2;
  int* aux;
  int temp;
  int temp2;
 
  if (the_len <= 1)
    return;
 
  span = INSERTION_SORT_BOUND;
 
  /* insertion sort the first pass */
 
  for (lb = 0; lb < the_len; lb += span)
  {
    if ((ub = lb + span) > the_len) ub = the_len;
 
    for (indx = lb + 1; indx < ub; ++indx)
    {
      temp = This[indx];
      indx2 = indx;
      do
      {
        temp2 = This[--indx2];
        if ((*fun_ptr)(temp2, temp) > 0)
          This[indx2 + 1] = temp2;
        else
          break;
      } while (indx2 > lb);
      This[indx2] = temp;
    }
  }
 
  aux = (int*) malloc(sizeof(int) * the_len / 2);
 
  while (span < the_len)
  {
    /* median is the start of second file */
    for (median = span; median < the_len;)
    {
      indx2 = median - 1;
      if ((*fun_ptr)(This[indx2], This[median]) > 0)
      {
        /* the two files are not yet sorted */
        if ((ub = median + span) > the_len)
        {
          ub = the_len;
        }

        /* skip over the already sorted largest elements */
        while ((*fun_ptr)(This[--ub], This[indx2]) >= 0)
        {
        }

        /* copy second file into buffer */
        for (indx = 0; indx2 < ub; ++indx)
        {
          *(aux + indx) = This[++indx2];
        }
        --indx;
        indx2 = median - 1;
        lb = median - span;
        /* merge two files into one */
        for (;;)
        {
          if ((*fun_ptr)(*(aux + indx), This[indx2]) >= 0)
          {
            This[ub--] = *(aux + indx);
            if (indx > 0) --indx;
            else
            {
              /* second file exhausted */
              for (;;)
              {
                This[ub--] = This[indx2];
                if (indx2 > lb) --indx2;
                else goto mydone; /* done */
              }
            }
          }
          else
          {
            This[ub--] = This[indx2];
            if (indx2 > lb) --indx2;
            else
            {
              /* first file exhausted */
              for (;;)
              {
                This[ub--] = *(aux + indx);
                if (indx > 0) --indx;
                else goto mydone; /* done */
              }
            }
          }
        }
      }
      mydone:
      median += span + span;
    }
    span += span;
  }
 
  free(aux);
 
}
 
#define ARRAY_SIZE 165537
 
int my_array[ARRAY_SIZE];
 
void fill_array()
{
  int indx;

  for (indx=0; indx < ARRAY_SIZE; ++indx)
  {
    my_array[indx] = rand();
  }
}
 
int cmpfun(int a, int b)
{
  if (a > b)
    return 1;
  else if (a < b)
    return -1;
  else
    return 0;
}
 
int main()
{
  int indx;
 
  fill_array();
 
  ArraySort(my_array, cmpfun, ARRAY_SIZE);
 
  for (indx=1; indx < ARRAY_SIZE; ++indx)
  {
    if (my_array[indx - 1] > my_array[indx])
    {
      printf("bad sort\n");
      return(1);
    }
  }

  return(0);
}