/* Unit clause queue */
int *Unit_cls, Unit_cls_idx, Unit_cls_idx_end;

#define uqueue_create() \
  Unit_cls = (int *) malloc(SX.Max_atom * (sizeof(int))); \
  memory_count(sizeof(int *) * (SX.Max_atom));

#define uqueue_init() Unit_cls_idx = Unit_cls_idx_end = 0

#define uqueue_nonempty() (Unit_cls_idx != Unit_cls_idx_end)

#define uqueue_add(i) \
   lit_timer(i) = Timer;\
   Unit_cls[Unit_cls_idx_end++] = i;\
   if (Unit_cls_idx_end == SX.Max_atom) Unit_cls_idx_end = 0;

#define uqueue_pop(i) \
   i=Unit_cls[Unit_cls_idx++];\
   if (Unit_cls_idx == SX.Max_atom) Unit_cls_idx = 0


/* value stack */

/* A value stack is an unsigned int array of length SX.Max_atom.
   Each entry in the stack contains the following info:
      the variable  -- the high 30 bits.
      the value assiged to the variable -- the third bit
      the second choice of the selected variable -- the second bit
      the assignment due to selection -- the first bit
  That is, the last two bits:
     01: selected, first choice
     10: selected, second choice
     00: forced by unit clause
     11: forced by unit clause from a masked clause (related to MAXSAT).
*/

#define SELECT_BIT 1
#define SECOND_BIT 2
#define MASK_BIT   3
#define VALUE_BIT  4

unsigned int *Vstack;
int Vstack_idx=0, Vstack_begin=0;

#define vstack_init() Vstack = (int *) malloc(SX.Max_atom * (sizeof(int)))

#define vstack_push_only(ks)\
   uqueue_add(ks); \
   Vstack[Vstack_idx++] = (ks<<2);\
   check(Vstack_idx>SX.Max_atom, { printf("Vstack overflow\n"); vstack_print(); exit(1);})

#define vstack_push0(ks)\
   uqueue_add(ks); \
   Vstack[Vstack_idx++] = (ks<<2);\
   check(Vstack_idx>SX.Max_atom, { printf("Vstack overflow\n"); vstack_print(); exit(1);})

#define vstack_push1(ks)\
   uqueue_add(ks); \
   Vstack[Vstack_idx++] = (ks<<2)+1;\
   check(Vstack_idx>SX.Max_atom, { printf("Vstack overflow\n"); vstack_print(); exit(1);})

#define vstack_push2(ks)\
   uqueue_add(ks); \
   Vstack[Vstack_idx++] = (ks<<2)+2;\
   check(Vstack_idx>SX.Max_atom, { printf("Vstack overflow\n"); vstack_print(); exit(1);})

#define vstack_of(k) Vstack[k]
#define vstack_nonempty() Vstack_idx
#define vstack_size() Vstack_idx
#define vstack_resize(k) Vstack_idx = k
#define vs_literal(i) (i>>2)
#define vs_var(i) (i>>3)
#define vs_value(i) ((i&VALUE_BIT)>>2)
#define vs_selected(i) ((i&MASK_BIT)==SELECT_BIT)
#define vs_second(i) ((i&MASK_BIT)==SECOND_BIT)
#define vs_mask(i) ((i&MASK_BIT)==MASK_BIT)
#define vstack_begin() (Vstack_begin)
#define remember_vs_size() Vstack_begin=vstack_size()

int vstack_set_second (v)
     int v;
{
  if (vstack_nonempty()) {
    int i;
    for (i=vstack_size()-1; i>=vstack_begin(); i--) if (v == vs_var(vstack_of(i))) {
      vstack_of(i) |= SECOND_BIT;
      return i;
    }
  }
  return 0;
}

int satbox_collect_selected (backup)
     int backup[];
{
  int i, idx=0; 
  for (i = vstack_begin(); i < vstack_size(); i++) 
    if (vs_selected(vstack_of(i))) 
      backup[idx++] = vs_var(vstack_of(i));
    else if (vs_second(vstack_of(i))) 
      backup[idx++] = -vs_var(vstack_of(i));
  return idx;
}

void vstack_reinit ()
{
  int i, k;

  for (i = vstack_begin(); i < vstack_size(); i++) {
    k = vs_var(vstack_of(i));
    unassign_value(k);
    var_gmark(k) = 0;
  }
  vstack_resize(vstack_begin());
  uqueue_init();
}

void vstack_print () 
{
  int i; 
  printf("value stack:\n");
  for (i = 0; i < vstack_size(); i++) {
    int info = vstack_of(i);
    int k = vs_var(info);
    if (vs_selected(info)) printf("\n");
    printf("%d: x%d, val %d=%d, lvl %d ", i, k, 
	   vs_value(info), var_value(k), var_level(k));
    if (var_gmark(k) && (var_gmark(k) != OUTSIDE)) 
      print_clause((int*)var_gmark(k)); else printf("\n");
  }
}

int vstack_backup (level)
     /* back up to Level level; return the last item of Level level */
     int level; 
{
  int vv=0, i, k, info;

  if (Default_level > level) Default_level = level;

  // for (k = vstack_size()-1; k >= vstack_begin(); k--) {
  k = vstack_size(); 
  while (--k >= vstack_begin()) {
    info = vstack_of(k);
    i = vs_var(info);

    if (var_level(i) < level) {
      vstack_resize(k+1);
      trace(8, printf("  touch x%d, level = %d\n", i, var_level(i)));
      return vv;
    }
    vv = vs_literal(info);

    trace(6, printf(" [%d,%d,%d]: ", k, var_level(i), var_order_satbox(i)));
    var_stamp(i) = 0;
#ifdef FLEXIBLE
    if (gcl=(int*)var_gmark(i)) {
      if (is_from_binary(gcl)) {
        j = key_from_binary(gcl);
      } else if (i == lit_var(gcl[0])) {
	j = lit_var(gcl[1]); 
      } else {
	j = lit_var(gcl[0]);
      }
      if (var_value_flexible(j)) {
	print_reset_x;
	var_gmark(i) = 0;
	unassign_value(i);
      } else {
	var_set_value_flexible(i);
      }
    } else {
      var_set_value_flexible(i);
    }   
#else
    print_reset_x;
    var_gmark(i) = 0;
    unassign_value(i);
#endif

    if (vs_selected(info)) { 
#ifdef AGE
      ages_delete_clauses(Level);
#endif
      SX.Branch_open--; 
      /* if (Backjumping_down) guide_path_add_satbox(1, vs_literal(info));*/
    } else {
      vv = 0;
      /* if (Backjumping_down && vs_second(info)) 
	 guide_path_add_satbox(0, vs_literal(info)); */
    }
  }
  vstack_resize(vstack_begin());
  return vv;
}
