This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/OPTYap/tab.tries.i
Vitor Santos Costa d0efa26d8b Merge branch 'rtries' of git.dcc.fc.up.pt:yap-6.3
Conflicts:
	OPTYap/tab.insts.i
	OPTYap/tab.tries.c
	OPTYap/tab.tries.i
2014-02-13 11:57:46 +00:00

2046 lines
82 KiB
OpenEdge ABL

/************************************************************************
** **
** The YapTab/YapOr/OPTYap systems **
** **
** YapTab extends the Yap Prolog engine to support sequential tabling **
** YapOr extends the Yap Prolog engine to support or-parallelism **
** OPTYap extends the Yap Prolog engine to support or-parallel tabling **
** **
** **
** Yap Prolog was developed at University of Porto, Portugal **
** **
************************************************************************/
/*********************
** Macros **
*********************/
#ifdef MODE_GLOBAL_TRIE_ENTRY
#define INCREMENT_GLOBAL_TRIE_REFERENCE(ENTRY) \
{ register gt_node_ptr entry_node = (gt_node_ptr) (ENTRY); \
TrNode_child(entry_node) = (gt_node_ptr) ((UInt) TrNode_child(entry_node) + 1); \
}
#define NEW_SUBGOAL_TRIE_NODE(NODE, ENTRY, CHILD, PARENT, NEXT) \
INCREMENT_GLOBAL_TRIE_REFERENCE(ENTRY); \
new_subgoal_trie_node(NODE, ENTRY, CHILD, PARENT, NEXT)
#define NEW_ANSWER_TRIE_NODE(NODE, INSTR, ENTRY, CHILD, PARENT, NEXT) \
INCREMENT_GLOBAL_TRIE_REFERENCE(ENTRY); \
new_answer_trie_node(NODE, INSTR, ENTRY, CHILD, PARENT, NEXT)
#define NEW_GLOBAL_TRIE_NODE(NODE, ENTRY, CHILD, PARENT, NEXT) \
INCREMENT_GLOBAL_TRIE_REFERENCE(ENTRY); \
new_global_trie_node(NODE, ENTRY, CHILD, PARENT, NEXT)
#else
#define NEW_SUBGOAL_TRIE_NODE(NODE, ENTRY, CHILD, PARENT, NEXT) \
new_subgoal_trie_node(NODE, ENTRY, CHILD, PARENT, NEXT)
#define NEW_ANSWER_TRIE_NODE(NODE, INSTR, ENTRY, CHILD, PARENT, NEXT) \
new_answer_trie_node(NODE, INSTR, ENTRY, CHILD, PARENT, NEXT)
#define NEW_GLOBAL_TRIE_NODE(NODE, ENTRY, CHILD, PARENT, NEXT) \
new_global_trie_node(NODE, ENTRY, CHILD, PARENT, NEXT)
#endif /* MODE_GLOBAL_TRIE_ENTRY */
#ifdef MODE_GLOBAL_TRIE_LOOP
#define SUBGOAL_CHECK_INSERT_ENTRY(TAB_ENT, NODE, ENTRY) \
NODE = global_trie_check_insert_entry(NODE, ENTRY PASS_REGS)
#define ANSWER_CHECK_INSERT_ENTRY(SG_FR, NODE, ENTRY, INSTR) \
NODE = global_trie_check_insert_entry(NODE, ENTRY PASS_REGS)
#else
#define SUBGOAL_CHECK_INSERT_ENTRY(TAB_ENT, NODE, ENTRY) \
NODE = subgoal_trie_check_insert_entry(TAB_ENT, NODE, ENTRY PASS_REGS)
#define ANSWER_CHECK_INSERT_ENTRY(SG_FR, NODE, ENTRY, INSTR) \
NODE = answer_trie_check_insert_entry(SG_FR, NODE, ENTRY, INSTR PASS_REGS)
#endif /* MODE_GLOBAL_TRIE_LOOP */
#ifdef INCLUDE_ANSWER_SEARCH_MODE_DIRECTED
#define ANSWER_SAFE_INSERT_ENTRY(NODE, ENTRY, INSTR) \
{ ans_node_ptr new_node; \
NEW_ANSWER_TRIE_NODE(new_node, INSTR, ENTRY, NULL, NODE, NULL); \
TrNode_child(NODE) = new_node; \
NODE = new_node; \
}
#ifdef THREADS
#define INVALIDATE_ANSWER_TRIE_NODE(NODE, SG_FR) \
TrNode_next(NODE) = SgFr_invalid_chain(SG_FR); \
SgFr_invalid_chain(SG_FR) = NODE
#else
#define INVALIDATE_ANSWER_TRIE_NODE(NODE, SG_FR) \
FREE_ANSWER_TRIE_NODE(NODE)
#endif /* THREADS */
#define INVALIDATE_ANSWER_TRIE_LEAF_NODE(NODE, SG_FR) \
TAG_AS_ANSWER_INVALID_NODE(NODE); \
TrNode_next(NODE) = SgFr_invalid_chain(SG_FR); \
SgFr_invalid_chain(SG_FR) = NODE
#endif /* INCLUDE_ANSWER_SEARCH_MODE_DIRECTED */
/************************************************************************
** subgoal_trie_check_insert_(gt)_entry **
************************************************************************/
#ifdef INCLUDE_SUBGOAL_TRIE_CHECK_INSERT
#ifndef SUBGOAL_TRIE_LOCK_AT_WRITE_LEVEL /* SUBGOAL_TRIE_LOCK_AT_ENTRY_LEVEL || SUBGOAL_TRIE_LOCK_AT_NODE_LEVEL || ! YAPOR */
#ifdef MODE_GLOBAL_TRIE_ENTRY
static inline sg_node_ptr subgoal_trie_check_insert_gt_entry(tab_ent_ptr tab_ent, sg_node_ptr parent_node, Term t USES_REGS) {
#else
static inline sg_node_ptr subgoal_trie_check_insert_entry(tab_ent_ptr tab_ent, sg_node_ptr parent_node, Term t USES_REGS) {
#endif /* MODE_GLOBAL_TRIE_ENTRY */
sg_node_ptr child_node;
LOCK_SUBGOAL_NODE(parent_node);
child_node = TrNode_child(parent_node);
if (child_node == NULL) {
NEW_SUBGOAL_TRIE_NODE(child_node, t, NULL, parent_node, NULL);
TrNode_child(parent_node) = child_node;
UNLOCK_SUBGOAL_NODE(parent_node);
return child_node;
}
if (! IS_SUBGOAL_TRIE_HASH(child_node)) {
int count_nodes = 0;
do {
if (TrNode_entry(child_node) == t) {
UNLOCK_SUBGOAL_NODE(parent_node);
return child_node;
}
count_nodes++;
child_node = TrNode_next(child_node);
} while (child_node);
NEW_SUBGOAL_TRIE_NODE(child_node, t, NULL, parent_node, TrNode_child(parent_node));
count_nodes++;
if (count_nodes >= MAX_NODES_PER_TRIE_LEVEL) {
/* alloc a new hash */
sg_hash_ptr hash;
sg_node_ptr chain_node, next_node, *bucket;
new_subgoal_trie_hash(hash, count_nodes, tab_ent);
chain_node = child_node;
do {
bucket = Hash_buckets(hash) + HASH_ENTRY(TrNode_entry(chain_node), BASE_HASH_BUCKETS);
next_node = TrNode_next(chain_node);
TrNode_next(chain_node) = *bucket;
*bucket = chain_node;
chain_node = next_node;
} while (chain_node);
TrNode_child(parent_node) = (sg_node_ptr) hash;
} else {
TrNode_child(parent_node) = child_node;
}
UNLOCK_SUBGOAL_NODE(parent_node);
return child_node;
}
{ /* trie nodes with hashing */
sg_hash_ptr hash;
sg_node_ptr *bucket;
int count_nodes = 0;
hash = (sg_hash_ptr) child_node;
bucket = Hash_buckets(hash) + HASH_ENTRY(t, Hash_num_buckets(hash));
child_node = *bucket;
while (child_node) {
if (TrNode_entry(child_node) == t) {
UNLOCK_SUBGOAL_NODE(parent_node);
return child_node;
}
count_nodes++;
child_node = TrNode_next(child_node);
}
NEW_SUBGOAL_TRIE_NODE(child_node, t, NULL, parent_node, *bucket);
*bucket = child_node;
Hash_num_nodes(hash)++;
count_nodes++;
if (count_nodes >= MAX_NODES_PER_BUCKET && Hash_num_nodes(hash) > Hash_num_buckets(hash)) {
/* expand current hash */
sg_node_ptr chain_node, next_node, *old_bucket, *old_hash_buckets, *new_hash_buckets;
int num_buckets;
num_buckets = Hash_num_buckets(hash) * 2;
ALLOC_BUCKETS(new_hash_buckets, num_buckets);
old_hash_buckets = Hash_buckets(hash);
old_bucket = old_hash_buckets + Hash_num_buckets(hash);
do {
if (*--old_bucket) {
chain_node = *old_bucket;
do {
bucket = new_hash_buckets + HASH_ENTRY(TrNode_entry(chain_node), num_buckets);
next_node = TrNode_next(chain_node);
TrNode_next(chain_node) = *bucket;
*bucket = chain_node;
chain_node = next_node;
} while (chain_node);
}
} while (old_bucket != old_hash_buckets);
Hash_buckets(hash) = new_hash_buckets;
Hash_num_buckets(hash) = num_buckets;
FREE_BUCKETS(old_hash_buckets);
}
UNLOCK_SUBGOAL_NODE(parent_node);
return child_node;
}
}
#else /* SUBGOAL_TRIE_LOCK_AT_WRITE_LEVEL */
#ifdef MODE_GLOBAL_TRIE_ENTRY
static inline sg_node_ptr subgoal_trie_check_insert_gt_entry(tab_ent_ptr tab_ent, sg_node_ptr parent_node, Term t USES_REGS) {
#else
static inline sg_node_ptr subgoal_trie_check_insert_entry(tab_ent_ptr tab_ent, sg_node_ptr parent_node, Term t USES_REGS) {
#endif /* MODE_GLOBAL_TRIE_ENTRY */
sg_node_ptr child_node;
sg_hash_ptr hash;
child_node = TrNode_child(parent_node);
if (child_node == NULL) {
#ifdef SUBGOAL_TRIE_ALLOC_BEFORE_CHECK
NEW_SUBGOAL_TRIE_NODE(child_node, t, NULL, parent_node, NULL);
#endif /* SUBGOAL_TRIE_ALLOC_BEFORE_CHECK */
LOCK_SUBGOAL_NODE(parent_node);
if (TrNode_child(parent_node)) {
sg_node_ptr chain_node = TrNode_child(parent_node);
if (IS_SUBGOAL_TRIE_HASH(chain_node)) {
#ifdef SUBGOAL_TRIE_ALLOC_BEFORE_CHECK
FREE_SUBGOAL_TRIE_NODE(child_node);
#endif /* SUBGOAL_TRIE_ALLOC_BEFORE_CHECK */
UNLOCK_SUBGOAL_NODE(parent_node);
hash = (sg_hash_ptr) chain_node;
goto subgoal_trie_hash;
}
do {
if (TrNode_entry(chain_node) == t) {
#ifdef SUBGOAL_TRIE_ALLOC_BEFORE_CHECK
FREE_SUBGOAL_TRIE_NODE(child_node);
#endif /* SUBGOAL_TRIE_ALLOC_BEFORE_CHECK */
UNLOCK_SUBGOAL_NODE(parent_node);
return chain_node;
}
chain_node = TrNode_next(chain_node);
} while (chain_node);
#ifdef SUBGOAL_TRIE_ALLOC_BEFORE_CHECK
TrNode_next(child_node) = TrNode_child(parent_node);
#else
NEW_SUBGOAL_TRIE_NODE(child_node, t, NULL, parent_node, TrNode_child(parent_node));
} else {
NEW_SUBGOAL_TRIE_NODE(child_node, t, NULL, parent_node, NULL);
#endif /* SUBGOAL_TRIE_ALLOC_BEFORE_CHECK */
}
TrNode_child(parent_node) = child_node;
UNLOCK_SUBGOAL_NODE(parent_node);
return child_node;
}
if (! IS_SUBGOAL_TRIE_HASH(child_node)) {
sg_node_ptr first_node = child_node;
int count_nodes = 0;
do {
if (TrNode_entry(child_node) == t)
return child_node;
count_nodes++;
child_node = TrNode_next(child_node);
} while (child_node);
#ifdef SUBGOAL_TRIE_ALLOC_BEFORE_CHECK
NEW_SUBGOAL_TRIE_NODE(child_node, t, NULL, parent_node, first_node);
#endif /* SUBGOAL_TRIE_ALLOC_BEFORE_CHECK */
LOCK_SUBGOAL_NODE(parent_node);
if (first_node != TrNode_child(parent_node)) {
sg_node_ptr chain_node = TrNode_child(parent_node);
if (IS_SUBGOAL_TRIE_HASH(chain_node)) {
#ifdef SUBGOAL_TRIE_ALLOC_BEFORE_CHECK
FREE_SUBGOAL_TRIE_NODE(child_node);
#endif /* SUBGOAL_TRIE_ALLOC_BEFORE_CHECK */
UNLOCK_SUBGOAL_NODE(parent_node);
hash = (sg_hash_ptr) chain_node;
goto subgoal_trie_hash;
}
do {
if (TrNode_entry(chain_node) == t) {
#ifdef SUBGOAL_TRIE_ALLOC_BEFORE_CHECK
FREE_SUBGOAL_TRIE_NODE(child_node);
#endif /* SUBGOAL_TRIE_ALLOC_BEFORE_CHECK */
UNLOCK_SUBGOAL_NODE(parent_node);
return chain_node;
}
count_nodes++;
chain_node = TrNode_next(chain_node);
} while (chain_node != first_node);
#ifdef SUBGOAL_TRIE_ALLOC_BEFORE_CHECK
TrNode_next(child_node) = TrNode_child(parent_node);
#else
NEW_SUBGOAL_TRIE_NODE(child_node, t, NULL, parent_node, TrNode_child(parent_node));
} else {
NEW_SUBGOAL_TRIE_NODE(child_node, t, NULL, parent_node, first_node);
#endif /* SUBGOAL_TRIE_ALLOC_BEFORE_CHECK */
}
count_nodes++;
if (count_nodes >= MAX_NODES_PER_TRIE_LEVEL) {
/* alloc a new hash */
sg_node_ptr chain_node, next_node, *bucket;
new_subgoal_trie_hash(hash, count_nodes, tab_ent);
chain_node = child_node;
do {
bucket = Hash_buckets(hash) + HASH_ENTRY(TrNode_entry(chain_node), BASE_HASH_BUCKETS);
next_node = TrNode_next(chain_node);
TrNode_next(chain_node) = *bucket;
*bucket = chain_node;
chain_node = next_node;
} while (chain_node);
TrNode_child(parent_node) = (sg_node_ptr) hash;
} else {
TrNode_child(parent_node) = child_node;
}
UNLOCK_SUBGOAL_NODE(parent_node);
return child_node;
}
hash = (sg_hash_ptr) child_node;
subgoal_trie_hash:
{ /* trie nodes with hashing */
sg_node_ptr *bucket, first_node;
int num_buckets, count_nodes = 0;
do {
num_buckets = Hash_num_buckets(hash);
// __sync_synchronize();
bucket = Hash_buckets(hash) + HASH_ENTRY(t, num_buckets);
first_node = child_node = *bucket;
} while (num_buckets != Hash_num_buckets(hash));
while (child_node) {
if (TrNode_entry(child_node) == t)
return child_node;
count_nodes++;
child_node = TrNode_next(child_node);
}
#ifdef SUBGOAL_TRIE_ALLOC_BEFORE_CHECK
NEW_SUBGOAL_TRIE_NODE(child_node, t, NULL, parent_node, first_node);
#endif /* SUBGOAL_TRIE_ALLOC_BEFORE_CHECK */
LOCK_SUBGOAL_NODE(parent_node);
if (num_buckets != Hash_num_buckets(hash)) {
/* the hash has been expanded */
#ifdef SUBGOAL_TRIE_ALLOC_BEFORE_CHECK
FREE_SUBGOAL_TRIE_NODE(child_node);
#endif /* SUBGOAL_TRIE_ALLOC_BEFORE_CHECK */
UNLOCK_SUBGOAL_NODE(parent_node);
goto subgoal_trie_hash;
}
if (first_node != *bucket) {
sg_node_ptr chain_node = *bucket;
do {
if (TrNode_entry(chain_node) == t) {
#ifdef SUBGOAL_TRIE_ALLOC_BEFORE_CHECK
FREE_SUBGOAL_TRIE_NODE(child_node);
#endif /* SUBGOAL_TRIE_ALLOC_BEFORE_CHECK */
UNLOCK_SUBGOAL_NODE(parent_node);
return chain_node;
}
count_nodes++;
chain_node = TrNode_next(chain_node);
} while (chain_node != first_node);
#ifdef SUBGOAL_TRIE_ALLOC_BEFORE_CHECK
TrNode_next(child_node) = *bucket;
#else
NEW_SUBGOAL_TRIE_NODE(child_node, t, NULL, parent_node, *bucket);
} else {
NEW_SUBGOAL_TRIE_NODE(child_node, t, NULL, parent_node, first_node);
#endif /* SUBGOAL_TRIE_ALLOC_BEFORE_CHECK */
}
*bucket = child_node;
Hash_num_nodes(hash)++;
count_nodes++;
if (count_nodes >= MAX_NODES_PER_BUCKET && Hash_num_nodes(hash) > Hash_num_buckets(hash)) {
/* expand current hash */
sg_node_ptr chain_node, next_node, *old_bucket, *old_hash_buckets, *new_hash_buckets;
num_buckets = Hash_num_buckets(hash) * 2;
ALLOC_BUCKETS(new_hash_buckets, num_buckets);
old_hash_buckets = Hash_buckets(hash);
old_bucket = old_hash_buckets + Hash_num_buckets(hash);
do {
if (*--old_bucket) {
chain_node = *old_bucket;
do {
bucket = new_hash_buckets + HASH_ENTRY(TrNode_entry(chain_node), num_buckets);
next_node = TrNode_next(chain_node);
TrNode_next(chain_node) = *bucket;
*bucket = chain_node;
chain_node = next_node;
} while (chain_node);
}
} while (old_bucket != old_hash_buckets);
Hash_buckets(hash) = new_hash_buckets;
Hash_num_buckets(hash) = num_buckets;
FREE_BUCKETS(old_hash_buckets);
}
UNLOCK_SUBGOAL_NODE(parent_node);
return child_node;
}
}
#endif /* SUBGOAL_TRIE_LOCK_LEVEL */
#endif /* INCLUDE_SUBGOAL_TRIE_CHECK_INSERT */
/************************************************************************
** answer_trie_check_insert_(gt)_entry **
************************************************************************/
#ifdef INCLUDE_ANSWER_TRIE_CHECK_INSERT
#ifndef ANSWER_TRIE_LOCK_AT_WRITE_LEVEL /* ANSWER_TRIE_LOCK_AT_ENTRY_LEVEL || ANSWER_TRIE_LOCK_AT_NODE_LEVEL || ! YAPOR */
#ifdef MODE_GLOBAL_TRIE_ENTRY
static inline ans_node_ptr answer_trie_check_insert_gt_entry(sg_fr_ptr sg_fr, ans_node_ptr parent_node, Term t, int instr USES_REGS) {
#else
static inline ans_node_ptr answer_trie_check_insert_entry(sg_fr_ptr sg_fr, ans_node_ptr parent_node, Term t, int instr USES_REGS) {
#endif /* MODE_GLOBAL_TRIE_ENTRY */
ans_node_ptr child_node;
TABLING_ERROR_CHECKING(answer_trie_check_insert_(gt)_entry, IS_ANSWER_LEAF_NODE(parent_node));
LOCK_ANSWER_NODE(parent_node);
child_node = TrNode_child(parent_node);
if (child_node == NULL) {
NEW_ANSWER_TRIE_NODE(child_node, instr, t, NULL, parent_node, NULL);
TrNode_child(parent_node) = child_node;
UNLOCK_ANSWER_NODE(parent_node);
return child_node;
}
if (! IS_ANSWER_TRIE_HASH(child_node)) {
int count_nodes = 0;
do {
if (TrNode_entry(child_node) == t) {
UNLOCK_ANSWER_NODE(parent_node);
return child_node;
}
count_nodes++;
child_node = TrNode_next(child_node);
} while (child_node);
NEW_ANSWER_TRIE_NODE(child_node, instr, t, NULL, parent_node, TrNode_child(parent_node));
count_nodes++;
if (count_nodes >= MAX_NODES_PER_TRIE_LEVEL) {
/* alloc a new hash */
ans_hash_ptr hash;
ans_node_ptr chain_node, next_node, *bucket;
new_answer_trie_hash(hash, count_nodes, sg_fr);
chain_node = child_node;
do {
bucket = Hash_buckets(hash) + HASH_ENTRY(TrNode_entry(chain_node), BASE_HASH_BUCKETS);
next_node = TrNode_next(chain_node);
TrNode_next(chain_node) = *bucket;
*bucket = chain_node;
chain_node = next_node;
} while (chain_node);
TrNode_child(parent_node) = (ans_node_ptr) hash;
} else {
TrNode_child(parent_node) = child_node;
}
UNLOCK_ANSWER_NODE(parent_node);
return child_node;
}
{ /* trie nodes with hashing */
ans_hash_ptr hash;
ans_node_ptr *bucket;
int count_nodes = 0;
hash = (ans_hash_ptr) child_node;
bucket = Hash_buckets(hash) + HASH_ENTRY(t, Hash_num_buckets(hash));
child_node = *bucket;
while (child_node) {
if (TrNode_entry(child_node) == t) {
UNLOCK_ANSWER_NODE(parent_node);
return child_node;
}
count_nodes++;
child_node = TrNode_next(child_node);
}
NEW_ANSWER_TRIE_NODE(child_node, instr, t, NULL, parent_node, *bucket);
*bucket = child_node;
Hash_num_nodes(hash)++;
count_nodes++;
if (count_nodes >= MAX_NODES_PER_BUCKET && Hash_num_nodes(hash) > Hash_num_buckets(hash)) {
/* expand current hash */
ans_node_ptr chain_node, next_node, *old_bucket, *old_hash_buckets, *new_hash_buckets;
int num_buckets;
num_buckets = Hash_num_buckets(hash) * 2;
ALLOC_BUCKETS(new_hash_buckets, num_buckets);
old_hash_buckets = Hash_buckets(hash);
old_bucket = old_hash_buckets + Hash_num_buckets(hash);
do {
if (*--old_bucket) {
chain_node = *old_bucket;
do {
bucket = new_hash_buckets + HASH_ENTRY(TrNode_entry(chain_node), num_buckets);
next_node = TrNode_next(chain_node);
TrNode_next(chain_node) = *bucket;
*bucket = chain_node;
chain_node = next_node;
} while (chain_node);
}
} while (old_bucket != old_hash_buckets);
Hash_buckets(hash) = new_hash_buckets;
Hash_num_buckets(hash) = num_buckets;
FREE_BUCKETS(old_hash_buckets);
}
UNLOCK_ANSWER_NODE(parent_node);
return child_node;
}
}
#else /* ANSWER_TRIE_LOCK_AT_WRITE_LEVEL */
#ifdef MODE_GLOBAL_TRIE_ENTRY
static inline ans_node_ptr answer_trie_check_insert_gt_entry(sg_fr_ptr sg_fr, ans_node_ptr parent_node, Term t, int instr USES_REGS) {
#else
static inline ans_node_ptr answer_trie_check_insert_entry(sg_fr_ptr sg_fr, ans_node_ptr parent_node, Term t, int instr USES_REGS) {
#endif /* MODE_GLOBAL_TRIE_ENTRY */
ans_node_ptr child_node;
ans_hash_ptr hash;
TABLING_ERROR_CHECKING(answer_trie_check_insert_(gt)_entry, IS_ANSWER_LEAF_NODE(parent_node));
child_node = TrNode_child(parent_node);
if (child_node == NULL) {
#ifdef ANSWER_TRIE_ALLOC_BEFORE_CHECK
NEW_ANSWER_TRIE_NODE(child_node, instr, t, NULL, parent_node, NULL);
#endif /* ANSWER_TRIE_ALLOC_BEFORE_CHECK */
LOCK_ANSWER_NODE(parent_node);
if (TrNode_child(parent_node)) {
ans_node_ptr chain_node = TrNode_child(parent_node);
if (IS_ANSWER_TRIE_HASH(chain_node)) {
#ifdef ANSWER_TRIE_ALLOC_BEFORE_CHECK
FREE_ANSWER_TRIE_NODE(child_node);
#endif /* ANSWER_TRIE_ALLOC_BEFORE_CHECK */
UNLOCK_ANSWER_NODE(parent_node);
hash = (ans_hash_ptr) chain_node;
goto answer_trie_hash;
}
do {
if (TrNode_entry(chain_node) == t) {
#ifdef ANSWER_TRIE_ALLOC_BEFORE_CHECK
FREE_ANSWER_TRIE_NODE(child_node);
#endif /* ANSWER_TRIE_ALLOC_BEFORE_CHECK */
UNLOCK_ANSWER_NODE(parent_node);
return chain_node;
}
chain_node = TrNode_next(chain_node);
} while (chain_node);
#ifdef ANSWER_TRIE_ALLOC_BEFORE_CHECK
TrNode_next(child_node) = TrNode_child(parent_node);
#else
NEW_ANSWER_TRIE_NODE(child_node, instr, t, NULL, parent_node, TrNode_child(parent_node));
} else {
NEW_ANSWER_TRIE_NODE(child_node, instr, t, NULL, parent_node, NULL);
#endif /* ANSWER_TRIE_ALLOC_BEFORE_CHECK */
}
TrNode_child(parent_node) = child_node;
UNLOCK_ANSWER_NODE(parent_node);
return child_node;
}
if (! IS_ANSWER_TRIE_HASH(child_node)) {
ans_node_ptr first_node = child_node;
int count_nodes = 0;
do {
if (TrNode_entry(child_node) == t)
return child_node;
count_nodes++;
child_node = TrNode_next(child_node);
} while (child_node);
#ifdef ANSWER_TRIE_ALLOC_BEFORE_CHECK
NEW_ANSWER_TRIE_NODE(child_node, instr, t, NULL, parent_node, first_node);
#endif /* ANSWER_TRIE_ALLOC_BEFORE_CHECK */
LOCK_ANSWER_NODE(parent_node);
if (first_node != TrNode_child(parent_node)) {
ans_node_ptr chain_node = TrNode_child(parent_node);
if (IS_ANSWER_TRIE_HASH(chain_node)) {
#ifdef ANSWER_TRIE_ALLOC_BEFORE_CHECK
FREE_ANSWER_TRIE_NODE(child_node);
#endif /* ANSWER_TRIE_ALLOC_BEFORE_CHECK */
UNLOCK_ANSWER_NODE(parent_node);
hash = (ans_hash_ptr) chain_node;
goto answer_trie_hash;
}
do {
if (TrNode_entry(chain_node) == t) {
#ifdef ANSWER_TRIE_ALLOC_BEFORE_CHECK
FREE_ANSWER_TRIE_NODE(child_node);
#endif /* ANSWER_TRIE_ALLOC_BEFORE_CHECK */
UNLOCK_ANSWER_NODE(parent_node);
return chain_node;
}
count_nodes++;
chain_node = TrNode_next(chain_node);
} while (chain_node != first_node);
#ifdef ANSWER_TRIE_ALLOC_BEFORE_CHECK
TrNode_next(child_node) = TrNode_child(parent_node);
#else
NEW_ANSWER_TRIE_NODE(child_node, instr, t, NULL, parent_node, TrNode_child(parent_node));
} else {
NEW_ANSWER_TRIE_NODE(child_node, instr, t, NULL, parent_node, first_node);
#endif /* ANSWER_TRIE_ALLOC_BEFORE_CHECK */
}
count_nodes++;
if (count_nodes >= MAX_NODES_PER_TRIE_LEVEL) {
/* alloc a new hash */
ans_node_ptr chain_node, next_node, *bucket;
new_answer_trie_hash(hash, count_nodes, sg_fr);
chain_node = child_node;
do {
bucket = Hash_buckets(hash) + HASH_ENTRY(TrNode_entry(chain_node), BASE_HASH_BUCKETS);
next_node = TrNode_next(chain_node);
TrNode_next(chain_node) = *bucket;
*bucket = chain_node;
chain_node = next_node;
} while (chain_node);
TrNode_child(parent_node) = (ans_node_ptr) hash;
} else {
TrNode_child(parent_node) = child_node;
}
UNLOCK_ANSWER_NODE(parent_node);
return child_node;
}
hash = (ans_hash_ptr) child_node;
answer_trie_hash:
{ /* trie nodes with hashing */
ans_node_ptr *bucket, first_node;
int num_buckets, count_nodes = 0;
do {
num_buckets = Hash_num_buckets(hash);
// __sync_synchronize();
bucket = Hash_buckets(hash) + HASH_ENTRY(t, num_buckets);
first_node = child_node = *bucket;
} while (num_buckets != Hash_num_buckets(hash));
while (child_node) {
if (TrNode_entry(child_node) == t)
return child_node;
count_nodes++;
child_node = TrNode_next(child_node);
}
#ifdef ANSWER_TRIE_ALLOC_BEFORE_CHECK
NEW_ANSWER_TRIE_NODE(child_node, instr, t, NULL, parent_node, first_node);
#endif /* ANSWER_TRIE_ALLOC_BEFORE_CHECK */
LOCK_ANSWER_NODE(parent_node);
if (num_buckets != Hash_num_buckets(hash)) {
/* the hash has been expanded */
#ifdef ANSWER_TRIE_ALLOC_BEFORE_CHECK
FREE_ANSWER_TRIE_NODE(child_node);
#endif /* ANSWER_TRIE_ALLOC_BEFORE_CHECK */
UNLOCK_ANSWER_NODE(parent_node);
goto answer_trie_hash;
}
if (first_node != *bucket) {
ans_node_ptr chain_node = *bucket;
do {
if (TrNode_entry(chain_node) == t) {
#ifdef ANSWER_TRIE_ALLOC_BEFORE_CHECK
FREE_ANSWER_TRIE_NODE(child_node);
#endif /* ANSWER_TRIE_ALLOC_BEFORE_CHECK */
UNLOCK_ANSWER_NODE(parent_node);
return chain_node;
}
count_nodes++;
chain_node = TrNode_next(chain_node);
} while (chain_node != first_node);
#ifdef ANSWER_TRIE_ALLOC_BEFORE_CHECK
TrNode_next(child_node) = *bucket;
#else
NEW_ANSWER_TRIE_NODE(child_node, instr, t, NULL, parent_node, *bucket);
} else {
NEW_ANSWER_TRIE_NODE(child_node, instr, t, NULL, parent_node, first_node);
#endif /* ANSWER_TRIE_ALLOC_BEFORE_CHECK */
}
*bucket = child_node;
Hash_num_nodes(hash)++;
count_nodes++;
if (count_nodes >= MAX_NODES_PER_BUCKET && Hash_num_nodes(hash) > Hash_num_buckets(hash)) {
/* expand current hash */
ans_node_ptr chain_node, next_node, *old_bucket, *old_hash_buckets, *new_hash_buckets;
num_buckets = Hash_num_buckets(hash) * 2;
ALLOC_BUCKETS(new_hash_buckets, num_buckets);
old_hash_buckets = Hash_buckets(hash);
old_bucket = old_hash_buckets + Hash_num_buckets(hash);
do {
if (*--old_bucket) {
chain_node = *old_bucket;
do {
bucket = new_hash_buckets + HASH_ENTRY(TrNode_entry(chain_node), num_buckets);
next_node = TrNode_next(chain_node);
TrNode_next(chain_node) = *bucket;
*bucket = chain_node;
chain_node = next_node;
} while (chain_node);
}
} while (old_bucket != old_hash_buckets);
Hash_buckets(hash) = new_hash_buckets;
Hash_num_buckets(hash) = num_buckets;
FREE_BUCKETS(old_hash_buckets);
}
UNLOCK_ANSWER_NODE(parent_node);
return child_node;
}
}
#endif /* ANSWER_TRIE_LOCK_LEVEL */
#endif /* INCLUDE_ANSWER_TRIE_CHECK_INSERT */
/************************************************************************
** global_trie_check_insert_(gt)_entry **
************************************************************************/
#ifdef INCLUDE_GLOBAL_TRIE_CHECK_INSERT
#ifndef GLOBAL_TRIE_LOCK_AT_WRITE_LEVEL /* GLOBAL_TRIE_LOCK_AT_NODE_LEVEL || ! YAPOR */
#ifdef MODE_GLOBAL_TRIE_ENTRY
static inline gt_node_ptr global_trie_check_insert_gt_entry(gt_node_ptr parent_node, Term t USES_REGS) {
#else
static inline gt_node_ptr global_trie_check_insert_entry(gt_node_ptr parent_node, Term t USES_REGS) {
#endif /* MODE_GLOBAL_TRIE_ENTRY */
gt_node_ptr child_node;
LOCK_GLOBAL_NODE(parent_node);
child_node = TrNode_child(parent_node);
if (child_node == NULL) {
NEW_GLOBAL_TRIE_NODE(child_node, t, NULL, parent_node, NULL);
TrNode_child(parent_node) = child_node;
UNLOCK_GLOBAL_NODE(parent_node);
return child_node;
}
if (! IS_GLOBAL_TRIE_HASH(child_node)) {
int count_nodes = 0;
do {
if (TrNode_entry(child_node) == t) {
UNLOCK_GLOBAL_NODE(parent_node);
return child_node;
}
count_nodes++;
child_node = TrNode_next(child_node);
} while (child_node);
NEW_GLOBAL_TRIE_NODE(child_node, t, NULL, parent_node, TrNode_child(parent_node));
count_nodes++;
if (count_nodes >= MAX_NODES_PER_TRIE_LEVEL) {
/* alloc a new hash */
gt_hash_ptr hash;
gt_node_ptr chain_node, next_node, *bucket;
new_global_trie_hash(hash, count_nodes);
chain_node = child_node;
do {
bucket = Hash_buckets(hash) + HASH_ENTRY(TrNode_entry(chain_node), BASE_HASH_BUCKETS);
next_node = TrNode_next(chain_node);
TrNode_next(chain_node) = *bucket;
*bucket = chain_node;
chain_node = next_node;
} while (chain_node);
TrNode_child(parent_node) = (gt_node_ptr) hash;
} else {
TrNode_child(parent_node) = child_node;
}
UNLOCK_GLOBAL_NODE(parent_node);
return child_node;
}
{ /* trie nodes with hashing */
gt_hash_ptr hash;
gt_node_ptr *bucket;
int count_nodes = 0;
hash = (gt_hash_ptr) child_node;
bucket = Hash_buckets(hash) + HASH_ENTRY(t, Hash_num_buckets(hash));
child_node = *bucket;
while (child_node) {
if (TrNode_entry(child_node) == t) {
UNLOCK_GLOBAL_NODE(parent_node);
return child_node;
}
count_nodes++;
child_node = TrNode_next(child_node);
}
NEW_GLOBAL_TRIE_NODE(child_node, t, NULL, parent_node, *bucket);
*bucket = child_node;
Hash_num_nodes(hash)++;
count_nodes++;
if (count_nodes >= MAX_NODES_PER_BUCKET && Hash_num_nodes(hash) > Hash_num_buckets(hash)) {
/* expand current hash */
gt_node_ptr chain_node, next_node, *old_bucket, *old_hash_buckets, *new_hash_buckets;
int num_buckets;
num_buckets = Hash_num_buckets(hash) * 2;
ALLOC_BUCKETS(new_hash_buckets, num_buckets);
old_hash_buckets = Hash_buckets(hash);
old_bucket = old_hash_buckets + Hash_num_buckets(hash);
do {
if (*--old_bucket) {
chain_node = *old_bucket;
do {
bucket = new_hash_buckets + HASH_ENTRY(TrNode_entry(chain_node), num_buckets);
next_node = TrNode_next(chain_node);
TrNode_next(chain_node) = *bucket;
*bucket = chain_node;
chain_node = next_node;
} while (chain_node);
}
} while (old_bucket != old_hash_buckets);
Hash_buckets(hash) = new_hash_buckets;
Hash_num_buckets(hash) = num_buckets;
FREE_BUCKETS(old_hash_buckets);
}
UNLOCK_GLOBAL_NODE(parent_node);
return child_node;
}
}
#else /* GLOBAL_TRIE_LOCK_AT_WRITE_LEVEL */
#ifdef MODE_GLOBAL_TRIE_ENTRY
static inline gt_node_ptr global_trie_check_insert_gt_entry(gt_node_ptr parent_node, Term t USES_REGS) {
#else
static inline gt_node_ptr global_trie_check_insert_entry(gt_node_ptr parent_node, Term t USES_REGS) {
#endif /* MODE_GLOBAL_TRIE_ENTRY */
gt_node_ptr child_node;
gt_hash_ptr hash;
child_node = TrNode_child(parent_node);
if (child_node == NULL) {
#ifdef GLOBAL_TRIE_ALLOC_BEFORE_CHECK
NEW_GLOBAL_TRIE_NODE(child_node, t, NULL, parent_node, NULL);
#endif /* GLOBAL_TRIE_ALLOC_BEFORE_CHECK */
LOCK_GLOBAL_NODE(parent_node);
if (TrNode_child(parent_node)) {
gt_node_ptr chain_node = TrNode_child(parent_node);
if (IS_GLOBAL_TRIE_HASH(chain_node)) {
#ifdef GLOBAL_TRIE_ALLOC_BEFORE_CHECK
FREE_GLOBAL_TRIE_NODE(child_node);
#endif /* GLOBAL_TRIE_ALLOC_BEFORE_CHECK */
UNLOCK_GLOBAL_NODE(parent_node);
hash = (gt_hash_ptr) chain_node;
goto global_trie_hash;
}
do {
if (TrNode_entry(chain_node) == t) {
#ifdef GLOBAL_TRIE_ALLOC_BEFORE_CHECK
FREE_GLOBAL_TRIE_NODE(child_node);
#endif /* GLOBAL_TRIE_ALLOC_BEFORE_CHECK */
UNLOCK_GLOBAL_NODE(parent_node);
return chain_node;
}
chain_node = TrNode_next(chain_node);
} while (chain_node);
#ifdef GLOBAL_TRIE_ALLOC_BEFORE_CHECK
TrNode_next(child_node) = TrNode_child(parent_node);
#else
NEW_GLOBAL_TRIE_NODE(child_node, t, NULL, parent_node, TrNode_child(parent_node));
} else {
NEW_GLOBAL_TRIE_NODE(child_node, t, NULL, parent_node, NULL);
#endif /* GLOBAL_TRIE_ALLOC_BEFORE_CHECK */
}
TrNode_child(parent_node) = child_node;
UNLOCK_GLOBAL_NODE(parent_node);
return child_node;
}
if (! IS_GLOBAL_TRIE_HASH(child_node)) {
gt_node_ptr first_node = child_node;
int count_nodes = 0;
do {
if (TrNode_entry(child_node) == t)
return child_node;
count_nodes++;
child_node = TrNode_next(child_node);
} while (child_node);
#ifdef GLOBAL_TRIE_ALLOC_BEFORE_CHECK
NEW_GLOBAL_TRIE_NODE(child_node, t, NULL, parent_node, first_node);
#endif /* GLOBAL_TRIE_ALLOC_BEFORE_CHECK */
LOCK_GLOBAL_NODE(parent_node);
if (first_node != TrNode_child(parent_node)) {
gt_node_ptr chain_node = TrNode_child(parent_node);
if (IS_GLOBAL_TRIE_HASH(chain_node)) {
#ifdef GLOBAL_TRIE_ALLOC_BEFORE_CHECK
FREE_GLOBAL_TRIE_NODE(child_node);
#endif /* GLOBAL_TRIE_ALLOC_BEFORE_CHECK */
UNLOCK_GLOBAL_NODE(parent_node);
hash = (gt_hash_ptr) chain_node;
goto global_trie_hash;
}
do {
if (TrNode_entry(chain_node) == t) {
#ifdef GLOBAL_TRIE_ALLOC_BEFORE_CHECK
FREE_GLOBAL_TRIE_NODE(child_node);
#endif /* GLOBAL_TRIE_ALLOC_BEFORE_CHECK */
UNLOCK_GLOBAL_NODE(parent_node);
return chain_node;
}
count_nodes++;
chain_node = TrNode_next(chain_node);
} while (chain_node != first_node);
#ifdef GLOBAL_TRIE_ALLOC_BEFORE_CHECK
TrNode_next(child_node) = TrNode_child(parent_node);
#else
NEW_GLOBAL_TRIE_NODE(child_node, t, NULL, parent_node, TrNode_child(parent_node));
} else {
NEW_GLOBAL_TRIE_NODE(child_node, t, NULL, parent_node, first_node);
#endif /* GLOBAL_TRIE_ALLOC_BEFORE_CHECK */
}
count_nodes++;
if (count_nodes >= MAX_NODES_PER_TRIE_LEVEL) {
/* alloc a new hash */
gt_node_ptr chain_node, next_node, *bucket;
new_global_trie_hash(hash, count_nodes);
chain_node = child_node;
do {
bucket = Hash_buckets(hash) + HASH_ENTRY(TrNode_entry(chain_node), BASE_HASH_BUCKETS);
next_node = TrNode_next(chain_node);
TrNode_next(chain_node) = *bucket;
*bucket = chain_node;
chain_node = next_node;
} while (chain_node);
TrNode_child(parent_node) = (gt_node_ptr) hash;
} else {
TrNode_child(parent_node) = child_node;
}
UNLOCK_GLOBAL_NODE(parent_node);
return child_node;
}
hash = (gt_hash_ptr) child_node;
global_trie_hash:
{ /* trie nodes with hashing */
gt_node_ptr *bucket, first_node;
int num_buckets, count_nodes = 0;
do {
num_buckets = Hash_num_buckets(hash);
// __sync_synchronize();
bucket = Hash_buckets(hash) + HASH_ENTRY(t, num_buckets);
first_node = child_node = *bucket;
} while (num_buckets != Hash_num_buckets(hash));
while (child_node) {
if (TrNode_entry(child_node) == t)
return child_node;
count_nodes++;
child_node = TrNode_next(child_node);
}
#ifdef GLOBAL_TRIE_ALLOC_BEFORE_CHECK
NEW_GLOBAL_TRIE_NODE(child_node, t, NULL, parent_node, first_node);
#endif /* GLOBAL_TRIE_ALLOC_BEFORE_CHECK */
LOCK_GLOBAL_NODE(parent_node);
if (num_buckets != Hash_num_buckets(hash)) {
/* the hash has been expanded */
#ifdef GLOBAL_TRIE_ALLOC_BEFORE_CHECK
FREE_GLOBAL_TRIE_NODE(child_node);
#endif /* GLOBAL_TRIE_ALLOC_BEFORE_CHECK */
UNLOCK_GLOBAL_NODE(parent_node);
goto global_trie_hash;
}
if (first_node != *bucket) {
gt_node_ptr chain_node = *bucket;
do {
if (TrNode_entry(chain_node) == t) {
#ifdef GLOBAL_TRIE_ALLOC_BEFORE_CHECK
FREE_GLOBAL_TRIE_NODE(child_node);
#endif /* GLOBAL_TRIE_ALLOC_BEFORE_CHECK */
UNLOCK_GLOBAL_NODE(parent_node);
return chain_node;
}
count_nodes++;
chain_node = TrNode_next(chain_node);
} while (chain_node != first_node);
#ifdef GLOBAL_TRIE_ALLOC_BEFORE_CHECK
TrNode_next(child_node) = *bucket;
#else
NEW_GLOBAL_TRIE_NODE(child_node, t, NULL, parent_node, *bucket);
} else {
NEW_GLOBAL_TRIE_NODE(child_node, t, NULL, parent_node, first_node);
#endif /* GLOBAL_TRIE_ALLOC_BEFORE_CHECK */
}
*bucket = child_node;
Hash_num_nodes(hash)++;
count_nodes++;
if (count_nodes >= MAX_NODES_PER_BUCKET && Hash_num_nodes(hash) > Hash_num_buckets(hash)) {
/* expand current hash */
gt_node_ptr chain_node, next_node, *old_bucket, *old_hash_buckets, *new_hash_buckets;
num_buckets = Hash_num_buckets(hash) * 2;
ALLOC_BUCKETS(new_hash_buckets, num_buckets);
old_hash_buckets = Hash_buckets(hash);
old_bucket = old_hash_buckets + Hash_num_buckets(hash);
do {
if (*--old_bucket) {
chain_node = *old_bucket;
do {
bucket = new_hash_buckets + HASH_ENTRY(TrNode_entry(chain_node), num_buckets);
next_node = TrNode_next(chain_node);
TrNode_next(chain_node) = *bucket;
*bucket = chain_node;
chain_node = next_node;
} while (chain_node);
}
} while (old_bucket != old_hash_buckets);
Hash_buckets(hash) = new_hash_buckets;
Hash_num_buckets(hash) = num_buckets;
FREE_BUCKETS(old_hash_buckets);
}
UNLOCK_GLOBAL_NODE(parent_node);
return child_node;
}
}
#endif /* GLOBAL_TRIE_LOCK_LEVEL */
#endif /* INCLUDE_GLOBAL_TRIE_CHECK_INSERT */
/************************************************************************
** subgoal_search(_global_trie)(_terms)_loop **
************************************************************************/
#ifdef INCLUDE_SUBGOAL_SEARCH_LOOP
#ifdef MODE_GLOBAL_TRIE_LOOP
#ifdef GLOBAL_TRIE_FOR_SUBTERMS
static inline gt_node_ptr subgoal_search_global_trie_terms_loop(Term t, int *subs_arity_ptr, CELL **stack_vars_ptr, CELL *stack_terms USES_REGS) {
#else
static inline gt_node_ptr subgoal_search_global_trie_loop(Term t, int *subs_arity_ptr, CELL **stack_vars_ptr USES_REGS) {
#endif /* GLOBAL_TRIE_FOR_SUBTERMS */
#else
#ifdef MODE_TERMS_LOOP
static inline sg_node_ptr subgoal_search_terms_loop(tab_ent_ptr tab_ent, sg_node_ptr current_node, Term t, int *subs_arity_ptr, CELL **stack_vars_ptr USES_REGS) {
#else
static inline sg_node_ptr subgoal_search_loop(tab_ent_ptr tab_ent, sg_node_ptr current_node, Term t, int *subs_arity_ptr, CELL **stack_vars_ptr USES_REGS) {
#endif /* MODE_TERMS_LOOP */
#endif /* MODE_GLOBAL_TRIE_LOOP */
/************************************************************************
===========
| |
| ... |
| |
-----------
| VAR_N | <-- stack_vars
----------- *
| ... | /|\
----------- | subs_arity (N+1)
| VAR_0 | \|/
----------- *
YENV --> | |
-----------
| |
| ... |
| |
===========
| |
| ... |
| |
-----------
TR --> | | <-- stack_terms_limit
-----------
| |
| ... |
| |
----------|
| TERM_N | <-- stack_terms
----------| *
| ... | /|\
----------| |
| TERM_1 | |
----------| |
| NULL | \|/
=========== *
LOCAL_TrailTop --> | |
-----------
************************************************************************/
#ifdef MODE_GLOBAL_TRIE_LOOP
gt_node_ptr current_node = GLOBAL_root_gt;
#endif /* MODE_GLOBAL_TRIE_LOOP */
int subs_arity = *subs_arity_ptr;
CELL *stack_vars = *stack_vars_ptr;
#if ! defined(MODE_GLOBAL_TRIE_LOOP) || ! defined(GLOBAL_TRIE_FOR_SUBTERMS)
CELL *stack_terms = (CELL *) LOCAL_TrailTop;
#endif /* ! MODE_GLOBAL_TRIE_LOOP || ! GLOBAL_TRIE_FOR_SUBTERMS */
CELL *stack_terms_limit = (CELL *) TR;
AUX_STACK_CHECK_EXPAND(stack_terms, stack_terms_limit + 1); /* + 1 because initially we stiil haven't done any STACK_POP_DOWN */
STACK_PUSH_UP(NULL, stack_terms);
#if defined(MODE_GLOBAL_TRIE_LOOP)
/* for the global trie, it is safe to skip the IsVarTerm() and IsAtomOrIntTerm() tests in the first iteration */
goto subgoal_search_loop_non_atomic;
#endif /* MODE_GLOBAL_TRIE_LOOP */
#ifdef TRIE_RATIONAL_TERMS
/* Needed structures, variables to support rational terms */
term_array Ts;
void* CyclicTerm;
term_array_init(&Ts, 10);
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
do {
if (IsVarTerm(t)) {
if (IsTableVarTerm(t)) {
t = MakeTableVarTerm(VarIndexOfTerm(t));
SUBGOAL_CHECK_INSERT_ENTRY(tab_ent, current_node, t);
} else {
if (subs_arity == MAX_TABLE_VARS)
Yap_Error(INTERNAL_ERROR, TermNil, "subgoal_search_loop: MAX_TABLE_VARS exceeded");
STACK_PUSH_UP(t, stack_vars);
*((CELL *)t) = GLOBAL_table_var_enumerator(subs_arity);
t = MakeTableVarTerm(subs_arity);
subs_arity = subs_arity + 1;
SUBGOAL_CHECK_INSERT_ENTRY(tab_ent, current_node, t);
}
} else if (IsAtomOrIntTerm(t)) {
SUBGOAL_CHECK_INSERT_ENTRY(tab_ent, current_node, t);
#ifdef MODE_TERMS_LOOP
} else {
gt_node_ptr entry_node;
#ifdef GLOBAL_TRIE_FOR_SUBTERMS
entry_node = subgoal_search_global_trie_terms_loop(t, &subs_arity, &stack_vars, stack_terms PASS_REGS);
#else
entry_node = subgoal_search_global_trie_loop(t, &subs_arity, &stack_vars PASS_REGS);
#endif /* GLOBAL_TRIE_FOR_SUBTERMS */
current_node = subgoal_trie_check_insert_gt_entry(tab_ent, current_node, (Term) entry_node PASS_REGS);
#else /* ! MODE_TERMS_LOOP */
} else
#ifdef TRIE_RATIONAL_TERMS
if (IsRationalTerm(t)) {
t = STACK_POP_DOWN(stack_terms);
SUBGOAL_CHECK_INSERT_ENTRY(tab_ent, current_node, t);
} else
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
#if defined(MODE_GLOBAL_TRIE_LOOP)
/* for the global trie, it is safe to start here in the first iteration */
subgoal_search_loop_non_atomic:
#endif /* MODE_GLOBAL_TRIE_LOOP */
#ifdef TRIE_COMPACT_PAIRS
if (IsPairTerm(t)) {
#ifdef TRIE_RATIONAL_TERMS
CyclicTerm = NULL;
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
CELL *aux_pair = RepPair(t);
if (aux_pair == PairTermMark) {
t = STACK_POP_DOWN(stack_terms);
#ifdef TRIE_RATIONAL_TERMS
if (IsPairTerm(t) && ! IsRationalTerm(t)) {
term_array_push(&Ts, (void *) t, (void *) current_node);
#else
if (IsPairTerm(t)) {
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
aux_pair = RepPair(t);
t = Deref(aux_pair[1]);
#ifdef TRIE_RATIONAL_TERMS
if (IsVarTerm(aux_pair[1]) || IsPairTerm(aux_pair[1])) {
CyclicTerm = term_array_member(Ts, (void *) t);
}
if (CyclicTerm != NULL) {
STACK_PUSH_UP((Term) CyclicTerm, stack_terms);
STACK_PUSH_UP((Term) RationalMark, stack_terms);
STACK_PUSH_UP(AbsPair(PairTermMark), stack_terms);
} else
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
if (t == TermNil) {
SUBGOAL_CHECK_INSERT_ENTRY(tab_ent, current_node, CompactPairEndList);
} else {
/* AUX_STACK_CHECK_EXPAND(stack_terms, stack_terms_limit + 2); */
/* AUX_STACK_CHECK_EXPAND is not necessary here because the situation of pushing **
** up 3 terms has already initially checked for the CompactPairInit term */
STACK_PUSH_UP(t, stack_terms);
STACK_PUSH_UP(AbsPair(PairTermMark), stack_terms);
}
#ifdef TRIE_RATIONAL_TERMS
CyclicTerm = NULL;
if (IsVarTerm(aux_pair[0]) || IsPairTerm(aux_pair[0]))
CyclicTerm = term_array_member(Ts, (void *) Deref(aux_pair[0]));
if (CyclicTerm != NULL) {
STACK_PUSH_UP((Term) CyclicTerm, stack_terms);
STACK_PUSH_UP((Term) RationalMark, stack_terms);
} else
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
STACK_PUSH_UP(Deref(aux_pair[0]), stack_terms);
} else {
SUBGOAL_CHECK_INSERT_ENTRY(tab_ent, current_node, CompactPairEndTerm);
STACK_PUSH_UP(t, stack_terms);
}
#if defined(MODE_GLOBAL_TRIE_LOOP) && defined(GLOBAL_TRIE_FOR_SUBTERMS)
} else if (current_node != GLOBAL_root_gt) {
gt_node_ptr entry_node = subgoal_search_global_trie_terms_loop(t, &subs_arity, &stack_vars, stack_terms PASS_REGS);
current_node = global_trie_check_insert_gt_entry(current_node, (Term) entry_node PASS_REGS);
#endif /* MODE_GLOBAL_TRIE_LOOP && GLOBAL_TRIE_FOR_SUBTERMS */
} else {
#ifdef TRIE_RATIONAL_TERMS
term_array_push(&Ts, (void *) t, (void *) current_node);
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
SUBGOAL_CHECK_INSERT_ENTRY(tab_ent, current_node, CompactPairInit);
t = Deref(aux_pair[1]);
#ifdef TRIE_RATIONAL_TERMS
if (IsVarTerm(aux_pair[1]) || IsPairTerm(aux_pair[1])) {
CyclicTerm = term_array_member(Ts, (void *) t);
}
if (CyclicTerm != NULL) {
STACK_PUSH_UP((Term) CyclicTerm, stack_terms);
STACK_PUSH_UP((Term) RationalMark, stack_terms);
STACK_PUSH_UP(AbsPair(PairTermMark), stack_terms);
} else
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
if (t == TermNil) {
SUBGOAL_CHECK_INSERT_ENTRY(tab_ent, current_node, CompactPairEndList);
} else {
AUX_STACK_CHECK_EXPAND(stack_terms, stack_terms_limit + 2);
STACK_PUSH_UP(t, stack_terms);
STACK_PUSH_UP(AbsPair(PairTermMark), stack_terms);
}
#ifdef TRIE_RATIONAL_TERMS
CyclicTerm = NULL;
if (IsVarTerm(aux_pair[0]) || IsPairTerm(aux_pair[0]))
CyclicTerm = term_array_member(Ts, (void *) Deref(aux_pair[0]));
if (CyclicTerm != NULL) {
STACK_PUSH_UP((Term) CyclicTerm, stack_terms);
STACK_PUSH_UP((Term) RationalMark, stack_terms);
} else
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
STACK_PUSH_UP(Deref(aux_pair[0]), stack_terms);
}
#if defined(MODE_GLOBAL_TRIE_LOOP) && defined(GLOBAL_TRIE_FOR_SUBTERMS)
} else if (current_node != GLOBAL_root_gt) {
gt_node_ptr entry_node = subgoal_search_global_trie_terms_loop(t, &subs_arity, &stack_vars, stack_terms PASS_REGS);
current_node = global_trie_check_insert_gt_entry(current_node, (Term) entry_node PASS_REGS);
#endif /* MODE_GLOBAL_TRIE_LOOP && GLOBAL_TRIE_FOR_SUBTERMS */
#else /* ! TRIE_COMPACT_PAIRS */
#if defined(MODE_GLOBAL_TRIE_LOOP) && defined(GLOBAL_TRIE_FOR_SUBTERMS)
if (current_node != GLOBAL_root_gt) {
gt_node_ptr entry_node = subgoal_search_global_trie_terms_loop(t, &subs_arity, &stack_vars, stack_terms PASS_REGS);
current_node = global_trie_check_insert_gt_entry(current_node, (Term) entry_node PASS_REGS);
} else
#endif /* MODE_GLOBAL_TRIE_LOOP && GLOBAL_TRIE_FOR_SUBTERMS */
if (IsPairTerm(t)) {
CELL *aux_pair = RepPair(t);
SUBGOAL_CHECK_INSERT_ENTRY(tab_ent, current_node, AbsPair(NULL));
AUX_STACK_CHECK_EXPAND(stack_terms, stack_terms_limit + 1);
STACK_PUSH_UP(Deref(aux_pair[1]), stack_terms);
STACK_PUSH_UP(Deref(aux_pair[0]), stack_terms);
#endif /* TRIE_COMPACT_PAIRS */
} else if (IsApplTerm(t)) {
Functor f = FunctorOfTerm(t);
if (f == FunctorDouble) {
union {
Term t_dbl[sizeof(Float)/sizeof(Term)];
Float dbl;
} u;
u.dbl = FloatOfTerm(t);
SUBGOAL_CHECK_INSERT_ENTRY(tab_ent, current_node, AbsAppl((Term *)f));
#if SIZEOF_DOUBLE == 2 * SIZEOF_INT_P
SUBGOAL_CHECK_INSERT_ENTRY(tab_ent, current_node, u.t_dbl[1]);
#endif /* SIZEOF_DOUBLE x SIZEOF_INT_P */
SUBGOAL_CHECK_INSERT_ENTRY(tab_ent, current_node, u.t_dbl[0]);
#ifdef MODE_GLOBAL_TRIE_LOOP
SUBGOAL_CHECK_INSERT_ENTRY(tab_ent, current_node, AbsAppl((Term *)f));
#endif /* MODE_GLOBAL_TRIE_LOOP */
} else if (f == FunctorLongInt) {
Int li = LongIntOfTerm(t);
SUBGOAL_CHECK_INSERT_ENTRY(tab_ent, current_node, AbsAppl((Term *)f));
SUBGOAL_CHECK_INSERT_ENTRY(tab_ent, current_node, li);
#ifdef MODE_GLOBAL_TRIE_LOOP
SUBGOAL_CHECK_INSERT_ENTRY(tab_ent, current_node, AbsAppl((Term *)f));
#endif /* MODE_GLOBAL_TRIE_LOOP */
} else if (f == FunctorBigInt || f == FunctorString) {
CELL *new = Yap_HeapStoreOpaqueTerm(t);
SUBGOAL_CHECK_INSERT_ENTRY(tab_ent, current_node, AbsAppl((Term *)f));
SUBGOAL_CHECK_INSERT_ENTRY(tab_ent, current_node, (CELL)new);
#ifdef MODE_GLOBAL_TRIE_LOOP
SUBGOAL_CHECK_INSERT_ENTRY(tab_ent, current_node, AbsAppl((Term *)f));
#endif /* MODE_GLOBAL_TRIE_LOOP */
} else if (f == FunctorDBRef) {
Yap_Error(INTERNAL_ERROR, TermNil, "subgoal_search_loop: unsupported type tag FunctorDBRef");
} else {
#ifdef TRIE_RATIONAL_TERMS
term_array_push(&Ts, (void *) t, (void *) current_node);
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
int i;
CELL *aux_appl = RepAppl(t);
SUBGOAL_CHECK_INSERT_ENTRY(tab_ent, current_node, AbsAppl((Term *)f));
AUX_STACK_CHECK_EXPAND(stack_terms, stack_terms_limit + ArityOfFunctor(f) - 1);
for (i = ArityOfFunctor(f); i >= 1; i--) {
#ifdef TRIE_RATIONAL_TERMS
CyclicTerm = NULL;
if (IsVarTerm(aux_appl[i]) || IsApplTerm(aux_appl[i]))
CyclicTerm = term_array_member(Ts, (void *) Deref(aux_appl[i]));
if (CyclicTerm != NULL) {
STACK_PUSH_UP((Term) CyclicTerm, stack_terms);
STACK_PUSH_UP((Term) RationalMark, stack_terms);
} else
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
STACK_PUSH_UP(Deref(aux_appl[i]), stack_terms);
}
}
} else {
Yap_Error(INTERNAL_ERROR, TermNil, "subgoal_search_loop: unknown type tag");
#endif /* MODE_TERMS_LOOP */
}
t = STACK_POP_DOWN(stack_terms);
} while (t);
#ifdef TRIE_RATIONAL_TERMS
term_array_free(&Ts);
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
*subs_arity_ptr = subs_arity;
*stack_vars_ptr = stack_vars;
return current_node;
}
#endif /* INCLUDE_SUBGOAL_SEARCH_LOOP */
/************************************************************************
** answer_search(_global_trie)(_terms)_loop **
************************************************************************/
#ifdef INCLUDE_ANSWER_SEARCH_LOOP
#ifdef MODE_GLOBAL_TRIE_LOOP
#ifdef GLOBAL_TRIE_FOR_SUBTERMS
static inline gt_node_ptr answer_search_global_trie_terms_loop(Term t, int *vars_arity_ptr, CELL *stack_terms USES_REGS) {
#else
static inline gt_node_ptr answer_search_global_trie_loop(Term t, int *vars_arity_ptr USES_REGS) {
#endif /* GLOBAL_TRIE_FOR_SUBTERMS */
#else
#ifdef MODE_TERMS_LOOP
static inline ans_node_ptr answer_search_terms_loop(sg_fr_ptr sg_fr, ans_node_ptr current_node, Term t, int *vars_arity_ptr USES_REGS) {
#else
static inline ans_node_ptr answer_search_loop(sg_fr_ptr sg_fr, ans_node_ptr current_node, Term t, int *vars_arity_ptr USES_REGS) {
#endif /* MODE_TERMS_LOOP */
#endif /* MODE_GLOBAL_TRIE_LOOP */
/************************************************************************
===========
| |
| ... |
| |
-----------
TR --> | VAR_0 | <-- stack_vars_base
----------- *
| ... | /|\
----------- | vars_arity (N+1)
| VAR_N | \|/
----------- *
| | <-- stack_terms_limit
-----------
| |
| ... |
| |
----------|
| TERM_N | <-- stack_terms
----------| *
| ... | /|\
----------| |
| TERM_1 | |
----------| |
| NULL | \|/
=========== *
LOCAL_TrailTop --> | |
-----------
************************************************************************/
#ifdef MODE_GLOBAL_TRIE_LOOP
gt_node_ptr current_node = GLOBAL_root_gt;
#endif /* MODE_GLOBAL_TRIE_LOOP */
int vars_arity = *vars_arity_ptr;
#if ! defined(MODE_GLOBAL_TRIE_LOOP) || ! defined(GLOBAL_TRIE_FOR_SUBTERMS)
CELL *stack_terms = (CELL *) LOCAL_TrailTop;
#endif /* ! MODE_GLOBAL_TRIE_LOOP || ! GLOBAL_TRIE_FOR_SUBTERMS */
CELL *stack_vars_base = (CELL *) TR;
#define stack_terms_limit (stack_vars_base + vars_arity)
#ifdef TRIE_COMPACT_PAIRS
int in_pair = 0;
#else
#define in_pair 0
#endif /* TRIE_COMPACT_PAIRS */
AUX_STACK_CHECK_EXPAND(stack_terms, stack_terms_limit + 1); /* + 1 because initially we stiil haven't done any STACK_POP_DOWN */
STACK_PUSH_UP(NULL, stack_terms);
#if defined(MODE_GLOBAL_TRIE_LOOP)
/* for the global trie, it is safe to skip the IsVarTerm() and IsAtomOrIntTerm() tests in the first iteration */
goto answer_search_loop_non_atomic;
#endif /* MODE_GLOBAL_TRIE_LOOP */
#ifdef TRIE_RATIONAL_TERMS
term_array Ts;
void* CyclicTerm;
term_array_init(&Ts, 10);
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
do {
if (IsVarTerm(t)) {
t = Deref(t);
if (IsTableVarTerm(t)) {
t = MakeTableVarTerm(VarIndexOfTerm(t));
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, t, _trie_retry_val + in_pair);
} else {
if (vars_arity == MAX_TABLE_VARS)
Yap_Error(INTERNAL_ERROR, TermNil, "answer_search_loop: MAX_TABLE_VARS exceeded");
stack_vars_base[vars_arity] = t;
*((CELL *)t) = GLOBAL_table_var_enumerator(vars_arity);
t = MakeTableVarTerm(vars_arity);
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, t, _trie_retry_var + in_pair);
vars_arity = vars_arity + 1;
}
#ifdef TRIE_COMPACT_PAIRS
in_pair = 0;
#endif /* TRIE_COMPACT_PAIRS */
} else if (IsAtomOrIntTerm(t)) {
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, t, _trie_retry_atom + in_pair);
#ifdef TRIE_COMPACT_PAIRS
in_pair = 0;
#endif /* TRIE_COMPACT_PAIRS */
#ifdef MODE_TERMS_LOOP
} else {
gt_node_ptr entry_node;
#ifdef GLOBAL_TRIE_FOR_SUBTERMS
entry_node = answer_search_global_trie_terms_loop(t, &vars_arity, stack_terms PASS_REGS);
#else
entry_node = answer_search_global_trie_loop(t, &vars_arity PASS_REGS);
#endif /* GLOBAL_TRIE_FOR_SUBTERMS */
current_node = answer_trie_check_insert_gt_entry(sg_fr, current_node, (Term) entry_node, _trie_retry_gterm + in_pair PASS_REGS);
#else /* ! MODE_TERMS_LOOP */
} else
#ifdef TRIE_RATIONAL_TERMS
if (IsRationalTerm(t)) {
t = STACK_POP_DOWN(stack_terms);
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, t, _trie_retry_var + in_pair); //TODO create _trie_.._rational
} else
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
#if defined(MODE_GLOBAL_TRIE_LOOP)
/* for the global trie, it is safe to start here in the first iteration */
answer_search_loop_non_atomic:
#endif /* MODE_GLOBAL_TRIE_LOOP */
#ifdef TRIE_COMPACT_PAIRS
if (IsPairTerm(t)) {
#ifdef TRIE_RATIONAL_TERMS
CyclicTerm = NULL;
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
CELL *aux_pair = RepPair(t);
if (aux_pair == PairTermMark) {
t = STACK_POP_DOWN(stack_terms);
#ifdef TRIE_RATIONAL_TERMS
if (IsPairTerm(t) && ! IsRationalTerm(t)) {
term_array_push(&Ts, (void *) t, (void *) current_node);
#else
if (IsPairTerm(t)) {
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
aux_pair = RepPair(t);
t = Deref(aux_pair[1]);
#ifdef TRIE_RATIONAL_TERMS
if (IsVarTerm(aux_pair[1]) || IsPairTerm(aux_pair[1])) {
CyclicTerm = term_array_member(Ts, (void *) t);
}
if (CyclicTerm != NULL) {
STACK_PUSH_UP((Term) CyclicTerm, stack_terms); // CyclicTerm
STACK_PUSH_UP((Term) RationalMark, stack_terms);
STACK_PUSH_UP(AbsPair(PairTermMark), stack_terms);
in_pair = 4;
} else
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
if (t == TermNil) {
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, CompactPairEndList, _trie_retry_pair);
} else {
/* AUX_STACK_CHECK_EXPAND(stack_terms, stack_terms_limit + 2); */
/* AUX_STACK_CHECK_EXPAND is not necessary here because the situation of pushing **
** up 3 terms has already initially checked for the CompactPairInit term */
STACK_PUSH_UP(t, stack_terms);
STACK_PUSH_UP(AbsPair(PairTermMark), stack_terms);
in_pair = 4;
}
#ifdef TRIE_RATIONAL_TERMS
CyclicTerm = NULL;
if (IsVarTerm(aux_pair[0]) || IsPairTerm(aux_pair[0]))
CyclicTerm = term_array_member(Ts, (void *) Deref(aux_pair[0]));
if (CyclicTerm != NULL) {
STACK_PUSH_UP((Term) CyclicTerm, stack_terms);
STACK_PUSH_UP((Term) RationalMark, stack_terms);
} else
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
STACK_PUSH_UP(Deref(aux_pair[0]), stack_terms);
} else {
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, CompactPairEndTerm, _trie_retry_null);
STACK_PUSH_UP(t, stack_terms);
}
#if defined(MODE_GLOBAL_TRIE_LOOP) && defined(GLOBAL_TRIE_FOR_SUBTERMS)
} else if (current_node != GLOBAL_root_gt) {
gt_node_ptr entry_node = answer_search_global_trie_terms_loop(t, &vars_arity, stack_terms PASS_REGS);
current_node = global_trie_check_insert_gt_entry(current_node, (Term) entry_node PASS_REGS);
#endif /* MODE_GLOBAL_TRIE_LOOP && GLOBAL_TRIE_FOR_SUBTERMS */
} else {
#ifdef TRIE_RATIONAL_TERMS
term_array_push(&Ts, (void *) t, (void *) current_node);
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, CompactPairInit, _trie_retry_null + in_pair);
t = Deref(aux_pair[1]);
#ifdef TRIE_RATIONAL_TERMS
if (IsVarTerm(aux_pair[1]) || IsPairTerm(aux_pair[1])) {
CyclicTerm = term_array_member(Ts, (void *) t);
}
if (CyclicTerm != NULL) {
STACK_PUSH_UP((Term) CyclicTerm, stack_terms);
STACK_PUSH_UP((Term) RationalMark, stack_terms);
STACK_PUSH_UP(AbsPair(PairTermMark), stack_terms);
in_pair = 4;
} else
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
if (t == TermNil) {
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, CompactPairEndList, _trie_retry_pair);
in_pair = 0;
} else {
AUX_STACK_CHECK_EXPAND(stack_terms, stack_terms_limit + 2);
STACK_PUSH_UP(t, stack_terms);
STACK_PUSH_UP(AbsPair(PairTermMark), stack_terms);
in_pair = 4;
}
#ifdef TRIE_RATIONAL_TERMS
CyclicTerm = NULL;
if (IsVarTerm(aux_pair[0]) || IsPairTerm(aux_pair[0]))
CyclicTerm = term_array_member(Ts, (void *) Deref(aux_pair[0]));
if (CyclicTerm != NULL) {
STACK_PUSH_UP((Term) CyclicTerm, stack_terms);
STACK_PUSH_UP((Term) RationalMark, stack_terms);
} else
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
STACK_PUSH_UP(Deref(aux_pair[0]), stack_terms);
}
#if defined(MODE_GLOBAL_TRIE_LOOP) && defined(GLOBAL_TRIE_FOR_SUBTERMS)
} else if (current_node != GLOBAL_root_gt) {
gt_node_ptr entry_node = answer_search_global_trie_terms_loop(t, &vars_arity, stack_terms PASS_REGS);
current_node = global_trie_check_insert_gt_entry(current_node, (Term) entry_node PASS_REGS);
#endif /* MODE_GLOBAL_TRIE_LOOP && GLOBAL_TRIE_FOR_SUBTERMS */
#else /* ! TRIE_COMPACT_PAIRS */
#if defined(MODE_GLOBAL_TRIE_LOOP) && defined(GLOBAL_TRIE_FOR_SUBTERMS)
if (current_node != GLOBAL_root_gt) {
gt_node_ptr entry_node = answer_search_global_trie_terms_loop(t, &vars_arity, stack_terms PASS_REGS);
current_node = global_trie_check_insert_gt_entry(current_node, (Term) entry_node PASS_REGS);
} else
#endif /* MODE_GLOBAL_TRIE_LOOP && GLOBAL_TRIE_FOR_SUBTERMS */
if (IsPairTerm(t)) {
CELL *aux_pair = RepPair(t);
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, AbsPair(NULL), _trie_retry_pair);
AUX_STACK_CHECK_EXPAND(stack_terms, stack_terms_limit + 1);
STACK_PUSH_UP(Deref(aux_pair[1]), stack_terms);
STACK_PUSH_UP(Deref(aux_pair[0]), stack_terms);
#endif /* TRIE_COMPACT_PAIRS */
} else if (IsApplTerm(t)) {
Functor f = FunctorOfTerm(t);
if (f == FunctorDouble) {
union {
Term t_dbl[sizeof(Float)/sizeof(Term)];
Float dbl;
} u;
u.dbl = FloatOfTerm(t);
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, AbsAppl((Term *)f), _trie_retry_null + in_pair);
#if SIZEOF_DOUBLE == 2 * SIZEOF_INT_P
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, u.t_dbl[1], _trie_retry_extension);
#endif /* SIZEOF_DOUBLE x SIZEOF_INT_P */
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, u.t_dbl[0], _trie_retry_extension);
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, AbsAppl((Term *)f), _trie_retry_double);
} else if (f == FunctorLongInt) {
Int li = LongIntOfTerm (t);
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, AbsAppl((Term *)f), _trie_retry_null + in_pair);
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, li, _trie_retry_extension);
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, AbsAppl((Term *)f), _trie_retry_longint);
} else if (f == FunctorBigInt || FunctorString) {
CELL *opq = Yap_HeapStoreOpaqueTerm(t);
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, AbsAppl((Term *)f), _trie_retry_null + in_pair);
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, (CELL)opq, _trie_retry_extension);
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, AbsAppl((Term *)f), _trie_retry_bigint);
} else if (f == FunctorDBRef) {
Yap_Error(INTERNAL_ERROR, TermNil, "answer_search_loop: unsupported type tag FunctorDBRef");
} else {
#ifdef TRIE_RATIONAL_TERMS
term_array_push(&Ts, (void *) t, (void *) current_node);
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
int i;
CELL *aux_appl = RepAppl(t);
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, AbsAppl((Term *)f), _trie_retry_appl + in_pair);
AUX_STACK_CHECK_EXPAND(stack_terms, stack_terms_limit + ArityOfFunctor(f) - 1);
for (i = ArityOfFunctor(f); i >= 1; i--) {
#ifdef TRIE_RATIONAL_TERMS
CyclicTerm = NULL;
if (IsVarTerm(aux_appl[i]) || IsApplTerm(aux_appl[i]))
CyclicTerm = term_array_member(Ts, (void *) Deref(aux_appl[i]));
if (CyclicTerm != NULL) {
STACK_PUSH_UP((Term) CyclicTerm, stack_terms);
STACK_PUSH_UP((Term) RationalMark, stack_terms);
} else
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
STACK_PUSH_UP(Deref(aux_appl[i]), stack_terms);
}
}
#ifdef TRIE_COMPACT_PAIRS
in_pair = 0;
#endif /* TRIE_COMPACT_PAIRS */
} else {
Yap_Error(INTERNAL_ERROR, TermNil, "answer_search_loop: unknown type tag");
#endif /* MODE_TERMS_LOOP */
}
t = STACK_POP_DOWN(stack_terms);
} while (t);
#ifdef TRIE_RATIONAL_TERMS
term_array_free(&Ts);
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
*vars_arity_ptr = vars_arity;
return current_node;
#undef stack_terms_limit
#ifndef TRIE_COMPACT_PAIRS
#undef in_pair
#endif /* TRIE_COMPACT_PAIRS */
}
#endif /* INCLUDE_ANSWER_SEARCH_LOOP */
/**************************************************************
** answer_search_min_max **
**************************************************************/
#ifdef INCLUDE_ANSWER_SEARCH_MODE_DIRECTED
static inline ans_node_ptr answer_search_min_max(sg_fr_ptr sg_fr, ans_node_ptr current_node, Term t, int mode USES_REGS) {
ans_node_ptr child_node;
Term child_term;
Term trie_value = 0, term_value = t;
int cmp;
/* start by computing the current value on the trie (trie_value) */
child_node = TrNode_child(current_node);
child_term = TrNode_entry(child_node);
if (IsIntTerm(child_term)) {
trie_value = child_term;
} else if (IsApplTerm(child_term)) {
Functor f = (Functor) RepAppl(child_term);
child_node = TrNode_child(child_node);
if (f == FunctorLongInt) {
trie_value = MkLongIntTerm( (Int) TrNode_entry(child_node) );
} else if (f == FunctorDouble) {
union {
Term t_dbl[sizeof(Float)/sizeof(Term)];
Float dbl;
} u;
u.t_dbl[0] = TrNode_entry(child_node);
#if SIZEOF_DOUBLE == 2 * SIZEOF_INT_P
child_node = TrNode_child(child_node);
u.t_dbl[1] = TrNode_entry(child_node);
#endif /* SIZEOF_DOUBLE x SIZEOF_INT_P */
trie_value = MkFloatTerm(u.dbl);
} else if (f == FunctorBigInt) {
trie_value = AbsAppl( (CELL *) TrNode_entry(child_node) );
} else
Yap_Error(INTERNAL_ERROR, TermNil, "answer_search_min_max: invalid arithmetic value");
child_node = TrNode_child(child_node);
}
cmp = Yap_acmp( term_value, trie_value PASS_REGS);
/* worse answer */
if ((mode == MODE_DIRECTED_MIN && cmp > 0) || (mode == MODE_DIRECTED_MAX && cmp < 0))
return NULL;
/* equal answer */
if (cmp == 0)
return child_node;
/* better answer */
if (IsAtomOrIntTerm(t)) {
ANSWER_SAFE_INSERT_ENTRY(current_node, t, _trie_retry_atom);
} else if (IsApplTerm(t)) {
Functor f = FunctorOfTerm(t);
if (f == FunctorDouble) {
union {
Term t_dbl[sizeof(Float)/sizeof(Term)];
Float dbl;
} u;
u.dbl = FloatOfTerm(t);
ANSWER_SAFE_INSERT_ENTRY(current_node, AbsAppl((Term *)f), _trie_retry_null);
#if SIZEOF_DOUBLE == 2 * SIZEOF_INT_P
ANSWER_SAFE_INSERT_ENTRY(current_node, u.t_dbl[1], _trie_retry_extension);
#endif /* SIZEOF_DOUBLE x SIZEOF_INT_P */
ANSWER_SAFE_INSERT_ENTRY(current_node, u.t_dbl[0], _trie_retry_extension);
ANSWER_SAFE_INSERT_ENTRY(current_node, AbsAppl((Term *)f), _trie_retry_double);
} else if (f == FunctorLongInt) {
Int li = LongIntOfTerm(t);
ANSWER_SAFE_INSERT_ENTRY(current_node, AbsAppl((Term *)f), _trie_retry_null);
ANSWER_SAFE_INSERT_ENTRY(current_node, li, _trie_retry_extension);
ANSWER_SAFE_INSERT_ENTRY(current_node, AbsAppl((Term *)f), _trie_retry_longint);
} else if (f == FunctorBigInt) {
CELL *li = Yap_HeapStoreOpaqueTerm(t);
ANSWER_SAFE_INSERT_ENTRY(current_node, AbsAppl((Term *)f), _trie_retry_null);
ANSWER_SAFE_INSERT_ENTRY(current_node, (CELL)li, _trie_retry_extension);
ANSWER_SAFE_INSERT_ENTRY(current_node, AbsAppl((Term *)f), _trie_retry_bigint);
}
}
return current_node;
}
#endif /* INCLUDE_ANSWER_SEARCH_MODE_DIRECTED */
/**********************************************************
** answer_search_sum **
**********************************************************/
#ifdef INCLUDE_ANSWER_SEARCH_MODE_DIRECTED
static inline ans_node_ptr answer_search_sum(sg_fr_ptr sg_fr, ans_node_ptr current_node, Term t USES_REGS) {
ans_node_ptr child_node;
Term child_term;
Term trie_value = 0, term_value = t, sum_value = 0;
/* start by computing the current value on the trie (trie_value) */
child_node = TrNode_child(current_node);
child_term = TrNode_entry(child_node);
if (IsIntTerm(child_term)) {
trie_value = child_term;
} else if (IsApplTerm(child_term)) {
Functor f = (Functor) RepAppl(child_term);
child_node = TrNode_child(child_node);
if (f == FunctorLongInt) {
trie_value = MkLongIntTerm( (Int) TrNode_entry(child_node) );
} else if (f == FunctorDouble) {
union {
Term t_dbl[sizeof(Float)/sizeof(Term)];
Float dbl;
} u;
u.t_dbl[0] = TrNode_entry(child_node);
#if SIZEOF_DOUBLE == 2 * SIZEOF_INT_P
child_node = TrNode_child(child_node);
u.t_dbl[1] = TrNode_entry(child_node);
#endif /* SIZEOF_DOUBLE x SIZEOF_INT_P */
trie_value = MkFloatTerm(u.dbl);
} else if (f == FunctorBigInt) {
trie_value = AbsAppl( (CELL *) TrNode_entry(child_node) );
} else
Yap_Error(INTERNAL_ERROR, TermNil, "answer_search_min_max: invalid arithmetic value");
child_node = TrNode_child(child_node);
}
sum_value = p_plus(trie_value, term_value PASS_REGS);
if (IsAtomOrIntTerm(sum_value)) {
ANSWER_SAFE_INSERT_ENTRY(current_node, sum_value, _trie_retry_atom);
} else if (IsApplTerm(sum_value)) {
Functor f = FunctorOfTerm(sum_value);
if (f == FunctorDouble) {
union {
Term t_dbl[sizeof(Float)/sizeof(Term)];
Float dbl;
} u;
u.dbl = FloatOfTerm(sum_value);
ANSWER_SAFE_INSERT_ENTRY(current_node, AbsAppl((Term *)f), _trie_retry_null);
#if SIZEOF_DOUBLE == 2 * SIZEOF_INT_P
ANSWER_SAFE_INSERT_ENTRY(current_node, u.t_dbl[1], _trie_retry_extension);
#endif /* SIZEOF_DOUBLE x SIZEOF_INT_P */
ANSWER_SAFE_INSERT_ENTRY(current_node, u.t_dbl[0], _trie_retry_extension);
ANSWER_SAFE_INSERT_ENTRY(current_node, AbsAppl((Term *)f), _trie_retry_double);
} else if (f == FunctorLongInt) {
Int li = LongIntOfTerm(sum_value);
ANSWER_SAFE_INSERT_ENTRY(current_node, AbsAppl((Term *)f), _trie_retry_null);
ANSWER_SAFE_INSERT_ENTRY(current_node, li, _trie_retry_extension);
ANSWER_SAFE_INSERT_ENTRY(current_node, AbsAppl((Term *)f), _trie_retry_longint);
} else if (f == FunctorBigInt) {
CELL *li = Yap_HeapStoreOpaqueTerm(sum_value);
ANSWER_SAFE_INSERT_ENTRY(current_node, AbsAppl((Term *)f), _trie_retry_null);
ANSWER_SAFE_INSERT_ENTRY(current_node, (CELL)li, _trie_retry_extension);
ANSWER_SAFE_INSERT_ENTRY(current_node, AbsAppl((Term *)f), _trie_retry_bigint);
}
}
return current_node;
}
#endif /* INCLUDE_ANSWER_SEARCH_MODE_DIRECTED */
/***************************************************************
** invalidate_answer_trie **
***************************************************************/
#ifdef INCLUDE_ANSWER_SEARCH_MODE_DIRECTED
static void invalidate_answer_trie(ans_node_ptr current_node, sg_fr_ptr sg_fr, int position USES_REGS) {
if (IS_ANSWER_TRIE_HASH(current_node)) {
ans_hash_ptr hash;
ans_node_ptr *bucket, *last_bucket;
hash = (ans_hash_ptr) current_node;
bucket = Hash_buckets(hash);
last_bucket = bucket + Hash_num_buckets(hash);
do {
current_node = *bucket;
if (current_node) {
ans_node_ptr next_node = TrNode_next(current_node);
if (IS_ANSWER_LEAF_NODE(current_node)) {
INVALIDATE_ANSWER_TRIE_LEAF_NODE(current_node, sg_fr);
} else {
invalidate_answer_trie(TrNode_child(current_node), sg_fr, TRAVERSE_POSITION_FIRST PASS_REGS);
INVALIDATE_ANSWER_TRIE_NODE(current_node, sg_fr);
}
while (next_node) {
current_node = next_node;
next_node = TrNode_next(current_node);
invalidate_answer_trie(current_node, sg_fr, TRAVERSE_POSITION_NEXT PASS_REGS);
}
}
} while (++bucket != last_bucket);
if (Hash_next(hash))
Hash_previous(Hash_next(hash)) = Hash_previous(hash);
if (Hash_previous(hash))
Hash_next(Hash_previous(hash)) = Hash_next(hash);
else
SgFr_hash_chain(sg_fr) = Hash_next(hash);
FREE_BUCKETS(Hash_buckets(hash));
FREE_ANSWER_TRIE_HASH(hash);
} else {
if (position == TRAVERSE_POSITION_FIRST) {
ans_node_ptr next_node = TrNode_next(current_node);
if (IS_ANSWER_LEAF_NODE(current_node)) {
INVALIDATE_ANSWER_TRIE_LEAF_NODE(current_node, sg_fr);
} else {
invalidate_answer_trie(TrNode_child(current_node), sg_fr, TRAVERSE_POSITION_FIRST PASS_REGS);
INVALIDATE_ANSWER_TRIE_NODE(current_node, sg_fr);
}
while (next_node) {
current_node = next_node;
next_node = TrNode_next(current_node);
invalidate_answer_trie(current_node, sg_fr, TRAVERSE_POSITION_NEXT PASS_REGS);
}
} else {
if (IS_ANSWER_LEAF_NODE(current_node)) {
INVALIDATE_ANSWER_TRIE_LEAF_NODE(current_node, sg_fr);
} else {
invalidate_answer_trie(TrNode_child(current_node), sg_fr, TRAVERSE_POSITION_FIRST PASS_REGS);
INVALIDATE_ANSWER_TRIE_NODE(current_node, sg_fr);
}
}
}
return;
}
#endif /* INCLUDE_ANSWER_SEARCH_MODE_DIRECTED */
/************************************************************************
** load_(answer|substitution)_loop **
************************************************************************/
#ifdef INCLUDE_LOAD_ANSWER_LOOP
#ifdef MODE_GLOBAL_TRIE_LOOP
static inline CELL *load_substitution_loop(gt_node_ptr current_node, int *vars_arity_ptr, CELL *stack_terms USES_REGS) {
#else
static inline CELL *load_answer_loop(ans_node_ptr current_node USES_REGS) {
#endif /* MODE_GLOBAL_TRIE_LOOP */
/************************************************************************
===========
| |
| ... |
| |
-----------
TR --> | VAR_0 | <-- stack_vars_base
----------- *
| ... | /|\
----------- | vars_arity (N+1)
| VAR_N | \|/
----------- *
| | <-- stack_terms_limit
-----------
| |
| ... |
| |
----------|
| TERM_N | <-- stack_terms
----------| *
| ... | /|\
----------| | stack_terms_pair_offset (TRIE_COMPACT_PAIRS)
| TERM_1 | \|/
=========== *
LOCAL_TrailTop --> | | <-- stack_terms_base (TRIE_COMPACT_PAIRS)
-----------
************************************************************************/
#ifdef MODE_GLOBAL_TRIE_LOOP
int vars_arity = *vars_arity_ptr;
#else
int vars_arity = 0;
CELL *stack_terms = (CELL *) LOCAL_TrailTop;
#endif /* MODE_GLOBAL_TRIE_LOOP */
CELL *stack_vars_base = (CELL *) TR;
#define stack_terms_limit (stack_vars_base + vars_arity)
#ifdef TRIE_COMPACT_PAIRS
#define stack_terms_base ((CELL *) LOCAL_TrailTop)
int stack_terms_pair_offset = 0;
#endif /* TRIE_COMPACT_PAIRS */
Term t = TrNode_entry(current_node);
#ifdef MODE_GLOBAL_TRIE_LOOP
current_node = TrNode_parent(current_node);
#else
current_node = (ans_node_ptr) UNTAG_ANSWER_NODE(TrNode_parent(current_node));
#endif /* MODE_GLOBAL_TRIE_LOOP */
#ifdef TRIE_RATIONAL_TERMS
term_array Ts;
void* CyclicTerm;
term_array_init(&Ts, 10);
Term RationalTermTMP; // a temporary temp to be used from the rational code
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
do {
#ifdef TRIE_RATIONAL_TERMS
CyclicTerm = term_array_member(Ts, (void *) current_node);
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
if (IsVarTerm(t)) {
#ifdef TRIE_RATIONAL_TERMS
if (t > VarIndexOfTableTerm(MAX_TABLE_VARS) && TrNode_child((gt_node_ptr) t) != (gt_node_ptr)(1)) { //TODO: substitute the != 1 test to something more appropriate
/* Rational term */
RationalTermTMP = (Term) term_array_member(Ts, (void *) t);
if (RationalTermTMP) {
/* rational term is assigned a variable already */
AUX_STACK_CHECK_EXPAND(stack_terms, stack_terms_limit);
STACK_PUSH_UP(RationalTermTMP, stack_terms);
} else {
RationalTermTMP = MkVarTerm();
STACK_PUSH_UP(RationalTermTMP, stack_terms);
/* memorize the rational term and assign it a variable */
term_array_push(&Ts, (void *) t, (void *) RationalTermTMP);
}
} else
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
{
#if ! defined(MODE_GLOBAL_TRIE_LOOP) || defined(GLOBAL_TRIE_FOR_SUBTERMS)
if (t > VarIndexOfTableTerm(MAX_TABLE_VARS)) {
stack_terms = load_substitution_loop((gt_node_ptr) t, &vars_arity, stack_terms PASS_REGS);
} else
#endif /* ! MODE_GLOBAL_TRIE_LOOP || GLOBAL_TRIE_FOR_SUBTERMS */
{ int var_index = VarIndexOfTableTerm(t);
AUX_STACK_CHECK_EXPAND(stack_terms, stack_terms_limit - vars_arity + var_index + 1);
if (var_index >= vars_arity) {
while (vars_arity < var_index)
stack_vars_base[vars_arity++] = 0;
stack_vars_base[vars_arity++] = MkVarTerm();
} else if (stack_vars_base[var_index] == 0)
stack_vars_base[var_index] = MkVarTerm();
STACK_PUSH_UP(stack_vars_base[var_index], stack_terms);
}
}
} else if (IsAtomOrIntTerm(t)) {
AUX_STACK_CHECK_EXPAND(stack_terms, stack_terms_limit);
#ifdef TRIE_RATIONAL_TERMS
if (CyclicTerm) {
AUX_STACK_CHECK_EXPAND(stack_terms, stack_terms_limit + 4);
STACK_PUSH_UP((Term) RationalMark, stack_terms); // Add a rational term marker necessary as we read both ways the stack //
STACK_PUSH_UP(t, stack_terms); // Add the term //
STACK_PUSH_UP(CyclicTerm, stack_terms); // Add the variable that the term will unify with //
STACK_PUSH_UP((Term) RationalMark, stack_terms); // Add a rational term marker necessary as we read both ways the stack //
} else
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
STACK_PUSH_UP(t, stack_terms);
} else if (IsPairTerm(t)) {
#ifdef TRIE_COMPACT_PAIRS
if (t == CompactPairInit) {
Term *stack_aux = stack_terms_base - stack_terms_pair_offset;
Term head, tail = STACK_POP_UP(stack_aux);
#ifdef TRIE_RATIONAL_TERMS
if (IsRationalTerm(tail)) {
Yap_Error(INTERNAL_ERROR, tail, "Rational element of a Rational Term appears as the first Tail of a list");
}
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
while (STACK_NOT_EMPTY(stack_aux, stack_terms)) {
head = STACK_POP_UP(stack_aux);
#ifdef TRIE_RATIONAL_TERMS
if (IsRationalTerm(head)) {
head = STACK_POP_UP(stack_aux); // thats the rational term
RationalTermTMP = STACK_POP_UP(stack_aux); // that is the variable to unify with
(void) STACK_POP_UP(stack_aux); // eat the second rational mark
tail = MkPairTerm(head, tail);
Yap_unify(RationalTermTMP, tail);
} else
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
tail = MkPairTerm(head, tail);
}
stack_terms = stack_terms_base - stack_terms_pair_offset;
stack_terms_pair_offset = (int) STACK_POP_DOWN(stack_terms);
STACK_PUSH_UP(tail, stack_terms);
} else { /* CompactPairEndList / CompactPairEndTerm */
Term last;
AUX_STACK_CHECK_EXPAND(stack_terms, stack_terms_limit + 1);
last = STACK_POP_DOWN(stack_terms);
#ifdef TRIE_RATIONAL_TERMS
RationalTermTMP = TermNil;
if (IsRationalTerm(last)) { // rather unlikely case the rational term is the last of a list
RationalTermTMP = STACK_POP_DOWN(stack_terms); // in this case we need to invert the term with the end of list
last = STACK_POP_DOWN(stack_terms); // variable to unify with
(void) STACK_POP_DOWN(stack_terms); // eat the second rational mark
}
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
STACK_PUSH_UP(stack_terms_pair_offset, stack_terms);
stack_terms_pair_offset = (int) (stack_terms_base - stack_terms);
if (t == CompactPairEndList)
STACK_PUSH_UP(TermNil, stack_terms);
#ifdef TRIE_RATIONAL_TERMS
if (RationalTermTMP && RationalTermTMP != TermNil) {
/* most probably this never occurs */
STACK_PUSH_UP((Term) RationalMark, stack_terms);
STACK_PUSH_UP(last, stack_terms);
STACK_PUSH_UP(RationalTermTMP, stack_terms);
STACK_PUSH_UP((Term) RationalMark, stack_terms);
} else
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
STACK_PUSH_UP(last, stack_terms);
}
#else /* ! TRIE_COMPACT_PAIRS */
Term head = STACK_POP_DOWN(stack_terms);
Term tail = STACK_POP_DOWN(stack_terms);
t = MkPairTerm(head, tail);
STACK_PUSH_UP(t, stack_terms);
#endif /* TRIE_COMPACT_PAIRS */
} else if (IsApplTerm(t)) {
Functor f = (Functor) RepAppl(t);
if (f == FunctorDouble) {
union {
Term t_dbl[sizeof(Float)/sizeof(Term)];
Float dbl;
} u;
t = TrNode_entry(current_node);
current_node = TrNode_parent(current_node);
u.t_dbl[0] = t;
#if SIZEOF_DOUBLE == 2 * SIZEOF_INT_P
t = TrNode_entry(current_node);
current_node = TrNode_parent(current_node);
u.t_dbl[1] = t;
#endif /* SIZEOF_DOUBLE x SIZEOF_INT_P */
current_node = TrNode_parent(current_node);
t = MkFloatTerm(u.dbl);
} else if (f == FunctorLongInt) {
Int li = TrNode_entry(current_node);
current_node = TrNode_parent(current_node);
current_node = TrNode_parent(current_node);
t = MkLongIntTerm(li);
} else if (f == FunctorBigInt || f == FunctorString) {
CELL *ptr = (CELL *)TrNode_entry(current_node);
current_node = TrNode_parent(current_node);
current_node = TrNode_parent(current_node);
t = AbsAppl( ptr );
} else {
int f_arity = ArityOfFunctor(f);
t = Yap_MkApplTerm(f, f_arity, stack_terms);
stack_terms += f_arity;
}
AUX_STACK_CHECK_EXPAND(stack_terms, stack_terms_limit);
STACK_PUSH_UP(t, stack_terms);
}
#ifdef TRIE_RATIONAL_TERMS
if (CyclicTerm) {
RationalTermTMP = STACK_POP_DOWN(stack_terms);
if IsRationalTerm(RationalTermTMP) {
//printf("Special Case\n");
} else if (IsPairTerm(RationalTermTMP)) {
Yap_unify((Term) CyclicTerm, RationalTermTMP);
} else if (IsApplTerm(RationalTermTMP)) {
Yap_unify((Term) CyclicTerm, RationalTermTMP);
}
STACK_PUSH_UP(RationalTermTMP, stack_terms);
}
RationalTermTMP = TermNil;
CyclicTerm = NULL;
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
t = TrNode_entry(current_node);
current_node = TrNode_parent(current_node);
} while (current_node);
#ifdef TRIE_RATIONAL_TERMS
term_array_free(&Ts);
#endif /* RATIONAL TERM SUPPORT FOR TRIES */
#ifdef MODE_GLOBAL_TRIE_LOOP
*vars_arity_ptr = vars_arity;
#endif /* MODE_GLOBAL_TRIE_LOOP */
return stack_terms;
#undef stack_terms_limit
#ifdef TRIE_COMPACT_PAIRS
#undef stack_terms_base
#endif /* TRIE_COMPACT_PAIRS */
}
#endif /* INCLUDE_LOAD_ANSWER_LOOP */
/***************************
** Undef Macros **
***************************/
#undef INCREMENT_GLOBAL_TRIE_REFERENCE
#undef NEW_SUBGOAL_TRIE_NODE
#undef NEW_ANSWER_TRIE_NODE
#undef NEW_GLOBAL_TRIE_NODE
#undef SUBGOAL_CHECK_INSERT_ENTRY
#undef ANSWER_CHECK_INSERT_ENTRY