#ifdef DOC_BUILD_INTERNAL
#endif
#include "clause.h"
const unsigned clause_EXTRA = 14;
const int clause_RES = -14;
const int clause_PROPS = -13;
const int clause_PARENTS = -12;
const int clause_INFOS = -11;
const int clause_CAPACITY = -10;
const int clause_FUNS = -9;
const int clause_VARS = -8;
const int clause_TYPES = -7;
const int clause_FLITS = -6;
const int clause_ID = -5;
const int clause_MARK = -4;
const int clause_CLITS = -3;
const int clause_CONC = -2;
const int clause_PREM = -1;
static const uintptr_t clause_FUNS_UNCOUNTED = ~(uintptr_t)0;
BOOL clause_IsMarkedProblemClause(CLAUSE Clause)
{
  return (Clause[clause_INFOS] & (uintptr_t)1);
}
void clause_MarkProblemClause(CLAUSE Cl, BOOL PClause)
{
  Cl[clause_INFOS] = (Cl[clause_INFOS] & ~(uintptr_t)1) | PClause;
}
void clause_MarkDelete(CLAUSE Cl, BOOL Delete)
{
  Cl[clause_INFOS] = (Cl[clause_INFOS] & ~(uintptr_t)2) | (Delete << 1);
}
BOOL clause_IsMarkedDelete(CLAUSE Cl)
{
  return (Cl[clause_INFOS] & (uintptr_t)2);
}
void clause_MarkNullAtoms(CLAUSE Cl, BOOL Null)
{
  Cl[clause_INFOS] = (Cl[clause_INFOS] & ~(uintptr_t)8) | (Null << 3);
}
BOOL clause_IsMarkedNullAtoms(CLAUSE Cl)
{
  return (Cl[clause_INFOS] & (uintptr_t)8);
}
void clause_MarkConjecture(CLAUSE Cl, BOOL Conjecture)
{
  Cl[clause_INFOS] = (Cl[clause_INFOS] & ~(uintptr_t)4) | (Conjecture << 2);
}
BOOL clause_IsMarkedConjecture(CLAUSE Cl)
{
  return (Cl[clause_INFOS] & (uintptr_t)4);
}
BOOL clause_IsMarkedTautology(CLAUSE Clause)
{
  return (Clause[clause_INFOS] & (uintptr_t)16) ? TRUE : FALSE;
}
void clause_MarkTautology(CLAUSE Cl, BOOL Tautology)
{
  Cl[clause_INFOS] = (Cl[clause_INFOS] & ~(uintptr_t)16) | (Tautology << 4);
}
const uintptr_t CLAUSE_MARK_PROP_ABSTR = ((uintptr_t)1) << 6;
BOOL clause_IsMarkedPropAbstr(CLAUSE Clause)
{
  return (Clause[clause_INFOS] & CLAUSE_MARK_PROP_ABSTR) ? TRUE : FALSE;
}
void clause_MarkPropAbstrTautology(CLAUSE Cl, BOOL IsPropAbstr)
{
  Cl[clause_INFOS] = (Cl[clause_INFOS] & ~CLAUSE_MARK_PROP_ABSTR)
    | (IsPropAbstr ? CLAUSE_MARK_PROP_ABSTR : 0);
}
TERM clause_GetAtom(CLAUSE Clause, unsigned Index)
{
  return (TERM)Clause[Index];
}
TERM clause_GetLiteral(FOLSTATE Folstate, CLAUSE Clause, unsigned Index)
{
  TERM result;
  if (Index < clause_GetPremiseLiterals(Clause)) {
    result = term_CreateArity(fol_GetStateTermstate(Folstate), fol_Not(Folstate), 1);
    term_SetArgument(result, 0, term_Copy(fol_GetStateTermstate(Folstate), (TERM)Clause[Index]));
  }
  else
    result = term_Copy(fol_GetStateTermstate(Folstate), (TERM)Clause[Index]);
  return result;
}
TYPING clause_GetTypes(CLAUSE Clause)
{
  return (TYPING)Clause[clause_TYPES];
}
void clause_SetTypes(CLAUSE Clause, TYPING types)
{
  Clause[clause_TYPES] = (uintptr_t)types;
}
void clause_CopyTypes(MEMORY Mem, CLAUSE New, CLAUSE Source)
{
#ifdef SPASS_CHECK
  if (clause_GetVariables(New) < clause_GetVariables(Source)) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s:", __func__);
    misc_ErrorReport("\n Typing of New clause too small.");
    misc_FinishErrorReport();
  }
#endif
  if (clause_GetTypes(Source)) {
    int i;
    for (i=0; i<(int)clause_GetVariables(Source);i++)
      clause_SetVarType(Mem, New, i, symbol_GetVarTypingType(clause_GetTypes(Source), i));
  }
}
void clause_UpdateTypingSize(MEMORY Mem, CLAUSE Clause)
{
  if (clause_GetTypes(Clause) && (int)clause_GetVariables(Clause) >= (clause_GetTypes(Clause))[-1]) {
    Clause[clause_TYPES] = (uintptr_t)symbol_ExtendVarTyping(Mem, clause_GetTypes(Clause), (clause_GetTypes(Clause))[-1]);
  }
}
unsigned clause_GetId(CLAUSE Clause)
{
  return Clause[clause_ID];
}
void clause_SetId(CLAUSE Clause, unsigned Id)
{
  Clause[clause_ID] = Id;
}
BOOL clause_IsClause(TERMSTATE Termstate, CLAUSE Clause)
{
  SYMBOL maxvar, result;
  ARRAY conslits;
  unsigned i;
  result = (SYMBOL)NULL;
  conslits = clause_GetConstraintLiterals(Clause);
  if (conslits) {
    for(i=0;i<array_GetSize(conslits);i++) {
      maxvar = term_MaxVar(Termstate, (TERM)conslits[i]);
      if (maxvar > result)
 result = maxvar;
    }
  }
  for (i=0;i<clause_GetFolLiterals(Clause); i++) {
    maxvar = term_MaxVar(Termstate, clause_GetAtom(Clause,i));
    if (maxvar > result)
      result = maxvar;
  }
  if (clause_GetVariables(Clause) != result + 1)
    return FALSE;
  if (clause_GetTypes(Clause) && symbol_VarTypingSize(clause_GetTypes(Clause)) != clause_GetVariables(Clause))
    return FALSE;
  return TRUE;
}
void clause_SetVarType(MEMORY Mem, CLAUSE Clause, SYMBOL Var, TYPE Type)
{
  if (Clause[clause_TYPES] == (uintptr_t)NULL) {
    Clause[clause_TYPES] = (uintptr_t)symbol_CreateVarTyping(Mem, Clause[clause_VARS]);
  }
  symbol_SetVarTyping((TYPING)Clause[clause_TYPES], Var, Type);
}
TYPE clause_GetVarType(CLAUSE Clause, SYMBOL Var)
{
  return symbol_GetVarTypingType((TYPING)Clause[clause_TYPES], Var);
}
uintptr_t clause_GetMark(CLAUSE Clause)
{
  return Clause[clause_MARK];
}
void clause_SetMark(CLAUSE Clause, uintptr_t Mark)
{
  Clause[clause_MARK] = Mark;
}
CLAUSE clause_ArithSimpleMalloc(MEMORY Mem, unsigned clits, unsigned plits, unsigned tlits, unsigned Id, BOOL ProblemClause)
{
  CLAUSE cl;
  cl = memory_Malloc(Mem, (clits+plits+clause_EXTRA)*sizeof(uintptr_t));
  cl = cl + clause_EXTRA;
  cl[clause_PREM] = plits;
  if (tlits > 0)
    cl[clause_CLITS] = (uintptr_t)array_Create(Mem, tlits);
  else
    cl[clause_CLITS] = (uintptr_t)NULL;
  cl[clause_CONC] = clits;
  cl[clause_CAPACITY] = clits+plits;
  cl[clause_FLITS] = clits+plits;
  cl[clause_ID] = Id;
  cl[clause_VARS] = 0;
  cl[clause_TYPES] = (uintptr_t)NULL;
  cl[clause_MARK] = 0;
  cl[clause_INFOS] = ProblemClause;
  cl[clause_PARENTS] = (uintptr_t)NULL;
  cl[clause_PROPS] = (uintptr_t)0;
  return cl;
}
CLAUSE clause_CreateFromLiterals(MEMORY Mem, ARRAY Cons, ARRAY Conc, ARRAY Prem, BOOL ProblemClause, unsigned Id)
{
  CLAUSE cl;
  unsigned i, j, flits;
  flits = array_GetSize(Conc) + array_GetSize(Prem);
  cl = memory_Malloc(Mem, (flits+clause_EXTRA)*sizeof(uintptr_t));
  cl = cl + clause_EXTRA;
  cl[clause_PREM] = array_GetSize(Prem);
  if (array_GetSize(Cons) > 0)
    cl[clause_CLITS] = (uintptr_t)array_Copy(Mem, Cons);
  else
    cl[clause_CLITS] = (uintptr_t)NULL;
  cl[clause_CONC] = array_GetSize(Conc);
  cl[clause_CAPACITY] = flits;
  cl[clause_FLITS] = flits;
  cl[clause_ID] = Id;
  cl[clause_VARS] = 0;
  cl[clause_FUNS] = clause_FUNS_UNCOUNTED;
  cl[clause_TYPES] = (uintptr_t)NULL;
  cl[clause_MARK] = 0;
  cl[clause_INFOS] = ProblemClause;
  cl[clause_PARENTS] = (uintptr_t)NULL;
  cl[clause_PROPS] = (uintptr_t)0;
  cl[clause_RES] = (uintptr_t)NULL;
  i = 0;
  for(j = 0; j < array_GetSize(Prem); j++,i++)
    cl[i] = array_GetElement(Prem, j);
  for(j = 0; j < array_GetSize(Conc); j++,i++)
    cl[i] = array_GetElement(Conc, j);
  return cl;
}
CLAUSE clause_CreateFromArrayOfLiterals(MEMORY Mem, FOLSTATE Folstate, ARRAY Literals, BOOL ProblemClause, unsigned Id)
{
  CLAUSE cl;
  unsigned i, j, k, l, plits, clits, tlits;
  void* Arithstate = NULL;
  plits = 0;
  tlits = 0;
  clits = 0;
  for (i=0; i<array_GetSize(Literals); i++) {
    if (symbol_Equal(term_TopSymbol((TERM)Literals[i]), fol_Not(Folstate)))
      plits++;
    else {
      if (Arithstate )
 tlits++;
      else
 clits++;
    }
  }
  cl = memory_Malloc(Mem, (clits+plits+clause_EXTRA)*sizeof(uintptr_t));
  cl = cl + clause_EXTRA;
  cl[clause_PREM] = plits;
  if (tlits > 0)
    cl[clause_CLITS] = (uintptr_t)array_Create(Mem, tlits);
  else
    cl[clause_CLITS] = (uintptr_t)NULL;
  cl[clause_CONC] = clits;
  cl[clause_CAPACITY] = clits+plits;
  cl[clause_FLITS] = clits+plits;
  cl[clause_ID] = Id;
  cl[clause_VARS] = 0;
  cl[clause_TYPES] = (uintptr_t)NULL;
  cl[clause_MARK] = 0;
  cl[clause_INFOS] = ProblemClause;
  cl[clause_PARENTS] = (uintptr_t)NULL;
  cl[clause_PROPS] = (uintptr_t)0;
  cl[clause_RES] = (uintptr_t)NULL;
  for(i = 0, k = 0, j = 0, l = 0; i < array_GetSize(Literals); i++) {
    if (symbol_Equal(term_TopSymbol((TERM)Literals[i]), fol_Not(Folstate))) {
      cl[k] = (intptr_t)term_FirstArgument((TERM)Literals[i]);
      term_Free(fol_GetStateTermstate(Folstate), (TERM)Literals[i]);
      k++;
    }
    else {
      if (Arithstate ) {
 j++;
      }
      else {
 cl[plits+l] = Literals[i];
 l++;
      }
    }
  }
  clause_SetSymbolOccurrences(fol_GetStateTermstate(Folstate),cl);
  return cl;
}
CLAUSE clause_CreateGeneric(MEMORY Mem, unsigned Literals, unsigned Constraints)
{
  CLAUSE cl;
  cl = memory_Malloc(Mem, (Literals+clause_EXTRA)*sizeof(uintptr_t));
  cl = cl + clause_EXTRA;
  cl[clause_PREM] = 0;
  if (Constraints > 0)
    cl[clause_CLITS] = (uintptr_t)array_Create(Mem, Constraints);
  else
    cl[clause_CLITS] = (uintptr_t)NULL;
  cl[clause_CONC] = 0;
  cl[clause_CAPACITY] = Literals;
  cl[clause_FLITS] = 0;
  cl[clause_ID] = 0;
  cl[clause_FUNS] = clause_FUNS_UNCOUNTED;
  cl[clause_VARS] = 0;
  cl[clause_TYPES] = (uintptr_t)NULL;
  cl[clause_MARK] = 0;
  cl[clause_INFOS] = 0;
  cl[clause_PARENTS] = (uintptr_t)NULL;
  cl[clause_PROPS] = (uintptr_t)0;
  cl[clause_RES] = (uintptr_t)NULL;
  return cl;
}
CLAUSE clause_EnlargeCapacity(MEMORY Mem, CLAUSE Clause, unsigned Lits)
{
  CLAUSE new;
  unsigned i;
  new = memory_Malloc(Mem, (Lits+clause_EXTRA)*sizeof(uintptr_t));
  new = new + clause_EXTRA;
  new[clause_PREM] = Clause[clause_PREM];
  new[clause_CLITS] = (uintptr_t)Clause[clause_CLITS];
  new[clause_CONC] = Clause[clause_CONC];
  new[clause_CAPACITY] = Lits;
  new[clause_FLITS] = Clause[clause_FLITS];
  new[clause_ID] = Clause[clause_ID];
  new[clause_FUNS] = Clause[clause_FUNS];
  new[clause_VARS] = Clause[clause_VARS];
  new[clause_TYPES] = Clause[clause_TYPES];
  new[clause_MARK] = 0;
  new[clause_INFOS] = Clause[clause_INFOS];
  new[clause_PARENTS] = Clause[clause_PARENTS];
  new[clause_PROPS] = Clause[clause_PROPS];
  new[clause_RES] = (uintptr_t)NULL;
  if (Clause[clause_RES]) {
    array_Delete(Mem, (ARRAY)Clause[clause_RES]);
    Clause[clause_RES] = (uintptr_t)NULL;
  }
  for(i = 0; i < new[clause_FLITS]; i++)
    new[i] = Clause[i];
  memory_Free(Mem, Clause-clause_EXTRA, (Clause[clause_CAPACITY]+clause_EXTRA)*sizeof(uintptr_t));
  return new;
}
void clause_EnlargeConstraintCapacity(MEMORY Mem, CLAUSE Clause, unsigned Lits)
{
  unsigned i;
  ARRAY new, old;
  new = array_Create(Mem, Lits);
  old = clause_GetConstraintLiterals(Clause);
  for(i = 0; i < array_GetSize(old); i++)
    new[i] = old[i];
  array_Delete(Mem, old);
  clause_SetConstraintLiterals(Clause, new);
}
void clause_InitClause(TERMSTATE Termstate, CLAUSE Clause, CLAUSE Partner)
{
  unsigned i;
  ARRAY clits;
  MEMORY mem;
  mem = symbol_GetStateMemory(term_GetSymbstate(Termstate));
  if (Clause[clause_CLITS] != (uintptr_t)NULL)
    clits = array_Copy(mem, (ARRAY)Clause[clause_CLITS]);
  else
    clits = NULL;
  Clause[clause_PREM] = Partner[clause_PREM];
  Clause[clause_CLITS] = (uintptr_t)clits;
  Clause[clause_CONC] = Partner[clause_CONC];
  Clause[clause_FLITS] = Partner[clause_FLITS];
  Clause[clause_ID] = Partner[clause_ID];
  Clause[clause_FUNS] = Partner[clause_FUNS];
  Clause[clause_VARS] = Partner[clause_VARS];
  Clause[clause_TYPES] = (uintptr_t)symbol_CopyVarTyping(mem, (TYPING)Partner[clause_TYPES], Partner[clause_VARS]);
  Clause[clause_MARK] = 0;
  Clause[clause_INFOS] = Partner[clause_INFOS];
  Clause[clause_PARENTS] = (uintptr_t)NULL;
  Clause[clause_PROPS] = (uintptr_t)0;
  Clause[clause_RES] = (uintptr_t)NULL;
  for(i = 0; i < Clause[clause_FLITS]; i++)
    Clause[i] = (uintptr_t)term_Copy(Termstate, (TERM)Partner[i]);
  if (clits) {
    for(i = 0; i < array_GetSize(clits); i++)
      clits[i] = (intptr_t)term_Copy(Termstate, (TERM)clits[i]);
  }
}
CLAUSE clause_Copy(TERMSTATE Termstate, CLAUSE Clause, BOOL CopyTerms)
{
  CLAUSE new;
  unsigned i;
  ARRAY clits;
  MEMORY mem;
  mem = symbol_GetStateMemory(term_GetSymbstate(Termstate));
  new = memory_Malloc(mem, (Clause[clause_FLITS]+clause_EXTRA)*sizeof(uintptr_t));
  new = new + clause_EXTRA;
  if (Clause[clause_CLITS] != (uintptr_t)NULL)
    clits = array_Copy(mem, (ARRAY)Clause[clause_CLITS]);
  else
    clits = NULL;
  new[clause_PREM] = Clause[clause_PREM];
  new[clause_CLITS] = (uintptr_t)clits;
  new[clause_CONC] = Clause[clause_CONC];
  new[clause_CAPACITY] = Clause[clause_FLITS];
  new[clause_FLITS] = Clause[clause_FLITS];
  new[clause_ID] = Clause[clause_ID];
  new[clause_FUNS] = Clause[clause_FUNS];
  new[clause_VARS] = Clause[clause_VARS];
  new[clause_TYPES] = (uintptr_t)symbol_CopyVarTyping(mem, (TYPING)Clause[clause_TYPES], Clause[clause_VARS]);
  new[clause_MARK] = 0;
  new[clause_INFOS] = Clause[clause_INFOS];
  if (Clause[clause_PARENTS])
    new[clause_PARENTS] = (uintptr_t)array_Copy(mem, (ARRAY)Clause[clause_PARENTS]);
  else
    new[clause_PARENTS] = (uintptr_t)NULL;
  new[clause_PROPS] = Clause[clause_PROPS];
  if (Clause[clause_RES]) {
    new[clause_RES] = (uintptr_t)array_Copy(mem, (ARRAY)Clause[clause_RES]);
  } else {
    new[clause_RES] = (uintptr_t)NULL;
  }
  if (CopyTerms) {
    for(i = 0; i < new[clause_FLITS]; i++)
      new[i] = (uintptr_t)term_Copy(Termstate, (TERM)Clause[i]);
    if (clits) {
      for(i = 0; i < array_GetSize((ARRAY)new[clause_CLITS]); i++)
 clits[i] = (intptr_t)term_Copy(Termstate, (TERM)(((ARRAY)Clause[clause_CLITS])[i]));
    }
  }
  else {
    for(i = 0; i < new[clause_FLITS]; i++)
      new[i] = (uintptr_t)Clause[i];
    if (clits) {
      for(i = 0; i < array_GetSize((ARRAY)new[clause_CLITS]); i++)
 clits[i] = (intptr_t)((ARRAY)Clause[clause_CLITS])[i];
    }
  }
  return new;
}
void clause_AddParent(MEMORY Mem, CLAUSE Clause, unsigned Id, unsigned Lit)
{
  if (Clause[clause_PARENTS] == (uintptr_t)NULL) {
    Clause[clause_PARENTS] = (uintptr_t)array_Create(Mem, 4);
  }
  Clause[clause_PARENTS] = (uintptr_t)array_Add(Mem, (ARRAY)Clause[clause_PARENTS], Id);
  Clause[clause_PARENTS] = (uintptr_t)array_Add(Mem, (ARRAY)Clause[clause_PARENTS], Lit);
}
uintptr_t clause_GetParents(CLAUSE Clause)
{
  return (uintptr_t)Clause[clause_PARENTS];
}
void clause_RemoveNullLiterals(CLAUSE Clause)
{
  unsigned i,j,k,m;
  i = Clause[clause_PREM];
  j = Clause[clause_CONC];
  for (k=0,m=0; k < Clause[clause_FLITS]; k++) {
    if (Clause[k] != (uintptr_t)NULL) {
      Clause[m] = Clause[k];
      m++;
    }
    else {
      if (k < Clause[clause_PREM])
 i--;
      else
 j--;
    }
  }
  Clause[clause_PREM] = i;
  Clause[clause_CONC] = j;
  Clause[clause_FLITS] = i+j;
  Clause[clause_FUNS] = clause_FUNS_UNCOUNTED;
  if (Clause[clause_RES]) {
    for (i = 0; i < clause_GetFolLiterals(Clause); i++) {
      array_SetElement((ARRAY)Clause[clause_RES], i, 0);
    }
  }
}
BOOL clause_NullIsEmpty(CLAUSE Clause)
{
  unsigned i;
  for (i=0; i < Clause[clause_FLITS]; i++) {
    if (Clause[i] != (uintptr_t)NULL)
      return FALSE;
  }
  return TRUE;
}
void clause_NullLiteral(CLAUSE Clause, unsigned Pos)
{
  Clause[Pos] = (uintptr_t)NULL;
  clause_MarkNullAtoms(Clause,TRUE);
}
void clause_RemoveDuplicateLiterals(TERMSTATE Termstate, CLAUSE Clause, BOOL Shared)
{
  unsigned i,j;
  BOOL hit;
  hit = FALSE;
  for (i=0; i < Clause[clause_PREM]; i++) {
    for (j=i+1; Clause[i] != (intptr_t)NULL && j < Clause[clause_PREM]; j++) {
      if (Shared) {
 if (Clause[i] == Clause[j]) {
   hit = TRUE;
   Clause[i] = (intptr_t)NULL;
 }
      }
      else {
 if (term_EqualNoValues((TERM)Clause[i], (TERM)Clause[j])) {
   hit = TRUE;
   term_Delete(Termstate, (TERM)Clause[i]);
   Clause[i] = (intptr_t)NULL;
 }
      }
    }
  }
  for (i=Clause[clause_PREM]; i < Clause[clause_FLITS]; i++) {
    for (j=i+1; Clause[i] != (intptr_t)NULL && j < Clause[clause_FLITS]; j++) {
      if (Shared) {
 if (Clause[i] == Clause[j]) {
   hit = TRUE;
   Clause[i] = (intptr_t)NULL;
 }
      }
      else {
 if (term_EqualNoValues((TERM)Clause[i], (TERM)Clause[j])) {
   hit = TRUE;
   term_Delete(Termstate, (TERM)Clause[i]);
   Clause[i] = (intptr_t)NULL;
 }
      }
    }
  }
  if (hit)
    clause_RemoveNullLiterals(Clause);
}
void clause_RemoveLiteral(CLAUSE Clause, unsigned l)
{
  unsigned i,j,k,m;
  i = Clause[clause_PREM];
  j = Clause[clause_CONC];
  for (k=0,m=0; k < Clause[clause_FLITS]; k++) {
    if (k != l) {
      Clause[m] = Clause[k];
      m++;
    }
    else {
      if (k < Clause[clause_PREM])
 i--;
      else
 j--;
    }
  }
  Clause[clause_PREM] = i;
  Clause[clause_CONC] = j;
  Clause[clause_FLITS] = i+j;
  Clause[clause_FUNS] = clause_FUNS_UNCOUNTED;
  if (Clause[clause_RES]) {
    for (i = 0; i < clause_GetFolLiterals(Clause); i++) {
      array_SetElement((ARRAY)Clause[clause_RES], i, 0);
    }
  }
}
CLAUSE clause_ComposeResolvent(TERMSTATE Termstate, CLAUSE Learn, unsigned i, CLAUSE Partner, unsigned j)
{
  MEMORY mem;
  unsigned k,l,m;
  ARRAY clitlearn, clitpartner;
  mem = symbol_GetStateMemory(term_GetSymbstate(Termstate));
  clitlearn = clause_GetConstraintLiterals(Learn);
  clitpartner = clause_GetConstraintLiterals(Partner);
  if (clause_GetFolLiterals(Learn)+clause_GetFolLiterals(Partner) > clause_GetCapacity(Learn))
    Learn = clause_EnlargeCapacity(mem, Learn, 2*clause_GetCapacity(Learn));
  if (array_GetCapacity(clitlearn) < array_GetSize(clitlearn) + array_GetSize(clitpartner))
    clause_EnlargeConstraintCapacity(mem, Learn, 2*(array_GetSize(clitlearn) + array_GetSize(clitpartner)));
  term_DeleteNoValueConstants(mem, (TERM)Learn[i]);
  Learn[i] = (uintptr_t)NULL;
  term_DeleteNoValueConstants(mem, (TERM)Partner[j]);
  Partner[j] = (uintptr_t)NULL;
  for(k=0;k<clause_GetVariables(Partner);k++)
    clause_SetVarType(mem, Learn, k + clause_GetVariables(Learn), clause_GetVarType(Partner, k));
  clause_SetVariables(Learn, clause_GetVariables(Learn)+clause_GetVariables(Partner));
  for (k=clause_GetPremiseLiterals(Learn), l = clause_GetFolLiterals(Learn), m=0; k < clause_GetPremiseLiterals(Learn) + clause_GetPremiseLiterals(Partner); k++, m++) {
    if (k != i) {
      Learn[l] = Learn[k];
      l++;
    }
    Learn[k] = Partner[m];
  }
  Learn[clause_PREM] = k;
  for (m = clause_GetPremiseLiterals(Partner); m < clause_GetFolLiterals(Partner); m++) {
    Learn[l] = Partner[m];
    if (l != i)
      l++;
  }
  for (k=0,m=array_GetSize(clitlearn);k<array_GetSize(clitpartner);k++,m++)
    array_NAddAtIndex(clitlearn, m, clitpartner[k]);
  array_SetSize(clitlearn, m);
  Learn[clause_FLITS] = l;
  Learn[clause_CONC] = l - Learn[clause_PREM];
  clause_RemoveNullLiterals(Learn);
  return Learn;
}
unsigned clause_GetCapacity(CLAUSE Clause)
{
  return (unsigned)Clause[clause_CAPACITY];
}
ARRAY clause_GetConstraintLiterals(CLAUSE Clause)
{
  return (ARRAY)Clause[clause_CLITS];
}
void clause_SetConstraintLiterals(CLAUSE Clause, ARRAY Clits)
{
  Clause[clause_CLITS] = (uintptr_t)Clits;
}
unsigned clause_GetPremiseLiterals(CLAUSE Clause)
{
  return Clause[clause_PREM];
}
void clause_SetPremiseLiterals(CLAUSE Clause, unsigned Prem)
{
  Clause[clause_PREM] = Prem;
}
unsigned clause_GetConclusionLiterals(CLAUSE Clause)
{
  return Clause[clause_CONC];
}
void clause_SetConclusionLiterals(CLAUSE Clause, unsigned Conc)
{
  Clause[clause_CONC] = Conc;
}
unsigned clause_GetFolLiterals(CLAUSE Clause)
{
  return Clause[clause_FLITS];
}
void clause_SetFolLiterals(CLAUSE Clause, unsigned Fol)
{
  Clause[clause_FLITS] = Fol;
}
BOOL clause_IsEmpty(CLAUSE Clause)
{
  return (clause_GetFolLiterals(Clause) == 0);
}
void clause_RangeFolLiterals(CLAUSE Clause, BOOL Polarity, unsigned int * Start, unsigned int * End)
{
  if (Polarity) {
    *Start = clause_GetPremiseLiterals(Clause);
    *End = clause_GetFolLiterals(Clause);
  } else {
    *Start = 0;
    *End = clause_GetPremiseLiterals(Clause);
  }
}
unsigned clause_GetVariables(CLAUSE Clause)
{
  return Clause[clause_VARS];
}
void clause_SetVariables(CLAUSE Clause, unsigned Vars)
{
  Clause[clause_VARS] = Vars;
}
NAT clause_GetSymbolOccurrences(TERMSTATE Termstate, CLAUSE Clause)
{
  return Clause[clause_FUNS];
}
unsigned clause_GetPropagations(CLAUSE Clause)
{
  return Clause[clause_PROPS];
}
void clause_IncrementPropagations(CLAUSE Clause)
{
  Clause[clause_PROPS]++;
}
void clause_DecrementPropagations(CLAUSE Clause)
{
  Clause[clause_PROPS]--;
}
unsigned clause_GetResolutions(CLAUSE Clause, unsigned Literal)
{
  if (!Clause[clause_RES]) {
    return 0;
  }
  return array_GetElement((ARRAY)Clause[clause_RES], Literal);
}
void clause_IncrementResolutions(MEMORY mem, CLAUSE Clause, unsigned Literal)
{
  if (!Clause[clause_RES]) {
    Clause[clause_RES] = (uintptr_t)array_Create(mem, clause_GetFolLiterals(Clause));
    array_SetSize((ARRAY)Clause[clause_RES], clause_GetFolLiterals(Clause));
  }
  ((ARRAY)Clause[clause_RES])[Literal]++;
}
BOOL clause_LiteralIsPositive(CLAUSE Clause, unsigned Index)
{
  return (Index >= clause_GetPremiseLiterals(Clause));
}
void clause_NormalizeAtom(SUBSTSTATE SState, TERMSTATE Termstate, SYMBSTATE Symbstate, TERM Term, CLAUSE Clause)
{
  SYMBOL top,new;
  top = term_TopSymbol(Term);
  if (symbol_IsVariable(Symbstate, top) && !term_AlreadyVisited(Termstate, Term)) {
    if (subst_ContextValueIsMarked(SState, top))
      term_RplacTop(Term, (SYMBOL)subst_ContextGetValue(SState, top));
    else {
      new = symbol_GetNextStandardVar(Symbstate);
      term_RplacTop(Term, new);
      subst_ContextSetValue(SState, top, new);
      subst_ContextSetExtraValue(SState, new, clause_GetVarType(Clause, top));
    }
    term_SetTermStamp(Termstate, Term);
  }
  else {
    unsigned i;
    for (i=0; i<term_GetArity(Term); i++)
      clause_NormalizeAtom(SState, Termstate, Symbstate, term_GetArgument(Term,i), Clause);
  }
}
void clause_RenameAtom(SUBSTSTATE SState, TERMSTATE Termstate, SYMBSTATE Symbstate, TERM Term, CLAUSE Clause)
{
  SYMBOL top,new;
  top = term_TopSymbol(Term);
  if (symbol_IsVariable(Symbstate, top) && !term_AlreadyVisited(Termstate, Term)) {
    if (subst_ContextValueIsMarked(SState, top))
      term_RplacTop(Term, (SYMBOL)subst_ContextGetValue(SState, top));
    else {
      new = symbol_GetNextStandardVar(Symbstate);
      term_RplacTop(Term, new);
      subst_ContextSetValue(SState, top, new);
    }
    term_SetTermStamp(Termstate, Term);
  }
  else {
    unsigned i;
    for (i=0; i<term_GetArity(Term); i++)
      clause_RenameAtom(SState, Termstate, Symbstate, term_GetArgument(Term,i), Clause);
  }
}
void clause_NormalizeVars(SUBSTSTATE SState, TERMSTATE Termstate, CLAUSE Clause)
{
  if (clause_GetVariables(Clause) > 0) {
    unsigned i;
    ARRAY clits;
    SYMBSTATE symbstate;
    symbstate = term_GetSymbstate(Termstate);
    subst_ContextStart(SState, symbstate);
    term_StartStamp(Termstate);
    symbol_ResetStandardVarCounter(symbstate);
    clits = (ARRAY)Clause[clause_CLITS];
    if (clits) {
      for(i=0;i<array_GetSize(clits);i++) {
 clause_NormalizeAtom(SState, Termstate, symbstate, (TERM)clits[i], Clause);
      }
    }
    for(i=0;i<Clause[clause_FLITS];i++) {
      clause_NormalizeAtom(SState, Termstate, symbstate, (TERM)Clause[i], Clause);
    }
    Clause[clause_VARS] = symbol_GetNextStandardVar(symbstate);
    for(i=0; i<clause_GetVariables(Clause); i++)
      clause_SetVarType(term_GetMemory(Termstate), Clause, i, subst_ContextGetExtraValue(SState, i));
    term_StopStamp(Termstate);
    subst_ContextStop(SState);
  }
}
void clause_RenameVars(SUBSTSTATE SState, TERMSTATE Termstate, CLAUSE Clause, int Var)
{
  if (clause_GetVariables(Clause) > 0) {
    unsigned i;
    ARRAY clits;
    SYMBSTATE symbstate;
    symbstate = term_GetSymbstate(Termstate);
    subst_ContextStart(SState, symbstate);
    term_StartStamp(Termstate);
    symbol_SetStandardVarCounter(symbstate, Var);
    clits = (ARRAY)Clause[clause_CLITS];
    if (clits) {
      for(i=0;i<array_GetSize(clits);i++) {
 clause_RenameAtom(SState, Termstate, symbstate, (TERM)clits[i], Clause);
      }
    }
    for(i=0;i<Clause[clause_FLITS];i++) {
      clause_RenameAtom(SState, Termstate, symbstate, (TERM)Clause[i], Clause);
    }
    term_StopStamp(Termstate);
    subst_ContextStop(SState);
  }
}
int clause_GetTopVariableLiteralIndex(TERMSTATE Termstate, CLAUSE Clause)
{
  unsigned result, vars, test, i;
  result = -1;
  vars = 0;
  for (i=0; clause_GetFolLiterals(Clause);i++) {
    test = term_NumberOfVariableSymbols(Termstate, clause_GetAtom(Clause, i));
    if (test > vars) {
      vars = test;
      result = i;
    }
  }
  return result;
}
void clause_NormalizeVarsEstablishTypes(SUBSTSTATE SState, TERMSTATE Termstate, TYPE Fol, CLAUSE Clause, ARRAY Vartypes, TYPE Type)
{
  unsigned i;
  ARRAY clits;
  TYPE type;
  SYMBSTATE symbstate;
  symbstate = term_GetSymbstate(Termstate);
  subst_StateUpdate(term_GetMemory(Termstate), symbstate, SState, symbol_GetMaxVars(symbstate));
  subst_ContextStart(SState, symbstate);
  term_StartStamp(Termstate);
  symbol_ResetStandardVarCounter(symbstate);
  clits = (ARRAY)Clause[clause_CLITS];
  if (Clause[clause_CLITS] != (uintptr_t)NULL) {
    for(i=0;i<array_GetSize(clits);i++)
      subst_VarNormalize(SState, Termstate, symbstate, (TERM)clits[i], Vartypes, Type);
  }
  for(i=0;i<Clause[clause_FLITS];i++)
    subst_VarNormalize(SState, Termstate, symbstate, (TERM)Clause[i], Vartypes, Type);
  Clause[clause_VARS] = symbol_GetNextStandardVar(symbstate);
  if (Vartypes != (ARRAY)NULL || Type != (TYPE)((intptr_t)NULL)) {
    for (i=0;i<Clause[clause_VARS];i++) {
      type = subst_ContextGetExtraValue(SState,i);
      clause_SetVarType(term_GetMemory(Termstate), Clause, i, type);
    }
  }
  term_StopStamp(Termstate);
  subst_ContextStop(SState);
}
void clause_NormalizeVarsAndSubst(SUBSTSTATE SState, TERMSTATE Termstate, CLAUSE Clause, SUBST *Subst)
{
  unsigned i,var,oldvars;
  SYMBSTATE symbstate;
  SUBST newsubst;
  symbstate = term_GetSymbstate(Termstate);
  subst_StateUpdate(term_GetMemory(Termstate), symbstate, SState, symbol_GetMaxVars(symbstate));
  subst_ContextStart(SState, symbstate);
  term_StartStamp(Termstate);
  symbol_ResetStandardVarCounter(symbstate);
  for(i=0;i<Clause[clause_FLITS];i++)
    subst_VarNormalize(SState, Termstate, symbstate, (TERM)Clause[i], NULL, (TYPE)(intptr_t)NULL);
  oldvars = Clause[clause_VARS];
  Clause[clause_VARS] = symbol_GetNextStandardVar(symbstate);
  newsubst = subst_Create(term_GetMemory(Termstate),Clause[clause_VARS]);
  for (i=0;i<oldvars;i++) {
    if (subst_ContextValueIsMarked(SState, i)) {
      var = subst_ContextGetValue(SState, i);
      clause_SetVarType(term_GetMemory(Termstate), Clause, var, clause_GetVarType(Clause,i));
      subst_SetValue(newsubst, var, subst_GetValue(*Subst,i));
    }
    else {
      if (subst_VarDefined(*Subst,i)) {
 term_Delete(Termstate, subst_GetValue(*Subst,i));
      }
    }
  }
  term_StopStamp(Termstate);
  subst_ContextStop(SState);
  subst_Delete(term_GetMemory(Termstate), *Subst);
  *Subst = newsubst;
}
void clause_Delete(MEMORY Mem, TERMSTATE Termstate, CLAUSE Clause)
{
  unsigned i,flits;
  ARRAY clits;
  flits = Clause[clause_FLITS];
  clits = (ARRAY)Clause[clause_CLITS];
  for (i=0;i<flits;i++) {
    if ((TERM)Clause[i])
      term_Delete(Termstate, (TERM)Clause[i]);
  }
  if (clits) {
    for (i=0;i<array_GetSize(clits);i++)
      term_Delete(Termstate, (TERM)(clits[i]));
    array_Delete(Mem, clits);
  }
  if (Clause[clause_TYPES])
    symbol_DeleteVarTyping(Mem, (TYPING)Clause[clause_TYPES]);
  if (Clause[clause_PARENTS])
    array_Delete(Mem, (ARRAY)Clause[clause_PARENTS]);
  if (Clause[clause_RES])
    array_Delete(Mem, (ARRAY)Clause[clause_RES]);
  memory_Free(Mem, Clause-clause_EXTRA, (Clause[clause_CAPACITY]+clause_EXTRA)*sizeof(uintptr_t));
}
void clause_DeleteGeneric(MEMORY Mem, TERMSTATE Termstate, CLAUSE Clause)
{
  if (Clause[clause_CLITS])
    array_Delete(Mem, (ARRAY)Clause[clause_CLITS]);
  if (Clause[clause_TYPES])
    symbol_DeleteVarTyping(Mem, (TYPING)Clause[clause_TYPES]);
  if (Clause[clause_PARENTS])
    array_Delete(Mem, (ARRAY)Clause[clause_PARENTS]);
  if (Clause[clause_RES])
    array_Delete(Mem, (ARRAY)Clause[clause_RES]);
  memory_Free(Mem, Clause-clause_EXTRA, (Clause[clause_CAPACITY]+clause_EXTRA)*sizeof(uintptr_t));
}
void clause_SharedDelete(MEMORY Mem, TERMSTATE Termstate, CLAUSE Clause)
{
  unsigned i;
  ARRAY clits;
  clits = (ARRAY)Clause[clause_CLITS];
  if (clits) {
    for (i=0;i<array_GetSize(clits);i++)
      term_Delete(Termstate, (TERM)(clits[i]));
    array_Delete(Mem, clits);
  }
  if (Clause[clause_TYPES])
    symbol_DeleteVarTyping(Mem, (TYPING)Clause[clause_TYPES]);
  if (Clause[clause_PARENTS])
    array_Delete(Mem, (ARRAY)Clause[clause_PARENTS]);
  if (Clause[clause_RES])
    array_Delete(Mem, (ARRAY)Clause[clause_RES]);
  memory_Free(Mem, Clause-clause_EXTRA, (Clause[clause_CAPACITY]+clause_EXTRA)*sizeof(uintptr_t));
}
void clause_PrintDatalog(TERMSTATE Termstate, CLAUSE Clause, SYMBOL Goal, BOOL Goalsplit, BOOL GoalsplitViaNegation)
{
  unsigned i, j, premises, arity;
  TERM head, prem;
  SYMBSTATE symbstate;
  premises = Clause[clause_PREM];
  head = (TERM)Clause[premises];
  prem = (TERM)Clause[0];
  arity = term_GetArity(prem);
  symbstate = term_GetSymbstate(Termstate);
  if (Goalsplit && symbol_Equal(Goal, term_TopSymbol(head))) {
    term_PrintPrefixDatalog(Termstate, head);
    printf(" :- ");
    printf(" All_True(1,%u).", premises);
    printf("\n All_True(?x,?z) :- All_True(?x,?y), All_True(?y,?z).");
    printf("\n All_True(?x,?y) :- True(?x), Num_succ(?x,?y), True(?y).");
    printf("\n True(?x) :- %s(", symbol_GetName(symbstate, term_TopSymbol(prem)));
    for(i=1;i<=arity;i++) {
      printf("?y%u", i);
      if (i< arity)
 printf(",");
    }
    printf("), Num_%s(?x,", symbol_GetName(symbstate, term_TopSymbol(prem)));
    for(i=1;i<=arity;i++) {
      printf("?y%u", i);
      if (i< arity)
 printf(",");
    }
    printf(").");
    for(i=1;i<premises;i++)
      printf("\n Num_succ(%u,%u).", i, i+1);
    for(i=0;i<premises;i++) {
      printf("\n Num_%s(%u,", symbol_GetName(symbstate, term_TopSymbol(prem)), i+1);
      for (j=0; j < arity;) {
 term_PrintPrefixDatalog(Termstate, (TERM)term_GetArgument((TERM)Clause[i], j));
 j++;
 if (j < arity)
   printf(",");
      }
      printf(").");
    }
  }else if (GoalsplitViaNegation && symbol_Equal(Goal, term_TopSymbol(head))) {
    printf("Oa(1).\n");
    term_PrintPrefixDatalog(Termstate, head);
    printf(" :- ");
    printf("Oa(?x), ~Missing(?x).");
    printf("\nMissing(1) :- Num_%s(?x,",symbol_GetName(symbstate, term_TopSymbol(prem)));
    for(i=1;i<=arity;i++) {
      printf("?y%u", i);
      if (i< arity)
 printf(",");
    }
    printf("), ~%s(", symbol_GetName(symbstate, term_TopSymbol(prem)));
    for(i=1;i<=arity;i++) {
      printf("?y%u", i);
      if (i< arity)
 printf(",");
    }
    printf(").");
    for(i=0;i<premises;i++) {
      printf("\nNum_%s(%u,", symbol_GetName(symbstate, term_TopSymbol(prem)), i+1);
      for (j=0; j < arity;) {
 term_PrintPrefixDatalog(Termstate, (TERM)term_GetArgument((TERM)Clause[i], j));
 j++;
 if (j < arity)
   printf(",");
      }
      printf(").");
    }
  }
  else {
    for (i = Clause[clause_PREM]; i < Clause[clause_FLITS];) {
      term_PrintPrefixDatalog(Termstate, (TERM)Clause[i]);
      i++;
      if (i < Clause[clause_FLITS])
 printf(",");
    }
    if (Clause[clause_PREM] != 0)
      printf(" :- ");
    for (i = 0; i < Clause[clause_PREM];) {
      term_PrintPrefixDatalog(Termstate, (TERM)Clause[i]);
      i++;
      if (i < Clause[clause_PREM])
 printf(",");
    }
    printf(".");
  }
}
void clause_PrintDFG(TERMSTATE Termstate, CLAUSE Clause)
{
  unsigned i;
  printf("\nclause(");
  if (clause_GetVariables(Clause) > 0) {
    printf("forall([");
    for (i=0; i<clause_GetVariables(Clause); ) {
      symbol_Print(term_GetSymbstate(Termstate), (SYMBOL)i);
      i++;
      if (i < clause_GetVariables(Clause))
 printf(",");
    }
    printf("],");
  }
  printf("or(");
  for (i = 0; i < Clause[clause_PREM];) {
    printf("not(");
    term_PrintPrefix(Termstate, (TERM)Clause[i]);
    printf(")");
    i++;
    if (i < Clause[clause_FLITS])
      printf(",");
  }
  for (; i < Clause[clause_FLITS];) {
    term_PrintPrefix(Termstate, (TERM)Clause[i]);
    i++;
    if (i < Clause[clause_FLITS])
      printf(",");
  }
  printf(")");
  if (clause_GetVariables(Clause) > 0) {
    printf(")");
  }
  printf(").");
}
void clause_PrintSMT(TERMSTATE Termstate, CLAUSE Clause, const char* Sort)
{
  unsigned i;
  ARRAY clits;
  if(Clause[clause_VARS] != 0){
    printf("(forall (");
    for (i=0;i<Clause[clause_VARS];i++) {
      printf("(");
      symbol_Print(term_GetSymbstate(Termstate),(SYMBOL)i);
      if(Sort != NULL){
 printf(" %s) ",Sort);
      }else{
 symbol_PrintVarTypingType(term_GetSymbstate(Termstate), clause_GetVarType(Clause,i));
 printf(") ");
      }
    }
    printf(")");
  }
  clits = (ARRAY)Clause[clause_CLITS];
  if(clits != NULL){
    if ((Clause[clause_PREM] + array_GetSize(clits)) != 0){
      printf("(=> ");
    }
    if ((Clause[clause_PREM] + array_GetSize(clits)) > 1){
      printf("(and ");
    }
  }else{
    if (Clause[clause_PREM] != 0){
      printf("(=> ");
    }
    if (Clause[clause_PREM] > 1){
      printf("(and ");
    }
  }
  if (clits != NULL) {
    for (i=0; i < array_GetSize(clits); i++) {
      term_FPrintSMT(stdout,Termstate, (TERM)clits[i]);
      printf(" ");
    }
  }
  for (i = 0; i < Clause[clause_PREM]; i++) {
    term_FPrintSMT(stdout, Termstate, (TERM)Clause[i]);
    printf(" ");
  }
  if(clits != NULL){
    if ((Clause[clause_PREM] + array_GetSize(clits)) > 1){
      printf(") ");
    }
  }else{
    if (Clause[clause_PREM] > 1){
      printf(") ");
    }
  }
  if(Clause[clause_PREM] == Clause[clause_FLITS]){
    printf("false");
  }else if (Clause[clause_PREM] + 1 < Clause[clause_FLITS]){
    printf("(or ");
  }
  for (i = Clause[clause_PREM]; i < Clause[clause_FLITS];i++) {
    term_FPrintSMT(stdout, Termstate, (TERM)Clause[i]);
    printf(" ");
  }
  if (Clause[clause_PREM] + 1 < Clause[clause_FLITS]){
    printf(")");
  }
  if(clits != NULL){
    if ((Clause[clause_PREM] + array_GetSize(clits)) != 0){
      printf(")");
    }
  }else{
    if (Clause[clause_PREM] != 0){
      printf(")");
    }
  }
  if(Clause[clause_VARS] != 0){
    printf(")");
  }
}
void clause_PrintSMTI(TERMSTATE Termstate, CLAUSE Clause, const char* Sort)
{
  unsigned i;
  ARRAY clits;
  if(Clause[clause_VARS] != 0){
    printf("(forall (");
    for (i=0;i<Clause[clause_VARS];i++) {
      printf("(");
      symbol_Print(term_GetSymbstate(Termstate),(SYMBOL)i);
      if(Sort != NULL){
 printf(" %s) ",Sort);
      }else{
 symbol_PrintVarTypingType(term_GetSymbstate(Termstate), clause_GetVarType(Clause,i));
 printf(") ");
      }
    }
    printf(")");
  }
  clits = (ARRAY)Clause[clause_CLITS];
  if(clits != NULL){
    if ((Clause[clause_PREM] + array_GetSize(clits)) != 0){
      printf("(=> ");
    }
    if ((Clause[clause_PREM] + array_GetSize(clits)) > 1){
      printf("(and ");
    }
  }else{
    if (Clause[clause_PREM] != 0){
      printf("(=> ");
    }
    if (Clause[clause_PREM] > 1){
      printf("(and ");
    }
  }
  if (clits != NULL) {
    for (i=0; i < array_GetSize(clits); i++) {
      term_FPrintSMTI(stdout,Termstate, (TERM)clits[i]);
      printf(" ");
    }
  }
  for (i = 0; i < Clause[clause_PREM]; i++) {
    term_FPrintSMTI(stdout, Termstate, (TERM)Clause[i]);
    printf(" ");
  }
  if(clits != NULL){
    if ((Clause[clause_PREM] + array_GetSize(clits)) > 1){
      printf(") ");
    }
  }else{
    if (Clause[clause_PREM] > 1){
      printf(") ");
    }
  }
  if(Clause[clause_PREM] == Clause[clause_FLITS]){
    printf("false");
  }else if (Clause[clause_PREM] + 1 < Clause[clause_FLITS]){
    printf("(or ");
  }
  for (i = Clause[clause_PREM]; i < Clause[clause_FLITS];i++) {
    term_FPrintSMTI(stdout, Termstate, (TERM)Clause[i]);
    printf(" ");
  }
  if (Clause[clause_PREM] + 1 < Clause[clause_FLITS]){
    printf(")");
  }
  if(clits != NULL){
    if ((Clause[clause_PREM] + array_GetSize(clits)) != 0){
      printf(")");
    }
  }else{
    if (Clause[clause_PREM] != 0){
      printf(")");
    }
  }
  if(Clause[clause_VARS] != 0){
    printf(")");
  }
}
void clause_PrintCHCI(TERMSTATE Termstate, CLAUSE Clause, const char* Sort)
{
  unsigned i;
  ARRAY clits;
  if(Clause[clause_VARS] != 0){
    printf("(forall (");
    for (i=0;i<Clause[clause_VARS];i++) {
      printf("(");
      symbol_Print(term_GetSymbstate(Termstate),(SYMBOL)i);
      if(Sort != NULL){
 printf(" %s) ",Sort);
      }else{
 symbol_PrintVarTypingType(term_GetSymbstate(Termstate), clause_GetVarType(Clause,i));
 printf(") ");
      }
    }
    printf(")");
  }
  clits = (ARRAY)Clause[clause_CLITS];
  if(clits != NULL){
    if ((Clause[clause_PREM] + array_GetSize(clits)) != 0){
      printf("(=> ");
    }
    if ((Clause[clause_PREM] + array_GetSize(clits)) > 1){
      printf("(and ");
    }
  }else{
    if (Clause[clause_PREM] != 0){
      printf("(=> ");
    }
    if (Clause[clause_PREM] > 1){
      printf("(and ");
    }
  }
  if (clits != NULL) {
    for (i=0; i < array_GetSize(clits); i++) {
      term_FPrintCHCI(stdout,Termstate, (TERM)clits[i]);
      printf(" ");
    }
  }
  for (i = 0; i < Clause[clause_PREM]; i++) {
    term_FPrintCHCI(stdout, Termstate, (TERM)Clause[i]);
    printf(" ");
  }
  if(clits != NULL){
    if ((Clause[clause_PREM] + array_GetSize(clits)) > 1){
      printf(") ");
    }
  }else{
    if (Clause[clause_PREM] > 1){
      printf(") ");
    }
  }
  if(Clause[clause_PREM] == Clause[clause_FLITS]){
    printf("false");
  }else if (Clause[clause_PREM] + 1 < Clause[clause_FLITS]){
    printf("(or ");
  }
  for (i = Clause[clause_PREM]; i < Clause[clause_FLITS];i++) {
    term_FPrintCHCI(stdout, Termstate, (TERM)Clause[i]);
    printf(" ");
  }
  if (Clause[clause_PREM] + 1 < Clause[clause_FLITS]){
    printf(")");
  }
  if(clits != NULL){
    if ((Clause[clause_PREM] + array_GetSize(clits)) != 0){
      printf(")");
    }
  }else{
    if (Clause[clause_PREM] != 0){
      printf(")");
    }
  }
  if(Clause[clause_VARS] != 0){
    printf(")");
  }
}
void clause_PrintSMTGC(TERMSTATE Termstate, CLAUSE Clause)
{
  unsigned i;
  ARRAY clits;
  clits = (ARRAY)Clause[clause_CLITS];
  if(clits != NULL){
    if ((Clause[clause_PREM] + array_GetSize(clits)) != 0){
      printf("(=> ");
    }
    if ((Clause[clause_PREM] + array_GetSize(clits)) > 1){
      printf("(and ");
    }
  }else{
    if (Clause[clause_PREM] != 0){
      printf("(=> ");
    }
    if (Clause[clause_PREM] > 1){
      printf("(and ");
    }
  }
  if (clits != NULL) {
    for (i=0; i < array_GetSize(clits); i++) {
      term_FPrintSMTGC(stdout,Termstate, (TERM)clits[i], "GC");
      printf(" ");
    }
  }
  for (i = 0; i < Clause[clause_PREM]; i++) {
    term_FPrintSMTGC(stdout, Termstate, (TERM)Clause[i], "GC");
    printf(" ");
  }
  if(clits != NULL){
    if ((Clause[clause_PREM] + array_GetSize(clits)) > 1){
      printf(") ");
    }
  }else{
    if (Clause[clause_PREM] > 1){
      printf(") ");
    }
  }
  if(Clause[clause_PREM] == Clause[clause_FLITS]){
    printf("false");
  }else if (Clause[clause_PREM] + 1 < Clause[clause_FLITS]){
    printf("(or ");
  }
  for (i = Clause[clause_PREM]; i < Clause[clause_FLITS];i++) {
    term_FPrintSMTGC(stdout, Termstate, (TERM)Clause[i],"GC");
    printf(" ");
  }
  if (Clause[clause_PREM] + 1 < Clause[clause_FLITS]){
    printf(")");
  }
  if(clits != NULL){
    if ((Clause[clause_PREM] + array_GetSize(clits)) != 0){
      printf(")");
    }
  }else{
    if (Clause[clause_PREM] != 0){
      printf(")");
    }
  }
}
void clause_PrintSMTIGC(TERMSTATE Termstate, CLAUSE Clause)
{
  unsigned i;
  ARRAY clits;
  clits = (ARRAY)Clause[clause_CLITS];
  if(clits != NULL){
    if ((Clause[clause_PREM] + array_GetSize(clits)) != 0){
      printf("(=> ");
    }
    if ((Clause[clause_PREM] + array_GetSize(clits)) > 1){
      printf("(and ");
    }
  }else{
    if (Clause[clause_PREM] != 0){
      printf("(=> ");
    }
    if (Clause[clause_PREM] > 1){
      printf("(and ");
    }
  }
  if (clits != NULL) {
    for (i=0; i < array_GetSize(clits); i++) {
      term_FPrintSMTIGC(stdout,Termstate, (TERM)clits[i], "GC");
      printf(" ");
    }
  }
  for (i = 0; i < Clause[clause_PREM]; i++) {
    term_FPrintSMTIGC(stdout, Termstate, (TERM)Clause[i], "GC");
    printf(" ");
  }
  if(clits != NULL){
    if ((Clause[clause_PREM] + array_GetSize(clits)) > 1){
      printf(") ");
    }
  }else{
    if (Clause[clause_PREM] > 1){
      printf(") ");
    }
  }
  if(Clause[clause_PREM] == Clause[clause_FLITS]){
    printf("false");
  }else if (Clause[clause_PREM] + 1 < Clause[clause_FLITS]){
    printf("(or ");
  }
  for (i = Clause[clause_PREM]; i < Clause[clause_FLITS];i++) {
    term_FPrintSMTIGC(stdout, Termstate, (TERM)Clause[i],"GC");
    printf(" ");
  }
  if (Clause[clause_PREM] + 1 < Clause[clause_FLITS]){
    printf(")");
  }
  if(clits != NULL){
    if ((Clause[clause_PREM] + array_GetSize(clits)) != 0){
      printf(")");
    }
  }else{
    if (Clause[clause_PREM] != 0){
      printf(")");
    }
  }
}
void clause_PrintCHCIGC(TERMSTATE Termstate, CLAUSE Clause)
{
  unsigned i;
  ARRAY clits;
  clits = (ARRAY)Clause[clause_CLITS];
  if(clits != NULL){
    if ((Clause[clause_PREM] + array_GetSize(clits)) != 0){
      printf("(=> ");
    }
    if ((Clause[clause_PREM] + array_GetSize(clits)) > 1){
      printf("(and ");
    }
  }else{
    if (Clause[clause_PREM] != 0){
      printf("(=> ");
    }
    if (Clause[clause_PREM] > 1){
      printf("(and ");
    }
  }
  if (clits != NULL) {
    for (i=0; i < array_GetSize(clits); i++) {
      term_FPrintCHCIGC(stdout,Termstate, (TERM)clits[i], "GC");
      printf(" ");
    }
  }
  for (i = 0; i < Clause[clause_PREM]; i++) {
    term_FPrintCHCIGC(stdout, Termstate, (TERM)Clause[i], "GC");
    printf(" ");
  }
  if(clits != NULL){
    if ((Clause[clause_PREM] + array_GetSize(clits)) > 1){
      printf(") ");
    }
  }else{
    if (Clause[clause_PREM] > 1){
      printf(") ");
    }
  }
  if(Clause[clause_PREM] == Clause[clause_FLITS]){
    printf("false");
  }else if (Clause[clause_PREM] + 1 < Clause[clause_FLITS]){
    printf("(or ");
  }
  for (i = Clause[clause_PREM]; i < Clause[clause_FLITS];i++) {
    term_FPrintCHCIGC(stdout, Termstate, (TERM)Clause[i],"GC");
    printf(" ");
  }
  if (Clause[clause_PREM] + 1 < Clause[clause_FLITS]){
    printf(")");
  }
  if(clits != NULL){
    if ((Clause[clause_PREM] + array_GetSize(clits)) != 0){
      printf(")");
    }
  }else{
    if (Clause[clause_PREM] != 0){
      printf(")");
    }
  }
}
void clause_PrintKind(CLAUSE Clause)
{
  if (clause_IsMarkedProblemClause(Clause))
    printf("INP:");
  else if (clause_IsMarkedTautology(Clause))
    printf("TAUT:");
  else
    printf("OTHER:");
}
void clause_Print(TERMSTATE Termstate, CLAUSE Clause)
{
  unsigned i;
  ARRAY clits;
  printf("%lu:%lu:%lu:", Clause[clause_ID],Clause[clause_FLITS],Clause[clause_VARS]);
  if (Clause[clause_PARENTS]) {
    printf("[");
    clits = (ARRAY)Clause[clause_PARENTS];
    i = 0;
    do {
      printf("%ld.%ld", clits[i], clits[i+1]);
      i = i + 2;
      if (i<array_GetSize(clits))
 printf(",");
    } while (i<array_GetSize(clits));
    printf("]:");
  }
  else
    clause_PrintKind(Clause);
  for (i=0;i<Clause[clause_VARS];i++) {
    symbol_PrintVarTypingType(term_GetSymbstate(Termstate), clause_GetVarType(Clause,i));
  }
  printf(": ");
  clits = (ARRAY)Clause[clause_CLITS];
  if (clits != NULL) {
    for (i=0; i < array_GetSize(clits);) {
      term_PrintPrefix(Termstate, (TERM)clits[i]);
      i++;
      if (i < array_GetSize(clits))
 printf(",");
    }
    i = 0;
    printf(" || ");
  }
  for (i=0; i < Clause[clause_PREM];) {
    if (Clause[i] != (uintptr_t)NULL) {
      term_PrintPrefix(Termstate, (TERM)Clause[i]);
    } else {
      printf("!NULL!");
    }
    i++;
    if (i < Clause[clause_PREM])
      printf(",");
  }
  printf(" -> ");
  for (; i < Clause[clause_FLITS];) {
    if (Clause[i] != (uintptr_t)NULL) {
      term_PrintPrefix(Termstate, (TERM)Clause[i]);
    } else {
      printf("!NULL!");
    }
    i++;
    if (i < Clause[clause_FLITS])
      printf(",");
  }
}
void clause_PrintSubst(TERMSTATE Termstate, CLAUSE Clause, SUBST Subst)
{
  unsigned i;
  ARRAY clits;
  printf("%lu:%lu:%lu:", Clause[clause_ID],Clause[clause_FLITS],Clause[clause_VARS]);
  if (Clause[clause_PARENTS]) {
    printf("[");
    clits = (ARRAY)Clause[clause_PARENTS];
    i = 0;
    do {
      printf("%ld.%ld", clits[i], clits[i+1]);
      i = i + 2;
      if (i<array_GetSize(clits))
 printf(",");
    } while (i<array_GetSize(clits));
    printf("]:");
  }
  else
    clause_PrintKind(Clause);
  for (i=0;i<Clause[clause_VARS];i++) {
    symbol_PrintVarTypingType(term_GetSymbstate(Termstate), clause_GetVarType(Clause,i));
  }
  printf(": ");
  clits = (ARRAY)Clause[clause_CLITS];
  if (clits != NULL) {
    for (i=0; i < array_GetSize(clits);) {
      subst_TermPrintPrefix(Termstate, (TERM)clits[i], Subst);
      i++;
      if (i < array_GetSize(clits))
 printf(",");
    }
    i = 0;
    printf(" || ");
  }
  for (i=0; i < Clause[clause_PREM];) {
    subst_TermPrintPrefix(Termstate, (TERM)Clause[i], Subst);
    i++;
    if (i < Clause[clause_PREM])
      printf(",");
  }
  printf(" -> ");
  for (; i < Clause[clause_FLITS];) {
    subst_TermPrintPrefix(Termstate, (TERM)Clause[i], Subst);
    i++;
    if (i < Clause[clause_FLITS])
      printf(",");
  }
}
void clause_FPrintAsTerm(FILE* Output, TERMSTATE Termstate, CLAUSE Clause)
{
  unsigned i;
  for(i=0;i<clause_GetPremiseLiterals(Clause);i++) {
    fprintf(Output,"~");
    term_FPrintPrefix(Output, Termstate, (TERM)Clause[i], TRUE);
    if (i<clause_GetFolLiterals(Clause)-1)
      fprintf(Output," | ");
  }
  for(;i<clause_GetFolLiterals(Clause);i++) {
    term_FPrintPrefix(Output, Termstate, (TERM)Clause[i], TRUE);
    if (i<clause_GetFolLiterals(Clause)-1)
      fprintf(Output," | ");
  }
}
void clause_FPrintTPTP(FILE* Output, TERMSTATE Termstate, CLAUSE Clause)
{
  fprintf(Output, "cnf(clause_%u, axiom, (", clause_GetId(Clause));
  clause_FPrintAsTerm(Output, Termstate, Clause);
  fprintf(Output, ")).");
}
VSUBST clause_VarsNotUsedInFol(MEMORY Mem, SYMBSTATE Symbstate, CLAUSE Clause)
{
  unsigned i, size;
  VSUBST subst;
  subst = subst_VIdentitySubst(Mem,Symbstate,clause_GetVariables(Clause));
  for(i = 0, size = clause_GetFolLiterals(Clause); i < size; i++){
    subst_VUndefineVariablesInTerm(Symbstate,clause_GetAtom(Clause,i),subst);
  }
  return subst;
}
BOOL clause_CheckForUnit(SYMBSTATE Symbstate, CLAUSE Clause)
{
  TERM first_atom;
  unsigned i;
  if (clause_GetPremiseLiterals(Clause) != 0 && clause_GetConclusionLiterals(Clause) != 0)
    return FALSE;
  if (clause_GetFolLiterals(Clause) == 1)
    return TRUE;
  first_atom = clause_GetAtom(Clause, 0);
  for (i = 1; i < clause_GetFolLiterals(Clause); i++)
    if (first_atom != clause_GetAtom(Clause, i))
      return FALSE;
  return TRUE;
}
void clause_SetSymbolOccurrences(const TERMSTATE Termstate, CLAUSE Clause)
{
  unsigned n;
  unsigned i;
  NAT result;
  n = clause_GetFolLiterals(Clause);
  result = 0;
  for (i = 0; i < n; i++) {
    if ((TERM)Clause[i] != (TERM)NULL)
      result += term_CountSymbolOccurrences(Termstate, (TERM)Clause[i]);
  }
  Clause[clause_FUNS] = result;
}
BOOL clause_ApplyEqualityResolution(FOLSTATE Folstate, TERMSTATE Termstate, SUBSTSTATE Subststate, CLAUSE Clause)
{
  unsigned n,i,j;
  TERM atom,newatom;
  SYMBSTATE symbstate;
  BOOL clean;
  n = clause_GetPremiseLiterals(Clause);
  symbstate = term_GetSymbstate(Termstate);
  clean = FALSE;
  for (i = 0; i < n; i++) {
    atom = (TERM)Clause[i];
    if (symbol_Equal(term_TopSymbol(atom), fol_Equal(Folstate))) {
      subst_ContextStart(Subststate,symbstate);
      if (subst_TermUnifyIdenticalVarsNoTypes(Subststate, Termstate, symbstate, term_FirstArgument(atom), term_SecondArgument(atom), TRUE)) {
 clean = TRUE;
 subst_ContextFlattenTerms(Subststate, symbstate, clause_GetVariables(Clause));
 Clause[i] = (uintptr_t)NULL;
 for (j=0;j<clause_GetFolLiterals(Clause);j++) {
   newatom = (TERM)Clause[j];
   if (newatom) {
     Clause[j] = (uintptr_t)subst_ContextTermApplyToTerm(Subststate, Termstate, newatom);
     term_Delete(Termstate, newatom);
   }
 }
 term_Delete(Termstate, atom);
      }
      subst_ContextStop(Subststate);
    }
  }
  if (clean) {
    clause_RemoveNullLiterals(Clause);
    clause_NormalizeVars(Subststate, Termstate, Clause);
    clause_SetSymbolOccurrences(Termstate, Clause);
  }
  return clean;
}
BOOL clause_EqualModuloSubst(MEMORY Mem, SYMBSTATE Symbstate, CLAUSE Clause, SUBST Subst1, SUBST Subst2)
{
  ARRAY used,stack;
  unsigned i,j;
  BOOL hit;
  used = array_Create(Mem, clause_GetFolLiterals(Clause));
  stack = array_Create(Mem, 2*clause_GetFolLiterals(Clause));
  i = 0;
  j = 0;
  while (i < clause_GetPremiseLiterals(Clause)) {
    hit = FALSE;
    while (j < clause_GetPremiseLiterals(Clause) && !hit) {
      if (used[j] == 0) {
 if (subst_TermEqualModuloSubsts(Symbstate, clause_GetAtom(Clause,i), Subst1, clause_GetAtom(Clause,j), Subst2)) {
   used[j] = 1;
   hit = TRUE;
   stack = array_Push(Mem, stack, i);
   stack = array_Push(Mem, stack, j);
 }
 else
   j++;
      }
      else
 j++;
    }
    if (!hit) {
      if (array_IsEmpty(stack)) {
 array_Delete(Mem,used);
 array_Delete(Mem,stack);
 return FALSE;
      }
      j = (unsigned)array_Pop(stack);
      i = (unsigned)array_Pop(stack);
      used[j] = 0;
      j++;
    }
    else {
      i++;
      j = 0;
    }
  }
  array_Clean(stack);
  i = clause_GetPremiseLiterals(Clause);
  j = clause_GetPremiseLiterals(Clause);
  while (i < clause_GetFolLiterals(Clause)) {
    hit = FALSE;
    while (j < clause_GetFolLiterals(Clause) && !hit) {
      if (used[j] == 0) {
 if (subst_TermEqualModuloSubsts(Symbstate, clause_GetAtom(Clause,i), Subst1, clause_GetAtom(Clause,j), Subst2)) {
   used[j] = 1;
   hit = TRUE;
   stack = array_Push(Mem, stack, i);
   stack = array_Push(Mem, stack, j);
 }
 else
   j++;
      }
      else
 j++;
    }
    if (!hit) {
      if (array_IsEmpty(stack)) {
 array_Delete(Mem,used);
 array_Delete(Mem,stack);
 return FALSE;
      }
      j = (unsigned)array_Pop(stack);
      i = (unsigned)array_Pop(stack);
      used[j] = 0;
      j++;
    }
    else {
      i++;
      j = clause_GetPremiseLiterals(Clause);
    }
  }
  array_Delete(Mem,used);
  array_Delete(Mem,stack);
  return TRUE;
}
