#ifdef DOC_BUILD_INTERNAL
#endif
#include "upqueue.h"
unsigned upq_GetSize(UPQUEUE Upq)
{
  return Upq->size;
}
unsigned upq_GetCapacity(UPQUEUE Upq)
{
  return Upq->capacity;
}
unsigned upq_LChild(unsigned Node)
{
  return 2*Node+1;
}
unsigned upq_Parent(unsigned Node)
{
#ifdef SPASS_CHECK
  return (Node == 0 ? UINT_MAX : (Node-1)/2);
#else
  return (Node-1)/2;
#endif
}
void upq_Swap(UPQUEUE Upq, unsigned PosA, unsigned PosB)
{
  unsigned t;
  t = Upq->heap[PosA];
  Upq->heap[PosA] = Upq->heap[PosB];
  Upq->heap[PosB] = t;
  Upq->pos[Upq->heap[PosA]] = PosA;
  Upq->pos[Upq->heap[PosB]] = PosB;
}
void upq_PDown(UPQUEUE Upq, unsigned Pos)
{
  unsigned maxPos, childPos;
  if (Pos >= upq_GetSize(Upq))
    return;
  maxPos = Pos;
  for (childPos = upq_LChild(Pos);
       childPos < upq_LChild(Pos)+2 && childPos < upq_GetSize(Upq);
       childPos++)
    if (Upq->prior[Upq->heap[childPos]] >
 Upq->prior[Upq->heap[maxPos]])
      maxPos = childPos;
  if (Pos != maxPos) {
    upq_Swap(Upq, Pos, maxPos);
    upq_PDown(Upq, maxPos);
  }
}
void upq_PUp(UPQUEUE Upq, unsigned Pos)
{
    unsigned parentPos;
    if (Pos != 0 && Pos < upq_GetSize(Upq)) {
    parentPos = upq_Parent(Pos);
    if (Upq->prior[Upq->heap[Pos]] >
 Upq->prior[Upq->heap[parentPos]]) {
      upq_Swap(Upq, parentPos,Pos);
      upq_PUp(Upq, parentPos);
    }
  }
}
UPQUEUE upq_Create(MEMORY Memory, unsigned Capacity)
{
  unsigned i;
  UPQUEUE res;
  res = (UPQUEUE)memory_Malloc(Memory, sizeof(UPQ_NODE));
  if (Capacity == 0)
    Capacity = 1;
  res->capacity = Capacity;
  res->size = 0;
  res->heap = memory_Malloc(Memory, Capacity *
       sizeof(*(res->heap)));
  res->prior = memory_Malloc(Memory, Capacity *
       sizeof(*(res->prior)));
  res->pos = memory_Malloc(Memory, Capacity *
       sizeof(*(res->pos)));
  res->upper_bound = 0;
  for (i = 0; i < Capacity; i++) {
    res->heap[i] = UINT_MAX;
    res->prior[i] = PRIOR_MAX;
    res->pos[i] = UINT_MAX;
  }
  return res;
}
UPQUEUE upq_Copy(MEMORY Memory, UPQUEUE Upq)
{
  UPQUEUE new;
  new = upq_Create(Memory, upq_GetCapacity(Upq));
  new->size = upq_GetSize(Upq);
  memcpy(new->heap, Upq->heap,
  Upq->capacity * sizeof(*(new->heap)));
  memcpy(new->prior, Upq->prior,
  Upq->capacity * sizeof(*(new->prior)));
  memcpy(new->pos, Upq->pos,
  Upq->capacity * sizeof(*(new->pos)));
  new->upper_bound = Upq->upper_bound;
  return new;
}
BOOL upq_Contains(UPQUEUE Upq, unsigned El)
{
  return El < upq_GetCapacity(Upq) &&
    Upq->pos[El] < upq_GetSize(Upq) &&
    Upq->heap[Upq->pos[El]] == El;
}
BOOL upq_ExtendIfNecessary(MEMORY Memory, UPQUEUE Upq, unsigned El)
{
  unsigned i;
  if (El >= upq_GetCapacity(Upq)) {
    Upq->heap = memory_Realloc(Memory, Upq->heap,
       upq_GetCapacity(Upq) *
       sizeof(*(Upq->heap)),
       (2*El+1) * sizeof(*(Upq->heap)));
    Upq->prior = memory_Realloc(Memory, Upq->prior,
       upq_GetCapacity(Upq) *
       sizeof(*(Upq->prior)),
       (2*El+1) * sizeof(*(Upq->prior)));
    Upq->pos = memory_Realloc(Memory, Upq->pos,
       upq_GetCapacity(Upq) *
       sizeof(*(Upq->pos)),
       (2*El+1) * sizeof(*(Upq->pos)));
    for (i = upq_GetCapacity(Upq); i < 2*El + 1; i++) {
      Upq->heap[i] = UINT_MAX;
      Upq->prior[i] = PRIOR_MAX;
      Upq->pos[i] = UINT_MAX;
    }
    Upq->capacity = 2*El + 1;
    return TRUE;
  }
  return FALSE;
}
BOOL upq_AddLazily(MEMORY Memory, UPQUEUE Upq,
     unsigned El, PRIOR_T Prior)
{
  if (upq_Contains(Upq, El))
    return FALSE;
  upq_ExtendIfNecessary(Memory,Upq,El);
  Upq->heap[upq_GetSize(Upq)] = El;
  Upq->pos[El] = upq_GetSize(Upq);
  Upq->prior[El] = Prior;
  Upq->size++;
  if (Prior > upq_GetUpperBound(Upq))
    Upq->upper_bound = Prior;
  return TRUE;
}
BOOL upq_Add(MEMORY Memory, UPQUEUE Upq,
      unsigned El, PRIOR_T Prior)
{
  if (upq_AddLazily(Memory, Upq, El, Prior)) {
    upq_PUp(Upq, Upq->pos[El]);
    return TRUE;
  }
  return FALSE;
}
void upq_Show(UPQUEUE Upq)
{
  unsigned i;
  printf("\n\n\nUPQUEUE: capacity=%u, n=%u, upper_bound: %u\nheap: ",
  upq_GetCapacity(Upq), upq_GetSize(Upq),
  upq_GetUpperBound(Upq));
  for (i = 0; i < upq_GetCapacity(Upq); i++)
    printf("%u  ", Upq->heap[i]);
  printf("\nprior: ");
  for (i = 0; i < upq_GetCapacity(Upq); i++)
    printf("%u  ", Upq->prior[i]);
  printf("\npos: ");
  for (i = 0; i < upq_GetCapacity(Upq); i++)
    printf("%u  ", Upq->pos[i]);
  printf("\n\n");
}
unsigned upq_ExtractMax(UPQUEUE Upq)
{
  if (upq_GetSize(Upq) == 0)
    return PRIOR_MAX;
  upq_Swap(Upq, 0, upq_GetSize(Upq)-1);
  Upq->size--;
  upq_PDown(Upq,0);
  return Upq->heap[upq_GetSize(Upq)];
}
unsigned upq_GetMax(UPQUEUE Upq)
{
  if (upq_GetSize(Upq) == 0)
    return UINT_MAX;
  return Upq->heap[0];
}
PRIOR_T upq_GetMaxPrior(UPQUEUE Upq)
{
  if (upq_GetSize(Upq) == 0)
    return PRIOR_MAX;
  return Upq->prior[Upq->heap[0]];
}
PRIOR_T upq_GetUpperBound(UPQUEUE Upq)
{
  return Upq->upper_bound;
}
void upq_SetUpperBound(UPQUEUE Upq, PRIOR_T bound)
{
  Upq->upper_bound = bound;
}
BOOL upq_Remove(UPQUEUE Upq, unsigned El)
{
  unsigned pos;
#ifdef SPASS_CHECK
  if (!upq_Contains(Upq, El))
    return FALSE;
#endif
  pos = Upq->pos[El];
  upq_Swap(Upq, pos, upq_GetSize(Upq)-1);
  Upq->size--;
  upq_PDown(Upq, pos);
  upq_PUp(Upq, pos);
  return TRUE;
}
unsigned upq_ReinsertElement(UPQUEUE Upq, unsigned El)
{
  if (upq_GetSize(Upq) == upq_GetCapacity(Upq))
    return UINT_MAX;
  Upq->pos[El] = upq_GetSize(Upq);
  Upq->heap[upq_GetSize(Upq)] = El;
  Upq->size++;
  upq_PUp(Upq, upq_GetSize(Upq)-1);
  return El;
}
void upq_Rescale(UPQUEUE Upq, signed Shift)
{
  unsigned i;
  if (Shift > 0) {
    for (i = 0; i < upq_GetCapacity(Upq); i++)
      Upq->prior[i] >>= Shift;
    Upq->upper_bound >>= Shift;
  } else {
    for (i = 0; i < upq_GetCapacity(Upq); i++)
      Upq->prior[i] <<= -Shift;
    Upq->upper_bound <<= -Shift;
  }
}
void upq_SetValue(UPQUEUE Upq, unsigned Value)
{
  unsigned i;
  for (i = 0; i < upq_GetCapacity(Upq); i++)
    Upq->prior[i] = Value;
  Upq->upper_bound = Value;
}
void upq_Normalize(UPQUEUE Upq, unsigned Bitsneeded)
{
  upq_Rescale(Upq,
       (signed)(log(upq_GetUpperBound(Upq))/log(2)) +
       1 - Bitsneeded);
}
void upq_UpdatePrior(UPQUEUE Upq, unsigned Number, PRIOR_T NewPrior)
{
  unsigned oldPrior;
  oldPrior = Upq->prior[Number];
  upq_UpdatePriorLazily(Upq, Number, NewPrior);
  if (oldPrior > NewPrior)
    upq_PDown(Upq, Upq->pos[Number]);
  else if (oldPrior < NewPrior)
    upq_PUp(Upq, Upq->pos[Number]);
}
void upq_UpdatePriorLazily(UPQUEUE Upq, unsigned Number,
      PRIOR_T NewPrior)
{
  if (NewPrior > upq_GetUpperBound(Upq))
    Upq->upper_bound = NewPrior;
  Upq->prior[Number] = NewPrior;
}
unsigned upq_IncreasePrior(UPQUEUE Upq, unsigned Number,
      PRIOR_T Diff)
{
  Upq->prior[Number] += Diff;
  if (Upq->prior[Number] > upq_GetUpperBound(Upq))
    Upq->upper_bound = Upq->prior[Number];
  upq_PUp(Upq, Upq->pos[Number]);
  return Upq->prior[Number];
}
unsigned upq_IncreasePriorLazily(UPQUEUE Upq, unsigned Number,
     PRIOR_T Diff)
{
  if (Upq->prior[Number] + Diff > upq_GetUpperBound(Upq))
    Upq->upper_bound = Upq->prior[Number] + Diff;
  return Upq->prior[Number] += Diff;
}
void upq_Heapify(UPQUEUE Upq)
{
  unsigned i;
  for (i = upq_GetSize(Upq); i-- > 0; ) {
    upq_PDown(Upq, i);
  }
}
PRIOR_T* upq_GetPrior(UPQUEUE Upq)
{
  return Upq->prior;
}
void upq_Delete(MEMORY Memory, UPQUEUE Upq)
{
  memory_Free(Memory, Upq->heap,
       upq_GetCapacity(Upq) * sizeof(*(Upq->heap)));
  memory_Free(Memory, Upq->prior,
       upq_GetCapacity(Upq) * sizeof(*(Upq->prior)));
  memory_Free(Memory, Upq->pos,
       upq_GetCapacity(Upq) * sizeof(*(Upq->pos)));
  memory_Free(Memory, Upq, sizeof(UPQ_NODE));
}
