#ifdef DOC_BUILD_INTERNAL
#endif
#include "bqueue.h"
const unsigned bqueue_EXTRA = 4;
const int bqueue_FIRST = -1;
const int bqueue_INSERT = -2;
const int bqueue_CAPACITY = -3;
const int bqueue_SUM = -4;
BQUEUE bqueue_Create(MEMORY Memory, unsigned Capacity_log)
{
  BQUEUE bq;
  unsigned i, capacity;
  capacity = (1<<Capacity_log);
  bq = (BQUEUE)memory_Malloc(Memory, (capacity + bqueue_EXTRA)*sizeof(*bq));
  bq = bq + bqueue_EXTRA;
  for(i = 0; i < capacity; i++)
    bq[i] = (intptr_t)NULL;
  bq[bqueue_CAPACITY] = capacity;
  bqueue_Clean(bq);
  return bq;
}
void bqueue_Delete(MEMORY Memory, BQUEUE Bq)
{
  memory_Free(Memory, Bq-bqueue_EXTRA, (bqueue_GetCapacity(Bq)+bqueue_EXTRA)*sizeof(*Bq));
}
void bqueue_Clean(BQUEUE Bq)
{
  Bq[bqueue_FIRST] = 0;
  Bq[bqueue_INSERT] = 0;
  Bq[bqueue_SUM] = 0;
}
intptr_t bqueue_GetCapacity(BQUEUE Bq)
{
  return Bq[bqueue_CAPACITY];
}
intptr_t bqueue_GetSum(BQUEUE Bq)
{
  return Bq[bqueue_SUM];
}
BOOL bqueue_IsEmpty(BQUEUE Bq)
{
  return Bq[bqueue_FIRST] == Bq[bqueue_INSERT];
}
BOOL bqueue_IsFull(BQUEUE Bq)
{
  return Bq[bqueue_FIRST] == ((Bq[bqueue_INSERT]+1) & (bqueue_GetCapacity(Bq)-1));
}
BOOL bqueue_GetSize(BQUEUE Bq)
{
  int size;
  size = Bq[bqueue_INSERT]-Bq[bqueue_FIRST];
  if (size < 0)
    return size + bqueue_GetCapacity(Bq);
  return size;
}
intptr_t bqueue_GetFront(BQUEUE Bq)
{
#ifdef SPASS_CHECK
  if (bqueue_IsEmpty(Bq))
    return -1;
#endif
  return Bq[Bq[bqueue_FIRST]];
}
intptr_t bqueue_GetBack(BQUEUE Bq)
{
#ifdef SPASS_CHECK
  if (bqueue_IsEmpty(Bq))
    return -1;
#endif
  if (Bq[bqueue_INSERT] == 0)
    return Bq[bqueue_GetCapacity(Bq)-1];
  return Bq[Bq[bqueue_INSERT]-1];
}
void bqueue_Dequeue(BQUEUE Bq)
{
  Bq[bqueue_SUM] -= bqueue_GetFront(Bq);
#ifdef SPASS_CHECK
  if (bqueue_IsEmpty(Bq)) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: tried to dequeue although queue is already empty. ", __func__);
    misc_FinishErrorReport();
  }
  Bq[Bq[bqueue_FIRST]] = -1;
#endif
  Bq[bqueue_FIRST] = (Bq[bqueue_FIRST] + 1) & (bqueue_GetCapacity(Bq)-1);
}
void bqueue_BoundedEnqueue(BQUEUE Bq, intptr_t El)
{
  if (bqueue_IsFull(Bq))
    bqueue_Dequeue(Bq);
  #ifdef SPASS_CHECK
  if (bqueue_IsFull(Bq)) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: Internal Error. ", __func__);
    misc_FinishErrorReport();
  }
#endif
  Bq[Bq[bqueue_INSERT]] = El;
  Bq[bqueue_INSERT] = (Bq[bqueue_INSERT] + 1) & (bqueue_GetCapacity(Bq)-1);
  Bq[bqueue_SUM] += El;
}
 void bqueue_Print(BQUEUE Bq)
{
  unsigned i;
  i = Bq[bqueue_FIRST];
  while (i != Bq[bqueue_INSERT]) {
    printf("%" PRIiPTR " ", Bq[i]);
    i = (i+1) & (bqueue_GetCapacity(Bq)-1);
  }
  printf("\t\tSUM: %" PRIiPTR ", SIZE: %u", bqueue_GetSum(Bq), bqueue_GetSize(Bq));
}
