/***************************************************
 *
 *  STRUCT Declaration
 *
 ***************************************************/

/* satbox statistics */
struct satbox {
  int Max_atom;
  unsigned int Lemma_num, Delete_num, Branch_open, Branch_jump;
  unsigned long Branch_fail, Memory_count;
};


/* Variable table element */
struct var5 {
  unsigned short value;
  unsigned short level; 
  int stamp;
  int timer;
  int gmark;
};

/* Literal table element */
struct lit5 {
  int deleted;
  int **hts;
  int *bicls;
#ifdef TLCLAUSE
  struct nlink *ncls;
#endif
};

/* TL-clause links */
struct nlink {
  int * cl;
  struct nlink *next;
};

/***************************************************
 *
 *  CONSTANT Declaration
 *
 ***************************************************/

#define MAX_ATOM (1+SX.Max_atom)           /* can be anything under MAX_VAR */
#define MAX_CONFLICT 1
#define Level SX.Branch_open

/***************************************************
 *
 *  MACRO Declaration 
 *
 **************************************************/

#ifdef MORETRACE
#define trace(x,y) if (Flags[TRACE]>=x) y
#define trace1(x,y) if (Flags[TRACE]==x || x>8) y
#define check(x,y) if (x) y
#else
#define trace(x,y) 
#define trace1(x,y) 
#define check(x,y) 
#endif

#define var_value(i) V5[i]->value
#define var_level(i) V5[i]->level
#define var_stamp(i) V5[i]->stamp
#define var_timer(i) V5[i]->timer
#define var_gmark(i) V5[i]->gmark

#define var_value_flexible(i) (L5[(i)<<1]->deleted&1)
#define var_set_value_flexible(i) \
    print_flexi_x(i);\
    L5[(i)<<1]->deleted |= 1
#define var_reset_value_flexible0(i) \
    print_clear_x(i);\
    L5[(i)<<1]->deleted &= 254
#define var_reset_value_flexible(i)\
   var_reset_value_flexible0(i); \
   unassign_value(i); \
   var_gmark(i) = 0


#define lit_clauses_deleted(i) (L5[i]->deleted&2)
#define set_lit_clauses_deleted(i) L5[i]->deleted |= 2
#define reset_lit_clauses_deleted(i) L5[i]->deleted &= 1

#define lit_value(i) ((V5[(i)>>1]->value == DC)? DC : (((i)&1)? V5[(i)>>1]->value :  NEG(V5[(i)>>1]->value)))
#define lit_timer(i) V5[(i)>>1]->timer
#define lit_stamp(i) V5[(i)>>1]->stamp
#define lit_umark(i) V5[(i)>>1]->stamp
#define lit_gmark(i) V5[(i)>>1]->gmark

#define dfs_done(i) DFS_done[i]
#define dfs_time(i) DFS_time[i]
#define dfs_lowlink(i) DFS_lowlink[i]

#define assign_value0(k) V5[(k)>>1]->value = (k)&1
#define assign_value1(k) V5[(k)>>1]->value = NEG((k)&1)

#define assign_value2(k) assign_value0(k)
#define unassign_value(i) var_timer(i) = MAX_INT;  var_value(i) = DC

/*
#define insert_head_tail(ptr,ks)\
{ \
  int **ptrs1 = L5[ks]->hts;\
  if (array_count(ptrs1) == array_max(ptrs1)) {\
    int **ptrs2 = (int **) malloc((array_max(ptrs1)<<1) * (sizeof(int *)));\
    memory_count(sizeof(int *) * array_max(ptrs1));\
    if (ptrs2 == NULL) { fprintf(stderr, "insert_head_tail failed.\n"); exit(1); }\
    for (i = array_max(ptrs1)-1; i >= 0; i--) ptrs2[i] = ptrs1[i];\
    array_max(ptrs2) += array_max(ptrs1);\
    free(ptrs1);\
    ptrs1 = L5[ks]->hts = ptrs2;\
  }\
  array_push(ptrs1, type, ptr);\
}
*/

#define insert_head_tail(ptr,ks)\
{ \
  int **ptrs1 = L5[ks]->hts;\
  array_insert(ptrs1,int*,ptr);\
  L5[ks]->hts = ptrs1;\
}

#define remove_head_cl()\
	    pts[j] = pts[--num]; \
	    /* \
	      printf("change head-tail from %d to %d at pos %d in ", \
	      lit_var(cl[head]), lit_var(ks), i);\
	      print_clause(cl);\
	    */\
	    switch_head_body(cl,head,p,i,ks);\
	    if (++i == endcl) i = lit0();  /* beginning */\
	    set_head_pos(p,i);\
	    insert_head_tail(cl,ks);\
	    /*\
	      print_clause(cl);\
	      print_var5_clause(lit_var(ks), 3);\
	    */

#ifdef FLEXIBLE

#define check_new_unit() \
  if (New_unit) { \
    s = New_unit; i = lit_var(s); \
    New_unit = 0;\
    trace(7, printf("New_unit = (%d, %d)\n", i, lit_sign(s)));\
    if (var_value_flexible(i)) { \
      var_reset_value_flexible0(i); \
      var_value(i) = DC; \
    } \
    if (var_value(i) == DC) { \
      var_level(i) = Level; \
      var_gmark(i) = (int) New_unit_clause; \
      if (New_unit_clause) { trace(6, { printf("%d: unit x%d at level %d by ", Timer, i, Level); \
                             print_clause(New_unit_clause);});} \
      print_x_has_to(s); \
      assign_value2(s); \
      vstack_push2(s);\
    } else if (var_value(i) != lit_sign(s)) { \
      return var5_fail_end(New_unit_clause);\
   }}

#else

#define check_new_unit()\
  if (New_unit) { \
      s = New_unit; \
      New_unit = 0;\
      i = lit_var(s);\
      if (var_value(i) == DC) { \
      var_level((i)) = Level; \
      var_gmark((i)) = (int) New_unit_clause; \
      trace(6, if (New_unit_clause) { printf("%d: unit x%d at level %d by ", Timer, i, Level); \
                             print_clause(New_unit_clause);}); \
      print_x_has_to(s); \
      assign_value2(s); \
      vstack_push2(s);\
    } else if (var_value(i) != lit_sign(s)) { \
      return var5_fail_end(New_unit_clause);\
  }}
#endif

#ifdef AGE
#define collect_one_key(i) \
  if (var_stamp(i) != Stamp) { \
    if (var_level(i) < Level) {\
       if (var_level(i)) {\
         if ((Level-var_level(i)) < max_cl_lvl) \
           cl_lvl[Level-var_level(i)]++;\
         cl_arr[total++] = i;\
         if (total >= MAX_LENGTH) { \
 	   trace(4, printf("new clause too big\n")); return 0; }}\
    } else { \
       var_num++;\
       trace(4, printf("queue %d (%d)\n", i, var_level(i)));\
    }\
    var_stamp(i) = Stamp; \
  }

#else

#ifdef OLD

#define collect_one_key(i) \
  if (var_stamp(i) != Stamp) { \
    if (var_level(i) < Level) {\
       if (var_level(i)) { cl_arr[total++] = i;\
         if (total >= MAX_LENGTH) { \
 	   trace(4, printf("new clause too big\n")); return 0; }}\
    } else { \
       var_num++;\
       trace(4, printf("queue %d (%d)\n", i, var_level(i)));\
    }\
    var_stamp(i) = Stamp; \
  }

#else

#define collect_one_key(i) \
  if (var_stamp(i) != Stamp) { \
    if (var_level(i) < Level) {\
       if (var_level(i)) {\
         total++;\
         trace(6, printf("  remember %d (%d)\n", i, var_level(i)));\
       }\
    } else { \
       var_num++;\
       trace(4, printf("queue %d (%d)\n", i, var_level(i)));\
    }\
    var_stamp(i) = Stamp; \
  }

#endif
#endif

#define print_let_x_have(k) \
   trace(4, printf("[%d]  let x%d = %d.\n", SX.Branch_open, lit_var(k), lit_sign(k)))

#define print_now_let_x_have(k) \
   trace(4, printf(" [%d]  now x%d = %d.\n", SX.Branch_open, lit_var(k), lit_sign(k)))

#define print_x_has_to(k) \
   trace(4, printf("      x%d has to be %d [%d %d].\n", lit_var(k), lit_sign(k), vstack_size(), Level))

#define print_x_confirm_to(k) \
   trace(4, printf("      x%d HAS to be %d [%d].\n", lit_var(k), lit_sign(k), vstack_size()))

#define print_x_contradictory(k) \
   trace(4, printf("      x%d has contradictory values.\n", lit_var(k)))

#define print_flexi_x(i) \
   trace(4, printf("      flexi x%d = %d.\n", i, var_value(i)))

#define print_clear_x(i) \
   trace(4, printf("      clear x%d.\n", i))

#define print_reset_x \
   trace(4, printf("      reset x%d = %d.\n", i, var_value(i)))

#define print_up_to_x \
   trace(4, printf("      reset x%d = %d.\n", i, var_value(i)))

#define report_unit_lit(ks,i,cl)\
	  trace(6, {\
	    printf("%d: Unit cl %s%d at %d from ", Timer, (lit_sign(ks))? "" : "-", i, Level);\
	    print_clause(cl);});\
	  var_gmark(i) = (int) cl;\
	  var_level(i) = Level;\
	  print_x_has_to(ks);\
	  vstack_push0(ks);\
	  assign_value0(ks)


#define memory_count(x) SX.Memory_count += (x)


/***************************************************
 *
 *  VARIBALE Declaration 
 *
 **************************************************/
/* The initials of names of global variables are capitalized. */
struct lit5 **L5;
struct var5 **V5;
int Second_try = 0;
int New_unit = 0;
int *New_unit_clause = NULL;
int *Conflict_gcl;
int Empty_binary[3];
unsigned int Stamp, Timer;
int Backjumping_down;
int *Conflict_cl;
int Conflict_cl_level;
int Default_level = 1;
int First_false_var;

int *DFS_done, *DFS_lowlink, *DFS_time;

int Flags[MAX_FLAGS];

#ifdef AGE
#define max_cl_lvl 128
int cl_lvl[max_cl_lvl];
#endif

struct satbox SX;
