再帰なしのマージソート

C言語で。 もう少し変数を減らせないものか。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int merge_sort(int n, int *a)
{
  int *tmp_a, *src, *tgt, *tmp;
  int *sp_ed, *tp, *tp_ed;
  int *p1, *p1_ed, *p2, *p2_ed;
  int w;

  tmp_a = (int*) malloc(n * sizeof(int));
  if (tmp_a == NULL)
    return 1;

  src = a;
  tgt = tmp_a;
  for (w = 1; w < n; w += w) {
    tp = tgt;
    tp_ed = tp + n;
    p2_ed = src;
    sp_ed = src + n;
    while (tp < tp_ed) {
      p1 = p2_ed;
      p1_ed = p1 + w;
      if (p1_ed >= sp_ed) {
        while (p1 < sp_ed)
          *tp++ = *p1++;
        break;
      }
      p2 = p1_ed;
      p2_ed = p2 + w;
      if (p2_ed > sp_ed) { p2_ed = sp_ed; }
      while (p1 < p1_ed && p2 < p2_ed) {
        if (*p1 < *p2)
          *tp++ = *p1++;
        else
          *tp++ = *p2++;
      }
      if (p1 == p1_ed) {
        while (p2 < p2_ed)
          *tp++ = *p2++;
      } else {
        while (p1 < p1_ed)
          *tp++ = *p1++;
      }
    }
    tmp = src;
    src = tgt;
    tgt = tmp;
  }
  if (a != src) {
    memcpy(a, tmp_a, n * sizeof(int));
  }
  free(tmp_a);
  return 0;
}

int main(int argc, char** argv)
{
  int a[] = {12, 32, 0, 5, 10, -3, 10, 77};
  int i, n;

  n = sizeof(a) / sizeof(int);

  if (merge_sort(n, a))
    exit(1);

  for (i = 0; i < n; i++)
    printf("%d\n", a[i]);
}