lpc4/lib/
lpc4/lib/doc/efun/
lpc4/lib/doc/lfun/
lpc4/lib/doc/operators/
lpc4/lib/doc/simul_efuns/
lpc4/lib/doc/types/
lpc4/lib/etc/
lpc4/lib/include/
lpc4/lib/include/arpa/
lpc4/lib/obj/d/
lpc4/lib/save/
lpc4/lib/secure/
lpc4/lib/std/
lpc4/lib/std/living/
/* fsort- a smarter quicksort / Profezzorn */
/* Optimized for minimum amount of compares */

#include "global.h"
#include "interpret.h"
#include "object.h"
#include "regexp.h"
#include "exec.h"
#include "simulate.h"

static int (*cmpfun)(const void *, const void *);
static void (*swapfun)(register void *, register void *);
static long size;
static char *tmp_area;

#ifdef DEBUG
static long elements;
static void *first;

static void ftest(void *a)
{
  int e;
  e=(char *)a-(char *)first;
  if(a<first || (e % size) || (e/size)>=elements)
    fatal("Error in fsort.\n");
}
#else
#define ftest(X) 
#endif

static void byteswap(register void *a,register void *b)
{
  char foo;
  ftest(a);
  ftest(b);
  foo=*(char *)a;
  *(char *)a=*(char *)b;
  *(char *)b=foo;
}

static void shortswap(register void *a,register void *b)
{
  short foo;
  ftest(a);
  ftest(b);
  foo=*(short *)a;
  *(short *)a=*(short *)b;
  *(short *)b=foo;
}


static void longswap(register void *a,register void *b)
{
  long foo;
  ftest(a);
  ftest(b);
  foo=*(long *)a;
  *(long *)a=*(long *)b;
  *(long *)b=foo;
}

static void long2swap(register void *a,register void *b)
{
  long foo;
  ftest(a);
  ftest(b);
  foo=((long *)a)[0];
  ((long *)a)[0]=((long *)b)[0];
  ((long *)b)[0]=foo;
  foo=((long *)a)[1];
  ((long *)a)[1]=((long *)b)[1];
  ((long *)b)[1]=foo;
}

static void fswap(register void *a,register void *b)
{
  ftest(a);
  ftest(b);
  MEMCPY(tmp_area,a,size);
  MEMCPY(a,b,size);
  MEMCPY(b,tmp_area,size);
}

static void fsort2(register char *bas,register char *last)
{
  register char *a,*b;
  register dum;

  ftest(bas);
  if(bas>=last) return;
  ftest(last);
  a=bas+size;
  if(a==last)
  {
    if((*cmpfun)(bas,last) > 0) swapfun(bas,last);
    return;
  }
  dum=(last-bas)>>1;
  dum-=dum % size;
  swapfun(bas,bas+dum);
  b=last;
  while(a<b)
  {
    while(a<=b && (*cmpfun)(a,bas) < 0) a+=size;
    while(a< b && (*cmpfun)(bas,b) < 0) b-=size;
    if(a<b)
    {
      swapfun(a,b);
      a+=size;
      if(b-a>size) b-=size;
    }
  }
  swapfun(bas,a-=size);
  fsort2(bas,a-=size);
  fsort2(b,last);
}

void fsort(base,elms,elmSize, cmpfunc)
void *base;
long elms;
long elmSize;
int (*cmpfunc)(const void *, const void *);
{

    if(elms<=0) return;
    cmpfun=cmpfunc;
    size=elmSize;
#ifdef DEBUG
    elements=elms;
    first=base;
#endif
    switch(elmSize)
    {
    case sizeof(char): swapfun=byteswap; break;
    case sizeof(short): swapfun=shortswap; break;
    case sizeof(long): swapfun=longswap; break;
    case sizeof(long)*2: swapfun=long2swap; break;
    default:
      swapfun=fswap;
      tmp_area=(char *)alloca(elmSize);
    }
    fsort2((char *)base,((char *)base) + size * (elms - 1));
}