I have the following code, which implements a bottom-up mergesort:

```
#include "sort.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#define CUTOFF 8
#define MIN(a, b) ((a) < (b) ? (a) : (b))

void merge(uint8_t *, uint8_t *, size_t, size_t, size_t, cmpfn);

// sort LEN elements of A, of SZ bytes each, using CMP to perform the
// comparisons
void merge_sort(void *a, size_t len, size_t sz, cmpfn cmp) {
  uint8_t *buf = malloc(len * sz);

  for (size_t i = 0; i < len; i += CUTOFF) {
    insertion_sort((uint8_t *) a + i * sz, MIN(CUTOFF, len - i), sz, cmp);
  }
  for (size_t w = CUTOFF; w < len; w *= 2) {
    for (size_t i = 0; i + w < len; i += w * 2) {
      merge((uint8_t *) a + i * sz, buf, MIN(w * 2, len - i), w, sz, cmp);
    }
  }
  free(buf);
}

void merge(uint8_t *a, uint8_t *buf, size_t len, size_t mid, size_t sz,
          cmpfn cmp) {
  if (cmp(a + mid * sz, a + (mid - 1) * sz) >= 0) {
    return;
  }

  size_t i = 0, j = mid, k = 0;

  memcpy(buf, a, len * sz);
  while (i < mid && j < len) {
    if (cmp(buf + j * sz, buf + i * sz) < 0) {
      memcpy(a + k * sz, buf + j++ * sz, sz);
    } else {
      memcpy(a + k * sz, buf + i++ * sz, sz);
    }
    ++k;
  }
  if (j == len) {
    memcpy(a + k * sz, buf + i * sz, (mid - i) * sz);
  }
}

```

Currently, during every call of `merge`, the code copies the contents of the array into `buf`. I know that in a top-down recursive approach, you can switch the order of the two arrays when calling merge to avoid the copy. How can I achieve this with an iterative approach?

EDIT: I got it working now, and I've posted the answer. If anyone has any suggestions or notices any drawbacks, feedback would be highly appreciated!