#ifdef DOC_BUILD_INTERNAL
#endif
#include "distrn.h"
const unsigned distrn_INITIALNODESIZECAP = 4;
const intptr_t distrn_LEAFIDENTIFIER = 1;
uint32_t distrn_HashSymbol(const SYMBOL Symb)
{
  return (uint32_t)Symb;
}
uint32_t distrn_HashData(const OHASH_KEY_TYPE Data)
{
  return (uint32_t)Data/16;
}
BOOL distrn_KeyEqualData(const OHASH_KEY_TYPE Data1, const OHASH_KEY_TYPE Data2)
{
  return (Data1 == Data2);
}
DISTRNP distrn_NodeCreate(MEMORY Mem)
{
  DISTRNP dnode;
  dnode = memory_Malloc(Mem, sizeof(DISTRN_NODE));
  dnode->nextvar = (DISTRNP)NULL;
  dnode->rmap = (intptr_t)NULL;
  return dnode;
}
DISTRN distrn_Create(MEMORY Mem)
{
  DISTRN dtree;
  dtree = memory_Malloc(Mem, sizeof(DISTRN_ROOT));
  dtree->stack = array_Create(Mem,20);
  dtree->flat = array_Create(Mem,10);
  dtree->skip = array_Create(Mem,10);
  dtree->root = distrn_NodeCreate(Mem);
  return dtree;
}
void distrn_TreeDelete(MEMORY Mem, DISTRNP Node)
{
  if (Node->nextvar != (DISTRNP)NULL) {
    if (Node->nextvar != (DISTRNP)distrn_LEAFIDENTIFIER)
      distrn_TreeDelete(Mem, Node->nextvar);
    else {
      if (Node->rmap != (intptr_t)NULL) {
 ohash_Delete((OHASH)Node->rmap, NULL, NULL);
 Node->rmap = (intptr_t)NULL;
      }
    }
  }
  if (Node->rmap != (intptr_t)NULL) {
    uint32_t i, cap;
    OHASH hash;
    hash = (OHASH)Node->rmap;
    cap = ohash_GetCapacity(hash);
    for (i = 0; i < cap; i++) {
      if (ohash_GetOccupancyAtIndex(hash, i) == ohash_ENTRY_OCCUPIED) {
 distrn_TreeDelete(Mem, (DISTRNP)ohash_GetDataAtIndex(hash, i));}
    }
    ohash_Free(hash);
  }
  memory_Free(Mem, Node, sizeof(DISTRN_NODE));
}
void distrn_Delete(MEMORY Mem, DISTRN Dtree)
{
  DISTRNP node;
  array_Delete(Mem, Dtree->stack);
  array_Delete(Mem, Dtree->flat);
  array_Delete(Mem, Dtree->skip);
  node = Dtree->root;
  memory_Free(Mem, Dtree, sizeof(DISTRN_ROOT));
  distrn_TreeDelete(Mem, node);
}
void distrn_TreeDeleteWithEntries(MEMORY Mem, DISTRNP Node, void (DeleteEntry)(MEMORY, OHASH_DATA_TYPE))
{
  if (Node->nextvar != (DISTRNP)NULL) {
    if (Node->nextvar != (DISTRNP)distrn_LEAFIDENTIFIER)
      distrn_TreeDeleteWithEntries(Mem, Node->nextvar, DeleteEntry);
    else {
      if (Node->rmap != (intptr_t)NULL) {
 ohash_Delete((OHASH)Node->rmap, NULL, DeleteEntry);
 Node->rmap = (intptr_t)NULL;
      }
    }
  }
  if (Node->rmap != (intptr_t)NULL) {
    uint32_t i, cap;
    OHASH hash;
    hash = (OHASH)Node->rmap;
    cap = ohash_GetCapacity(hash);
    for (i = 0; i < cap; i++) {
      if (ohash_GetOccupancyAtIndex(hash, i) == ohash_ENTRY_OCCUPIED) {
 distrn_TreeDeleteWithEntries(Mem, (DISTRNP)ohash_GetDataAtIndex(hash, i), DeleteEntry);}
    }
    ohash_Free(hash);
  }
  memory_Free(Mem, Node, sizeof(DISTRN_NODE));
}
void distrn_TreeDeleteIter(MEMORY Mem, DISTRNP Node)
{
  ARRAY stack;
  stack = array_Create(Mem, 100);
  stack = array_Push(Mem, stack, (intptr_t)Node);
  while (!array_IsEmpty(stack)) {
    Node = (DISTRNP)array_Pop(stack);
    if (Node->nextvar != (DISTRNP)NULL) {
      if (Node->nextvar != (DISTRNP)distrn_LEAFIDENTIFIER)
 stack = array_Push(Mem, stack, (intptr_t)Node->nextvar);
      else {
 if (Node->rmap != (intptr_t)NULL) {
   ohash_Delete((OHASH)Node->rmap, NULL, NULL);
   Node->rmap = (intptr_t)NULL;
 }
      }
    }
    if (Node->rmap != (intptr_t)NULL) {
      uint32_t i, cap;
      OHASH hash;
      hash = (OHASH)Node->rmap;
      cap = ohash_GetCapacity(hash);
      for (i = 0; i < cap; i++) {
 if (ohash_GetOccupancyAtIndex(hash, i) == ohash_ENTRY_OCCUPIED) {
   stack = array_Push(Mem, stack, (intptr_t)ohash_GetDataAtIndex(hash, i));
 }
      }
      ohash_Free(hash);
    }
    memory_Free(Mem, Node, sizeof(DISTRN_NODE));
  }
  array_Delete(Mem, stack);
}
void distrn_DeleteIter(MEMORY Mem, DISTRN Dtree)
{
  DISTRNP node;
  array_Delete(Mem, Dtree->stack);
  array_Delete(Mem, Dtree->flat);
  array_Delete(Mem, Dtree->skip);
  node = Dtree->root;
  memory_Free(Mem, Dtree, sizeof(DISTRN_ROOT));
  distrn_TreeDeleteIter(Mem, node);
}
void distrn_TreeDeleteWithEntriesIter(MEMORY Mem, DISTRNP Node, void (DeleteEntry)(MEMORY, OHASH_DATA_TYPE))
{
  ARRAY stack;
  stack = array_Create(Mem, 100);
  stack = array_Push(Mem, stack, (intptr_t)Node);
  while (!array_IsEmpty(stack)) {
    Node = (DISTRNP)array_Pop(stack);
    if (Node->nextvar != (DISTRNP)NULL) {
      if (Node->nextvar != (DISTRNP)distrn_LEAFIDENTIFIER)
 stack = array_Push(Mem, stack, (intptr_t)Node->nextvar);
      else {
 if (Node->rmap != (intptr_t)NULL) {
   ohash_Delete((OHASH)Node->rmap, NULL, DeleteEntry);
   Node->rmap = (intptr_t)NULL;
 }
      }
    }
    if (Node->rmap != (intptr_t)NULL) {
      uint32_t i, cap;
      OHASH hash;
      hash = (OHASH)Node->rmap;
      cap = ohash_GetCapacity(hash);
      for (i = 0; i < cap; i++) {
 if (ohash_GetOccupancyAtIndex(hash, i) == ohash_ENTRY_OCCUPIED) {
   stack = array_Push(Mem, stack, (intptr_t)ohash_GetDataAtIndex(hash, i));
 }
      }
      ohash_Free(hash);
    }
    memory_Free(Mem, Node, sizeof(DISTRN_NODE));
  }
  array_Delete(Mem, stack);
}
void distrn_DeleteWithEntriesIter(MEMORY Mem, DISTRN Dtree, void (DeleteEntry)(MEMORY, OHASH_DATA_TYPE))
{
  DISTRNP node;
  array_Delete(Mem, Dtree->stack);
  array_Delete(Mem, Dtree->flat);
  array_Delete(Mem, Dtree->skip);
  node = Dtree->root;
  memory_Free(Mem, Dtree, sizeof(DISTRN_ROOT));
  distrn_TreeDeleteWithEntriesIter(Mem, node, DeleteEntry);
}
void distrn_DeleteWithEntries(MEMORY Mem, DISTRN Dtree, void (DeleteEntry)(MEMORY, OHASH_DATA_TYPE))
{
  DISTRNP node;
  array_Delete(Mem, Dtree->stack);
  array_Delete(Mem, Dtree->flat);
  array_Delete(Mem, Dtree->skip);
  node = Dtree->root;
  memory_Free(Mem, Dtree, sizeof(DISTRN_ROOT));
  distrn_TreeDeleteWithEntries(Mem, node, DeleteEntry);
}
DISTRNP distrn_InsertIntern(MEMORY Mem, DISTRNP Dnode, TERMSTATE Termstate, TERM Term, SUBST Subst)
{
  SYMBOL top;
  unsigned arity;
  unsigned i;
  DISTRNP next;
  top = term_TopSymbol(Term);
  if (Subst != NULL && symbol_IsVariable(term_GetSymbstate(Termstate), top) == TRUE && subst_VarDefined(Subst, top)) {
    Term = subst_GetValue(Subst, top);
    top = term_TopSymbol(Term);
    Subst = NULL;
  }
  if (term_IsVariable(Termstate, Term)) {
    if (Dnode->nextvar == (DISTRNP)NULL) {
      next = distrn_NodeCreate(Mem);
      Dnode->nextvar = next;
    }
    else
      next = Dnode->nextvar;
    return next;
  }
  if (Dnode->rmap == (intptr_t)NULL)
    Dnode->rmap = (intptr_t)ohash_Create(Mem, distrn_INITIALNODESIZECAP, distrn_HashSymbol, symbol_Equal);
  next = (DISTRNP)ohash_Search((OHASH)Dnode->rmap, top);
  if (next == (DISTRNP)NULL) {
    next = distrn_NodeCreate(Mem);
    Dnode->rmap = (intptr_t)ohash_Insert((OHASH)Dnode->rmap, top, (OHASH_DATA_TYPE)next, NULL, NULL);
  }
  if (symbol_IsConstant(top))
    return next;
  arity = term_GetArity(Term);
  for (i = 0; i < arity; i++)
    next = distrn_InsertIntern(Mem, next, Termstate, (TERM)Term[i], Subst);
  return next;
}
void distrn_Insert(MEMORY Mem, DISTRN Dtree, TERMSTATE Termstate, TERM Term, SUBST Subst, intptr_t Entry)
{
  DISTRNP dnode;
  dnode = distrn_InsertIntern(Mem, Dtree->root, Termstate, Term, Subst);
#ifdef SPASS_CHECK
  if (dnode->nextvar != (DISTRNP)NULL && dnode->nextvar != (DISTRNP)distrn_LEAFIDENTIFIER) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: expected leaf node seems to be an internal node.", __func__);
    misc_FinishErrorReport();
  }
#endif
  dnode->nextvar = (DISTRNP)distrn_LEAFIDENTIFIER;
  if (dnode->rmap == (intptr_t)NULL)
    dnode->rmap = (intptr_t)ohash_Create(Mem, distrn_INITIALNODESIZECAP, distrn_HashData, distrn_KeyEqualData);
  dnode->rmap = (intptr_t)ohash_Insert((OHASH)dnode->rmap, Entry, Entry, NULL, NULL);
}
void distrn_InsertDataHash(MEMORY Mem, DISTRN Dtree, TERMSTATE Termstate, TERM Term, SUBST Subst, intptr_t Entry, uint32_t (*HashData)(const OHASH_KEY_TYPE))
{
  DISTRNP dnode;
  dnode = distrn_InsertIntern(Mem, Dtree->root, Termstate, Term, Subst);
#ifdef SPASS_CHECK
  if (dnode->nextvar != (DISTRNP)NULL && dnode->nextvar != (DISTRNP)distrn_LEAFIDENTIFIER) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: expected leaf node seems to be an internal node.", __func__);
    misc_FinishErrorReport();
  }
#endif
  dnode->nextvar = (DISTRNP)distrn_LEAFIDENTIFIER;
  if (dnode->rmap == (intptr_t)NULL)
    dnode->rmap = (intptr_t)ohash_Create(Mem, distrn_INITIALNODESIZECAP, HashData, distrn_KeyEqualData);
  dnode->rmap = (intptr_t)ohash_Insert((OHASH)dnode->rmap, Entry, Entry, NULL, NULL);
}
DISTRNP distrn_RemoveIntern(DISTRNP Dnode, TERMSTATE Termstate, TERM Term, SUBST Subst)
{
  SYMBOL top;
  unsigned arity;
  unsigned i;
  DISTRNP next;
  top = term_TopSymbol(Term);
  if (Subst != NULL && symbol_IsVariable(term_GetSymbstate(Termstate), top) == TRUE && subst_VarDefined(Subst, top)) {
    Term = subst_GetValue(Subst, top);
    top = term_TopSymbol(Term);
    Subst = NULL;
  }
  if (term_IsVariable(Termstate, Term)) {
#ifdef SPASS_CHECK
    if (Dnode->nextvar == (DISTRNP)NULL) {
      misc_StartErrorReport();
      misc_ErrorReport("\n In %s: expected variable node does not exist.", __func__);
      misc_FinishErrorReport();
    }
#endif
    return Dnode->nextvar;
  }
#ifdef SPASS_CHECK
    if (Dnode->rmap == (intptr_t)NULL) {
      misc_StartErrorReport();
      misc_ErrorReport("\n In %s: expected function hash array does not exist.", __func__);
      misc_FinishErrorReport();
    }
#endif
  next = (DISTRNP)ohash_Search((OHASH)Dnode->rmap, top);
#ifdef SPASS_CHECK
  if (next == (DISTRNP)NULL) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: function symbol not contained in hash array.", __func__);
    misc_FinishErrorReport();
  }
#endif
  if (symbol_IsConstant(top))
    return next;
  arity = term_GetArity(Term);
  for (i = 0; i < arity; i++)
    next = distrn_RemoveIntern(next, Termstate, (TERM)Term[i], Subst);
  return next;
}
void distrn_Remove(DISTRN Dtree, TERMSTATE Termstate, TERM Term, SUBST Subst, intptr_t Entry)
{
  DISTRNP dnode;
  dnode = distrn_RemoveIntern(Dtree->root, Termstate, Term, Subst);
#ifdef SPASS_CHECK
  if (dnode->nextvar != (DISTRNP)NULL && dnode->nextvar != (DISTRNP)distrn_LEAFIDENTIFIER) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: expected leaf node seems to be an internal node.", __func__);
    misc_FinishErrorReport();
  }
#endif
  dnode->rmap = (intptr_t)ohash_Remove((OHASH)dnode->rmap, Entry, NULL, NULL);
}
void distrn_RemoveIf(DISTRN Dtree, TERMSTATE Termstate, TERM Term, SUBST Subst, BOOL (*Test)(intptr_t, intptr_t), intptr_t Testarg, void (*Free)(MEMORY, intptr_t))
{
  DISTRNP dnode;
  unsigned i, cap;
  OHASH hash;
  dnode = distrn_RemoveIntern(Dtree->root, Termstate, Term, Subst);
#ifdef SPASS_CHECK
  if (dnode->nextvar != (DISTRNP)NULL && dnode->nextvar != (DISTRNP)distrn_LEAFIDENTIFIER) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: expected leaf node seems to be an internal node.", __func__);
    misc_FinishErrorReport();
  }
#endif
  hash = (OHASH)dnode->rmap;
  cap = ohash_GetCapacity(hash);
  for (i = 0; i < cap; i++) {
    if (ohash_GetOccupancyAtIndex(hash, i) == ohash_ENTRY_OCCUPIED) {
      if (Test(Testarg, (intptr_t)ohash_GetDataAtIndex(hash,i))) {
 Free(term_GetMemory(Termstate), (intptr_t)ohash_GetDataAtIndex(hash,i));
 hash = ohash_RemoveEntryAtIndex(hash,i);
 break;
      }
    }
  }
}
void distrn_CreateFlat(MEMORY Mem, DISTRN Dtree, TERM Term, int *index)
{
  SYMBOL top;
  top = term_TopSymbol(Term);
  Dtree->flat = array_AddAtIndex(Mem, Dtree->flat, *index, (intptr_t)top);
  if (!symbol_IsVariableFast(top) && !symbol_IsConstant(top)) {
    unsigned i,j;
    j = *index;
    for (i = 0; i < term_GetArity(Term); i++) {
      (*index)++;
      distrn_CreateFlat(Mem, Dtree, (TERM)Term[i], index);
    }
    Dtree->skip = array_AddAtIndex(Mem, Dtree->skip, j, (*index)+1);
  }
  else {
    Dtree->skip = array_AddAtIndex(Mem, Dtree->skip, *index, (*index) + 1);
  }
}
void distrn_TransferResult(MEMORY Mem, DISTRNP Leaf, ARRAY *Result)
{
  *Result = ohash_AppendDataToArr(Mem, (OHASH)Leaf->rmap, Result);
}
void distrn_RemoveIfTrueIntern(MEMORY Mem, DISTRNP Dnode, SYMBSTATE Symbstate, BOOL (*FilterFunc)(intptr_t, intptr_t), intptr_t State, void (*FreeFunc)(MEMORY, intptr_t))
{
  if (Dnode->nextvar == (DISTRNP)distrn_LEAFIDENTIFIER) {
    OHASH hash;
    unsigned i, cap;
    i = 0;
    hash = (OHASH)Dnode->rmap;
    cap = ohash_GetCapacity(hash);
    for (i = 0; i < cap; i++) {
      if (ohash_GetOccupancyAtIndex(hash, i) == ohash_ENTRY_OCCUPIED) {
 if (FilterFunc(State, ohash_GetDataAtIndex(hash,i))) {
     if (FreeFunc != NULL)
       FreeFunc(Mem, ohash_GetDataAtIndex(hash,i));
     hash = ohash_RemoveEntryAtIndex(hash,i);
   }
      }
    }
  }
  else {
    if (Dnode->nextvar != (DISTRNP)NULL)
      distrn_RemoveIfTrueIntern(Mem, Dnode->nextvar, Symbstate, FilterFunc, State, FreeFunc);
    if (Dnode->rmap != (intptr_t)NULL) {
      int32_t i, cap;
      OHASH hash;
      hash = (OHASH)Dnode->rmap;
      cap = ohash_GetCapacity(hash);
      for (i = 0; i < cap; i++) {
 if (ohash_GetOccupancyAtIndex(hash, i) == ohash_ENTRY_OCCUPIED)
   distrn_RemoveIfTrueIntern(Mem, (DISTRNP)ohash_GetDataAtIndex(hash, i), Symbstate, FilterFunc, State, FreeFunc);
      }
    }
  }
}
void distrn_RemoveIfTrue(MEMORY Mem, DISTRN Dtree, SYMBSTATE Symbstate, BOOL (*FilterFunc)(intptr_t, intptr_t), intptr_t State, void (*FreeFunc)(MEMORY, intptr_t))
{
  distrn_RemoveIfTrueIntern(Mem, Dtree->root, Symbstate, FilterFunc, State, FreeFunc);
}
ARRAY distrn_SearchGeneralizations(MEMORY Mem, DISTRN Dtree, TERMSTATE Termstate, TERM Term, ARRAY *Result)
{
  SYMBOL top;
  unsigned i,size;
  DISTRNP next;
  array_SetSize(Dtree->stack,0);
  array_SetSize(Dtree->flat, 0);
  array_SetSize(Dtree->skip, 0);
  i = 0;
  distrn_CreateFlat(Mem, Dtree, Term, (int *)&i);
  size = array_GetSize(Dtree->flat);
  Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)0);
  Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)Dtree->root);
  while (array_GetSize(Dtree->stack) > 0) {
    next = (DISTRNP)array_Pop(Dtree->stack);
    i = (unsigned)array_Pop(Dtree->stack);
    top = (SYMBOL)Dtree->flat[i];
    if(next->nextvar == (DISTRNP)distrn_LEAFIDENTIFIER)
      distrn_TransferResult(Mem, next, Result);
    else {
      if (next->nextvar != (DISTRNP)NULL) {
 if (Dtree->skip[i] < size) {
   Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)(Dtree->skip[i]));
   Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)next->nextvar);
 }
 else {
   distrn_TransferResult(Mem, next->nextvar, Result);
 }
      }
      i++;
      if (!symbol_IsVariableFast(top) && next->rmap != (intptr_t)NULL) {
 next = (DISTRNP)ohash_Search((OHASH)next->rmap, top);
 if (next != (DISTRNP)NULL) {
   if (i < size) {
     Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)i);
     Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)next);
   }
   else {
     distrn_TransferResult(Mem, next, Result);
   }
 }
      }
    }
  }
  return *Result;
}
ARRAY distrn_SearchInstances(MEMORY Mem, DISTRN Dtree, TERMSTATE Termstate, TERM Term, ARRAY *Result)
{
  SYMBOL top;
  unsigned i,j,k,cap,size;
  DISTRNP next;
  OHASH hash;
  SYMBSTATE symbstate;
  symbstate = term_GetSymbstate(Termstate);
  array_SetSize(Dtree->stack,0);
  array_SetSize(Dtree->flat, 0);
  i = 0;
  distrn_CreateFlat(Mem, Dtree, Term, (int *)&i);
  size = array_GetSize(Dtree->flat);
  Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)0);
  Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)0);
  Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)Dtree->root);
  while (array_GetSize(Dtree->stack) > 0) {
    next = (DISTRNP)array_Pop(Dtree->stack);
    i = (unsigned)array_Pop(Dtree->stack);
    j = (unsigned)array_Pop(Dtree->stack);
    if (j==0) {
      if (i < size) {
 top = (SYMBOL)Dtree->flat[i];
 if (symbol_IsVariableFast(top)) {
   i++;
   if (next->nextvar != (DISTRNP)NULL) {
     Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)j);
     Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)i);
     Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)next->nextvar);
   }
   if (next->rmap!=(intptr_t)NULL) {
     hash = (OHASH)next->rmap;
     cap = ohash_GetCapacity(hash);
     for (k = 0; k < cap; k++) {
       if (ohash_GetOccupancyAtIndex(hash, k) == ohash_ENTRY_OCCUPIED) {
  Dtree->stack = array_Push(Mem, Dtree->stack, symbol_GetArity(symbstate, (SYMBOL)ohash_GetKeyAtIndex(hash, k)));
  Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)i);
  Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)ohash_GetDataAtIndex(hash, k));
       }
     }
   }
 }
 else {
   i++;
   if (next->rmap != (intptr_t)NULL) {
     next = (DISTRNP)ohash_Search((OHASH)next->rmap, top);
     if (next != (DISTRNP)NULL) {
       if (i < size) {
  Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)j);
  Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)i);
  Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)next);
       }
       else {
  distrn_TransferResult(Mem, next, Result);
       }
     }
   }
 }
      }
      else
 distrn_TransferResult(Mem, next, Result);
    }
    else {
      j--;
      if (next->nextvar != (DISTRNP)NULL) {
 Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)j);
 Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)i);
 Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)next->nextvar);
      }
      if (next->rmap!=(intptr_t)NULL) {
 hash = (OHASH)next->rmap;
 cap = ohash_GetCapacity(hash);
 for (k = 0; k < cap; k++) {
   if (ohash_GetOccupancyAtIndex(hash, k) == ohash_ENTRY_OCCUPIED) {
     Dtree->stack = array_Push(Mem, Dtree->stack, j + symbol_GetArity(symbstate, (SYMBOL)ohash_GetKeyAtIndex(hash, k)));
     Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)i);
     Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)ohash_GetDataAtIndex(hash, k));
   }
 }
      }
    }
  }
  return *Result;
}
ARRAY distrn_SearchUnifiables(MEMORY Mem, DISTRN Dtree, TERMSTATE Termstate, TERM Term, ARRAY *Result)
{
  SYMBOL top;
  unsigned i,j,k,cap,size;
  DISTRNP next;
  OHASH hash;
  SYMBSTATE symbstate;
  symbstate = term_GetSymbstate(Termstate);
  array_SetSize(Dtree->stack,0);
  array_SetSize(Dtree->flat, 0);
  i = 0;
  distrn_CreateFlat(Mem, Dtree, Term, (int *)&i);
  size = array_GetSize(Dtree->flat);
  Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)0);
  Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)0);
  Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)Dtree->root);
  while (array_GetSize(Dtree->stack) > 0) {
    next = (DISTRNP)array_Pop(Dtree->stack);
    i = (unsigned)array_Pop(Dtree->stack);
    j = (unsigned)array_Pop(Dtree->stack);
    if (j==0) {
      if (i < size) {
 top = (SYMBOL)Dtree->flat[i];
 if (symbol_IsVariableFast(top)) {
   i++;
   if (next->nextvar != (DISTRNP)NULL) {
     Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)j);
     Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)i);
     Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)next->nextvar);
   }
   if (next->rmap!=(intptr_t)NULL) {
     hash = (OHASH)next->rmap;
     cap = ohash_GetCapacity(hash);
     for (k = 0; k < cap; k++) {
       if (ohash_GetOccupancyAtIndex(hash, k) == ohash_ENTRY_OCCUPIED) {
  Dtree->stack = array_Push(Mem, Dtree->stack, symbol_GetArity(symbstate, (SYMBOL)ohash_GetKeyAtIndex(hash, k)));
  Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)i);
  Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)ohash_GetDataAtIndex(hash, k));
       }
     }
   }
 }
 else {
   if(next->nextvar == (DISTRNP)distrn_LEAFIDENTIFIER)
     distrn_TransferResult(Mem, next, Result);
   else {
     if (next->nextvar != (DISTRNP)NULL) {
       if (Dtree->skip[i] < size) {
  Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)j);
  Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)(Dtree->skip[i]));
  Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)next->nextvar);
       }
       else {
  distrn_TransferResult(Mem, next->nextvar, Result);
       }
     }
     i++;
     if (next->rmap != (intptr_t)NULL) {
       next = (DISTRNP)ohash_Search((OHASH)next->rmap, top);
       if (next != (DISTRNP)NULL) {
  if (i < size) {
    Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)j);
    Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)i);
    Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)next);
  }
  else {
    distrn_TransferResult(Mem, next, Result);
  }
       }
     }
   }
 }
      }
      else
 distrn_TransferResult(Mem, next, Result);
    }
    else {
      j--;
      if (next->nextvar != (DISTRNP)NULL) {
 Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)j);
 Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)i);
 Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)next->nextvar);
      }
      if (next->rmap!=(intptr_t)NULL) {
 hash = (OHASH)next->rmap;
 cap = ohash_GetCapacity(hash);
 for (k = 0; k < cap; k++) {
   if (ohash_GetOccupancyAtIndex(hash, k) == ohash_ENTRY_OCCUPIED) {
     Dtree->stack = array_Push(Mem, Dtree->stack, j + symbol_GetArity(symbstate, (SYMBOL)ohash_GetKeyAtIndex(hash, k)));
     Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)i);
     Dtree->stack = array_Push(Mem, Dtree->stack, (intptr_t)ohash_GetDataAtIndex(hash, k));
   }
 }
      }
    }
  }
  return *Result;
}
void distrn_Print(DISTRN DTree, TERMSTATE Termstate, void (*PrintEntry) (TERMSTATE, intptr_t))
{
  unsigned i,j;
  uint32_t cap;
  DISTRNP next;
  SYMBOL top;
  SYMBSTATE symbstate;
  OHASH hash;
  MEMORY mem;
  mem = term_GetMemory(Termstate);
  symbstate = term_GetSymbstate(Termstate);
  array_SetSize(DTree->stack,0);
  array_SetSize(DTree->flat, 0);
  DTree->stack = array_Push(mem, DTree->stack, (intptr_t)0);
  DTree->stack = array_Push(mem, DTree->stack, (intptr_t)symbol_MinimalStandardVar());
  DTree->stack = array_Push(mem, DTree->stack, (intptr_t)DTree->root);
  printf("\n PRINTING TREE:");
  while (array_GetSize(DTree->stack) > 0) {
    next = (DISTRNP)array_Pop(DTree->stack);
    top = (SYMBOL)array_Pop(DTree->stack);
    i = (unsigned)array_Pop(DTree->stack);
    DTree->flat[i] = (intptr_t)top;
    if (next->nextvar == (DISTRNP)distrn_LEAFIDENTIFIER) {
      printf("\nPath: ");
      for (j = 0; j <= i; j++) {
 symbol_Print(symbstate, (SYMBOL)DTree->flat[j]);
 printf(" ");
      }
      hash = (OHASH)next->rmap;
      cap = ohash_GetCapacity(hash);
      for (i = 0; i < cap; i++) {
 if (ohash_GetOccupancyAtIndex(hash, i) == ohash_ENTRY_OCCUPIED) {
   PrintEntry(Termstate, ohash_GetDataAtIndex(hash,i));
 }
      }
    }
    else {
      if (next->nextvar != (DISTRNP)NULL) {
 DTree->stack = array_Push(mem, DTree->stack, (intptr_t)i + 1);
 DTree->stack = array_Push(mem, DTree->stack, (intptr_t)symbol_MinimalStandardVar());
 DTree->stack = array_Push(mem, DTree->stack, (intptr_t)next->nextvar);
      }
      if (next->rmap != (intptr_t)NULL) {
 uint32_t k;
 hash = (OHASH)next->rmap;
 cap = ohash_GetCapacity(hash);
 i++;
 for (k = 0; k < cap; k++) {
   if (ohash_GetOccupancyAtIndex(hash, k) == ohash_ENTRY_OCCUPIED) {
     DTree->stack = array_Push(mem, DTree->stack, (intptr_t)i);
     DTree->stack = array_Push(mem, DTree->stack, (intptr_t)ohash_GetKeyAtIndex(hash, k));
     DTree->stack = array_Push(mem, DTree->stack, (intptr_t)ohash_GetDataAtIndex(hash, k));
   }
 }
      }
    }
  }
}
DISTRNP distrn_ContainsTermIntern(DISTRNP Dnode, TERMSTATE Termstate, TERM Term)
{
  SYMBOL top;
  unsigned arity;
  unsigned i;
  DISTRNP next;
  top = term_TopSymbol(Term);
  if (term_IsVariable(Termstate, Term)) {
    if (Dnode->nextvar == (DISTRNP)NULL)
      return NULL;
    else
      return Dnode->nextvar;
  }
  if (Dnode->rmap == (intptr_t)NULL)
    return NULL;
  next = (DISTRNP)ohash_Search((OHASH)Dnode->rmap, top);
  if (next == (DISTRNP)NULL)
    return NULL;
  if (symbol_IsConstant(top))
    return next;
  arity = term_GetArity(Term);
  for (i = 0; i < arity; i++) {
    next = distrn_ContainsTermIntern(next, Termstate, (TERM)Term[i]);
    if (next == (DISTRNP)NULL)
      return NULL;
  }
  return next;
}
ARRAY distrn_ContainsTermCandidates(DISTRN DTree, TERMSTATE Termstate, TERM Term)
{
  DISTRNP dnode;
  MEMORY mem;
  dnode = distrn_ContainsTermIntern(DTree->root, Termstate, Term);
  mem = term_GetMemory(Termstate);
#ifdef SPASS_CHECK
  if (dnode != NULL && dnode->nextvar != (DISTRNP)NULL && dnode->nextvar != (DISTRNP)distrn_LEAFIDENTIFIER) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: expected leaf node seems to be an internal node.", __func__);
    misc_FinishErrorReport();
  }
#endif
  if (dnode == NULL)
    return NULL;
  if (dnode->rmap != (intptr_t)NULL) {
    ARRAY result;
    result = array_Create(mem, 10);
    return ohash_AppendDataToArr(mem, (OHASH)dnode->rmap, &result);
  }
  return NULL;
}
