#ifdef DOC_BUILD_INTERNAL
#endif
#include "prlits.h"
const unsigned prlits_INITIALCAP = 16;
PRLITS prlits_Create(MEMORY Mem)
{
  PRLITS plits;
  plits = memory_Malloc(Mem, sizeof(struct PRLITS_HELP));
  plits->stack = array_Create(Mem, prlits_INITIALCAP);
  plits->litsmap = ohash_Create(Mem, prlits_INITIALCAP, (OHASH_HASH_FCT)prlits_Hash, (OHASH_ELEM_EQUAL)prlits_KeyEqual);
  plits->mem = Mem;
  return plits;
}
void prlits_Delete(PRLITS PLits)
{
  array_Delete(prlits_GetMemory(PLits), prlits_GetStack(PLits));
  ohash_Delete(prlits_GetLitsmap(PLits), NULL, prlits_HashDataDelete);
  memory_Free(prlits_GetMemory(PLits), PLits, sizeof(struct PRLITS_HELP));
}
PRLITS_ANNO_LIT prlits_CreateAnnoLit(MEMORY Mem, SHARER Sharer, TERMSTATE Termstate, SUBSTSTATE SState, CLAUSE PropClause, SUBST Subst, unsigned Position, unsigned TrailSize)
{
#ifdef SPASS_CHECK
  if (PropClause == NULL) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: Clause that propagates the given literal is NULL.", __func__);
    misc_FinishErrorReport();
  }
#endif
  PRLITS_ANNO_LIT anno_lit;
  TERM norm_atom, atom;
  VSUBST variable_mapping;
  SYMBSTATE symbstate;
  symbstate = term_GetSymbstate(Termstate);
  atom = clause_GetAtom(PropClause, Position);
  if (term_IsGround(Termstate, atom)) {
    norm_atom = atom;
    variable_mapping = NULL;
  } else {
    norm_atom = term_Copy(Termstate, atom);
    norm_atom = subst_SubstApplyTerm(Termstate, norm_atom, Subst, TRUE);
    if (term_IsGround(Termstate, norm_atom))
      variable_mapping = NULL;
    else {
      subst_ContextStart(SState, symbstate);
      term_StartStamp(Termstate);
      symbol_ResetStandardVarCounter(symbstate);
      variable_mapping = subst_VVarNormalize(SState, Termstate, symbstate, norm_atom, term_NumberOfVariableSymbols(Termstate, norm_atom));
      term_StopStamp(Termstate);
      subst_ContextStop(SState);
    }
    norm_atom = sharing_GetSharedTerm(Sharer, norm_atom);
  }
  anno_lit = memory_Malloc(Mem, sizeof(struct PRLITS_ANNO_LIT_HELP));
  anno_lit->atom = norm_atom;
  anno_lit->variable_mapping = variable_mapping;
  anno_lit->clause = PropClause;
  if (Subst != (SUBST)NULL)
    anno_lit->subst = subst_Copy(Mem,Subst);
  else
    anno_lit->subst = Subst;
  anno_lit->value = clause_LiteralIsPositive(PropClause, Position);
  anno_lit->pos = Position;
  anno_lit->trailsize = TrailSize;
  return anno_lit;
}
void prlits_DeleteAnnoLit(MEMORY Mem, PRLITS_ANNO_LIT AnnoLit)
{
  if (prlits_GetAnnoLitVarMap(AnnoLit) != NULL)
    subst_VDelete(Mem, prlits_GetAnnoLitVarMap(AnnoLit));
  if (prlits_GetAnnoLitSubst(AnnoLit) != (SUBST)NULL)
    subst_Delete(Mem,prlits_GetAnnoLitSubst(AnnoLit));
  memory_Free(Mem, AnnoLit, sizeof(struct PRLITS_ANNO_LIT_HELP));
}
TERM prlits_GetAnnoLitAtom(PRLITS_ANNO_LIT AnnoLit)
{
  return AnnoLit->atom;
}
VSUBST prlits_GetAnnoLitVarMap(PRLITS_ANNO_LIT AnnoLit)
{
  return AnnoLit->variable_mapping;
}
CLAUSE prlits_GetAnnoLitOriginClause(PRLITS_ANNO_LIT AnnoLit)
{
  return AnnoLit->clause;
}
SUBST prlits_GetAnnoLitSubst(PRLITS_ANNO_LIT AnnoLit)
{
  return AnnoLit->subst;
}
BOOL prlits_GetAnnoLitValue(PRLITS_ANNO_LIT AnnoLit)
{
  return AnnoLit->value;
}
unsigned prlits_GetAnnoLitPosition(PRLITS_ANNO_LIT AnnoLit)
{
  return AnnoLit->pos;
}
unsigned prlits_GetAnnoLitTrailsize(PRLITS_ANNO_LIT AnnoLit)
{
  return AnnoLit->trailsize;
}
MEMORY prlits_GetMemory(PRLITS Plits)
{
  return Plits->mem;
}
ARRAY prlits_GetStack(PRLITS Plits)
{
  return Plits->stack;
}
void prlits_SetStack(PRLITS Plits, ARRAY Stack)
{
  Plits->stack = Stack;
}
OHASH prlits_GetLitsmap(PRLITS Plits)
{
  return Plits->litsmap;
}
void prlits_SetLitsmap(PRLITS Plits, OHASH Litsmap)
{
  Plits->litsmap = Litsmap;
}
BOOL prlits_IsAnnoLitPropagated(PRLITS Plits, PRLITS_ANNO_LIT AnnoLit)
{
  if (ohash_Search(prlits_GetLitsmap(Plits), (OHASH_KEY_TYPE)AnnoLit) == (OHASH_DATA_TYPE)NULL)
    return FALSE;
  else
    return TRUE;
}
BOOL prlits_IsPropagated(PRLITS Plits, SHARER Sharer, TERMSTATE Termstate, SUBSTSTATE SState, CLAUSE PropClause, SUBST Subst, unsigned Position)
{
  PRLITS_ANNO_LIT anno_lit;
  BOOL result;
  anno_lit = prlits_CreateAnnoLit(prlits_GetMemory(Plits), Sharer, Termstate, SState, PropClause, Subst, Position, 0);
  result = prlits_IsAnnoLitPropagated(Plits, anno_lit);
  prlits_DeleteAnnoLit(prlits_GetMemory(Plits), anno_lit);
  return result;
}
void prlits_AddAnnoLit(PRLITS Plits, PRLITS_ANNO_LIT AnnoLit, BOOL Lazy)
{
#ifdef SPASS_CHECK
  if (!Lazy && !array_IsEmpty(prlits_GetStack(Plits)))
    if (prlits_GetAnnoLitTrailsize((PRLITS_ANNO_LIT)array_Top(prlits_GetStack(Plits))) > prlits_GetAnnoLitTrailsize(AnnoLit)) {
      misc_StartErrorReport();
      misc_ErrorReport("\n In %s: Trailsize of the literal to add is smaller than largest trailsize in set.", __func__);
      misc_FinishErrorReport();
    }
#endif
  prlits_SetStack(Plits, array_Push(prlits_GetMemory(Plits), prlits_GetStack(Plits), (intptr_t)AnnoLit));
  prlits_SetLitsmap(Plits, ohash_Insert(prlits_GetLitsmap(Plits), (OHASH_KEY_TYPE)AnnoLit, (OHASH_DATA_TYPE)AnnoLit, NULL, NULL));
}
void prlits_Add(PRLITS Plits, SHARER Sharer, TERMSTATE Termstate, SUBSTSTATE SState, CLAUSE PropClause, SUBST Subst, unsigned Position, unsigned TrailSize)
{
#ifdef SPASS_CHECK
  if (!array_IsEmpty(prlits_GetStack(Plits)))
    if (prlits_GetAnnoLitTrailsize((PRLITS_ANNO_LIT)array_Top(prlits_GetStack(Plits))) > TrailSize) {
      misc_StartErrorReport();
      misc_ErrorReport("\n In %s: Trailsize of the literal to add is smaller than largest trailsize in set.", __func__);
      misc_FinishErrorReport();
    }
#endif
  PRLITS_ANNO_LIT anno_lit;
  anno_lit = prlits_CreateAnnoLit(prlits_GetMemory(Plits), Sharer, Termstate, SState, PropClause, Subst, Position, TrailSize);
  prlits_AddAnnoLit(Plits, anno_lit, FALSE);
}
BOOL prlits_AddIfNotMember(PRLITS Plits, SHARER Sharer, TERMSTATE Termstate, SUBSTSTATE SState, CLAUSE PropClause, SUBST Subst, unsigned Position, unsigned TrailSize)
{
#ifdef SPASS_CHECK
  if (!array_IsEmpty(prlits_GetStack(Plits)))
    if (prlits_GetAnnoLitTrailsize((PRLITS_ANNO_LIT)array_Top(prlits_GetStack(Plits))) > TrailSize) {
      misc_StartErrorReport();
      misc_ErrorReport("\n In %s: Trailsize of the literal to add is smaller than largest trailsize in set.", __func__);
      misc_FinishErrorReport();
    }
#endif
  PRLITS_ANNO_LIT anno_lit;
  anno_lit = prlits_CreateAnnoLit(prlits_GetMemory(Plits), Sharer, Termstate, SState, PropClause, Subst, Position, TrailSize);
  if (prlits_IsAnnoLitPropagated(Plits, anno_lit)) {
    prlits_DeleteAnnoLit(prlits_GetMemory(Plits), anno_lit);
    return FALSE;
  }
  prlits_AddAnnoLit(Plits, anno_lit, FALSE);
  return TRUE;
}
void prlits_RemoveUntilTrailsize(PRLITS PLits, TERMSTATE Termstate, unsigned TrailSize)
{
  PRLITS_ANNO_LIT cur;
  ARRAY stack;
  stack = prlits_GetStack(PLits);
  if (array_GetSize(stack) == 0)
    return;
  cur = (PRLITS_ANNO_LIT)array_Top(stack);
  while (prlits_GetAnnoLitTrailsize(cur) > TrailSize) {
    array_Pop(stack);
    prlits_SetLitsmap(PLits, ohash_Remove(prlits_GetLitsmap(PLits), (OHASH_KEY_TYPE)cur, NULL, (OHASH_DELETE_DATA_FCT)prlits_HashDataDelete));
    if (array_GetSize(stack) == 0)
      return;
    cur = (PRLITS_ANNO_LIT)array_Top(stack);
  }
}
void prlits_RestartAndForget(PRLITS PLits, TERMSTATE Termstate, ARRAY Origins)
{
  PRLITS_ANNO_LIT cur;
  ARRAY stack;
  int it;
  prlits_RemoveUntilTrailsize(PLits, Termstate, 0);
  if (Origins == NULL)
    return;
  stack = prlits_GetStack(PLits);
  for (it = array_GetSize(stack) - 1; it >= 0; it--) {
    cur = (PRLITS_ANNO_LIT)array_GetElement(stack, it);
    if (array_HasElement(Origins, (intptr_t)prlits_GetAnnoLitOriginClause(cur))) {
      array_RemoveAtIndex(stack, it);
      prlits_SetLitsmap(PLits, ohash_Remove(prlits_GetLitsmap(PLits), (OHASH_KEY_TYPE)cur, NULL, (OHASH_DELETE_DATA_FCT)prlits_HashDataDelete));
    }
  }
}
void prlits_Print(PRLITS PLits, TERMSTATE Termstate, BOOL PrintOrigin)
{
  PRLITS_ANNO_LIT cur;
  ARRAY stack;
  unsigned it;
  stack = prlits_GetStack(PLits);
  for (it = 0; it < array_GetSize(stack); it++) {
    cur = (PRLITS_ANNO_LIT)array_GetElement(stack, it);
    printf("%d: ", prlits_GetAnnoLitTrailsize(cur));
    if (!prlits_GetAnnoLitValue(cur))
      printf("~");
    term_PrintPrefix(Termstate, prlits_GetAnnoLitAtom(cur));
    if (!PrintOrigin)
      printf(", ");
    else {
      printf(" ");
      clause_Print(Termstate, prlits_GetAnnoLitOriginClause(cur));
      if (prlits_GetAnnoLitSubst(cur) != NULL) {
        printf(" ");
        subst_Print(Termstate, term_GetSymbstate(Termstate), prlits_GetAnnoLitSubst(cur));
      }
      printf("\n");
    }
  }
}
void prlits_HashDataDelete(MEMORY Mem, OHASH_DATA_TYPE AnnoLit)
{
  prlits_DeleteAnnoLit(Mem, (PRLITS_ANNO_LIT)AnnoLit);
}
uint32_t prlits_Hash(const OHASH_KEY_TYPE Literal)
{
  PRLITS_ANNO_LIT anno_lit;
  anno_lit = (PRLITS_ANNO_LIT)Literal;
  uint32_t h = ((intptr_t)(term_Index(prlits_GetAnnoLitAtom(anno_lit))) * 762152471
      + prlits_GetAnnoLitValue(anno_lit) * 218958569 + (intptr_t) clause_GetId(prlits_GetAnnoLitOriginClause(anno_lit)) * 1905616763);
  h += instset_SubstHash((OHASH_KEY_TYPE)prlits_GetAnnoLitSubst(anno_lit)) * 1438513469;
  h %= 1378999961;
  return h;
}
BOOL prlits_KeyEqual(const OHASH_KEY_TYPE Literal1, const OHASH_KEY_TYPE Literal2)
{
  PRLITS_ANNO_LIT anno_lit1, anno_lit2;
  VSUBST varmap1, varmap2;
  SUBST subst1, subst2;
  TYPING types1, types2;
  unsigned i;
  SYMBOL variable1, variable2;
  anno_lit1 = (PRLITS_ANNO_LIT)Literal1;
  anno_lit2 = (PRLITS_ANNO_LIT)Literal2;
  if (prlits_GetAnnoLitAtom(anno_lit1) != prlits_GetAnnoLitAtom(anno_lit2) || prlits_GetAnnoLitValue(anno_lit1) != prlits_GetAnnoLitValue(anno_lit2) ||
      prlits_GetAnnoLitOriginClause(anno_lit1) != prlits_GetAnnoLitOriginClause(anno_lit2))
    return FALSE;
  subst1 = prlits_GetAnnoLitSubst(anno_lit1);
  subst2 = prlits_GetAnnoLitSubst(anno_lit2);
  if ((subst1 == NULL) != (subst2 == NULL))
    return FALSE;
  for (i = 0; i < subst_NumberOfVariables(subst1); i++) {
    if (subst_VarDefined(subst1, (SYMBOL)i) != subst_VarDefined(subst2, (SYMBOL)i))
      return FALSE;
    if (subst_VarDefined(subst1, (SYMBOL)i) == TRUE && subst_VarDefined(subst2, (SYMBOL)i) && subst_GetValue(subst1, (SYMBOL)i) != subst_GetValue(subst2, (SYMBOL)i))
      return FALSE;
  }
  varmap1 = prlits_GetAnnoLitVarMap(anno_lit1);
  if (varmap1 == NULL)
    return TRUE;
  varmap2 = prlits_GetAnnoLitVarMap(anno_lit2);
  types1 = clause_GetTypes(prlits_GetAnnoLitOriginClause(anno_lit1));
  types2 = clause_GetTypes(prlits_GetAnnoLitOriginClause(anno_lit2));
  for (i = 0; i < subst_VNumberOfVariables(varmap1); i++) {
    variable1 = subst_VGetValue(varmap1, (SYMBOL)i);
    variable2 = subst_VGetValue(varmap2, (SYMBOL)i);
    if (symbol_GetVarTypingType(types1, variable1) != symbol_GetVarTypingType(types2, variable2))
      return FALSE;
  }
  return TRUE;
}
unsigned prlits_TestSpecialConstantValue(SYMBSTATE Symbstate, SYMBOL Constant)
{
  char * Name;
  Name = symbol_GetName(Symbstate, Constant);
  if (Name[1] == '1') {
    if (string_Length(Name) == 2)
      return 1;
    else
      return 10;
  }
  if (Name[1] == '2')
    return 2;
  if (Name[1] == '3')
    return 3;
  if (Name[1] == '4')
    return 4;
  if (Name[1] == '5')
    return 5;
  if (Name[1] == '6')
    return 6;
  if (Name[1] == '7')
    return 7;
  if (Name[1] == '8')
    return 8;
  if (Name[1] == '9')
    return 9;
  if (Name[1] == '0')
    return 0;
  return 42;
}
void prlits_Test(MEMORY Mem, ARRAY Clauses, TERMSTATE Termstate, SUBSTSTATE SState, SHARER Sharer, SYMBOL Control)
{
  PRLITS pLits;
  CLAUSE clause;
  TERM op, atom;
  int clause_it;
  unsigned trailsize, it;
  BOOL result;
  SUBST subst;
  pLits = prlits_Create(Mem);
  printf("\n");
  for (clause_it = 0; clause_it < array_GetSize(Clauses); clause_it++) {
    clause = (CLAUSE)array_GetElement(Clauses, clause_it);
    op = clause_GetAtom(clause, 0);
    clause_RemoveLiteral(clause, 0);
    trailsize = (unsigned)prlits_TestSpecialConstantValue(term_GetSymbstate(Termstate), term_TopSymbol(term_SecondArgument(op)));
    if (term_TopSymbol(clause_GetAtom(clause, 0)) != Control) {
      subst = subst_Create(Mem, 8);
      while (term_TopSymbol(clause_GetAtom(clause, 0)) != Control) {
        atom = clause_GetAtom(clause, 0);
        clause_RemoveLiteral(clause, 0);
        subst_SetValue(subst, term_TopSymbol(term_FirstArgument(atom)), term_SecondArgument(atom));
      }
    } else
      subst = NULL;
    switch (prlits_TestSpecialConstantValue(term_GetSymbstate(Termstate), term_TopSymbol(term_FirstArgument(op)))) {
    case 1:
      printf("Add(%d): ", trailsize);
      for (it = 0; it < clause_GetPremiseLiterals(clause); it++) {
        result = prlits_AddIfNotMember(pLits, Sharer, Termstate, SState, clause, subst, it, trailsize);
        if (result)
          printf("TRUE, ");
        else
          printf("FALSE, ");
      }
      printf("-> ");
      for (; it < clause_GetPremiseLiterals(clause) + clause_GetConclusionLiterals(clause); it++) {
        result = prlits_AddIfNotMember(pLits, Sharer, Termstate, SState, clause, subst, it, trailsize);
        if (result)
          printf("TRUE, ");
        else
          printf("FALSE, ");
      }
      break;
    case 2:
      printf("Remove(%d): ", trailsize);
      prlits_RemoveUntilTrailsize(pLits, Termstate, trailsize);
      break;
    case 3:
      printf("In Set: ");
      for (it = 0; it < clause_GetPremiseLiterals(clause); it++) {
        result = prlits_IsPropagated(pLits, Sharer, Termstate, SState, clause, subst, it);
        if (result)
          printf("TRUE, ");
        else
          printf("FALSE, ");
      }
      printf("-> ");
      for (; it < clause_GetPremiseLiterals(clause) + clause_GetConclusionLiterals(clause); it++) {
        result = prlits_IsPropagated(pLits, Sharer, Termstate, SState, clause, subst, it);
        if (result)
          printf("TRUE, ");
        else
          printf("FALSE, ");
      }
      break;
    default:
      break;
    }
    if (subst != NULL)
      subst_Delete(Mem, subst);
    printf("\n");
  }
  prlits_Delete(pLits);
}
BOOL prlits_TrailPosCompare(PRLITS_ANNO_LIT* Triple1, PRLITS_ANNO_LIT* Triple2) {
  return ((*Triple1)->trailsize > (*Triple2)->trailsize);
}
void prlits_Sort(PRLITS PLits)
{
  ARRAY prlits;
  prlits = prlits_GetStack(PLits);
  srtg_AMergeSortCompare(prlits_GetMemory(PLits), prlits, prlits, prlits+(array_GetSize(prlits)-1), (BOOL (*)(POINTER,POINTER))prlits_TrailPosCompare);
}
