diff --git a/library/tries.yap b/library/tries.yap old mode 100644 new mode 100755 index 096cbfa4a..569b69ce1 --- a/library/tries.yap +++ b/library/tries.yap @@ -37,7 +37,18 @@ put_trie_entry/4, get_trie_entry/3, remove_trie_entry/1, - print_trie/1 + print_trie/1, + trie_traverse_mode/1, + trie_disable_hash/0, + trie_enable_hash/0, + trie_traverse_first/2, + trie_traverse_next/2, + trie_to_list/2, + trie_to_depth_breadth_trie/4, + trie_to_depth_breadth_trie/6, + trie_get_depth_breadth_reduction_entry/1, + trie_get_depth_breadth_reduction_opt_level_count/2, + trie_replace_nested_trie/3 ]). :- load_foreign_files([tries], [], init_tries). @@ -51,3 +62,13 @@ trie_dup(Trie, CopyTrie) :- trie_traverse(Trie, Ref) :- trie_traverse(Trie, 0, Ref). + +trie_to_depth_breadth_trie(Trie, DepthBreadthTrie, FinalLabel, OptimizationLevel) :- + integer(OptimizationLevel), + trie_dup(Trie, CopyTrie), + trie_open(DepthBreadthTrie), + trie_depth_breadth(CopyTrie, DepthBreadthTrie, FinalLabel, OptimizationLevel, 0, _), + trie_close(CopyTrie). + +trie_to_depth_breadth_trie(Trie, DepthBreadthTrie, FinalLabel, OptimizationLevel, StartCounter, EndCounter) :- + trie_depth_breadth(Trie, DepthBreadthTrie, FinalLabel, OptimizationLevel, StartCounter, EndCounter). diff --git a/library/tries/Makefile.in b/library/tries/Makefile.in index 59db2e2e5..b8ddc06e2 100644 --- a/library/tries/Makefile.in +++ b/library/tries/Makefile.in @@ -44,13 +44,13 @@ SOBJS=tries.@SO@ itries.@SO@ all: $(SOBJS) -core_tries.o: $(srcdir)/core_tries.h $(srcdir)/core_tries.c +core_tries.o: $(srcdir)/core_tries.h $(srcdir)/core_tries.c $(srcdir)/core_dbtries.h $(srcdir)/core_dbtries.c $(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/core_tries.c -o core_tries.o -base_tries.o: $(srcdir)/core_tries.h $(srcdir)/base_tries.h $(srcdir)/base_tries.c +base_tries.o: $(srcdir)/core_tries.h $(srcdir)/base_tries.h $(srcdir)/base_tries.c $(srcdir)/core_dbtries.h $(srcdir)/base_dbtries.h $(srcdir)/base_dbtries.c $(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/base_tries.c -o base_tries.o -tries.o: $(srcdir)/core_tries.h $(srcdir)/base_tries.h $(srcdir)/tries.c +tries.o: $(srcdir)/core_tries.h $(srcdir)/base_tries.h $(srcdir)/tries.c $(srcdir)/core_dbtries.h $(srcdir)/base_dbtries.h $(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/tries.c -o tries.o base_itries.o: $(srcdir)/core_tries.h $(srcdir)/base_itries.h $(srcdir)/base_itries.c diff --git a/library/tries/base_tries.c b/library/tries/base_tries.c index 36c90e12b..75d14483b 100644 --- a/library/tries/base_tries.c +++ b/library/tries/base_tries.c @@ -18,6 +18,12 @@ #include "base_tries.h" +/* -------------------------- */ +/* Local Procedures */ +/* -------------------------- */ + +static TrData get_data_from_trie_node(TrNode node); + /* -------------------------- */ /* Local Variables */ @@ -26,6 +32,7 @@ static TrEngine TRIE_ENGINE; static TrEntry FIRST_TRIE, CURRENT_TRIE; +static YAP_Int CURRENT_TRAVERSE_MODE; /* -------------------------- */ @@ -36,6 +43,7 @@ inline void trie_init_module(void) { TRIE_ENGINE = core_trie_init_module(); FIRST_TRIE = NULL; + CURRENT_TRAVERSE_MODE = TRAVERSE_MODE_FORWARD; return; } @@ -192,7 +200,10 @@ TrData trie_traverse_init(TrEntry trie, TrData init_data) { if (init_data) { data = TrData_next(init_data); } else { - data = TrEntry_first_data(trie); + if (CURRENT_TRAVERSE_MODE == TRAVERSE_MODE_FORWARD) + data = TrEntry_first_data(trie); + else + data = TrEntry_last_data(trie); } TrEntry_traverse_data(trie) = data; return data; @@ -205,7 +216,13 @@ TrData trie_traverse_cont(TrEntry trie) { data = TrEntry_traverse_data(trie); if (data) { - data = TrData_next(data); + if (CURRENT_TRAVERSE_MODE == TRAVERSE_MODE_FORWARD) + data = TrData_next(data); + else { + data = TrData_previous(data); + if (data == TrData_previous(TrEntry_first_data(trie))) + data = NULL; + } TrEntry_traverse_data(trie) = data; } return data; @@ -305,3 +322,87 @@ void trie_print(TrEntry trie) { core_trie_print(TrEntry_trie(trie), NULL); return; } + + +inline +void trie_data_construct(TrNode node) { + TrData data; + + new_trie_data(data, CURRENT_TRIE, node); + PUT_DATA_IN_LEAF_TRIE_NODE(node, data); + return; +} + + +inline +void trie_set_traverse_mode(YAP_Int mode) { + CURRENT_TRAVERSE_MODE = mode; + return; +} + + +inline +YAP_Int trie_get_traverse_mode(void) { + return CURRENT_TRAVERSE_MODE; +} + + +inline +TrData trie_traverse_first(TrEntry trie) { + TrData data; + if (CURRENT_TRAVERSE_MODE == TRAVERSE_MODE_FORWARD) + data = TrEntry_first_data(trie); + else + data = TrEntry_last_data(trie); + return data; +} + + +inline +TrData trie_traverse_next(TrData cur) { + TrData data = NULL; + if (cur) { + if (CURRENT_TRAVERSE_MODE == TRAVERSE_MODE_FORWARD) + data = TrData_next(cur); + else { + data = TrData_previous(cur); + if (data == TrData_previous(TrEntry_first_data(TrData_trie(cur)))) + data = NULL; + } + } + return data; +} + + +inline +void trie_disable_hash_table(void) { + core_disable_hash_table(); + return; +} + + +inline +void trie_enable_hash_table(void) { + core_enable_hash_table(); + return; +} + + +/* -------------------------- */ +/* Local Procedures */ +/* -------------------------- */ + +static +TrData get_data_from_trie_node(TrNode node) { + while(!IS_LEAF_TRIE_NODE(node)) + node = TrNode_child(node); + return (TrData) GET_DATA_FROM_LEAF_TRIE_NODE(node); +} + + +inline +YAP_Term trie_to_list(TrEntry trie) { + return core_trie_to_list(TrEntry_trie(trie)); +} + +#include "base_dbtries.c" diff --git a/library/tries/base_tries.h b/library/tries/base_tries.h index e8c7a8788..55429313c 100644 --- a/library/tries/base_tries.h +++ b/library/tries/base_tries.h @@ -7,6 +7,14 @@ +/* --------------------------- */ +/* Defines */ +/* --------------------------- */ + +#define TRAVERSE_MODE_FORWARD 0 +#define TRAVERSE_MODE_BACKWARD 1 + + /* --------------------------- */ /* Structs */ /* --------------------------- */ @@ -126,3 +134,15 @@ inline void trie_stats(YAP_Int *memory, YAP_Int *tries, YAP_Int *entries, YA inline void trie_max_stats(YAP_Int *memory, YAP_Int *tries, YAP_Int *entries, YAP_Int *nodes); inline void trie_usage(TrEntry trie, YAP_Int *entries, YAP_Int *nodes, YAP_Int *virtual_nodes); inline void trie_print(TrEntry trie); + +inline void trie_data_construct(TrNode node); +inline void trie_set_traverse_mode(YAP_Int mode); +inline YAP_Int trie_get_traverse_mode(void); +inline TrData trie_traverse_first(TrEntry trie); +inline TrData trie_traverse_next(TrData data); +inline void trie_disable_hash_table(void); +inline void trie_enable_hash_table(void); + +inline YAP_Term trie_to_list(TrEntry trie); + +#include "base_dbtries.h" diff --git a/library/tries/core_tries.c b/library/tries/core_tries.c index 7655ed088..59248403b 100644 --- a/library/tries/core_tries.c +++ b/library/tries/core_tries.c @@ -39,6 +39,9 @@ static void traverse_and_save(TrNode node, FILE *file, int float_block); static void traverse_and_load(TrNode parent, FILE *file); static void traverse_and_print(TrNode node, int *arity, char *str, int str_index, int mode); +static YAP_Term trie_to_list(TrNode node); +static YAP_Term trie_to_list_node(TrNode node); +static YAP_Term trie_to_list_floats(TrNode node); /* -------------------------- */ @@ -58,6 +61,7 @@ static void (*DATA_ADD_FUNCTION)(TrNode, TrNode); static void (*DATA_COPY_FUNCTION)(TrNode, TrNode); static void (*DATA_DESTRUCT_FUNCTION)(TrNode); +static YAP_Int TRIE_DISABLE_HASH_TABLE = 0; /* -------------------------- */ @@ -82,7 +86,7 @@ TrNode trie_node_check_insert(TrNode parent, YAP_Term t) { child = *bucket; count = 0; while (child) { - if (TrNode_entry(child) == t) + if ((TrNode_entry(child) == t) || (((TrNode_entry(child) == PairEndTermTag) || (TrNode_entry(child) == PairEndEmptyTag)) && ((CURRENT_TRIE_MODE & TRIE_MODE_MINIMAL) == TRIE_MODE_MINIMAL))) return child; count++; child = TrNode_next(child); @@ -108,9 +112,9 @@ TrNode trie_node_check_insert(TrNode parent, YAP_Term t) { new_bucket = TrHash_bucket(hash, HASH_TERM(TrNode_entry(chain), seed)); next = TrNode_next(chain); TrNode_next(chain) = *new_bucket; - TrNode_previous(chain) = AS_TR_NODE_NEXT(bucket); - if (*new_bucket) - TrNode_previous(*new_bucket) = chain; + TrNode_previous(chain) = AS_TR_NODE_NEXT(bucket); + if (*new_bucket) + TrNode_previous(*new_bucket) = chain; *new_bucket = chain; chain = next; } while (chain); @@ -121,14 +125,14 @@ TrNode trie_node_check_insert(TrNode parent, YAP_Term t) { } else { int count = 0; do { - if (TrNode_entry(child) == t) + if ((TrNode_entry(child) == t) || (((TrNode_entry(child) == PairEndTermTag) || (TrNode_entry(child) == PairEndEmptyTag)) && ((CURRENT_TRIE_MODE & TRIE_MODE_MINIMAL) == TRIE_MODE_MINIMAL))) return child; count++; child = TrNode_next(child); } while (child); new_trie_node(child, t, parent, NULL, TrNode_child(parent), NULL); TrNode_previous(TrNode_child(parent)) = child; - if (++count > MAX_NODES_PER_TRIE_LEVEL) { + if ((++count > MAX_NODES_PER_TRIE_LEVEL) && (TRIE_DISABLE_HASH_TABLE == 0)) { /* alloc a new trie hash */ TrHash hash; TrNode chain, next, *bucket; @@ -139,8 +143,8 @@ TrNode trie_node_check_insert(TrNode parent, YAP_Term t) { next = TrNode_next(chain); TrNode_next(chain) = *bucket; TrNode_previous(chain) = AS_TR_NODE_NEXT(bucket); - if (*bucket) - TrNode_previous(*bucket) = chain; + if (*bucket) + TrNode_previous(*bucket) = chain; *bucket = chain; chain = next; } while (chain); @@ -199,6 +203,45 @@ TrNode trie_node_check(TrNode parent, YAP_Term t) { } +static inline +YAP_Term trie_to_list_create_simple(const char *atom_name, TrNode node) { + YAP_Functor f = YAP_MkFunctor(YAP_LookupAtom(atom_name), 1); + YAP_Term child = trie_to_list(TrNode_child(node)); + + return YAP_MkApplTerm(f, 1, &child); +} + + +static inline +YAP_Term trie_to_list_create_simple_end(const char *atom_name, TrNode node) { + YAP_Atom atom = YAP_LookupAtom(atom_name); + + if (IS_LEAF_TRIE_NODE(node)) { + return YAP_MkAtomTerm(atom); + } else { + YAP_Functor f = YAP_MkFunctor(atom, 1); + YAP_Term child = trie_to_list(TrNode_child(node)); + return YAP_MkApplTerm(f, 1, &child); + } +} + + +static inline +YAP_Term trie_to_list_create_two(const char *atom_name, TrNode node, YAP_Term operand) { + YAP_Atom atom = YAP_LookupAtom(atom_name); + + if(IS_LEAF_TRIE_NODE(node)) { + YAP_Functor f = YAP_MkFunctor(atom, 1); + return YAP_MkApplTerm(f, 1, &operand); + } else { + YAP_Functor f = YAP_MkFunctor(atom, 2); + YAP_Term args[2] = { + operand, trie_to_list(TrNode_child(node)) + }; + return YAP_MkApplTerm(f, 2, args); + } +} + /* -------------------------- */ /* API */ @@ -523,6 +566,27 @@ void core_trie_print(TrNode node, void (*print_function)(TrNode)) { } +inline +void core_disable_hash_table(void) { + TRIE_DISABLE_HASH_TABLE = 1; +} + + +inline +void core_enable_hash_table(void) { + TRIE_DISABLE_HASH_TABLE = 0; +} + + +inline +YAP_Term core_trie_to_list(TrNode node) { + TrNode root = TrNode_child(node); + + if (root) + return trie_to_list(root); + else + return YAP_MkAtomTerm(YAP_LookupAtom("empty")); +} /* -------------------------- */ @@ -558,32 +622,32 @@ TrNode put_entry(TrNode node, YAP_Term entry) { node = trie_node_check_insert(node, FloatEndTag); } else if (YAP_IsPairTerm(t)) { node = trie_node_check_insert(node, PairInitTag); - if (CURRENT_TRIE_MODE == TRIE_MODE_STANDARD) { + if ((CURRENT_TRIE_MODE & TRIE_MODE_REVERSE) == TRIE_MODE_STANDARD) { do { - node = put_entry(node, YAP_HeadOfTerm(t)); - t = YAP_Deref(YAP_TailOfTerm(t)); + node = put_entry(node, YAP_HeadOfTerm(t)); + t = YAP_Deref(YAP_TailOfTerm(t)); } while (YAP_IsPairTerm(t)); if (t == YAP_TermNil()) { - node = trie_node_check_insert(node, PairEndEmptyTag); + node = trie_node_check_insert(node, PairEndEmptyTag); } else { - node = put_entry(node, t); - node = trie_node_check_insert(node, PairEndTermTag); + node = put_entry(node, t); + node = trie_node_check_insert(node, PairEndTermTag); } - } else { /* TRIE_MODE_REVERSE */ + } else if (CURRENT_TRIE_MODE & TRIE_MODE_REVERSE) { /* TRIE_MODE_REVERSE */ YAP_Term *stack_list = stack_args; do { - PUSH_DOWN(stack_args, YAP_HeadOfTerm(t), stack_vars); - t = YAP_Deref(YAP_TailOfTerm(t)); + PUSH_DOWN(stack_args, YAP_HeadOfTerm(t), stack_vars); + t = YAP_Deref(YAP_TailOfTerm(t)); } while (YAP_IsPairTerm(t)); if (t == YAP_TermNil()) { - while (STACK_NOT_EMPTY(stack_args, stack_list)) - node = put_entry(node, POP_UP(stack_args)); - node = trie_node_check_insert(node, PairEndEmptyTag); + while (STACK_NOT_EMPTY(stack_args, stack_list)) + node = put_entry(node, POP_UP(stack_args)); + node = trie_node_check_insert(node, PairEndEmptyTag); } else { - PUSH_DOWN(stack_args, t, stack_vars); - while (STACK_NOT_EMPTY(stack_args, stack_list)) - node = put_entry(node, POP_UP(stack_args)); - node = trie_node_check_insert(node, PairEndTermTag); + PUSH_DOWN(stack_args, t, stack_vars); + while (STACK_NOT_EMPTY(stack_args, stack_list)) + node = put_entry(node, POP_UP(stack_args)); + node = trie_node_check_insert(node, PairEndTermTag); } } } else if (YAP_IsApplTerm(t)) { @@ -591,8 +655,8 @@ TrNode put_entry(TrNode node, YAP_Term entry) { if (f == FunctorComma) { node = trie_node_check_insert(node, CommaInitTag); do { - node = put_entry(node, YAP_ArgOfTerm(1, t)); - t = YAP_Deref(YAP_ArgOfTerm(2, t)); + node = put_entry(node, YAP_ArgOfTerm(1, t)); + t = YAP_Deref(YAP_ArgOfTerm(2, t)); } while (YAP_IsApplTerm(t) && YAP_FunctorOfTerm(t) == FunctorComma); node = put_entry(node, t); node = trie_node_check_insert(node, CommaEndTag); @@ -600,7 +664,7 @@ TrNode put_entry(TrNode node, YAP_Term entry) { int i; node = trie_node_check_insert(node, ApplTag | ((YAP_Term) f)); for (i = 1; i <= YAP_ArityOfFunctor(f); i++) - node = put_entry(node, YAP_ArgOfTerm(i, t)); + node = put_entry(node, YAP_ArgOfTerm(i, t)); } } else { fprintf(stderr, "***************************************\n"); @@ -618,10 +682,10 @@ TrNode check_entry(TrNode node, YAP_Term entry) { if (YAP_IsVarTerm(t)) { if (IsTrieVar(t, stack_vars, stack_vars_base)) { if (!(node = trie_node_check(node, MkTrieVar((stack_vars_base - 1 - (YAP_Term *)t) / 2)))) - return NULL; + return NULL; } else { if (!(node = trie_node_check(node, MkTrieVar((stack_vars_base - stack_vars) / 2)))) - return NULL; + return NULL; PUSH_UP(stack_vars, t, stack_args); *((YAP_Term *)t) = (YAP_Term)stack_vars; PUSH_UP(stack_vars, stack_vars, stack_args); @@ -650,63 +714,63 @@ TrNode check_entry(TrNode node, YAP_Term entry) { } else if (YAP_IsPairTerm(t)) { if (!(node = trie_node_check(node, PairInitTag))) return NULL; - if (CURRENT_TRIE_MODE == TRIE_MODE_STANDARD) { + if ((CURRENT_TRIE_MODE & TRIE_MODE_REVERSE) == TRIE_MODE_STANDARD) { do { - if (!(node = check_entry(node, YAP_HeadOfTerm(t)))) - return NULL; - t = YAP_Deref(YAP_TailOfTerm(t)); + if (!(node = check_entry(node, YAP_HeadOfTerm(t)))) + return NULL; + t = YAP_Deref(YAP_TailOfTerm(t)); } while (YAP_IsPairTerm(t)); if (t == YAP_TermNil()) { - if (!(node = trie_node_check(node, PairEndEmptyTag))) - return NULL; + if (!(node = trie_node_check(node, PairEndEmptyTag))) + return NULL; } else { - if (!(node = check_entry(node, t))) - return NULL; - if (!(node = trie_node_check(node, PairEndTermTag))) - return NULL; + if (!(node = check_entry(node, t))) + return NULL; + if (!(node = trie_node_check(node, PairEndTermTag))) + return NULL; } - } else { /* TRIE_MODE_REVERSE */ + } else if (CURRENT_TRIE_MODE & TRIE_MODE_REVERSE) { /* TRIE_MODE_REVERSE */ YAP_Term *stack_list = stack_args; do { - PUSH_DOWN(stack_args, YAP_HeadOfTerm(t), stack_vars); - t = YAP_Deref(YAP_TailOfTerm(t)); + PUSH_DOWN(stack_args, YAP_HeadOfTerm(t), stack_vars); + t = YAP_Deref(YAP_TailOfTerm(t)); } while (YAP_IsPairTerm(t)); if (t == YAP_TermNil()) { - while (STACK_NOT_EMPTY(stack_args, stack_list)) - if (!(node = check_entry(node, POP_UP(stack_args)))) - return NULL; - if (!(node = trie_node_check(node, PairEndEmptyTag))) - return NULL; + while (STACK_NOT_EMPTY(stack_args, stack_list)) + if (!(node = check_entry(node, POP_UP(stack_args)))) + return NULL; + if (!(node = trie_node_check(node, PairEndEmptyTag))) + return NULL; } else { - PUSH_DOWN(stack_args, t, stack_vars); - while (STACK_NOT_EMPTY(stack_args, stack_list)) - if (!(node = check_entry(node, POP_UP(stack_args)))) - return NULL; - if (!(node = trie_node_check(node, PairEndTermTag))) - return NULL; + PUSH_DOWN(stack_args, t, stack_vars); + while (STACK_NOT_EMPTY(stack_args, stack_list)) + if (!(node = check_entry(node, POP_UP(stack_args)))) + return NULL; + if (!(node = trie_node_check(node, PairEndTermTag))) + return NULL; } } } else if (YAP_IsApplTerm(t)) { YAP_Functor f = YAP_FunctorOfTerm(t); if (f == FunctorComma) { if (!(node = trie_node_check(node, CommaInitTag))) - return NULL; + return NULL; do { - if (!(node = check_entry(node, YAP_ArgOfTerm(1, t)))) - return NULL; - t = YAP_Deref(YAP_ArgOfTerm(2, t)); + if (!(node = check_entry(node, YAP_ArgOfTerm(1, t)))) + return NULL; + t = YAP_Deref(YAP_ArgOfTerm(2, t)); } while (YAP_IsApplTerm(t) && YAP_FunctorOfTerm(t) == FunctorComma); if (!(node = check_entry(node, t))) - return NULL; + return NULL; if (!(node = trie_node_check(node, CommaEndTag))) - return NULL; + return NULL; } else { int i; if (!(node = trie_node_check(node, ApplTag | ((YAP_Term) f)))) - return NULL; + return NULL; for (i = 1; i <= YAP_ArityOfFunctor(f); i++) - if (!(node = check_entry(node, YAP_ArgOfTerm(i, t)))) - return NULL; + if (!(node = check_entry(node, YAP_ArgOfTerm(i, t)))) + return NULL; } } else { fprintf(stderr, "***************************************\n"); @@ -729,10 +793,10 @@ YAP_Term get_entry(TrNode node, YAP_Term *stack_mark, TrNode *cur_node) { int i; stack_vars = &stack_vars_base[index + 1]; if (stack_vars > stack_args + 1) { - fprintf(stderr, "**************************************\n"); - fprintf(stderr, " Tries core module: term stack full\n"); - fprintf(stderr, "**************************************\n"); - } + fprintf(stderr, "**************************************\n"); + fprintf(stderr, " Tries core module: term stack full\n"); + fprintf(stderr, "**************************************\n"); + } for (i = index; i > CURRENT_INDEX; i--) stack_vars_base[i] = 0; CURRENT_INDEX = index; @@ -751,37 +815,37 @@ YAP_Term get_entry(TrNode node, YAP_Term *stack_mark, TrNode *cur_node) { } else if (YAP_IsPairTerm(t)) { if (t == PairInitTag) { YAP_Term t2; - if (CURRENT_TRIE_MODE == TRIE_MODE_STANDARD) { + if ((CURRENT_TRIE_MODE & TRIE_MODE_REVERSE) == TRIE_MODE_STANDARD) { YAP_Term *stack_aux = stack_mark; t = *stack_aux--; while (STACK_NOT_EMPTY(stack_aux, stack_args)) { t2 = *stack_aux--; t = YAP_MkPairTerm(t2, t); } - } else { /* TRIE_MODE_REVERSE */ + } else if (CURRENT_TRIE_MODE & TRIE_MODE_REVERSE) { /* TRIE_MODE_REVERSE */ YAP_Term *stack_aux = stack_mark; t = *stack_aux; - if (t == YAP_TermNil()) - stack_aux--; - else - t = POP_DOWN(stack_args); + if (t == YAP_TermNil()) + stack_aux--; + else + t = POP_DOWN(stack_args); while (STACK_NOT_EMPTY(stack_args, stack_aux)) { t2 = POP_DOWN(stack_args); t = YAP_MkPairTerm(t2, t); } } - stack_args = stack_mark; + stack_args = stack_mark; *cur_node = node; return t; } else if (t == PairEndEmptyTag) { - t = YAP_TermNil(); - PUSH_UP(stack_args, t, stack_vars); - node = TrNode_parent(node); - t = get_entry(node, &stack_args[1], &node); + t = YAP_TermNil(); + PUSH_UP(stack_args, t, stack_vars); + node = TrNode_parent(node); + t = get_entry(node, &stack_args[1], &node); PUSH_UP(stack_args, t, stack_vars); } else if (t == PairEndTermTag) { - node = TrNode_parent(node); - t = get_entry(node, stack_args, &node); + node = TrNode_parent(node); + t = get_entry(node, stack_args, &node); PUSH_UP(stack_args, t, stack_vars); } else if (t == CommaEndTag) { node = TrNode_parent(node); @@ -1555,3 +1619,163 @@ void traverse_and_print(TrNode node, int *arity, char *str, int str_index, int m } return; } + + +static +YAP_Term trie_to_list(TrNode node) { + YAP_Term tail = YAP_MkAtomTerm(YAP_LookupAtom("[]")); + +#define CONSUME_NODE_LIST \ + do { \ + /* add node result to list */ \ + tail = YAP_MkPairTerm(trie_to_list_node(node), tail); \ + } while((node = TrNode_next(node))); + + if (IS_HASH_NODE(node)) { + TrNode *first_bucket, *bucket; + TrHash hash = (TrHash) node; + + first_bucket = TrHash_buckets(hash); + bucket = first_bucket + TrHash_num_buckets(hash); + + /* iterate through valid hash positions and consume each list */ + do { + if (*--bucket) { + node = *bucket; + CONSUME_NODE_LIST; + } + } while (bucket != first_bucket); + } else { + CONSUME_NODE_LIST; + } +#undef CONSUME_NODE_LIST + + /* return list of trie options at this level */ + return tail; +} + + +static +YAP_Term trie_to_list_node(TrNode node) { + YAP_Term t = TrNode_entry(node); + + if(YAP_IsIntTerm(t) || YAP_IsAtomTerm(t)) { + return trie_to_list_create_two(YAP_IsIntTerm(t) ? "int" : "atom", node, t); + } else if (YAP_IsVarTerm(t)) { + int index = TrieVarIndex(t); + YAP_Term index_term = YAP_MkIntTerm((YAP_Int)index); + return trie_to_list_create_two("var", node, index_term); + } else if (YAP_IsPairTerm(t)) { + if(t == FloatInitTag) { + node = TrNode_child(node); /* consume FloatInitTag */ + YAP_Functor f = YAP_MkFunctor(YAP_LookupAtom("floats"), 1); + YAP_Term child = trie_to_list_floats(node); + return YAP_MkApplTerm(f, 1, &child); + } else if(t == PairInitTag) { + return trie_to_list_create_simple("list", node); + } else if (t == PairEndEmptyTag) { + return trie_to_list_create_simple_end("endlist", node); + } else if (t == CommaInitTag) { + return trie_to_list_create_simple("comma", node); + } else if (t == CommaEndTag) { + return trie_to_list_create_simple_end("endcomma", node); + } + } else if (ApplTag & t) { + YAP_Functor f = (YAP_Functor)(~ApplTag & t); + int arity = YAP_ArityOfFunctor(f); + YAP_Functor new_f = YAP_MkFunctor(YAP_LookupAtom("functor"), 3); + YAP_Term args[3] = { + YAP_MkAtomTerm(YAP_NameOfFunctor(f)), + YAP_MkIntTerm((YAP_Int)arity), + trie_to_list(TrNode_child(node)) + }; + return YAP_MkApplTerm(new_f, 3, args); + } + fprintf(stderr, "***************************************\n"); + fprintf(stderr, " Tries core module: unknown type tag\n"); + fprintf(stderr, "***************************************\n"); + + return YAP_MkAtomTerm(YAP_LookupAtom("fail")); +} + + +#define PUSH_NEW_FLOAT_TERM(val) \ + result = YAP_MkPairTerm( \ + trie_to_list_create_two("float", TrNode_child(node), YAP_MkFloatTerm(val)), \ + result); + + +#ifdef TAG_LOW_BITS_32 +static inline +YAP_Term trie_to_list_floats_tag_low_32(YAP_Term result, TrNode node, volatile YAP_Term **p, volatile double *f) { + if(IS_HASH_NODE(node)) { + TrNode *first_bucket, *bucket; + TrHash hash = (TrHash) node; + + first_bucket = TrHash_buckets(hash); + bucket = first_bucket + TrHash_num_buckets(hash); + + do { + if(*--bucket) { + node = *bucket; + + do { + *(*p + 1) = TrNode_entry(node); + PUSH_NEW_FLOAT_TERM(*f); + } while((node = TrNode_next(node))); + } + } while (bucket != first_bucket); + } else { + do { + *(*p + 1) = TrNode_entry(node); + PUSH_NEW_FLOAT_TERM(*f); + } while((node = TrNode_next(node))); + } + + return result; +} +#endif /* TAG_LOW_BITS_32 */ + + +static +YAP_Term trie_to_list_floats(TrNode node) { + volatile double f; + volatile YAP_Term *p; + YAP_Term result = YAP_MkAtomTerm(YAP_LookupAtom("[]")); + + p = (YAP_Term *)((void *) &f); /* to avoid gcc warning */ + if (IS_HASH_NODE(node)) { + TrNode *first_bucket, *bucket; + TrHash hash = (TrHash) node; + first_bucket = TrHash_buckets(hash); + bucket = first_bucket + TrHash_num_buckets(hash); + do { + if (*--bucket) { + node = *bucket; + do { + *p = TrNode_entry(node); +#ifdef TAG_LOW_BITS_32 + result = trie_to_list_floats_tag_low_32(result, TrNode_child(node), &p, &f); +#else + PUSH_NEW_FLOAT_TERM(f); +#endif /* TAG_LOW_BITS_32 */ + } while((node = TrNode_next(node))); + } + } while (bucket != first_bucket); + } else { + do { + *p = TrNode_entry(node); +#ifdef TAG_LOW_BITS_32 + result = trie_to_list_floats_tag_low_32(result, TrNode_child(node), &p, &f); +#else + PUSH_NEW_FLOAT_TERM(f); +#endif /* TAG_LOW_BITS_32 */ + } while((node = TrNode_next(node))); + } + + return result; +} +#undef PUSH_NEW_FLOAT_TERM + + +#include "core_dbtries.c" diff --git a/library/tries/core_tries.h b/library/tries/core_tries.h index ff5130f4f..f627911be 100644 --- a/library/tries/core_tries.h +++ b/library/tries/core_tries.h @@ -41,6 +41,8 @@ #define TRIE_MODE_STANDARD 0 #define TRIE_MODE_REVERSE 1 +#define TRIE_MODE_MINIMAL 2 +#define TRIE_MODE_REVMIN TRIE_MODE_REVERSE || TRIE_MODE_MINIMAL //3 #define TRIE_PRINT_NORMAL 0 #define TRIE_PRINT_FLOAT 1 @@ -273,6 +275,11 @@ typedef struct trie_hash { TrEngine_nodes(TR_ENGINE)-- +#define IS_FUNCTOR_NODE(N) (((ApplTag & TrNode_entry(N)) == ApplTag) && \ + (TrNode_entry(N) != PairInitTag) && \ + (TrNode_entry(N) != PairEndEmptyTag) && \ + (TrNode_entry(N) != PairEndTermTag)) + /* --------------------------- */ /* API */ @@ -300,3 +307,10 @@ inline void core_trie_stats(TrEngine engine, YAP_Int *memory, YAP_Int *tries inline void core_trie_max_stats(TrEngine engine, YAP_Int *memory, YAP_Int *tries, YAP_Int *entries, YAP_Int *nodes); inline void core_trie_usage(TrNode node, YAP_Int *entries, YAP_Int *nodes, YAP_Int *virtual_nodes); inline void core_trie_print(TrNode node, void (*print_function)(TrNode)); + +inline void core_disable_hash_table(void); +inline void core_enable_hash_table(void); + +inline YAP_Term core_trie_to_list(TrNode node); + +#include "core_dbtries.h" diff --git a/library/tries/tries.c b/library/tries/tries.c index 9e58fc1fb..712f1efb0 100644 --- a/library/tries/tries.c +++ b/library/tries/tries.c @@ -18,6 +18,14 @@ #include "base_tries.h" +/* -------------------------- */ +/* Structures */ +/* -------------------------- */ + +typedef struct { + YAP_Term value; +} db_trie_opt_level; + /* -------------------------- */ /* Procedures */ @@ -47,6 +55,23 @@ static int p_trie_stats(void); static int p_trie_max_stats(void); static int p_trie_usage(void); static int p_trie_print(void); + +static int p_trie_traverse_mode(void); +static int p_trie_disable_hash(void); +static int p_trie_enable_hash(void); +static int p_trie_traverse_first(void); +static int p_trie_traverse_next(void); + +static int p_trie_to_list(void); + +/* dbtries support */ +static int p_trie_depth_breadth(void); +static int p_trie_get_depth_breadth_reduction_current_data(void); +static int p_trie_get_db_opt_level_count_init(void); +static int p_trie_get_db_opt_level_count_cont(void); +static int p_trie_replace_nested_trie(void); +static int p_trie_db_opt_min_prefix(void); + /* backwards compatibility */ static int p_open_trie(void); static int p_close_trie(void); @@ -87,6 +112,22 @@ void init_tries(void) { YAP_UserCPredicate("trie_stats", p_trie_stats, 4); YAP_UserCPredicate("trie_max_stats", p_trie_max_stats, 4); YAP_UserCPredicate("trie_print", p_trie_print, 1); + + YAP_UserCPredicate("trie_traverse_mode", p_trie_traverse_mode, 1); + YAP_UserCPredicate("trie_disable_hash", p_trie_disable_hash, 0); + YAP_UserCPredicate("trie_enable_hash", p_trie_enable_hash, 0); + YAP_UserCPredicate("trie_traverse_first", p_trie_traverse_first, 2); + YAP_UserCPredicate("trie_traverse_next", p_trie_traverse_next, 2); + + YAP_UserCPredicate("trie_to_list", p_trie_to_list, 2); + + /* dbtries support */ + YAP_UserCPredicate("trie_depth_breadth", p_trie_depth_breadth, 6); + YAP_UserCPredicate("trie_get_depth_breadth_reduction_entry", p_trie_get_depth_breadth_reduction_current_data, 1); + YAP_UserBackCPredicate("trie_get_depth_breadth_reduction_opt_level_count", p_trie_get_db_opt_level_count_init, p_trie_get_db_opt_level_count_cont, 2, sizeof(db_trie_opt_level)); + YAP_UserCPredicate("trie_replace_nested_trie", p_trie_replace_nested_trie, 3); + YAP_UserCPredicate("trie_db_opt_min_prefix", p_trie_db_opt_min_prefix, 1); + /* backwards compatibility */ YAP_UserCPredicate("open_trie", p_open_trie, 1); YAP_UserCPredicate("close_trie", p_close_trie, 1); @@ -674,3 +715,243 @@ static int p_trie_print(void) { return TRUE; } #undef arg_trie + + +/* trie_traverse_mode(?Mode) */ +#define arg_mode YAP_ARG1 +static int p_trie_traverse_mode(void) { + YAP_Term mode_term; + const char *mode_str; + YAP_Int mode; + + /* get mode */ + if (YAP_IsVarTerm(arg_mode)) { + mode = trie_get_traverse_mode(); + if (mode == TRAVERSE_MODE_FORWARD) + mode_term = YAP_MkAtomTerm(YAP_LookupAtom("forward")); + else if (mode == TRAVERSE_MODE_BACKWARD) + mode_term = YAP_MkAtomTerm(YAP_LookupAtom("backward")); + else + return FALSE; + return YAP_Unify(arg_mode, mode_term); + } + + /* set mode */ + mode_str = YAP_AtomName(YAP_AtomOfTerm(arg_mode)); + if (!strcmp(mode_str, "forward")) + mode = TRAVERSE_MODE_FORWARD; + else if (!strcmp(mode_str, "backward")) + mode = TRAVERSE_MODE_BACKWARD; + else + return FALSE; + trie_set_traverse_mode(mode); + return TRUE; +} +#undef arg_mode + + +/* trie_traverse_first(+Trie, -Ref) */ +#define arg_trie YAP_ARG1 +#define arg_ref YAP_ARG2 +static int p_trie_traverse_first(void) { + TrData data; + + /* check arg */ + if (!YAP_IsIntTerm(arg_trie)) + return FALSE; + + /* traverse trie */ + if (!(data = trie_traverse_first((TrEntry) YAP_IntOfTerm(arg_trie)))) { + return FALSE; + } + return YAP_Unify(arg_ref, YAP_MkIntTerm((YAP_Int) data)); +} +#undef arg_trie +#undef arg_ref + + +/* trie_traverse_next(+Ref, -Ref) */ +#define arg_cur YAP_ARG1 +#define arg_next YAP_ARG2 +static int p_trie_traverse_next(void) { + TrData data; + + /* check arg */ + if (!YAP_IsIntTerm(arg_cur)) + return FALSE; + + /* traverse trie */ + if (!(data = trie_traverse_next((TrData) YAP_IntOfTerm(arg_cur)))) { + return FALSE; + } + return YAP_Unify(arg_next, YAP_MkIntTerm((YAP_Int) data)); +} +#undef arg_cur +#undef arg_next + + +/* trie_disable_hash */ +static int p_trie_disable_hash(void) { + trie_disable_hash_table(); + return TRUE; +} + + +/* trie_enable_hash */ +static int p_trie_enable_hash(void) { + trie_enable_hash_table(); + return TRUE; +} + + +/* trie_to_list(+Trie, -List) */ +#define arg_trie YAP_ARG1 +#define arg_list YAP_ARG2 +static int p_trie_to_list(void) { + YAP_Term list; + + /* check arg */ + if (!YAP_IsIntTerm(arg_trie)) + return FALSE; + + /* get list from trie */ + list = trie_to_list((TrEntry) YAP_IntOfTerm(arg_trie)); + return YAP_Unify(arg_list, list); +} +#undef arg_trie +#undef arg_list + + +/* trie_depth_breadth(+Trie, -DepthBreadthTrie, -FinalLabel, +OptimizationLevel, +StartCounter, -EndCounter) */ +#define arg_trie YAP_ARG1 +#define arg_db_trie YAP_ARG2 +#define arg_final_label YAP_ARG3 +#define arg_opt_level YAP_ARG4 +#define arg_start_counter YAP_ARG5 +#define arg_end_counter YAP_ARG6 +static int p_trie_depth_breadth(void) { + /* get depth breadth trie */ + if (!YAP_IsIntTerm(arg_opt_level)) + return FALSE; + if (!YAP_IsIntTerm(arg_start_counter)) + return FALSE; + YAP_Int End; + YAP_Term t = trie_depth_breadth((TrEntry) YAP_IntOfTerm(arg_trie), (TrEntry) YAP_IntOfTerm(arg_db_trie), YAP_IntOfTerm(arg_opt_level), YAP_IntOfTerm(arg_start_counter), &End); + int a = YAP_Unify(t, arg_final_label); + a = a && YAP_Unify(YAP_MkIntTerm(End), arg_end_counter); + return a; +} +#undef arg_trie +#undef arg_db_trie +#undef arg_final_label +#undef arg_opt_level +#undef arg_start_counter +#undef arg_end_counter + + +/* trie_get_depth_breadth_reduction_entry(-Entry) */ +#define arg_entry YAP_ARG1 +static int p_trie_get_depth_breadth_reduction_current_data(void) { + TrData data = trie_get_depth_breadth_reduction_current_data(); + if (data) + return YAP_Unify(arg_entry, YAP_MkIntTerm((YAP_Int) data)); + return FALSE; +} +#undef arg_entry + + +db_trie_opt_level *opt_level; + +/* trie_get_depth_breadth_reduction_opt_level_count(?OptLevel, -Count) */ +#define arg_opt_level YAP_ARG1 +#define arg_count YAP_ARG2 +static int p_trie_get_db_opt_level_count_init(void) { + if (YAP_IsIntTerm(arg_opt_level)) { + if (YAP_IntOfTerm(arg_opt_level) > 0 && YAP_IntOfTerm(arg_opt_level) < 4) { + if (YAP_Unify(arg_count, YAP_MkIntTerm(trie_get_db_opt_level_count(YAP_IntOfTerm(arg_opt_level))))) { + YAP_cut_succeed(); + return TRUE; + } else { + YAP_cut_fail(); + return FALSE; + } + } else { + YAP_cut_fail(); + return FALSE; + } + } + if (YAP_IsVarTerm(arg_opt_level)) { + YAP_PRESERVE_DATA(opt_level, db_trie_opt_level); + opt_level->value = YAP_MkIntTerm(1); + if (YAP_Unify(arg_opt_level, opt_level->value)) { + return YAP_Unify(arg_count, YAP_MkIntTerm(trie_get_db_opt_level_count(YAP_IntOfTerm(arg_opt_level)))); + } + YAP_cut_fail(); + return FALSE; + } + YAP_cut_fail(); + return FALSE; +} +#undef arg_opt_level +#undef arg_count + + +/* trie_get_depth_breadth_reduction_opt_level_count(?OptLevel, -Count) */ +#define arg_opt_level YAP_ARG1 +#define arg_count YAP_ARG2 +static int p_trie_get_db_opt_level_count_cont(void) { + YAP_PRESERVED_DATA(opt_level, db_trie_opt_level); + opt_level->value = YAP_MkIntTerm(YAP_IntOfTerm(opt_level->value) + 1); + if (YAP_IntOfTerm(opt_level->value) < 4) { + if (YAP_Unify(arg_opt_level, opt_level->value)); + return YAP_Unify(arg_count, YAP_MkIntTerm(trie_get_db_opt_level_count(YAP_IntOfTerm(arg_opt_level)))); + YAP_cut_fail(); + return FALSE; + } else { + YAP_cut_fail(); + return FALSE; + } +} +#undef arg_opt_level +#undef arg_count + + +/* trie_replace_nested_trie(+Trie, +NestedTrieID, +ReplaceTerm) */ +#define arg_trie YAP_ARG1 +#define arg_nested_id YAP_ARG2 +#define arg_term YAP_ARG3 +static int p_trie_replace_nested_trie(void) { + if (!YAP_IsIntTerm(arg_nested_id)) + return FALSE; + if (!YAP_IsNonVarTerm(arg_term)) + return FALSE; + trie_replace_nested_trie((TrEntry) YAP_IntOfTerm(arg_trie), YAP_IntOfTerm(arg_nested_id), arg_term); + return TRUE; +} +#undef arg_trie +#undef arg_nested_id +#undef arg_term + + +/* trie_db_opt_min_prefix(?MinPrefix) */ +#define arg_min_prefix YAP_ARG1 +static int p_trie_db_opt_min_prefix(void) { + YAP_Int min_prefix; + + /* get mode */ + if (YAP_IsVarTerm(arg_min_prefix)) { + min_prefix = trie_get_db_opt_min_prefix(); + return YAP_Unify(arg_min_prefix, YAP_MkIntTerm(min_prefix)); + } + + /* set mode */ + if (YAP_IsIntTerm(arg_min_prefix)) { + min_prefix = YAP_IntOfTerm(arg_min_prefix); + if (min_prefix > 1) { + trie_set_db_opt_min_prefix(min_prefix); + return TRUE; + } + } + return FALSE; +} +#undef min_prefix