static char *SccsId = "@(#)pqueue.c 4.2 (TU-Delft) 08/28/90";
/**********************************************************

Name/Version      : makegln/4.2

Language          : C
Operating system  : UNIX SYSTEM V
Host machine      : HP9000

Author            : N.P. van der Meijs
Creation date     : 15-Mar-1988
Modified by       :
Modification date :


        Delft University of Technology
        Department of Electrical Engineering
        Network Theory Section
        Mekelweg 4 - P.O.Box 5031
        2600 GA DELFT
        The Netherlands

        Phone : 015 - 786234

        COPYRIGHT (C) 1988. All rights reserved.
**********************************************************/
#include "config.h"
#include <stdio.h>
#include "aux/aux.h"
#include "makegln.h"

typedef struct pqEntry_t {
    _edge_t * edge;
    int       block;
} pqEntry_t;


#define swap(pq,i,j) {{ \
register _edge_t * E = pq[i].edge; pq[i].edge = pq[j].edge; pq[j].edge = E;} {\
register int   B = pq[i].block; pq[i].block = pq[j].block; pq[j].block = B;}}

static int size;			/* number of entries now in queue */
static int maxSize = 0;			/* max number of entries in queue */
static pqEntry_t * pq = NULL;		/* head of queue */

/* This module assumes heap is in pq[1...N], pq[0] is unused.
 * So allocate N+1 entries
 */

void pqInit (N)
int N;
{
    size = 0;
    if (maxSize < N) {		/* re-initialization */
	if (pq)
	    DISPOSE (pq);
	pq = NEW (pqEntry_t, N + 1);
	maxSize = N;
    }
}

void pqHead (ep, np)
_edge_t ** ep;
int * np;
{
    *ep = pq[1].edge;
    *np = pq[1].block;
}

void pqInsert (e, n)
_edge_t * e;
int n;
{
    void siftup ();

    size++;

    ASSERT (size <= maxSize);

    pq[size].edge  = e;
    pq[size].block = n;

    siftup (pq, size);
}

void pqReplaceHead (e, n)
_edge_t * e;
int n;
{
    void siftdown ();

    pq[1].edge  = e;
    pq[1].block = n;

    siftdown (pq, size);
}

private
void siftup (base, N)
pqEntry_t * base;
int N;
{
    register int i = N;
    register int p;		/* parent */

    for (;;) {
	if (i == 1) break;
	p = i / 2;
	if (!larger (base[p].edge, base[i].edge)) break;
	swap (base, p, i);
	/* ASSERT (!larger (base[p].edge, base[i].edge)); */
	i = p;
    }
}

private
void siftdown (base, N)
pqEntry_t * base;
int N;
{
    register int i = 1;
    register int c;		/* child */

    for (;;) {
	c = i + i;		/* c is left child of i */
	if (c > N) break;
	if (c+1 <= N 		/* c + 1 is right child of i */
	&& (smaller (base[c+1].edge, base[c].edge)))
	    c += 1;

	/* c is least child of i */
	if (!larger (base[i].edge, base[c].edge)) break;

        swap (base, i, c);

	/* ASSERT (!larger (base[i].edge, base[c].edge)); */
	i = c;
    }
}
