/*=-=-=-=-=-=-=-=-=-=-  RCCL/RCI Notice of Copyright  -=-=-=-=-=-=-=-=-=-=-=*
 *									    *
 *	Copyright (C) 1987 by Mike Parker. Permission to use, distribute    *
 *	and copy is granted for non-commercial and research purposes only,  *
 *	providing the authors are acknowledged and this copyright notice is *
 *	displayed. The authors provide this software in hope that it will   *
 *	useful, but do not assume responsibility for its use.		    *
 *									    *
 *	This software was developed using the facilities of the McGill 	    *
 *	University Research Center for Intelligent Machines, Montreal,	    *
 *	Canada, for a project undertaken and supported by the RCA Advanced  *
 *	Technology Laboratories, Moorestown, New Jersey.		    *
 *									    *
 *=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/

static _heapsort_bubble_up();
static _heapsort_bubble_down();

heapsort(ptrs,nels,cmp)
char **ptrs; /* should be `<unknown>**ptrs', but we must name some type */
int nels;
int (*cmp)();
/*
	Sorts the ptrs vector.  (*cmp)(ptrs[i],ptrs[j]) should return:

		< 0	if *ptrs[i] < *ptrs[j]
		= 0	if *ptrs[i] = *ptrs[j]
		> 0	if *ptrs[i] > *ptrs[j]

	For example, if the ptrs are actually pointers to int, it would
	be perfectly good to write a cmp function as follows (unless the
	integers are so large that overflow can occur in the subtraction):

		int cmp(p1,p2)
		int *p1;
		int *p2;
		{
		 return(*p1 - *p2);
		}

	Tip:  If the ptrs are character string pointers, the standard
	strcmp() function is a good cmp function.

	The vector will be in non-decreasing order by this criterion on
	return from heapsort.
									*/
{
 int size;
 char *temp;

 if (nels <= 1)
  { return;
  }
 size = 1;
 while (size < nels)
  { _heapsort_bubble_up(size,ptrs,cmp);
    size ++;
  }
 while (size > 1)
  { size --;
    temp = ptrs[size];
    ptrs[size] = ptrs[0];
    ptrs[0] = temp;
    _heapsort_bubble_down(size,ptrs,cmp);
  }
}

static _heapsort_bubble_up(size,ptrs,cmp)
int size;
char **ptrs;
int (*cmp)();
{
 int i;
 int p;
 char *temp;

 i = size;
 while (1)
  { if (i == 0)
     { return;
     }
    p = (i - 1) >> 1;
    if (cmp(ptrs[i],ptrs[p]) > 0)
     { temp = ptrs[i];
       ptrs[i] = ptrs[p];
       ptrs[p] = temp;
       i = p;
     }
    else
     { return;
     }
  }
}

static _heapsort_bubble_down(size,ptrs,cmp)
int size;
char **ptrs;
int (*cmp)();
{
 int i;
 int j;
 int l;
 int r;
 int cl;
 int cr;
 char *temp;

 i = 0;
 while (1)
  { if (i >= size)
     { return;
     }
    l = i + i + 1;
    r = l + 1;
    cl = (l >= size) ? 1 : (cmp(ptrs[i],ptrs[l]) >= 0);
    cr = (r >= size) ? 1 : (cmp(ptrs[i],ptrs[r]) >= 0);
    switch ((cl<<1)|cr)
     { case 0:
	  j = (cmp(ptrs[l],ptrs[r]) > 0) ? l : r;
	  break;
       case 1:
	  j = l;
	  break;
       case 2:
	  j = r;
	  break;
       case 3:
	  return;
     }
    temp = ptrs[j];
    ptrs[j] = ptrs[i];
    ptrs[i] = temp;
    i = j;
  }
}
