/* median-3 variant of quicksort - coded by John Garnett.

   using this quicksort rather than the builtin one because most
   builtin implementations choke on non-deterministic compare functions
   (and we can't control what compare function is used since it is at
   the mudlib level).  Based on algorithm appearing in _Data Structures and
   Algorithm Analysis_ by Cawnthorpe.
*/

#ifdef __386BSD__
#include <sys/types.h>
#include <string.h>
#endif
#include "config.h"
#include "lint.h"
#include "mudlib_stats.h"
#include "interpret.h"

#define LEN sizeof(struct svalue)
#define MAX_LEN 1000

INLINE static void
doSwap(one, two, size)
void *one, *two;
int size;
{
	static char buf[MAX_LEN];

	memcpy(buf, one, size);
	memcpy(one, two, size);
	memcpy(two, buf, size);
}

/* qsort adapted from page 87 of K&R 2nd edition */

void
qSort(v, left, right, size, rightmost, compar)
void *v;
int left, right, size, rightmost;
int (*compar) PROT((void *, void *));
{
	int i, last, szleft;

	if ((left >= right) || (left < 0) || (right > rightmost) || (right < 0)) {
		return;
	}
	szleft = size * left;
	doSwap((char *)v + szleft, (char *)v + (size * ((left + right) / 2)), size);
	last = left;
	for (i = left + 1; i <= right; i++) {
		if (compar((char *)v + (size * i), (char *)v + szleft) < 0) {
			doSwap((char *)v + (size * ++last), (char *)v + (size * i), size);
		}
	}
	doSwap((char *)v + szleft, (char *)v + (size * last), size);
	qSort(v, left, last - 1, size, rightmost, compar);
	qSort(v, last + 1, right, size, rightmost, compar);
}

void
quickSort(a, nmemb, size, compar)
void *a;
int nmemb, size;
int (*compar) PROT((void *, void *));
{
	if (nmemb < 2) {
		return;
	}
	qSort(a, 0, nmemb - 1, size, nmemb - 1, compar);
}
