diff --git a/library/Tries/Makefile.in b/library/Tries/Makefile.in index b4048055b..675eb3c10 100644 --- a/library/Tries/Makefile.in +++ b/library/Tries/Makefile.in @@ -33,7 +33,7 @@ SHLIB_SUFFIX=@SHLIB_SUFFIX@ CWD=$(PWD) # -OBJS=base_tries.o tries.o base_itries.o itries.o +OBJS=core_tries.o base_tries.o tries.o base_itries.o itries.o SOBJS=tries@SHLIB_SUFFIX@ itries@SHLIB_SUFFIX@ #in some systems we just create a single object, in others we need to @@ -41,26 +41,29 @@ SOBJS=tries@SHLIB_SUFFIX@ itries@SHLIB_SUFFIX@ all: $(SOBJS) -base_tries.o: $(srcdir)/base_tries.h $(srcdir)/base_tries.c +core_tries.o: $(srcdir)/core_tries.h $(srcdir)/core_tries.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 $(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/base_tries.c -o base_tries.o -tries.o: $(srcdir)/base_tries.h $(srcdir)/tries.c +tries.o: $(srcdir)/core_tries.h $(srcdir)/base_tries.h $(srcdir)/tries.c $(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/tries.c -o tries.o -base_itries.o: $(srcdir)/base_tries.h $(srcdir)/base_itries.h $(srcdir)/base_itries.c +base_itries.o: $(srcdir)/core_tries.h $(srcdir)/base_itries.h $(srcdir)/base_itries.c $(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/base_itries.c -o base_itries.o -itries.o: $(srcdir)/base_tries.h $(srcdir)/base_itries.h $(srcdir)/itries.c +itries.o: $(srcdir)/core_tries.h $(srcdir)/base_itries.h $(srcdir)/itries.c $(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/itries.c -o itries.o @DO_SECOND_LD@%@SHLIB_SUFFIX@: %.o @DO_SECOND_LD@ @SHLIB_LD@ -o $@ $< -@DO_SECOND_LD@tries@SHLIB_SUFFIX@: base_tries.o tries.o -@DO_SECOND_LD@ @SHLIB_LD@ -o tries@SHLIB_SUFFIX@ base_tries.o tries.o +@DO_SECOND_LD@tries@SHLIB_SUFFIX@: core_tries.o base_tries.o tries.o +@DO_SECOND_LD@ @SHLIB_LD@ -o tries@SHLIB_SUFFIX@ core_tries.o base_tries.o tries.o -@DO_SECOND_LD@itries@SHLIB_SUFFIX@: base_tries.o base_itries.o itries.o -@DO_SECOND_LD@ @SHLIB_LD@ -o itries@SHLIB_SUFFIX@ base_tries.o base_itries.o itries.o +@DO_SECOND_LD@itries@SHLIB_SUFFIX@: core_tries.o base_itries.o itries.o +@DO_SECOND_LD@ @SHLIB_LD@ -o itries@SHLIB_SUFFIX@ core_tries.o base_itries.o itries.o install: all $(INSTALL_PROGRAM) $(SOBJS) $(DESTDIR)$(LIBDIR) diff --git a/library/Tries/base_itries.c b/library/Tries/base_itries.c index e39b76e28..133fa57f9 100644 --- a/library/Tries/base_itries.c +++ b/library/Tries/base_itries.c @@ -14,7 +14,7 @@ #include #include #include -#include "base_tries.h" +#include "core_tries.h" #include "base_itries.h" @@ -34,7 +34,7 @@ static TrEntry FIRST_ITRIE, CURRENT_ITRIE; inline void itrie_init_module(void) { - ITRIE_ENGINE = trie_init_module(); + ITRIE_ENGINE = core_trie_init_module(); FIRST_ITRIE = NULL; return; } @@ -73,7 +73,7 @@ void itrie_data_print(TrNode node) { inline -void itrie_data_construct(TrNode node_dest, TrNode node_source) { +void itrie_data_copy(TrNode node_dest, TrNode node_source) { TrData data_dest, data_source; data_source = (TrData) GET_DATA_FROM_LEAF_TRIE_NODE(node_source); @@ -135,7 +135,7 @@ TrEntry itrie_open(void) { TrEntry itrie; TrNode node; - node = trie_open(ITRIE_ENGINE); + node = core_trie_open(ITRIE_ENGINE); new_itrie_entry(itrie, node); if (FIRST_ITRIE) TrEntry_previous(FIRST_ITRIE) = itrie; @@ -146,7 +146,7 @@ TrEntry itrie_open(void) { inline void itrie_close(TrEntry itrie) { - trie_close(ITRIE_ENGINE, TrEntry_trie(itrie), &itrie_data_destruct); + core_trie_close(ITRIE_ENGINE, TrEntry_trie(itrie), &itrie_data_destruct); if (TrEntry_next(itrie)) { TrEntry_previous(TrEntry_next(itrie)) = TrEntry_previous(itrie); TrEntry_next(TrEntry_previous(itrie)) = TrEntry_next(itrie); @@ -161,7 +161,7 @@ inline void itrie_close_all(void) { TrEntry itrie; - trie_close_all(ITRIE_ENGINE, &itrie_data_destruct); + core_trie_close_all(ITRIE_ENGINE, &itrie_data_destruct); while (FIRST_ITRIE) { itrie = TrEntry_next(FIRST_ITRIE); free_itrie_entry(FIRST_ITRIE); @@ -203,7 +203,7 @@ void itrie_put_entry(TrEntry itrie, YAP_Term entry) { TrNode node; YAP_Int depth; - node = trie_put_entry(ITRIE_ENGINE, TrEntry_trie(itrie), entry, &depth); + node = core_trie_put_entry(ITRIE_ENGINE, TrEntry_trie(itrie), entry, &depth); if (!(data = (TrData) GET_DATA_FROM_LEAF_TRIE_NODE(node))) { new_itrie_data(data, itrie, node, 0, 0, -1, depth); PUT_DATA_IN_LEAF_TRIE_NODE(node, data); @@ -218,7 +218,7 @@ void itrie_update_entry(TrEntry itrie, YAP_Term entry) { TrData data; TrNode node; - if ((node = trie_check_entry(TrEntry_trie(itrie), entry)) != NULL) { + if ((node = core_trie_check_entry(TrEntry_trie(itrie), entry)) != NULL) { data = (TrData) GET_DATA_FROM_LEAF_TRIE_NODE(node); update_itrie_data(data, TrEntry_timestamp(itrie), TrEntry_mode(itrie)); } @@ -230,7 +230,7 @@ inline TrData itrie_check_entry(TrEntry itrie, YAP_Term entry) { TrNode node; - if (!(node = trie_check_entry(TrEntry_trie(itrie), entry))) + if (!(node = core_trie_check_entry(TrEntry_trie(itrie), entry))) return NULL; return (TrData) GET_DATA_FROM_LEAF_TRIE_NODE(node); } @@ -238,7 +238,7 @@ TrData itrie_check_entry(TrEntry itrie, YAP_Term entry) { inline YAP_Term itrie_get_entry(TrData data) { - return trie_get_entry(TrData_leaf(data)); + return core_trie_get_entry(TrData_leaf(data)); } @@ -296,28 +296,28 @@ TrData itrie_traverse_cont(TrEntry itrie) { inline void itrie_remove_entry(TrData data) { - trie_remove_entry(ITRIE_ENGINE, TrData_leaf(data), &itrie_data_destruct); + core_trie_remove_entry(ITRIE_ENGINE, TrData_leaf(data), &itrie_data_destruct); return; } inline void itrie_remove_subtree(TrData data) { - trie_remove_subtree(ITRIE_ENGINE, TrData_leaf(data), &itrie_data_destruct); + core_trie_remove_subtree(ITRIE_ENGINE, TrData_leaf(data), &itrie_data_destruct); return; } inline void itrie_add(TrEntry itrie_dest, TrEntry itrie_source) { - trie_add(TrEntry_trie(itrie_dest), TrEntry_trie(itrie_source), &itrie_data_add); + core_trie_add(TrEntry_trie(itrie_dest), TrEntry_trie(itrie_source), &itrie_data_add); return; } inline void itrie_subtract(TrEntry itrie_dest, TrEntry itrie_source) { - trie_add(TrEntry_trie(itrie_dest), TrEntry_trie(itrie_source), &itrie_data_subtract); + core_trie_add(TrEntry_trie(itrie_dest), TrEntry_trie(itrie_source), &itrie_data_subtract); return; } @@ -325,33 +325,40 @@ void itrie_subtract(TrEntry itrie_dest, TrEntry itrie_source) { inline void itrie_join(TrEntry itrie_dest, TrEntry itrie_source) { CURRENT_ITRIE = itrie_dest; - trie_join(ITRIE_ENGINE, TrEntry_trie(itrie_dest), TrEntry_trie(itrie_source), &itrie_data_add, &itrie_data_construct); + core_trie_join(ITRIE_ENGINE, TrEntry_trie(itrie_dest), TrEntry_trie(itrie_source), &itrie_data_add, &itrie_data_copy); return; } inline void itrie_intersect(TrEntry itrie_dest, TrEntry itrie_source) { - trie_intersect(ITRIE_ENGINE, TrEntry_trie(itrie_dest), TrEntry_trie(itrie_source), &itrie_data_add, &itrie_data_destruct); + core_trie_intersect(ITRIE_ENGINE, TrEntry_trie(itrie_dest), TrEntry_trie(itrie_source), &itrie_data_add, &itrie_data_destruct); return; } inline YAP_Int itrie_count_join(TrEntry itrie1, TrEntry itrie2) { - return trie_count_join(TrEntry_trie(itrie1), TrEntry_trie(itrie2)); + return core_trie_count_join(TrEntry_trie(itrie1), TrEntry_trie(itrie2)); } inline YAP_Int itrie_count_intersect(TrEntry itrie1, TrEntry itrie2) { - return trie_count_intersect(TrEntry_trie(itrie1), TrEntry_trie(itrie2)); + return core_trie_count_intersect(TrEntry_trie(itrie1), TrEntry_trie(itrie2)); } inline void itrie_save(TrEntry itrie, FILE *file) { - trie_save(TrEntry_trie(itrie), file, &itrie_data_save); + core_trie_save(TrEntry_trie(itrie), file, &itrie_data_save); + return; +} + + +inline +void itrie_save_as_trie(TrEntry itrie, FILE *file) { + core_trie_save(TrEntry_trie(itrie), file, NULL); return; } @@ -366,7 +373,7 @@ TrEntry itrie_load(FILE *file) { TrEntry_previous(FIRST_ITRIE) = itrie; FIRST_ITRIE = itrie; CURRENT_ITRIE = itrie; - node = trie_load(ITRIE_ENGINE, file, &itrie_data_load); + node = core_trie_load(ITRIE_ENGINE, file, &itrie_data_load); TrEntry_trie(itrie) = node; return itrie; } @@ -374,27 +381,27 @@ TrEntry itrie_load(FILE *file) { inline void itrie_stats(YAP_Int *memory, YAP_Int *tries, YAP_Int *entries, YAP_Int *nodes) { - trie_stats(ITRIE_ENGINE, memory, tries, entries, nodes); + core_trie_stats(ITRIE_ENGINE, memory, tries, entries, nodes); return; } inline void itrie_max_stats(YAP_Int *memory, YAP_Int *tries, YAP_Int *entries, YAP_Int *nodes) { - trie_max_stats(ITRIE_ENGINE, memory, tries, entries, nodes); + core_trie_max_stats(ITRIE_ENGINE, memory, tries, entries, nodes); return; } inline void itrie_usage(TrEntry itrie, YAP_Int *entries, YAP_Int *nodes, YAP_Int *virtual_nodes) { - trie_usage(TrEntry_trie(itrie), entries, nodes, virtual_nodes); + core_trie_usage(TrEntry_trie(itrie), entries, nodes, virtual_nodes); return; } inline void itrie_print(TrEntry itrie) { - trie_print(TrEntry_trie(itrie), &itrie_data_print); + core_trie_print(TrEntry_trie(itrie), &itrie_data_print); return; } diff --git a/library/Tries/base_itries.h b/library/Tries/base_itries.h index b7582b4e7..178ba3486 100644 --- a/library/Tries/base_itries.h +++ b/library/Tries/base_itries.h @@ -147,6 +147,7 @@ typedef struct itrie_data { } + #define free_itrie_entry(STR) \ { free_itrie_buckets(TrEntry_buckets(STR), TrEntry_num_buckets(STR)); \ free_struct(STR); \ @@ -171,7 +172,7 @@ inline void itrie_init_module(void); inline void itrie_data_save(TrNode node, FILE *file); inline void itrie_data_load(TrNode node, YAP_Int depth, FILE *file); inline void itrie_data_print(TrNode node); -inline void itrie_data_construct(TrNode node_dest, TrNode node_source); +inline void itrie_data_copy(TrNode node_dest, TrNode node_source); inline void itrie_data_destruct(TrNode node); inline void itrie_data_add(TrNode node_dest, TrNode node_source); inline void itrie_data_subtract(TrNode node_dest, TrNode node_source); @@ -198,6 +199,7 @@ inline void itrie_intersect(TrEntry itrie_dest, TrEntry itrie_source); inline YAP_Int itrie_count_join(TrEntry itrie1, TrEntry itrie2); inline YAP_Int itrie_count_intersect(TrEntry itrie1, TrEntry itrie2); inline void itrie_save(TrEntry itrie, FILE *file); +inline void itrie_save_as_trie(TrEntry itrie, FILE *file); inline TrEntry itrie_load(FILE *file); inline void itrie_stats(YAP_Int *memory, YAP_Int *tries, YAP_Int *entries, YAP_Int *nodes); inline void itrie_max_stats(YAP_Int *memory, YAP_Int *tries, YAP_Int *entries, YAP_Int *nodes); diff --git a/library/Tries/base_tries.c b/library/Tries/base_tries.c index 90cdb2a15..8ed21dfa7 100644 --- a/library/Tries/base_tries.c +++ b/library/Tries/base_tries.c @@ -14,188 +14,17 @@ #include #include #include +#include "core_tries.h" #include "base_tries.h" -/* -------------------------- */ -/* Local Procedures */ -/* -------------------------- */ - -static TrNode put_trie(TrNode node, YAP_Term entry); -static TrNode check_trie(TrNode node, YAP_Term entry); -static YAP_Term get_trie(TrNode node, YAP_Term *stack_list, TrNode *cur_node); -static void remove_trie(TrNode node); -static void free_child_nodes(TrNode node); -static TrNode copy_child_nodes(TrNode parent_dest, TrNode node_source); -static void traverse_tries(TrNode parent_dest, TrNode parent_source); -static void traverse_tries_join(TrNode parent_dest, TrNode parent_source); -static void traverse_tries_intersect(TrNode parent_dest, TrNode parent_source); -static YAP_Int count_tries_intersect(TrNode parent1, TrNode parent2); -static YAP_Int count_trie(TrNode node); -static void traverse_trie_usage(TrNode node, YAP_Int depth); -static void traverse_trie_save(TrNode node, FILE *file, int float_block); -static void traverse_trie_load(TrNode parent, FILE *file); -static void traverse_trie_print(TrNode node, YAP_Int *arity, char *str, int str_index, int mode); - - - /* -------------------------- */ /* Local Variables */ /* -------------------------- */ -static TrEngine CURRENT_TRIE_ENGINE; -static YAP_Int USAGE_ENTRIES, USAGE_NODES, USAGE_VIRTUAL_NODES; -static YAP_Int CURRENT_AUXILIARY_TERM_STACK_SIZE, CURRENT_TRIE_MODE, CURRENT_LOAD_VERSION, CURRENT_DEPTH, CURRENT_INDEX; -static YAP_Term *AUXILIARY_TERM_STACK; -static YAP_Term *stack_args, *stack_args_base, *stack_vars, *stack_vars_base; -static YAP_Functor FunctorComma; -static void (*DATA_SAVE_FUNCTION)(TrNode, FILE *); -static void (*DATA_LOAD_FUNCTION)(TrNode, YAP_Int, FILE *); -static void (*DATA_PRINT_FUNCTION)(TrNode); -static void (*DATA_ADD_FUNCTION)(TrNode, TrNode); -static void (*DATA_CONSTRUCT_FUNCTION)(TrNode, TrNode); -static void (*DATA_DESTRUCT_FUNCTION)(TrNode); - - - -/* -------------------------- */ -/* Inline Procedures */ -/* -------------------------- */ - -static inline -TrNode trie_node_check_insert(TrNode parent, YAP_Term t) { - TrNode child; - - CURRENT_DEPTH++; - child = TrNode_child(parent); - if (child == NULL) { - new_trie_node(child, t, parent, NULL, NULL, NULL); - TrNode_child(parent) = child; - } else if (IS_HASH_NODE(child)) { - TrHash hash; - TrNode *bucket; - int count; - hash = (TrHash) child; - bucket = TrHash_bucket(hash, HASH_TERM(t, TrHash_seed(hash))); - child = *bucket; - count = 0; - while (child) { - if (TrNode_entry(child) == t) - return child; - count++; - child = TrNode_next(child); - } while (child); - TrHash_num_nodes(hash)++; - new_trie_node(child, t, parent, NULL, *bucket, AS_TR_NODE_NEXT(bucket)); - if (*bucket) - TrNode_previous(*bucket) = child; - *bucket = child; - if (count > MAX_NODES_PER_BUCKET && TrHash_num_nodes(hash) > TrHash_num_buckets(hash)) { - /* expand trie hash */ - TrNode chain, next, *first_bucket, *new_bucket; - int seed; - first_bucket = TrHash_buckets(hash); - bucket = first_bucket + TrHash_num_buckets(hash); - TrHash_num_buckets(hash) *= 2; - new_hash_buckets(hash, TrHash_num_buckets(hash)); - seed = TrHash_num_buckets(hash) - 1; - do { - if (*--bucket) { - chain = *bucket; - do { - 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; - *new_bucket = chain; - chain = next; - } while (chain); - } - } while (bucket != first_bucket); - free_hash_buckets(first_bucket, TrHash_num_buckets(hash) / 2); - } - } else { - int count = 0; - do { - if (TrNode_entry(child) == t) - 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) { - /* alloc a new trie hash */ - TrHash hash; - TrNode chain, next, *bucket; - new_trie_hash(hash, count, BASE_HASH_BUCKETS); - chain = child; - do { - bucket = TrHash_bucket(hash, HASH_TERM(TrNode_entry(chain), BASE_HASH_BUCKETS - 1)); - next = TrNode_next(chain); - TrNode_next(chain) = *bucket; - TrNode_previous(chain) = AS_TR_NODE_NEXT(bucket); - if (*bucket) - TrNode_previous(*bucket) = chain; - *bucket = chain; - chain = next; - } while (chain); - TrNode_child(parent) = (TrNode) hash; - } else - TrNode_child(parent) = child; - } - return child; -} - - -static inline -TrNode trie_node_insert(TrNode parent, YAP_Term t, TrHash hash) { - TrNode child; - - CURRENT_DEPTH++; - if (hash) { - /* is trie hash */ - TrNode *bucket; - TrHash_num_nodes(hash)++; - bucket = TrHash_bucket(hash, HASH_TERM(t, TrHash_seed(hash))); - new_trie_node(child, t, parent, NULL, *bucket, AS_TR_NODE_NEXT(bucket)); - if (*bucket) - TrNode_previous(*bucket) = child; - *bucket = child; - } else { - new_trie_node(child, t, parent, NULL, TrNode_child(parent), NULL); - if (TrNode_child(parent)) - TrNode_previous(TrNode_child(parent)) = child; - TrNode_child(parent) = child; - } - return child; -} - - -static inline -TrNode trie_node_check(TrNode parent, YAP_Term t) { - TrNode child; - - child = TrNode_child(parent); - if (IS_HASH_NODE(child)) { - TrHash hash; - TrNode *bucket; - hash = (TrHash) child; - bucket = TrHash_bucket(hash, HASH_TERM(t, TrHash_seed(hash))); - child = *bucket; - if (!child) - return NULL; - } - do { - if (TrNode_entry(child) == t) - return child; - child = TrNode_next(child); - } while (child); - return NULL; -} +static TrEngine TRIE_ENGINE; +static TrEntry FIRST_TRIE, CURRENT_TRIE; @@ -204,1250 +33,246 @@ TrNode trie_node_check(TrNode parent, YAP_Term t) { /* -------------------------- */ inline -TrEngine trie_init_module(void) { - static int init_once = 1; - TrEngine engine; - - if (init_once) { - new_struct(AUXILIARY_TERM_STACK, YAP_Term, BASE_AUXILIARY_TERM_STACK_SIZE * sizeof(YAP_Term)); - CURRENT_AUXILIARY_TERM_STACK_SIZE = BASE_AUXILIARY_TERM_STACK_SIZE; - CURRENT_TRIE_MODE = TRIE_MODE_STANDARD; - FunctorComma = YAP_MkFunctor(YAP_LookupAtom(","), 2); - init_once = 0; - } - new_trie_engine(engine); - return engine; -} - - -inline -TrNode trie_open(TrEngine engine) { - TrNode node; - - CURRENT_TRIE_ENGINE = engine; - new_trie_node(node, 0, NULL, NULL, TrEngine_trie(engine), AS_TR_NODE_NEXT(&TrEngine_trie(engine))); - if (TrEngine_trie(engine)) - TrNode_previous(TrEngine_trie(engine)) = node; - TrEngine_trie(engine) = node; - INCREMENT_TRIES(CURRENT_TRIE_ENGINE); - return node; -} - - -inline -void trie_close(TrEngine engine, TrNode node, void (*destruct_function)(TrNode)) { - CURRENT_TRIE_ENGINE = engine; - DATA_DESTRUCT_FUNCTION = destruct_function; - if (TrNode_child(node)) - free_child_nodes(TrNode_child(node)); - if (TrNode_next(node)) { - TrNode_previous(TrNode_next(node)) = TrNode_previous(node); - TrNode_next(TrNode_previous(node)) = TrNode_next(node); - } else - TrNode_next(TrNode_previous(node)) = NULL; - free_trie_node(node); - DECREMENT_TRIES(CURRENT_TRIE_ENGINE); +void trie_init_module(void) { + TRIE_ENGINE = core_trie_init_module(); + FIRST_TRIE = NULL; return; } inline -void trie_close_all(TrEngine engine, void (*destruct_function)(TrNode)) { - while (TrEngine_trie(engine)) - trie_close(engine, TrEngine_trie(engine), destruct_function); +void trie_data_load(TrNode node, YAP_Int depth, FILE *file) { + TrData data; + + new_trie_data(data, CURRENT_TRIE, node); + PUT_DATA_IN_LEAF_TRIE_NODE(node, data); + return; +} + + +inline +void trie_data_copy(TrNode node_dest, TrNode node_source) { + TrData data_dest; + + new_trie_data(data_dest, CURRENT_TRIE, node_dest); + PUT_DATA_IN_LEAF_TRIE_NODE(node_dest, data_dest); + return; +} + + +inline +void trie_data_destruct(TrNode node) { + TrEntry trie; + TrData data; + + data = (TrData) GET_DATA_FROM_LEAF_TRIE_NODE(node); + trie = TrData_trie(data); + if (data == TrEntry_traverse_data(trie)) + TrEntry_traverse_data(trie) = TrData_previous(data); + if (TrData_next(data)) { + TrData_previous(TrData_next(data)) = TrData_previous(data); + TrData_next(TrData_previous(data)) = TrData_next(data); + } else + TrData_next(TrData_previous(data)) = NULL; + free_trie_data(data); + return; +} + + +inline +TrEntry trie_open(void) { + TrEntry trie; + TrNode node; + + node = core_trie_open(TRIE_ENGINE); + new_trie_entry(trie, node); + if (FIRST_TRIE) + TrEntry_previous(FIRST_TRIE) = trie; + FIRST_TRIE = trie; + return trie; +} + + +inline +void trie_close(TrEntry trie) { + core_trie_close(TRIE_ENGINE, TrEntry_trie(trie), &trie_data_destruct); + if (TrEntry_next(trie)) { + TrEntry_previous(TrEntry_next(trie)) = TrEntry_previous(trie); + TrEntry_next(TrEntry_previous(trie)) = TrEntry_next(trie); + } else + TrEntry_next(TrEntry_previous(trie)) = NULL; + free_trie_entry(trie); + return; +} + + +inline +void trie_close_all(void) { + TrEntry trie; + + core_trie_close_all(TRIE_ENGINE, &trie_data_destruct); + while (FIRST_TRIE) { + trie = TrEntry_next(FIRST_TRIE); + free_trie_entry(FIRST_TRIE); + FIRST_TRIE = trie; + } return; } inline void trie_set_mode(YAP_Int mode) { - CURRENT_TRIE_MODE = mode; + core_trie_set_mode(mode); return; } inline YAP_Int trie_get_mode(void) { - return CURRENT_TRIE_MODE; + return core_trie_get_mode(); } inline -TrNode trie_put_entry(TrEngine engine, TrNode node, YAP_Term entry, YAP_Int *depth) { - CURRENT_TRIE_ENGINE = engine; - CURRENT_DEPTH = 0; - stack_args_base = stack_args = AUXILIARY_TERM_STACK; - stack_vars_base = stack_vars = AUXILIARY_TERM_STACK + CURRENT_AUXILIARY_TERM_STACK_SIZE - 1; - node = put_trie(node, entry); - if (!IS_LEAF_TRIE_NODE(node)) { - MARK_AS_LEAF_TRIE_NODE(node); - INCREMENT_ENTRIES(CURRENT_TRIE_ENGINE); - } - /* reset var terms */ - while (STACK_NOT_EMPTY(stack_vars++, stack_vars_base)) { - POP_DOWN(stack_vars); - *((YAP_Term *)*stack_vars) = *stack_vars; - } - if (depth) - *depth = CURRENT_DEPTH; - return node; -} - - -inline -TrNode trie_check_entry(TrNode node, YAP_Term entry) { - if (!TrNode_child(node)) - return NULL; - stack_args_base = stack_args = AUXILIARY_TERM_STACK; - stack_vars_base = stack_vars = AUXILIARY_TERM_STACK + CURRENT_AUXILIARY_TERM_STACK_SIZE - 1; - node = check_trie(node, entry); - /* reset var terms */ - while (STACK_NOT_EMPTY(stack_vars++, stack_vars_base)) { - POP_DOWN(stack_vars); - *((YAP_Term *)*stack_vars) = *stack_vars; - } - return node; -} - - -inline -YAP_Term trie_get_entry(TrNode node) { - CURRENT_INDEX = -1; - stack_vars_base = stack_vars = AUXILIARY_TERM_STACK; - stack_args_base = stack_args = AUXILIARY_TERM_STACK + CURRENT_AUXILIARY_TERM_STACK_SIZE - 1; - return get_trie(node, stack_args, &node); -} - - -inline -void trie_remove_entry(TrEngine engine, TrNode node, void (*destruct_function)(TrNode)) { - CURRENT_TRIE_ENGINE = engine; - DATA_DESTRUCT_FUNCTION = destruct_function; - if (DATA_DESTRUCT_FUNCTION) - (*DATA_DESTRUCT_FUNCTION)(node); - DECREMENT_ENTRIES(CURRENT_TRIE_ENGINE); - remove_trie(node); - return; -} - - -inline -void trie_remove_subtree(TrEngine engine, TrNode node, void (*destruct_function)(TrNode)) { - TrNode parent; - - CURRENT_TRIE_ENGINE = engine; - DATA_DESTRUCT_FUNCTION = destruct_function; - parent = TrNode_parent(node); - free_child_nodes(TrNode_child(parent)); - remove_trie(parent); - return; -} - - -inline -void trie_add(TrNode node_dest, TrNode node_source, void (*add_function)(TrNode, TrNode)) { - DATA_ADD_FUNCTION = add_function; - if (TrNode_child(node_dest) && TrNode_child(node_source)) - traverse_tries(node_dest, node_source); - return; -} - - -inline -void trie_join(TrEngine engine, TrNode node_dest, TrNode node_source, void (*add_function)(TrNode, TrNode), void (*construct_function)(TrNode, TrNode)) { - CURRENT_TRIE_ENGINE = engine; - DATA_ADD_FUNCTION = add_function; - DATA_CONSTRUCT_FUNCTION = construct_function; - if (TrNode_child(node_dest)) { - if (TrNode_child(node_source)) - traverse_tries_join(node_dest, node_source); - } else if (TrNode_child(node_source)) - TrNode_child(node_dest) = copy_child_nodes(node_dest, TrNode_child(node_source)); - return; -} - - -inline -void trie_intersect(TrEngine engine, TrNode node_dest, TrNode node_source, void (*add_function)(TrNode, TrNode), void (*destruct_function)(TrNode)) { - CURRENT_TRIE_ENGINE = engine; - DATA_ADD_FUNCTION = add_function; - DATA_DESTRUCT_FUNCTION = destruct_function; - if (TrNode_child(node_dest)) { - if (TrNode_child(node_source)) - traverse_tries_intersect(node_dest, node_source); - else { - free_child_nodes(TrNode_child(node_dest)); - TrNode_child(node_dest) = NULL; - } - } - return; -} - - -inline -YAP_Int trie_count_join(TrNode node1, TrNode node2) { - YAP_Int count = 0; - - if (TrNode_child(node1)) { - count += count_trie(TrNode_child(node1)); - if (TrNode_child(node2)) { - count += count_trie(TrNode_child(node2)); - count -= count_tries_intersect(node1, node2); - } - } else if (TrNode_child(node2)) - count += count_trie(TrNode_child(node2)); - return count; -} - - -inline -YAP_Int trie_count_intersect(TrNode node1, TrNode node2) { - YAP_Int count = 0; - - if (TrNode_child(node1)) - if (TrNode_child(node2)) - count = count_tries_intersect(node1, node2); - return count; -} - - -inline -void trie_save(TrNode node, FILE *file, void (*save_function)(TrNode, FILE *)) { - CURRENT_INDEX = -1; - DATA_SAVE_FUNCTION = save_function; - if (TrNode_child(node)) { - fprintf(file, "BEGIN_TRIE_v2 "); - traverse_trie_save(TrNode_child(node), file, 0); - fprintf(file, "END_TRIE_v2"); - } - return; -} - - -inline -TrNode trie_load(TrEngine engine, FILE *file, void (*load_function)(TrNode, YAP_Int, FILE *)) { +TrData trie_put_entry(TrEntry trie, YAP_Term entry) { + TrData data; TrNode node; - char version[15]; - CURRENT_TRIE_ENGINE = engine; - CURRENT_INDEX = -1; - CURRENT_DEPTH = 0; - DATA_LOAD_FUNCTION = load_function; - node = trie_open(engine); - fscanf(file, "%s", version); - if (!strcmp(version, "BEGIN_TRIE_v2")) { - CURRENT_LOAD_VERSION = 2; - traverse_trie_load(node, file); - } else if (!strcmp(version, "BEGIN_TRIE")) { - CURRENT_LOAD_VERSION = 1; - traverse_trie_load(node, file); + node = core_trie_put_entry(TRIE_ENGINE, TrEntry_trie(trie), entry, NULL); + if (!(data = (TrData) GET_DATA_FROM_LEAF_TRIE_NODE(node))) { + new_trie_data(data, trie, node); + PUT_DATA_IN_LEAF_TRIE_NODE(node, data); } - return node; + return data; } inline -void trie_stats(TrEngine engine, YAP_Int *memory, YAP_Int *tries, YAP_Int *entries, YAP_Int *nodes) { - *memory = TrEngine_memory(engine); - *tries = TrEngine_tries(engine); - *entries = TrEngine_entries(engine); - *nodes = TrEngine_nodes(engine); +TrData trie_check_entry(TrEntry trie, YAP_Term entry) { + TrNode node; + + if (!(node = core_trie_check_entry(TrEntry_trie(trie), entry))) + return NULL; + return (TrData) GET_DATA_FROM_LEAF_TRIE_NODE(node); +} + + +inline +YAP_Term trie_get_entry(TrData data) { + return core_trie_get_entry(TrData_leaf(data)); +} + + +inline +TrData trie_traverse_init(TrEntry trie) { + TrData data; + + data = TrEntry_first_data(trie); + TrEntry_traverse_data(trie) = data; + return data; +} + + +inline +TrData trie_traverse_cont(TrEntry trie) { + TrData data; + + data = TrEntry_traverse_data(trie); + if (data) { + data = TrData_next(data); + TrEntry_traverse_data(trie) = data; + } + return data; +} + + +inline +void trie_remove_entry(TrData data) { + core_trie_remove_entry(TRIE_ENGINE, TrData_leaf(data), &trie_data_destruct); return; } inline -void trie_max_stats(TrEngine engine, YAP_Int *memory, YAP_Int *tries, YAP_Int *entries, YAP_Int *nodes) { - *memory = TrEngine_memory_max(engine); - *tries = TrEngine_tries_max(engine); - *entries = TrEngine_entries_max(engine); - *nodes = TrEngine_nodes_max(engine); +void trie_remove_subtree(TrData data) { + core_trie_remove_subtree(TRIE_ENGINE, TrData_leaf(data), &trie_data_destruct); return; } inline -void trie_usage(TrNode node, YAP_Int *entries, YAP_Int *nodes, YAP_Int *virtual_nodes) { - USAGE_ENTRIES = 0; - USAGE_NODES = 0; - USAGE_VIRTUAL_NODES = 0; - if (TrNode_child(node)) - traverse_trie_usage(TrNode_child(node), 0); - *entries = USAGE_ENTRIES; - *nodes = USAGE_NODES; - *virtual_nodes = USAGE_VIRTUAL_NODES; +void trie_join(TrEntry trie_dest, TrEntry trie_source) { + CURRENT_TRIE = trie_dest; + core_trie_join(TRIE_ENGINE, TrEntry_trie(trie_dest), TrEntry_trie(trie_source), NULL, &trie_data_copy); return; } inline -void trie_print(TrNode node, void (*print_function)(TrNode)) { - DATA_PRINT_FUNCTION = print_function; - if (TrNode_child(node)) { - YAP_Int arity[100]; - char str[1000]; - arity[0] = 0; - traverse_trie_print(TrNode_child(node), arity, str, 0, TRIE_PRINT_NORMAL); - } else - fprintf(stdout, "(empty)\n"); +void trie_intersect(TrEntry trie_dest, TrEntry trie_source) { + core_trie_intersect(TRIE_ENGINE, TrEntry_trie(trie_dest), TrEntry_trie(trie_source), NULL, &trie_data_destruct); return; } - - -/* -------------------------- */ -/* Local Procedures */ -/* -------------------------- */ - -static -TrNode put_trie(TrNode node, YAP_Term entry) { - YAP_Term t = YAP_Deref(entry); - if (YAP_IsVarTerm(t)) { - if (IsTrieVar(t, stack_vars, stack_vars_base)) { - node = trie_node_check_insert(node, MkTrieVar((stack_vars_base - 1 - (YAP_Term *)t) / 2)); - } else { - node = trie_node_check_insert(node, MkTrieVar((stack_vars_base - stack_vars) / 2)); - PUSH_UP(stack_vars, t, stack_args); - *((YAP_Term *)t) = (YAP_Term)stack_vars; - PUSH_UP(stack_vars, stack_vars, stack_args); - } - } else if (YAP_IsAtomTerm(t)) { - node = trie_node_check_insert(node, t); - } else if (YAP_IsIntTerm(t)) { - node = trie_node_check_insert(node, t); - } else if (YAP_IsFloatTerm(t)) { - volatile double f; - volatile YAP_Term *p; - f = YAP_FloatOfTerm(t); - p = (YAP_Term *)((void *) &f); /* to avoid gcc warning */ - node = trie_node_check_insert(node, FloatInitTag); - node = trie_node_check_insert(node, *p); -#ifdef TAG_LOW_BITS_32 - node = trie_node_check_insert(node, *(p + 1)); -#endif /* TAG_LOW_BITS_32 */ - 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) { - do { - node = put_trie(node, YAP_HeadOfTerm(t)); - t = YAP_Deref(YAP_TailOfTerm(t)); - } while (YAP_IsPairTerm(t)); - } else { /* 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)); - } while (YAP_IsPairTerm(t)); - while (STACK_NOT_EMPTY(stack_args, stack_list)) - node = put_trie(node, POP_UP(stack_args)); - } - node = trie_node_check_insert(node, PairEndTag); - } else if (YAP_IsApplTerm(t)) { - YAP_Functor f = YAP_FunctorOfTerm(t); - if (f == FunctorComma) { - node = trie_node_check_insert(node, CommaInitTag); - do { - node = put_trie(node, YAP_ArgOfTerm(1, t)); - t = YAP_Deref(YAP_ArgOfTerm(2, t)); - } while (YAP_IsApplTerm(t) && YAP_FunctorOfTerm(t) == FunctorComma); - node = put_trie(node, t); - node = trie_node_check_insert(node, CommaEndTag); - } else { - int i; - node = trie_node_check_insert(node, ApplTag | ((YAP_Term) f)); - for (i = 1; i <= YAP_ArityOfFunctor(f); i++) - node = put_trie(node, YAP_ArgOfTerm(i, t)); - } - } else - fprintf(stderr, "\nTries base module: unknown type tag\n"); - - return node; +inline +YAP_Int trie_count_join(TrEntry trie1, TrEntry trie2) { + return core_trie_count_join(TrEntry_trie(trie1), TrEntry_trie(trie2)); } -static -TrNode check_trie(TrNode node, YAP_Term entry) { - YAP_Term t = YAP_Deref(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; - } else { - if (!(node = trie_node_check(node, MkTrieVar((stack_vars_base - stack_vars) / 2)))) - return NULL; - PUSH_UP(stack_vars, t, stack_args); - *((YAP_Term *)t) = (YAP_Term)stack_vars; - PUSH_UP(stack_vars, stack_vars, stack_args); - } - } else if (YAP_IsAtomTerm(t)) { - if (!(node = trie_node_check(node, t))) - return NULL; - } else if (YAP_IsIntTerm(t)) { - if (!(node = trie_node_check(node, t))) - return NULL; - } else if (YAP_IsFloatTerm(t)) { - volatile double f; - volatile YAP_Term *p; - f = YAP_FloatOfTerm(t); - p = (YAP_Term *)((void *) &f); /* to avoid gcc warning */ - if (!(node = trie_node_check(node, FloatInitTag))) - return NULL; - if (!(node = trie_node_check(node, *p))) - return NULL; -#ifdef TAG_LOW_BITS_32 - if (!(node = trie_node_check(node, *(p + 1)))) - return NULL; -#endif /* TAG_LOW_BITS_32 */ - if (!(node = trie_node_check(node, FloatEndTag))) - return NULL; - } else if (YAP_IsPairTerm(t)) { - if (!(node = trie_node_check(node, PairInitTag))) - return NULL; - if (CURRENT_TRIE_MODE == TRIE_MODE_STANDARD) { - do { - if (!(node = check_trie(node, YAP_HeadOfTerm(t)))) - return NULL; - t = YAP_Deref(YAP_TailOfTerm(t)); - } while (YAP_IsPairTerm(t)); - } else { /* 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)); - } while (YAP_IsPairTerm(t)); - while (STACK_NOT_EMPTY(stack_args, stack_list)) - if (!(node = check_trie(node, POP_UP(stack_args)))) - return NULL; - } - if (!(node = trie_node_check(node, PairEndTag))) - 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; - do { - if (!(node = check_trie(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_trie(node, t))) - return NULL; - if (!(node = trie_node_check(node, CommaEndTag))) - return NULL; - } else { - int i; - if (!(node = trie_node_check(node, ApplTag | ((YAP_Term) f)))) - return NULL; - for (i = 1; i <= YAP_ArityOfFunctor(f); i++) - if (!(node = check_trie(node, YAP_ArgOfTerm(i, t)))) - return NULL; - } - } else - fprintf(stderr, "\nTries base module: unknown type tag\n"); - - return node; +inline +YAP_Int trie_count_intersect(TrEntry trie1, TrEntry trie2) { + return core_trie_count_intersect(TrEntry_trie(trie1), TrEntry_trie(trie2)); } -static -YAP_Term get_trie(TrNode node, YAP_Term *stack_mark, TrNode *cur_node) { - YAP_Term t = (YAP_Term) &t; - while (TrNode_parent(node)) { - t = TrNode_entry(node); - if (YAP_IsVarTerm(t)) { - int index = TrieVarIndex(t); - if (index > CURRENT_INDEX) { - int i; - stack_vars = &stack_vars_base[index + 1]; - if (stack_vars > stack_args + 1) - fprintf(stderr, "\nTries base module: term stack full"); - for (i = index; i > CURRENT_INDEX; i--) - stack_vars_base[i] = 0; - CURRENT_INDEX = index; - } - if (stack_vars_base[index]) { - t = stack_vars_base[index]; - } else { - t = YAP_MkVarTerm(); - stack_vars_base[index] = t; - } - PUSH_UP(stack_args, t, stack_vars); - } else if (YAP_IsAtomTerm(t)) { - PUSH_UP(stack_args, t, stack_vars); - } else if (YAP_IsIntTerm(t)) { - PUSH_UP(stack_args, t, stack_vars); - } else if (YAP_IsPairTerm(t)) { - if (t == PairEndTag) { - if (CURRENT_TRIE_MODE == TRIE_MODE_STANDARD) { - t = YAP_MkAtomTerm(YAP_LookupAtom("[]")); - PUSH_UP(stack_args, t, stack_vars); - node = TrNode_parent(node); - t = get_trie(node, &stack_args[1], &node); - } else { /* TRIE_MODE_REVERSE */ - node = TrNode_parent(node); - t = get_trie(node, stack_args, &node); - } - PUSH_UP(stack_args, t, stack_vars); - } else if (t == PairInitTag) { - YAP_Term t2; - if (CURRENT_TRIE_MODE == 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); - } - stack_args = stack_mark; - } else { /* TRIE_MODE_REVERSE */ - t = YAP_MkAtomTerm(YAP_LookupAtom("[]")); - while (STACK_NOT_EMPTY(stack_args, stack_mark)) { - t2 = POP_DOWN(stack_args); - t = YAP_MkPairTerm(t2, t); - } - } - *cur_node = node; - return t; - } else if (t == CommaEndTag) { - node = TrNode_parent(node); - t = get_trie(node, stack_args, &node); - PUSH_UP(stack_args, t, stack_vars); - } else if (t == CommaInitTag) { - YAP_Term *stack_aux = stack_mark; - stack_aux--; - while (STACK_NOT_EMPTY(stack_aux, stack_args)) { - t = YAP_MkApplTerm(FunctorComma, 2, stack_aux); - *stack_aux = t; - stack_aux--; - } - stack_args = stack_mark; - *cur_node = node; - return t; - } else if (t == FloatEndTag) { - volatile double f; - volatile YAP_Term *p; - p = (YAP_Term *)((void *) &f); /* to avoid gcc warning */ -#ifdef TAG_LOW_BITS_32 - node = TrNode_parent(node); - *(p + 1) = TrNode_entry(node); -#endif /* TAG_LOW_BITS_32 */ - node = TrNode_parent(node); - *p = TrNode_entry(node); - node = TrNode_parent(node); /* ignore FloatInitTag */ - t = YAP_MkFloatTerm(f); - PUSH_UP(stack_args, t, stack_vars); - } else if (t == FloatInitTag) { - } - } else if (ApplTag & t) { - YAP_Functor f = (YAP_Functor)(~ApplTag & t); - int arity = YAP_ArityOfFunctor(f); - t = YAP_MkApplTerm(f, arity, &stack_args[1]); - stack_args += arity; - PUSH_UP(stack_args, t, stack_vars); - } else - fprintf(stderr, "\nTries base module: unknown type tag\n"); - node = TrNode_parent(node); - } - *cur_node = node; - return t; -} - - -static -void remove_trie(TrNode node) { - TrNode parent = TrNode_parent(node); - while (parent) { - if (TrNode_previous(node)) { - if (IS_HASH_NODE(TrNode_child(parent))) { - TrHash hash = (TrHash) TrNode_child(parent); - TrHash_num_nodes(hash)--; - if (TrHash_num_nodes(hash)) { - if (TrNode_next(node)) { - TrNode_next(TrNode_previous(node)) = TrNode_next(node); - TrNode_previous(TrNode_next(node)) = TrNode_previous(node); - } else { - TrNode_next(TrNode_previous(node)) = NULL; - } - free_trie_node(node); - return; - } - free_hash_buckets(TrHash_buckets(hash), TrHash_num_buckets(hash)); - free_trie_hash(hash); - } else { - if (TrNode_next(node)) { - TrNode_next(TrNode_previous(node)) = TrNode_next(node); - TrNode_previous(TrNode_next(node)) = TrNode_previous(node); - } else { - TrNode_next(TrNode_previous(node)) = NULL; - } - free_trie_node(node); - return; - } - } else if (TrNode_next(node)) { - TrNode_child(parent) = TrNode_next(node); - TrNode_previous(TrNode_next(node)) = NULL; - free_trie_node(node); - return; - } - free_trie_node(node); - node = parent; - parent = TrNode_parent(node); - } - TrNode_child(node) = NULL; +inline +void trie_save(TrEntry trie, FILE *file) { + core_trie_save(TrEntry_trie(trie), file, NULL); return; } -static -void free_child_nodes(TrNode 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); - do { - if (*--bucket) - free_child_nodes(*bucket); - } while (bucket != first_bucket); - free_hash_buckets(first_bucket, TrHash_num_buckets(hash)); - free_trie_hash(hash); - return; - } - if (TrNode_next(node)) - free_child_nodes(TrNode_next(node)); - if (!IS_LEAF_TRIE_NODE(node)) - free_child_nodes(TrNode_child(node)); - else { - if (DATA_DESTRUCT_FUNCTION) - (*DATA_DESTRUCT_FUNCTION)(node); - DECREMENT_ENTRIES(CURRENT_TRIE_ENGINE); - } - free_trie_node(node); +inline +TrEntry trie_load(FILE *file) { + TrEntry trie; + TrNode node; + + new_trie_entry(trie, NULL); + if (FIRST_TRIE) + TrEntry_previous(FIRST_TRIE) = trie; + FIRST_TRIE = trie; + CURRENT_TRIE = trie; + node = core_trie_load(TRIE_ENGINE, file, &trie_data_load); + TrEntry_trie(trie) = node; + return trie; +} + + +inline +void trie_stats(YAP_Int *memory, YAP_Int *tries, YAP_Int *entries, YAP_Int *nodes) { + core_trie_stats(TRIE_ENGINE, memory, tries, entries, nodes); return; } -static -TrNode copy_child_nodes(TrNode parent_dest, TrNode child_source) { - TrNode child_dest, next_dest; - - if (IS_HASH_NODE(child_source)) { - TrNode *bucket_dest, *first_bucket_source, *bucket_source; - TrHash hash_dest, hash_source; - hash_source = (TrHash) child_source; - first_bucket_source = TrHash_buckets(hash_source); - bucket_source = first_bucket_source + TrHash_num_buckets(hash_source); - new_trie_hash(hash_dest, TrHash_num_nodes(hash_source), TrHash_num_buckets(hash_source)); - bucket_dest = TrHash_buckets(hash_dest) + TrHash_num_buckets(hash_dest); - do { - bucket_dest--; - if (*--bucket_source) { - *bucket_dest = copy_child_nodes(parent_dest, *bucket_source); - TrNode_previous(*bucket_dest) = AS_TR_NODE_NEXT(bucket_dest); - } else - *bucket_dest = NULL; - } while (bucket_source != first_bucket_source); - return (TrNode) hash_dest; - } - - if (TrNode_next(child_source)) - next_dest = copy_child_nodes(parent_dest, TrNode_next(child_source)); - else - next_dest = NULL; - new_trie_node(child_dest, TrNode_entry(child_source), parent_dest, NULL, next_dest, NULL); - if (next_dest) - TrNode_previous(next_dest) = child_dest; - if (IS_LEAF_TRIE_NODE(child_source)) { - MARK_AS_LEAF_TRIE_NODE(child_dest); - INCREMENT_ENTRIES(CURRENT_TRIE_ENGINE); - if (DATA_CONSTRUCT_FUNCTION) - (*DATA_CONSTRUCT_FUNCTION)(child_dest, child_source); - } else - TrNode_child(child_dest) = copy_child_nodes(child_dest, TrNode_child(child_source)); - return child_dest; -} - - -static -void traverse_tries(TrNode parent_dest, TrNode parent_source) { - TrNode child_dest, child_source; - - /* parent_source is not a leaf node */ - child_source = TrNode_child(parent_source); - if (IS_HASH_NODE(child_source)) { - TrNode *first_bucket_source, *bucket_source; - TrHash hash_source; - hash_source = (TrHash) child_source; - first_bucket_source = TrHash_buckets(hash_source); - bucket_source = first_bucket_source + TrHash_num_buckets(hash_source); - do { - child_source = *--bucket_source; - while (child_source) { - /* parent_dest is not a leaf node */ - child_dest = trie_node_check(parent_dest, TrNode_entry(child_source)); - if (child_dest) { - if (IS_LEAF_TRIE_NODE(child_dest)) { - /* child_source is a leaf node */ - if (DATA_ADD_FUNCTION) - (*DATA_ADD_FUNCTION)(child_dest, child_source); - } else - /* child_dest and child_source are not leaf nodes */ - traverse_tries(child_dest, child_source); - } - child_source = TrNode_next(child_source); - } - } while (bucket_source != first_bucket_source); - return; - } - while (child_source) { - /* parent_dest is not a leaf node */ - child_dest = trie_node_check(parent_dest, TrNode_entry(child_source)); - if (child_dest) { - if (IS_LEAF_TRIE_NODE(child_dest)) { - /* child_source is a leaf node */ - if (DATA_ADD_FUNCTION) - (*DATA_ADD_FUNCTION)(child_dest, child_source); - } else - /* child_dest and child_source are not leaf nodes */ - traverse_tries(child_dest, child_source); - } - child_source = TrNode_next(child_source); - } +inline +void trie_max_stats(YAP_Int *memory, YAP_Int *tries, YAP_Int *entries, YAP_Int *nodes) { + core_trie_max_stats(TRIE_ENGINE, memory, tries, entries, nodes); return; } -static -void traverse_tries_join(TrNode parent_dest, TrNode parent_source) { - TrNode child_dest, child_source; - - /* parent_source is not a leaf node */ - child_source = TrNode_child(parent_source); - if (IS_HASH_NODE(child_source)) { - TrNode *first_bucket_source, *bucket_source; - TrHash hash_source; - hash_source = (TrHash) child_source; - first_bucket_source = TrHash_buckets(hash_source); - bucket_source = first_bucket_source + TrHash_num_buckets(hash_source); - do { - child_source = *--bucket_source; - while (child_source) { - /* parent_dest is not a leaf node */ - child_dest = trie_node_check(parent_dest, TrNode_entry(child_source)); - if (child_dest) { - if (IS_LEAF_TRIE_NODE(child_dest)) { - /* child_source is a leaf node */ - if (DATA_ADD_FUNCTION) - (*DATA_ADD_FUNCTION)(child_dest, child_source); - } else - /* child_dest and child_source are not leaf nodes */ - traverse_tries_join(child_dest, child_source); - } else { - child_dest = trie_node_check_insert(parent_dest, TrNode_entry(child_source)); - if (IS_LEAF_TRIE_NODE(child_source)) { - MARK_AS_LEAF_TRIE_NODE(child_dest); - INCREMENT_ENTRIES(CURRENT_TRIE_ENGINE); - if (DATA_CONSTRUCT_FUNCTION) - (*DATA_CONSTRUCT_FUNCTION)(child_dest, child_source); - } else - TrNode_child(child_dest) = copy_child_nodes(child_dest, TrNode_child(child_source)); - } - child_source = TrNode_next(child_source); - } - } while (bucket_source != first_bucket_source); - return; - } - while (child_source) { - /* parent_dest is not a leaf node */ - child_dest = trie_node_check(parent_dest, TrNode_entry(child_source)); - if (child_dest) { - if (IS_LEAF_TRIE_NODE(child_dest)) { - /* child_source is a leaf node */ - if (DATA_ADD_FUNCTION) - (*DATA_ADD_FUNCTION)(child_dest, child_source); - } else - /* child_dest and child_source are not leaf nodes */ - traverse_tries_join(child_dest, child_source); - } else { - child_dest = trie_node_check_insert(parent_dest, TrNode_entry(child_source)); - if (IS_LEAF_TRIE_NODE(child_source)) { - MARK_AS_LEAF_TRIE_NODE(child_dest); - INCREMENT_ENTRIES(CURRENT_TRIE_ENGINE); - if (DATA_CONSTRUCT_FUNCTION) - (*DATA_CONSTRUCT_FUNCTION)(child_dest, child_source); - } else - TrNode_child(child_dest) = copy_child_nodes(child_dest, TrNode_child(child_source)); - } - child_source = TrNode_next(child_source); - } +inline +void trie_usage(TrEntry trie, YAP_Int *entries, YAP_Int *nodes, YAP_Int *virtual_nodes) { + core_trie_usage(TrEntry_trie(trie), entries, nodes, virtual_nodes); return; } -static -void traverse_tries_intersect(TrNode parent_dest, TrNode parent_source) { - TrNode child_dest, child_source, child_next; - - /* parent_dest is not a leaf node */ - child_dest = TrNode_child(parent_dest); - if (IS_HASH_NODE(child_dest)) { - TrNode *first_bucket_dest, *bucket_dest; - TrHash hash_dest; - hash_dest = (TrHash) child_dest; - first_bucket_dest = TrHash_buckets(hash_dest); - bucket_dest = first_bucket_dest + TrHash_num_buckets(hash_dest); - do { - child_dest = *--bucket_dest; - while (child_dest) { - child_next = TrNode_next(child_dest); - /* parent_source is not a leaf node */ - child_source = trie_node_check(parent_source, TrNode_entry(child_dest)); - if (child_source) { - if (IS_LEAF_TRIE_NODE(child_dest)) { - /* child_source is a leaf node */ - if (DATA_ADD_FUNCTION) - (*DATA_ADD_FUNCTION)(child_dest, child_source); - } else - /* child_dest and child_source are not leaf nodes */ - traverse_tries_intersect(child_dest, child_source); - } else { - if (IS_LEAF_TRIE_NODE(child_dest)) { - if (DATA_DESTRUCT_FUNCTION) - (*DATA_DESTRUCT_FUNCTION)(child_dest); - DECREMENT_ENTRIES(CURRENT_TRIE_ENGINE); - } else - free_child_nodes(TrNode_child(child_dest)); - remove_trie(child_dest); - } - child_dest = child_next; - } - } while (bucket_dest != first_bucket_dest); - return; - } - while (child_dest) { - child_next = TrNode_next(child_dest); - /* parent_source is not a leaf node */ - child_source = trie_node_check(parent_source, TrNode_entry(child_dest)); - if (child_source) { - if (IS_LEAF_TRIE_NODE(child_dest)) { - /* child_source is a leaf node */ - if (DATA_ADD_FUNCTION) - (*DATA_ADD_FUNCTION)(child_dest, child_source); - } else - /* child_dest and child_source are not leaf nodes */ - traverse_tries_intersect(child_dest, child_source); - } else { - if (IS_LEAF_TRIE_NODE(child_dest)) { - if (DATA_DESTRUCT_FUNCTION) - (*DATA_DESTRUCT_FUNCTION)(child_dest); - DECREMENT_ENTRIES(CURRENT_TRIE_ENGINE); - } else - free_child_nodes(TrNode_child(child_dest)); - remove_trie(child_dest); - } - child_dest = child_next; - } - return; -} - - -static -YAP_Int count_tries_intersect(TrNode parent1, TrNode parent2) { - TrNode child1, child2; - YAP_Int count = 0; - - /* parent1 is not a leaf node */ - child1 = TrNode_child(parent1); - if (IS_HASH_NODE(child1)) { - TrNode *first_bucket, *bucket; - TrHash hash; - hash = (TrHash) child1; - first_bucket = TrHash_buckets(hash); - bucket = first_bucket + TrHash_num_buckets(hash); - do { - child1 = *--bucket; - while (child1) { - /* parent2 is not a leaf node */ - child2 = trie_node_check(parent2, TrNode_entry(child1)); - if (child2) { - if (IS_LEAF_TRIE_NODE(child1)) - /* child2 is a leaf node */ - count++; - else - /* child1 and child2 are not leaf nodes */ - count += count_tries_intersect(child1, child2); - } - child1 = TrNode_next(child1); - } - } while (bucket != first_bucket); - return count; - } - while (child1) { - /* parent2 is not a leaf node */ - child2 = trie_node_check(parent2, TrNode_entry(child1)); - if (child2) { - if (IS_LEAF_TRIE_NODE(child1)) - /* child2 is a leaf node */ - count++; - else - /* child1 and child2 are not leaf nodes */ - count += count_tries_intersect(child1, child2); - } - child1 = TrNode_next(child1); - } - return count; -} - - -static -YAP_Int count_trie(TrNode node) { - YAP_Int count = 0; - - if (IS_HASH_NODE(node)) { - TrNode *first_bucket, *bucket; - TrHash hash; - hash = (TrHash) node; - first_bucket = TrHash_buckets(hash); - bucket = first_bucket + TrHash_num_buckets(hash); - do { - if (*--bucket) { - node = *bucket; - count += count_trie(node); - } - } while (bucket != first_bucket); - return count; - } - - if (TrNode_next(node)) - count += count_trie(TrNode_next(node)); - if (!IS_LEAF_TRIE_NODE(node)) - count += count_trie(TrNode_child(node)); - else - count++; - return count; -} - - -static -void traverse_trie_usage(TrNode node, YAP_Int depth) { - if (IS_HASH_NODE(node)) { - TrNode *first_bucket, *bucket; - TrHash hash; - hash = (TrHash) node; - first_bucket = TrHash_buckets(hash); - bucket = first_bucket + TrHash_num_buckets(hash); - do { - if (*--bucket) { - node = *bucket; - traverse_trie_usage(node, depth); - } - } while (bucket != first_bucket); - return; - } - - USAGE_NODES++; - if (TrNode_next(node)) - traverse_trie_usage(TrNode_next(node), depth); - depth++; - if (!IS_LEAF_TRIE_NODE(node)) { - traverse_trie_usage(TrNode_child(node), depth); - } else { - USAGE_ENTRIES++; - USAGE_VIRTUAL_NODES+= depth; - } - return; -} - - -static -void traverse_trie_save(TrNode node, FILE *file, int float_block) { - YAP_Term t; - - if (IS_HASH_NODE(node)) { - TrNode *first_bucket, *bucket; - TrHash hash; - hash = (TrHash) node; - fprintf(file, "%lu %d ", HASH_SAVE_MARK, TrHash_num_buckets(hash)); - first_bucket = TrHash_buckets(hash); - bucket = first_bucket + TrHash_num_buckets(hash); - do { - if (*--bucket) { - node = *bucket; - traverse_trie_save(node, file, float_block); - } - } while (bucket != first_bucket); - return; - } - - if (TrNode_next(node)) - traverse_trie_save(TrNode_next(node), file, float_block); - - t = TrNode_entry(node); - if (float_block) { - float_block--; - fprintf(file, "%lu %lu ", FLOAT_SAVE_MARK, t); - } else if (YAP_IsPairTerm(t)) { - if (t == FloatInitTag) { -#ifdef TAG_LOW_BITS_32 - float_block++; -#endif /* TAG_LOW_BITS_32 */ - float_block ++; - } - fprintf(file, "%lu ", t); - } else if (YAP_IsVarTerm(t) || YAP_IsIntTerm(t)) - fprintf(file, "%lu ", t); - else { - int index; - for (index = 0; index <= CURRENT_INDEX; index++) - if (AUXILIARY_TERM_STACK[index] == t) - break; - if (index > CURRENT_INDEX) { - CURRENT_INDEX = index; - if (CURRENT_INDEX == CURRENT_AUXILIARY_TERM_STACK_SIZE) - expand_auxiliary_term_stack(); - AUXILIARY_TERM_STACK[CURRENT_INDEX] = t; - if (YAP_IsAtomTerm(t)) - fprintf(file, "%lu %d %s%c ", ATOM_SAVE_MARK, index, YAP_AtomName(YAP_AtomOfTerm(t)), '\0'); - else /* (ApplTag & t) */ - fprintf(file, "%lu %d %s %d ", FUNCTOR_SAVE_MARK, index, - YAP_AtomName(YAP_NameOfFunctor((YAP_Functor)(~ApplTag & t))), - YAP_ArityOfFunctor((YAP_Functor)(~ApplTag & t))); - } else - if (YAP_IsAtomTerm(t)) - fprintf(file, "%lu %d ", ATOM_SAVE_MARK, index); - else - fprintf(file, "%lu %d ", FUNCTOR_SAVE_MARK, index); - } - if (IS_LEAF_TRIE_NODE(node)) { - fprintf(file, "- "); - if (DATA_SAVE_FUNCTION) - (*DATA_SAVE_FUNCTION)(node, file); - } - else { - traverse_trie_save(TrNode_child(node), file, float_block); - fprintf(file, "- "); - } - return; -} - - -static -void traverse_trie_load(TrNode parent, FILE *file) { - TrHash hash = NULL; - YAP_Term t; - - if (!fscanf(file, "%lu", &t)) { - MARK_AS_LEAF_TRIE_NODE(parent); - INCREMENT_ENTRIES(CURRENT_TRIE_ENGINE); - if (DATA_LOAD_FUNCTION) - (*DATA_LOAD_FUNCTION)(parent, CURRENT_DEPTH, file); - CURRENT_DEPTH--; - return; - } - if (t == HASH_SAVE_MARK) { - /* alloc a new trie hash */ - int num_buckets; - fscanf(file, "%d", &num_buckets); - new_trie_hash(hash, 0, num_buckets); - TrNode_child(parent) = (TrNode) hash; - fscanf(file, "%lu", &t); - } - do { - TrNode child; - if (t == ATOM_SAVE_MARK) { - int index; - fscanf(file, "%d", &index); - if (index > CURRENT_INDEX) { - char atom[1000]; - if (CURRENT_LOAD_VERSION == 2) { - char *ptr, ch; - ptr = atom; - fgetc(file); /* skip the first empty space */ - while ((ch = fgetc(file))) - *ptr++ = ch; - *ptr = '\0'; - } else if (CURRENT_LOAD_VERSION == 1) { - fscanf(file, "%s", atom); - } - CURRENT_INDEX = index; - if (CURRENT_INDEX == CURRENT_AUXILIARY_TERM_STACK_SIZE) - expand_auxiliary_term_stack(); - AUXILIARY_TERM_STACK[CURRENT_INDEX] = YAP_MkAtomTerm(YAP_LookupAtom(atom)); - } - t = AUXILIARY_TERM_STACK[index]; - } else if (t == FUNCTOR_SAVE_MARK) { - int index; - fscanf(file, "%d", &index); - if (index > CURRENT_INDEX) { - char atom[1000]; - int arity; - fscanf(file, "%s %d", atom, &arity); - CURRENT_INDEX = index; - if (CURRENT_INDEX == CURRENT_AUXILIARY_TERM_STACK_SIZE) - expand_auxiliary_term_stack(); - AUXILIARY_TERM_STACK[CURRENT_INDEX] = ApplTag | ((YAP_Term) YAP_MkFunctor(YAP_LookupAtom(atom), arity)); - } - t = AUXILIARY_TERM_STACK[index]; - } else if (t == FLOAT_SAVE_MARK) - fscanf(file, "%lu", &t); - child = trie_node_insert(parent, t, hash); - traverse_trie_load(child, file); - } while (fscanf(file, "%lu", &t)); - CURRENT_DEPTH--; - return; -} - - -static -void traverse_trie_print(TrNode node, YAP_Int *arity, char *str, int str_index, int mode) { - YAP_Term t; - YAP_Int new_arity[100]; - - if (IS_HASH_NODE(node)) { - TrNode *first_bucket, *bucket; - TrHash hash; - hash = (TrHash) node; - first_bucket = TrHash_buckets(hash); - bucket = first_bucket + TrHash_num_buckets(hash); - do { - if (*--bucket) { - node = *bucket; - memcpy(new_arity, arity, sizeof(YAP_Int) * 100); - traverse_trie_print(node, new_arity, str, str_index, mode); - } - } while (bucket != first_bucket); - return; - } - - if (TrNode_next(node)) { - memcpy(new_arity, arity, sizeof(YAP_Int) * 100); - traverse_trie_print(TrNode_next(node), new_arity, str, str_index, mode); - } - - t = TrNode_entry(node); - if (mode == TRIE_PRINT_FLOAT) { -#ifdef TAG_LOW_BITS_32 - arity[arity[0]] = (YAP_Int) t; - mode = TRIE_PRINT_FLOAT2; - } else if (mode == TRIE_PRINT_FLOAT2) { - volatile double f; - volatile YAP_Term *p; - p = (YAP_Term *)((void *) &f); /* to avoid gcc warning */ - *(p + 1) = t; - *p = (YAP_Term) arity[arity[0]]; -#else /* TAG_64BITS */ - volatile double f; - volatile YAP_Term *p; - p = (YAP_Term *)((void *) &f); /* to avoid gcc warning */ - *p = t; -#endif /* TAG_SCHEME */ - str_index += sprintf(& str[str_index], "%.10f", f); - mode = TRIE_PRINT_FLOAT_END; - } else if (mode == TRIE_PRINT_FLOAT_END) { - arity[0]--; - while (arity[0]) { - arity[arity[0]]--; - if (arity[arity[0]] == 0) { - str_index += sprintf(& str[str_index], ")"); - arity[0]--; - } else { - str_index += sprintf(& str[str_index], ","); - break; - } - } - mode = TRIE_PRINT_NORMAL; - } else if (YAP_IsVarTerm(t)) { - str_index += sprintf(& str[str_index], "VAR%ld", TrieVarIndex(t)); - while (arity[0]) { - arity[arity[0]]--; - if (arity[arity[0]] == 0) { - str_index += sprintf(& str[str_index], ")"); - arity[0]--; - } else { - str_index += sprintf(& str[str_index], ","); - break; - } - } - } else if (YAP_IsAtomTerm(t)) { - str_index += sprintf(& str[str_index], "%s", YAP_AtomName(YAP_AtomOfTerm(t))); - while (arity[0]) { - arity[arity[0]]--; - if (arity[arity[0]] == 0) { - str_index += sprintf(& str[str_index], ")"); - arity[0]--; - } else { - str_index += sprintf(& str[str_index], ","); - break; - } - } - } else if (YAP_IsIntTerm(t)) { - str_index += sprintf(& str[str_index], "%ld", YAP_IntOfTerm(t)); - while (arity[0]) { - arity[arity[0]]--; - if (arity[arity[0]] == 0) { - str_index += sprintf(& str[str_index], ")"); - arity[0]--; - } else { - str_index += sprintf(& str[str_index], ","); - break; - } - } - } else if (YAP_IsPairTerm(t)) { - if (t == FloatInitTag) { - mode = TRIE_PRINT_FLOAT; - arity[0]++; - arity[arity[0]] = -1; - } else if (t == PairInitTag) { - str_index += sprintf(& str[str_index], "["); - arity[0]++; - arity[arity[0]] = -1; - } else if (t == CommaInitTag) { - str_index += sprintf(& str[str_index], "("); - arity[0]++; - arity[arity[0]] = -1; - } else { - if (t == PairEndTag) - str[str_index - 1] = ']'; - else /* (t == CommaEndTag) */ - str[str_index - 1] = ')'; - arity[0]--; - while (arity[0]) { - arity[arity[0]]--; - if (arity[arity[0]] == 0) { - str_index += sprintf(& str[str_index], ")"); - arity[0]--; - } else { - str_index += sprintf(& str[str_index], ","); - break; - } - } - if (arity[0]) { - traverse_trie_print(TrNode_child(node), arity, str, str_index, mode); - } else { - str[str_index] = 0; - fprintf(stdout, "%s\n", str); - if (DATA_PRINT_FUNCTION) - (*DATA_PRINT_FUNCTION)(node); - } - str[str_index - 1] = ','; - return; - } - } else if (ApplTag & t) { - str_index += sprintf(& str[str_index], "%s(", YAP_AtomName(YAP_NameOfFunctor((YAP_Functor)(~ApplTag & t)))); - arity[0]++; - arity[arity[0]] = YAP_ArityOfFunctor((YAP_Functor)(~ApplTag & t)); - } else - fprintf(stderr, "\nTries base module: unknown type tag\n"); - - if (arity[0]) { - traverse_trie_print(TrNode_child(node), arity, str, str_index, mode); - } else { - str[str_index] = 0; - fprintf(stdout, "%s\n", str); - if (DATA_PRINT_FUNCTION) - (*DATA_PRINT_FUNCTION)(node); - } +inline +void trie_print(TrEntry trie) { + core_trie_print(TrEntry_trie(trie), NULL); return; } diff --git a/library/Tries/base_tries.h b/library/Tries/base_tries.h index acd40a4eb..7430b21cf 100644 --- a/library/Tries/base_tries.h +++ b/library/Tries/base_tries.h @@ -7,112 +7,45 @@ -/* -------------------------------------- */ -/* Yap Tagging Scheme */ -/* -------------------------------------- */ - -#include "config.h" -#if SIZEOF_INT_P==4 -#define TAG_LOW_BITS_32 /* 'Tags_32LowTag.h' tagging scheme */ -#elif SIZEOF_INT_P==8 -#define TAG_64BITS /* 'Tags_64bits.h' tagging scheme */ -#else -#error Unknown tagging scheme -#endif /* YAP_SCHEME */ - - - -/* --------------------------- */ -/* Defines */ -/* --------------------------- */ - -#ifdef TAG_LOW_BITS_32 -#define ApplTag 1 /* 0x01 */ -#else /* TAG_64BITS */ -#define ApplTag 5 /* 0x05 */ -#endif /* TAG_SCHEME */ -#define PairInitTag 3 /* 0x03 */ -#define PairEndTag 19 /* 0x13 */ -#define CommaInitTag 35 /* 0x23 */ -#define CommaEndTag 51 /* 0x33 */ -#define FloatInitTag 67 /* 0x43 */ -#define FloatEndTag 83 /* 0x53 */ - -#define TRIE_MODE_STANDARD 0 -#define TRIE_MODE_REVERSE 1 - -#define TRIE_PRINT_NORMAL 0 -#define TRIE_PRINT_FLOAT 1 -#define TRIE_PRINT_FLOAT2 2 -#define TRIE_PRINT_FLOAT_END 3 - -#define BASE_AUXILIARY_TERM_STACK_SIZE 1000 - - - /* --------------------------- */ /* Structs */ /* --------------------------- */ -typedef struct trie_engine { - struct trie_node *first_trie; - YAP_Int memory_in_use; - YAP_Int tries_in_use; - YAP_Int entries_in_use; - YAP_Int nodes_in_use; - YAP_Int memory_max_used; - YAP_Int tries_max_used; - YAP_Int entries_max_used; - YAP_Int nodes_max_used; -} *TrEngine; +typedef struct trie_entry { + struct trie_node *top_trie_node; + struct trie_data *first_trie_data; + struct trie_data *last_trie_data; + struct trie_data *traverse_trie_data; + struct trie_entry *next; + struct trie_entry *previous; +} *TrEntry; -#define TrEngine_trie(X) ((X)->first_trie) -#define TrEngine_memory(X) ((X)->memory_in_use) -#define TrEngine_tries(X) ((X)->tries_in_use) -#define TrEngine_entries(X) ((X)->entries_in_use) -#define TrEngine_nodes(X) ((X)->nodes_in_use) -#define TrEngine_memory_max(X) ((X)->memory_max_used) -#define TrEngine_tries_max(X) ((X)->tries_max_used) -#define TrEngine_entries_max(X) ((X)->entries_max_used) -#define TrEngine_nodes_max(X) ((X)->nodes_max_used) +#define TrEntry_trie(X) ((X)->top_trie_node) +#define TrEntry_first_data(X) ((X)->first_trie_data) +#define TrEntry_last_data(X) ((X)->last_trie_data) +#define TrEntry_traverse_data(X) ((X)->traverse_trie_data) +#define TrEntry_next(X) ((X)->next) +#define TrEntry_previous(X) ((X)->previous) -typedef struct trie_node { - struct trie_node *parent; - struct trie_node *child; - struct trie_node *next; - struct trie_node *previous; - YAP_Term entry; -} *TrNode; +typedef struct trie_data { + struct trie_entry *trie; + struct trie_node *leaf_trie_node; + struct trie_data *next; + struct trie_data *previous; +} *TrData; -#define TrNode_parent(X) ((X)->parent) -#define TrNode_child(X) ((X)->child) -#define TrNode_next(X) ((X)->next) -#define TrNode_previous(X) ((X)->previous) -#define TrNode_entry(X) ((X)->entry) +#define TrData_trie(X) ((X)->trie) +#define TrData_leaf(X) ((X)->leaf_trie_node) +#define TrData_next(X) ((X)->next) +#define TrData_previous(X) ((X)->previous) -typedef struct trie_hash { - struct trie_node *parent; /* for compatibility with the trie_node data structure */ - struct trie_node **buckets; - int number_of_buckets; - int number_of_nodes; -} *TrHash; +#define TYPE_TR_ENTRY struct trie_entry +#define TYPE_TR_DATA struct trie_data +#define SIZEOF_TR_ENTRY sizeof(TYPE_TR_ENTRY) +#define SIZEOF_TR_DATA sizeof(TYPE_TR_DATA) -#define TrHash_mark(X) ((X)->parent) -#define TrHash_buckets(X) ((X)->buckets) -#define TrHash_bucket(X,N) ((X)->buckets + N) -#define TrHash_num_buckets(X) ((X)->number_of_buckets) -#define TrHash_seed(X) ((X)->number_of_buckets - 1) -#define TrHash_num_nodes(X) ((X)->number_of_nodes) - -#define TYPE_TR_ENGINE struct trie_engine -#define TYPE_TR_NODE struct trie_node -#define TYPE_TR_HASH struct trie_hash -#define SIZEOF_TR_ENGINE sizeof(TYPE_TR_ENGINE) -#define SIZEOF_TR_NODE sizeof(TYPE_TR_NODE) -#define SIZEOF_TR_HASH sizeof(TYPE_TR_HASH) -#define SIZEOF_TR_BUCKET sizeof(TYPE_TR_NODE *) - -#define AS_TR_NODE_NEXT(ADDR) (TrNode)((unsigned long int)(ADDR) - 2 * sizeof(struct trie_node *)) +#define AS_TR_ENTRY_NEXT(ADDR) (TrEntry)((unsigned long int)(ADDR) - sizeof(struct trie_node *) - 3 * sizeof(struct trie_data *)) +#define AS_TR_DATA_NEXT(ADDR) (TrData)((unsigned long int)(ADDR) - sizeof(struct trie_entry *) - sizeof(struct trie_node *)) @@ -120,144 +53,44 @@ typedef struct trie_hash { /* Macros */ /* --------------------------- */ -#define TAG_ADDR(ADDR) ((unsigned long int)(ADDR) | 0x1) -#define UNTAG_ADDR(ADDR) ((unsigned long int)(ADDR) & ~(0x1)) -#define PUT_DATA_IN_LEAF_TRIE_NODE(TR_NODE, DATA) TrNode_child(TR_NODE) = (TrNode)TAG_ADDR(DATA) -#define GET_DATA_FROM_LEAF_TRIE_NODE(TR_NODE) UNTAG_ADDR(TrNode_child(TR_NODE)) -#define MARK_AS_LEAF_TRIE_NODE(TR_NODE) PUT_DATA_IN_LEAF_TRIE_NODE(TR_NODE, TrNode_child(TR_NODE)) -#define IS_LEAF_TRIE_NODE(TR_NODE) ((unsigned long int)(TrNode_child(TR_NODE)) & 0x1) - -#define IsTrieVar(TERM, STACK, STACK_BASE) ((YAP_Term *)(TERM) > STACK && (YAP_Term *)(TERM) <= STACK_BASE) -#define MkTrieVar(INDEX) ((INDEX) << 4) -#define TrieVarIndex(TERM) ((TERM) >> 4) - -#define BASE_HASH_BUCKETS 64 -#define MAX_NODES_PER_TRIE_LEVEL 8 -#define MAX_NODES_PER_BUCKET (MAX_NODES_PER_TRIE_LEVEL / 2) -#define HASH_TERM(TERM, SEED) (((TERM) >> 4) & (SEED)) -#define IS_HASH_NODE(NODE) (TrHash_mark(NODE) == NULL) - -#define BASE_SAVE_MARK 1000 /* could lead to errors if the number of different variables in a term is greater than it */ -#define HASH_SAVE_MARK ((YAP_Term) MkTrieVar(BASE_SAVE_MARK)) -#define ATOM_SAVE_MARK ((YAP_Term) MkTrieVar(BASE_SAVE_MARK + 1)) -#define FUNCTOR_SAVE_MARK ((YAP_Term) MkTrieVar(BASE_SAVE_MARK + 2)) -#define FLOAT_SAVE_MARK ((YAP_Term) MkTrieVar(BASE_SAVE_MARK + 3)) - -#define STACK_NOT_EMPTY(STACK, STACK_BASE) STACK != STACK_BASE -#define POP_UP(STACK) *--STACK -#define POP_DOWN(STACK) *++STACK -#define PUSH_UP(STACK, ITEM, STACK_TOP) \ - { if (STACK < STACK_TOP) \ - fprintf(stderr, "\nTries base module: term stack full"); \ - *STACK = (YAP_Term)(ITEM); \ - STACK--; \ - } -#define PUSH_DOWN(STACK, ITEM, STACK_TOP) \ - { if (STACK > STACK_TOP) \ - fprintf(stderr, "\nTries base module: term stack full"); \ - *STACK = (YAP_Term)(ITEM); \ - STACK++; \ +#define new_trie_entry(TR_ENTRY, TR_NODE) \ + { new_struct(TR_ENTRY, TYPE_TR_ENTRY, SIZEOF_TR_ENTRY); \ + TrEntry_trie(TR_ENTRY) = TR_NODE; \ + TrEntry_first_data(TR_ENTRY) = NULL; \ + TrEntry_last_data(TR_ENTRY) = NULL; \ + TrEntry_traverse_data(TR_ENTRY) = NULL; \ + TrEntry_next(TR_ENTRY) = FIRST_TRIE; \ + TrEntry_previous(TR_ENTRY) = AS_TR_ENTRY_NEXT(&FIRST_TRIE); \ + INCREMENT_MEMORY(TRIE_ENGINE, SIZEOF_TR_ENTRY); \ } +#define new_trie_data(TR_DATA, TR_ENTRY, TR_NODE) \ + { TrData last_data = TrEntry_last_data(TR_ENTRY); \ + new_struct(TR_DATA, TYPE_TR_DATA, SIZEOF_TR_DATA); \ + TrData_trie(TR_DATA) = TR_ENTRY; \ + TrData_leaf(TR_DATA) = TR_NODE; \ + TrData_next(TR_DATA) = NULL; \ + if (last_data) { \ + TrData_next(last_data) = TR_DATA; \ + TrData_previous(TR_DATA) = last_data; \ + TrEntry_last_data(TR_ENTRY) = TR_DATA; \ + } else { \ + TrData_previous(TR_DATA) = AS_TR_DATA_NEXT(&TrEntry_first_data(TR_ENTRY)); \ + TrEntry_first_data(TR_ENTRY) = TR_DATA; \ + TrEntry_last_data(TR_ENTRY) = TR_DATA; \ + } \ + INCREMENT_MEMORY(TRIE_ENGINE, SIZEOF_TR_DATA); \ + } -#define new_struct(STR, STR_TYPE, STR_SIZE) \ - STR = (STR_TYPE *) YAP_AllocSpaceFromYap(STR_SIZE) -#define new_trie_engine(TR_ENGINE) \ - { new_struct(TR_ENGINE, TYPE_TR_ENGINE, SIZEOF_TR_ENGINE); \ - TrEngine_trie(TR_ENGINE) = NULL; \ - TrEngine_memory(TR_ENGINE) = 0; \ - TrEngine_tries(TR_ENGINE) = 0; \ - TrEngine_entries(TR_ENGINE) = 0; \ - TrEngine_nodes(TR_ENGINE) = 0; \ - TrEngine_memory_max(TR_ENGINE) = 0; \ - TrEngine_tries_max(TR_ENGINE) = 0; \ - TrEngine_entries_max(TR_ENGINE) = 0; \ - TrEngine_nodes_max(TR_ENGINE) = 0; \ - } -#define new_trie_node(TR_NODE, ENTRY, PARENT, CHILD, NEXT, PREVIOUS) \ - { new_struct(TR_NODE, TYPE_TR_NODE, SIZEOF_TR_NODE); \ - TrNode_entry(TR_NODE) = ENTRY; \ - TrNode_parent(TR_NODE) = PARENT; \ - TrNode_child(TR_NODE) = CHILD; \ - TrNode_next(TR_NODE) = NEXT; \ - TrNode_previous(TR_NODE) = PREVIOUS; \ - INCREMENT_NODES(CURRENT_TRIE_ENGINE); \ - INCREMENT_MEMORY(CURRENT_TRIE_ENGINE, SIZEOF_TR_NODE); \ - } -#define new_trie_hash(TR_HASH, NUM_NODES, NUM_BUCKETS) \ - { new_struct(TR_HASH, TYPE_TR_HASH, SIZEOF_TR_HASH); \ - TrHash_mark(TR_HASH) = NULL; \ - TrHash_num_buckets(TR_HASH) = NUM_BUCKETS; \ - new_hash_buckets(TR_HASH, NUM_BUCKETS); \ - TrHash_num_nodes(TR_HASH) = NUM_NODES; \ - INCREMENT_MEMORY(CURRENT_TRIE_ENGINE, SIZEOF_TR_HASH); \ - } -#define new_hash_buckets(TR_HASH, NUM_BUCKETS) \ - { int i; void **ptr; \ - new_struct(ptr, void *, NUM_BUCKETS * sizeof(void *)); \ - TrHash_buckets(TR_HASH) = (TYPE_TR_NODE **) ptr; \ - for (i = NUM_BUCKETS; i != 0; i--) \ - *ptr++ = NULL; \ - INCREMENT_MEMORY(CURRENT_TRIE_ENGINE, (NUM_BUCKETS) * SIZEOF_TR_BUCKET); \ - } - -#define expand_auxiliary_term_stack() \ - { YAP_Term *aux_stack; \ - YAP_Int aux_size = CURRENT_AUXILIARY_TERM_STACK_SIZE * sizeof(YAP_Term); \ - new_struct(aux_stack, YAP_Term, aux_size * 2); \ - memcpy(aux_stack, AUXILIARY_TERM_STACK, aux_size); \ - free_struct(AUXILIARY_TERM_STACK); \ - AUXILIARY_TERM_STACK = aux_stack; \ - CURRENT_AUXILIARY_TERM_STACK_SIZE *= 2; \ +#define free_trie_entry(STR) \ + { free_struct(STR); \ + DECREMENT_MEMORY(TRIE_ENGINE, SIZEOF_TR_ENTRY); \ } - - -#define free_struct(STR) \ - YAP_FreeSpaceFromYap((char *) (STR)) -#define free_trie_node(STR) \ - { free_struct(STR); \ - DECREMENT_NODES(CURRENT_TRIE_ENGINE); \ - DECREMENT_MEMORY(CURRENT_TRIE_ENGINE, SIZEOF_TR_NODE); \ - } -#define free_trie_hash(STR) \ - { free_struct(STR); \ - DECREMENT_MEMORY(CURRENT_TRIE_ENGINE, SIZEOF_TR_HASH); \ - } -#define free_hash_buckets(STR, NUM_BUCKETS) \ - { free_struct(STR); \ - DECREMENT_MEMORY(CURRENT_TRIE_ENGINE, (NUM_BUCKETS) * SIZEOF_TR_BUCKET); \ - } - - -#define INCREMENT_MEMORY(TR_ENGINE, SIZE) \ - { TrEngine_memory(TR_ENGINE) += SIZE; \ - if (TrEngine_memory(TR_ENGINE) > TrEngine_memory_max(TR_ENGINE)) \ - TrEngine_memory_max(TR_ENGINE) = TrEngine_memory(TR_ENGINE); \ - } -#define INCREMENT_TRIES(TR_ENGINE) \ - { TrEngine_tries(TR_ENGINE)++; \ - if (TrEngine_tries(TR_ENGINE) > TrEngine_tries_max(TR_ENGINE)) \ - TrEngine_tries_max(TR_ENGINE) = TrEngine_tries(TR_ENGINE); \ - } -#define INCREMENT_ENTRIES(TR_ENGINE) \ - { TrEngine_entries(TR_ENGINE)++; \ - if (TrEngine_entries(TR_ENGINE) > TrEngine_entries_max(TR_ENGINE)) \ - TrEngine_entries_max(TR_ENGINE) = TrEngine_entries(TR_ENGINE); \ - } -#define INCREMENT_NODES(TR_ENGINE) \ - { TrEngine_nodes(TR_ENGINE)++; \ - if (TrEngine_nodes(TR_ENGINE) > TrEngine_nodes_max(TR_ENGINE)) \ - TrEngine_nodes_max(TR_ENGINE) = TrEngine_nodes(TR_ENGINE); \ - } -#define DECREMENT_MEMORY(TR_ENGINE, SIZE) \ - TrEngine_memory(TR_ENGINE) -= SIZE -#define DECREMENT_TRIES(TR_ENGINE) \ - TrEngine_tries(TR_ENGINE)-- -#define DECREMENT_ENTRIES(TR_ENGINE) \ - TrEngine_entries(TR_ENGINE)-- -#define DECREMENT_NODES(TR_ENGINE) \ - TrEngine_nodes(TR_ENGINE)-- +#define free_trie_data(STR) \ + { free_struct(STR); \ + DECREMENT_MEMORY(TRIE_ENGINE, SIZEOF_TR_DATA); \ + } @@ -265,25 +98,29 @@ typedef struct trie_hash { /* API */ /* --------------------------- */ -inline TrEngine trie_init_module(void); -inline TrNode trie_open(TrEngine engine); -inline void trie_close(TrEngine engine, TrNode node, void (*destruct_function)(TrNode)); -inline void trie_close_all(TrEngine engine, void (*destruct_function)(TrNode)); +inline void trie_init_module(void); +inline void trie_data_load(TrNode node, YAP_Int depth, FILE *file); +inline void trie_data_copy(TrNode node_dest, TrNode node_source); +inline void trie_data_destruct(TrNode node); +inline TrEntry trie_open(void); +inline void trie_close(TrEntry trie); +inline void trie_close_all(void); inline void trie_set_mode(YAP_Int mode); inline YAP_Int trie_get_mode(void); -inline TrNode trie_put_entry(TrEngine engine, TrNode node, YAP_Term entry, YAP_Int *depth); -inline TrNode trie_check_entry(TrNode node, YAP_Term entry); -inline YAP_Term trie_get_entry(TrNode node); -inline void trie_remove_entry(TrEngine engine, TrNode node, void (*destruct_function)(TrNode)); -inline void trie_remove_subtree(TrEngine engine, TrNode node, void (*destruct_function)(TrNode)); -inline void trie_add(TrNode node_dest, TrNode node_source, void (*add_function)(TrNode, TrNode)); -inline void trie_join(TrEngine engine, TrNode node_dest, TrNode node_source, void (*add_function)(TrNode, TrNode), void (*construct_function)(TrNode, TrNode)); -inline void trie_intersect(TrEngine engine, TrNode node_dest, TrNode node_source, void (*add_function)(TrNode, TrNode), void (*destruct_function)(TrNode)); -inline YAP_Int trie_count_join(TrNode node1, TrNode node2); -inline YAP_Int trie_count_intersect(TrNode node1, TrNode node2); -inline void trie_save(TrNode node, FILE *file, void (*save_function)(TrNode, FILE *)); -inline TrNode trie_load(TrEngine engine, FILE *file, void (*load_function)(TrNode, YAP_Int, FILE *)); -inline void trie_stats(TrEngine engine, YAP_Int *memory, YAP_Int *tries, YAP_Int *entries, YAP_Int *nodes); -inline void trie_max_stats(TrEngine engine, YAP_Int *memory, YAP_Int *tries, YAP_Int *entries, YAP_Int *nodes); -inline void trie_usage(TrNode node, YAP_Int *entries, YAP_Int *nodes, YAP_Int *virtual_nodes); -inline void trie_print(TrNode node, void (*print_function)(TrNode)); +inline TrData trie_put_entry(TrEntry trie, YAP_Term entry); +inline TrData trie_check_entry(TrEntry trie, YAP_Term entry); +inline YAP_Term trie_get_entry(TrData data); +inline TrData trie_traverse_init(TrEntry trie); +inline TrData trie_traverse_cont(TrEntry trie); +inline void trie_remove_entry(TrData data); +inline void trie_remove_subtree(TrData data); +inline void trie_join(TrEntry trie_dest, TrEntry trie_source); +inline void trie_intersect(TrEntry trie_dest, TrEntry trie_source); +inline YAP_Int trie_count_join(TrEntry trie1, TrEntry trie2); +inline YAP_Int trie_count_intersect(TrEntry trie1, TrEntry trie2); +inline void trie_save(TrEntry trie, FILE *file); +inline TrEntry trie_load(FILE *file); +inline void trie_stats(YAP_Int *memory, YAP_Int *tries, YAP_Int *entries, YAP_Int *nodes); +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); diff --git a/library/Tries/core_tries.c b/library/Tries/core_tries.c new file mode 100644 index 000000000..4e276cec2 --- /dev/null +++ b/library/Tries/core_tries.c @@ -0,0 +1,1468 @@ +/********************************************* + File: core_tries.c + Author: Ricardo Rocha + Comments: Tries core module for Yap Prolog + version: $ID$ +*********************************************/ + + + +/* -------------------------- */ +/* Includes */ +/* -------------------------- */ + +#include +#include +#include +#include "core_tries.h" + + + +/* -------------------------- */ +/* Local Procedures */ +/* -------------------------- */ + +static TrNode put_entry(TrNode node, YAP_Term entry); +static TrNode check_entry(TrNode node, YAP_Term entry); +static YAP_Term get_entry(TrNode node, YAP_Term *stack_list, TrNode *cur_node); +static void remove_entry(TrNode node); +static void remove_child_nodes(TrNode node); +static TrNode copy_child_nodes(TrNode parent_dest, TrNode node_source); +static void traverse_and_add(TrNode parent_dest, TrNode parent_source); +static void traverse_and_join(TrNode parent_dest, TrNode parent_source); +static void traverse_and_intersect(TrNode parent_dest, TrNode parent_source); +static YAP_Int traverse_and_count_common_entries(TrNode parent1, TrNode parent2); +static YAP_Int traverse_and_count_entries(TrNode node); +static void traverse_and_get_usage(TrNode node, YAP_Int depth); +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, YAP_Int *arity, char *str, int str_index, int mode); + + + +/* -------------------------- */ +/* Local Variables */ +/* -------------------------- */ + +static TrEngine CURRENT_TRIE_ENGINE; +static YAP_Int USAGE_ENTRIES, USAGE_NODES, USAGE_VIRTUAL_NODES; +static YAP_Int CURRENT_AUXILIARY_TERM_STACK_SIZE, CURRENT_TRIE_MODE, CURRENT_LOAD_VERSION, CURRENT_DEPTH, CURRENT_INDEX; +static YAP_Term *AUXILIARY_TERM_STACK; +static YAP_Term *stack_args, *stack_args_base, *stack_vars, *stack_vars_base; +static YAP_Functor FunctorComma; +static void (*DATA_SAVE_FUNCTION)(TrNode, FILE *); +static void (*DATA_LOAD_FUNCTION)(TrNode, YAP_Int, FILE *); +static void (*DATA_PRINT_FUNCTION)(TrNode); +static void (*DATA_ADD_FUNCTION)(TrNode, TrNode); +static void (*DATA_COPY_FUNCTION)(TrNode, TrNode); +static void (*DATA_DESTRUCT_FUNCTION)(TrNode); + + + +/* -------------------------- */ +/* Inline Procedures */ +/* -------------------------- */ + +static inline +TrNode trie_node_check_insert(TrNode parent, YAP_Term t) { + TrNode child; + + CURRENT_DEPTH++; + child = TrNode_child(parent); + if (child == NULL) { + new_trie_node(child, t, parent, NULL, NULL, NULL); + TrNode_child(parent) = child; + } else if (IS_HASH_NODE(child)) { + TrHash hash; + TrNode *bucket; + int count; + hash = (TrHash) child; + bucket = TrHash_bucket(hash, HASH_TERM(t, TrHash_seed(hash))); + child = *bucket; + count = 0; + while (child) { + if (TrNode_entry(child) == t) + return child; + count++; + child = TrNode_next(child); + } while (child); + TrHash_num_nodes(hash)++; + new_trie_node(child, t, parent, NULL, *bucket, AS_TR_NODE_NEXT(bucket)); + if (*bucket) + TrNode_previous(*bucket) = child; + *bucket = child; + if (count > MAX_NODES_PER_BUCKET && TrHash_num_nodes(hash) > TrHash_num_buckets(hash)) { + /* expand trie hash */ + TrNode chain, next, *first_bucket, *new_bucket; + int seed; + first_bucket = TrHash_buckets(hash); + bucket = first_bucket + TrHash_num_buckets(hash); + TrHash_num_buckets(hash) *= 2; + new_hash_buckets(hash, TrHash_num_buckets(hash)); + seed = TrHash_num_buckets(hash) - 1; + do { + if (*--bucket) { + chain = *bucket; + do { + 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; + *new_bucket = chain; + chain = next; + } while (chain); + } + } while (bucket != first_bucket); + free_hash_buckets(first_bucket, TrHash_num_buckets(hash) / 2); + } + } else { + int count = 0; + do { + if (TrNode_entry(child) == t) + 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) { + /* alloc a new trie hash */ + TrHash hash; + TrNode chain, next, *bucket; + new_trie_hash(hash, count, BASE_HASH_BUCKETS); + chain = child; + do { + bucket = TrHash_bucket(hash, HASH_TERM(TrNode_entry(chain), BASE_HASH_BUCKETS - 1)); + next = TrNode_next(chain); + TrNode_next(chain) = *bucket; + TrNode_previous(chain) = AS_TR_NODE_NEXT(bucket); + if (*bucket) + TrNode_previous(*bucket) = chain; + *bucket = chain; + chain = next; + } while (chain); + TrNode_child(parent) = (TrNode) hash; + } else + TrNode_child(parent) = child; + } + return child; +} + + +static inline +TrNode trie_node_insert(TrNode parent, YAP_Term t, TrHash hash) { + TrNode child; + + CURRENT_DEPTH++; + if (hash) { + /* is trie hash */ + TrNode *bucket; + TrHash_num_nodes(hash)++; + bucket = TrHash_bucket(hash, HASH_TERM(t, TrHash_seed(hash))); + new_trie_node(child, t, parent, NULL, *bucket, AS_TR_NODE_NEXT(bucket)); + if (*bucket) + TrNode_previous(*bucket) = child; + *bucket = child; + } else { + new_trie_node(child, t, parent, NULL, TrNode_child(parent), NULL); + if (TrNode_child(parent)) + TrNode_previous(TrNode_child(parent)) = child; + TrNode_child(parent) = child; + } + return child; +} + + +static inline +TrNode trie_node_check(TrNode parent, YAP_Term t) { + TrNode child; + + child = TrNode_child(parent); + if (IS_HASH_NODE(child)) { + TrHash hash; + TrNode *bucket; + hash = (TrHash) child; + bucket = TrHash_bucket(hash, HASH_TERM(t, TrHash_seed(hash))); + child = *bucket; + if (!child) + return NULL; + } + do { + if (TrNode_entry(child) == t) + return child; + child = TrNode_next(child); + } while (child); + return NULL; +} + + + +/* -------------------------- */ +/* API */ +/* -------------------------- */ + +inline +TrEngine core_trie_init_module(void) { + static int init_once = 1; + TrEngine engine; + + if (init_once) { + new_struct(AUXILIARY_TERM_STACK, YAP_Term, BASE_AUXILIARY_TERM_STACK_SIZE * sizeof(YAP_Term)); + CURRENT_AUXILIARY_TERM_STACK_SIZE = BASE_AUXILIARY_TERM_STACK_SIZE; + CURRENT_TRIE_MODE = TRIE_MODE_STANDARD; + FunctorComma = YAP_MkFunctor(YAP_LookupAtom(","), 2); + init_once = 0; + } + new_trie_engine(engine); + return engine; +} + + +inline +TrNode core_trie_open(TrEngine engine) { + TrNode node; + + CURRENT_TRIE_ENGINE = engine; + new_trie_node(node, 0, NULL, NULL, TrEngine_trie(engine), AS_TR_NODE_NEXT(&TrEngine_trie(engine))); + if (TrEngine_trie(engine)) + TrNode_previous(TrEngine_trie(engine)) = node; + TrEngine_trie(engine) = node; + INCREMENT_TRIES(CURRENT_TRIE_ENGINE); + return node; +} + + +inline +void core_trie_close(TrEngine engine, TrNode node, void (*destruct_function)(TrNode)) { + CURRENT_TRIE_ENGINE = engine; + DATA_DESTRUCT_FUNCTION = destruct_function; + if (TrNode_child(node)) + remove_child_nodes(TrNode_child(node)); + if (TrNode_next(node)) { + TrNode_previous(TrNode_next(node)) = TrNode_previous(node); + TrNode_next(TrNode_previous(node)) = TrNode_next(node); + } else + TrNode_next(TrNode_previous(node)) = NULL; + free_trie_node(node); + DECREMENT_TRIES(CURRENT_TRIE_ENGINE); + return; +} + + +inline +void core_trie_close_all(TrEngine engine, void (*destruct_function)(TrNode)) { + while (TrEngine_trie(engine)) + core_trie_close(engine, TrEngine_trie(engine), destruct_function); + return; +} + + +inline +void core_trie_set_mode(YAP_Int mode) { + CURRENT_TRIE_MODE = mode; + return; +} + + +inline +YAP_Int core_trie_get_mode(void) { + return CURRENT_TRIE_MODE; +} + + +inline +TrNode core_trie_put_entry(TrEngine engine, TrNode node, YAP_Term entry, YAP_Int *depth) { + CURRENT_TRIE_ENGINE = engine; + CURRENT_DEPTH = 0; + stack_args_base = stack_args = AUXILIARY_TERM_STACK; + stack_vars_base = stack_vars = AUXILIARY_TERM_STACK + CURRENT_AUXILIARY_TERM_STACK_SIZE - 1; + node = put_entry(node, entry); + if (!IS_LEAF_TRIE_NODE(node)) { + MARK_AS_LEAF_TRIE_NODE(node); + INCREMENT_ENTRIES(CURRENT_TRIE_ENGINE); + } + /* reset var terms */ + while (STACK_NOT_EMPTY(stack_vars++, stack_vars_base)) { + POP_DOWN(stack_vars); + *((YAP_Term *)*stack_vars) = *stack_vars; + } + if (depth) + *depth = CURRENT_DEPTH; + return node; +} + + +inline +TrNode core_trie_check_entry(TrNode node, YAP_Term entry) { + if (!TrNode_child(node)) + return NULL; + stack_args_base = stack_args = AUXILIARY_TERM_STACK; + stack_vars_base = stack_vars = AUXILIARY_TERM_STACK + CURRENT_AUXILIARY_TERM_STACK_SIZE - 1; + node = check_entry(node, entry); + /* reset var terms */ + while (STACK_NOT_EMPTY(stack_vars++, stack_vars_base)) { + POP_DOWN(stack_vars); + *((YAP_Term *)*stack_vars) = *stack_vars; + } + return node; +} + + +inline +YAP_Term core_trie_get_entry(TrNode node) { + CURRENT_INDEX = -1; + stack_vars_base = stack_vars = AUXILIARY_TERM_STACK; + stack_args_base = stack_args = AUXILIARY_TERM_STACK + CURRENT_AUXILIARY_TERM_STACK_SIZE - 1; + return get_entry(node, stack_args, &node); +} + + +inline +void core_trie_remove_entry(TrEngine engine, TrNode node, void (*destruct_function)(TrNode)) { + CURRENT_TRIE_ENGINE = engine; + DATA_DESTRUCT_FUNCTION = destruct_function; + if (DATA_DESTRUCT_FUNCTION) + (*DATA_DESTRUCT_FUNCTION)(node); + DECREMENT_ENTRIES(CURRENT_TRIE_ENGINE); + remove_entry(node); + return; +} + + +inline +void core_trie_remove_subtree(TrEngine engine, TrNode node, void (*destruct_function)(TrNode)) { + TrNode parent; + + CURRENT_TRIE_ENGINE = engine; + DATA_DESTRUCT_FUNCTION = destruct_function; + parent = TrNode_parent(node); + remove_child_nodes(TrNode_child(parent)); + remove_entry(parent); + return; +} + + +inline +void core_trie_add(TrNode node_dest, TrNode node_source, void (*add_function)(TrNode, TrNode)) { + DATA_ADD_FUNCTION = add_function; + if (TrNode_child(node_dest) && TrNode_child(node_source)) + traverse_and_add(node_dest, node_source); + return; +} + + +inline +void core_trie_join(TrEngine engine, TrNode node_dest, TrNode node_source, void (*add_function)(TrNode, TrNode), void (*copy_function)(TrNode, TrNode)) { + CURRENT_TRIE_ENGINE = engine; + DATA_ADD_FUNCTION = add_function; + DATA_COPY_FUNCTION = copy_function; + if (TrNode_child(node_dest)) { + if (TrNode_child(node_source)) + traverse_and_join(node_dest, node_source); + } else if (TrNode_child(node_source)) + TrNode_child(node_dest) = copy_child_nodes(node_dest, TrNode_child(node_source)); + return; +} + + +inline +void core_trie_intersect(TrEngine engine, TrNode node_dest, TrNode node_source, void (*add_function)(TrNode, TrNode), void (*destruct_function)(TrNode)) { + CURRENT_TRIE_ENGINE = engine; + DATA_ADD_FUNCTION = add_function; + DATA_DESTRUCT_FUNCTION = destruct_function; + if (TrNode_child(node_dest)) { + if (TrNode_child(node_source)) + traverse_and_intersect(node_dest, node_source); + else { + remove_child_nodes(TrNode_child(node_dest)); + TrNode_child(node_dest) = NULL; + } + } + return; +} + + +inline +YAP_Int core_trie_count_join(TrNode node1, TrNode node2) { + YAP_Int count = 0; + + if (TrNode_child(node1)) { + count += traverse_and_count_entries(TrNode_child(node1)); + if (TrNode_child(node2)) { + count += traverse_and_count_entries(TrNode_child(node2)); + count -= traverse_and_count_common_entries(node1, node2); + } + } else if (TrNode_child(node2)) + count += traverse_and_count_entries(TrNode_child(node2)); + return count; +} + + +inline +YAP_Int core_trie_count_intersect(TrNode node1, TrNode node2) { + YAP_Int count = 0; + + if (TrNode_child(node1)) + if (TrNode_child(node2)) + count = traverse_and_count_common_entries(node1, node2); + return count; +} + + +inline +void core_trie_save(TrNode node, FILE *file, void (*save_function)(TrNode, FILE *)) { + CURRENT_INDEX = -1; + DATA_SAVE_FUNCTION = save_function; + if (TrNode_child(node)) { + fprintf(file, "BEGIN_TRIE_v2 "); + traverse_and_save(TrNode_child(node), file, 0); + fprintf(file, "END_TRIE_v2"); + } + return; +} + + +inline +TrNode core_trie_load(TrEngine engine, FILE *file, void (*load_function)(TrNode, YAP_Int, FILE *)) { + TrNode node; + char version[15]; + + CURRENT_TRIE_ENGINE = engine; + CURRENT_INDEX = -1; + CURRENT_DEPTH = 0; + DATA_LOAD_FUNCTION = load_function; + node = core_trie_open(engine); + fscanf(file, "%s", version); + if (!strcmp(version, "BEGIN_TRIE_v2")) { + CURRENT_LOAD_VERSION = 2; + traverse_and_load(node, file); + } else if (!strcmp(version, "BEGIN_TRIE")) { + CURRENT_LOAD_VERSION = 1; + traverse_and_load(node, file); + } + return node; +} + + +inline +void core_trie_stats(TrEngine engine, YAP_Int *memory, YAP_Int *tries, YAP_Int *entries, YAP_Int *nodes) { + *memory = TrEngine_memory(engine); + *tries = TrEngine_tries(engine); + *entries = TrEngine_entries(engine); + *nodes = TrEngine_nodes(engine); + return; +} + + +inline +void core_trie_max_stats(TrEngine engine, YAP_Int *memory, YAP_Int *tries, YAP_Int *entries, YAP_Int *nodes) { + *memory = TrEngine_memory_max(engine); + *tries = TrEngine_tries_max(engine); + *entries = TrEngine_entries_max(engine); + *nodes = TrEngine_nodes_max(engine); + return; +} + + +inline +void core_trie_usage(TrNode node, YAP_Int *entries, YAP_Int *nodes, YAP_Int *virtual_nodes) { + USAGE_ENTRIES = 0; + USAGE_NODES = 0; + USAGE_VIRTUAL_NODES = 0; + if (TrNode_child(node)) + traverse_and_get_usage(TrNode_child(node), 0); + *entries = USAGE_ENTRIES; + *nodes = USAGE_NODES; + *virtual_nodes = USAGE_VIRTUAL_NODES; + return; +} + + +inline +void core_trie_print(TrNode node, void (*print_function)(TrNode)) { + DATA_PRINT_FUNCTION = print_function; + if (TrNode_child(node)) { + YAP_Int arity[100]; + char str[1000]; + arity[0] = 0; + traverse_and_print(TrNode_child(node), arity, str, 0, TRIE_PRINT_NORMAL); + } else + fprintf(stdout, "(empty)\n"); + return; +} + + + + +/* -------------------------- */ +/* Local Procedures */ +/* -------------------------- */ + +static +TrNode put_entry(TrNode node, YAP_Term entry) { + YAP_Term t = YAP_Deref(entry); + if (YAP_IsVarTerm(t)) { + if (IsTrieVar(t, stack_vars, stack_vars_base)) { + node = trie_node_check_insert(node, MkTrieVar((stack_vars_base - 1 - (YAP_Term *)t) / 2)); + } else { + node = trie_node_check_insert(node, MkTrieVar((stack_vars_base - stack_vars) / 2)); + PUSH_UP(stack_vars, t, stack_args); + *((YAP_Term *)t) = (YAP_Term)stack_vars; + PUSH_UP(stack_vars, stack_vars, stack_args); + } + } else if (YAP_IsAtomTerm(t)) { + node = trie_node_check_insert(node, t); + } else if (YAP_IsIntTerm(t)) { + node = trie_node_check_insert(node, t); + } else if (YAP_IsFloatTerm(t)) { + volatile double f; + volatile YAP_Term *p; + f = YAP_FloatOfTerm(t); + p = (YAP_Term *)((void *) &f); /* to avoid gcc warning */ + node = trie_node_check_insert(node, FloatInitTag); + node = trie_node_check_insert(node, *p); +#ifdef TAG_LOW_BITS_32 + node = trie_node_check_insert(node, *(p + 1)); +#endif /* TAG_LOW_BITS_32 */ + 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) { + do { + node = put_entry(node, YAP_HeadOfTerm(t)); + t = YAP_Deref(YAP_TailOfTerm(t)); + } while (YAP_IsPairTerm(t)); + } else { /* 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)); + } while (YAP_IsPairTerm(t)); + while (STACK_NOT_EMPTY(stack_args, stack_list)) + node = put_entry(node, POP_UP(stack_args)); + } + node = trie_node_check_insert(node, PairEndTag); + } else if (YAP_IsApplTerm(t)) { + YAP_Functor f = YAP_FunctorOfTerm(t); + 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)); + } while (YAP_IsApplTerm(t) && YAP_FunctorOfTerm(t) == FunctorComma); + node = put_entry(node, t); + node = trie_node_check_insert(node, CommaEndTag); + } else { + 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)); + } + } else { + fprintf(stderr, "***************************************\n"); + fprintf(stderr, " Tries core module: unknown type tag\n"); + fprintf(stderr, "***************************************\n"); + } + + return node; +} + + +static +TrNode check_entry(TrNode node, YAP_Term entry) { + YAP_Term t = YAP_Deref(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; + } else { + if (!(node = trie_node_check(node, MkTrieVar((stack_vars_base - stack_vars) / 2)))) + return NULL; + PUSH_UP(stack_vars, t, stack_args); + *((YAP_Term *)t) = (YAP_Term)stack_vars; + PUSH_UP(stack_vars, stack_vars, stack_args); + } + } else if (YAP_IsAtomTerm(t)) { + if (!(node = trie_node_check(node, t))) + return NULL; + } else if (YAP_IsIntTerm(t)) { + if (!(node = trie_node_check(node, t))) + return NULL; + } else if (YAP_IsFloatTerm(t)) { + volatile double f; + volatile YAP_Term *p; + f = YAP_FloatOfTerm(t); + p = (YAP_Term *)((void *) &f); /* to avoid gcc warning */ + if (!(node = trie_node_check(node, FloatInitTag))) + return NULL; + if (!(node = trie_node_check(node, *p))) + return NULL; +#ifdef TAG_LOW_BITS_32 + if (!(node = trie_node_check(node, *(p + 1)))) + return NULL; +#endif /* TAG_LOW_BITS_32 */ + if (!(node = trie_node_check(node, FloatEndTag))) + return NULL; + } else if (YAP_IsPairTerm(t)) { + if (!(node = trie_node_check(node, PairInitTag))) + return NULL; + if (CURRENT_TRIE_MODE == TRIE_MODE_STANDARD) { + do { + if (!(node = check_entry(node, YAP_HeadOfTerm(t)))) + return NULL; + t = YAP_Deref(YAP_TailOfTerm(t)); + } while (YAP_IsPairTerm(t)); + } else { /* 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)); + } while (YAP_IsPairTerm(t)); + 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, PairEndTag))) + 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; + do { + 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; + if (!(node = trie_node_check(node, CommaEndTag))) + return NULL; + } else { + int i; + if (!(node = trie_node_check(node, ApplTag | ((YAP_Term) f)))) + return NULL; + for (i = 1; i <= YAP_ArityOfFunctor(f); i++) + if (!(node = check_entry(node, YAP_ArgOfTerm(i, t)))) + return NULL; + } + } else { + fprintf(stderr, "***************************************\n"); + fprintf(stderr, " Tries core module: unknown type tag\n"); + fprintf(stderr, "***************************************\n"); + } + + return node; +} + + +static +YAP_Term get_entry(TrNode node, YAP_Term *stack_mark, TrNode *cur_node) { + YAP_Term t = (YAP_Term) &t; + while (TrNode_parent(node)) { + t = TrNode_entry(node); + if (YAP_IsVarTerm(t)) { + int index = TrieVarIndex(t); + if (index > CURRENT_INDEX) { + 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"); + } + for (i = index; i > CURRENT_INDEX; i--) + stack_vars_base[i] = 0; + CURRENT_INDEX = index; + } + if (stack_vars_base[index]) { + t = stack_vars_base[index]; + } else { + t = YAP_MkVarTerm(); + stack_vars_base[index] = t; + } + PUSH_UP(stack_args, t, stack_vars); + } else if (YAP_IsAtomTerm(t)) { + PUSH_UP(stack_args, t, stack_vars); + } else if (YAP_IsIntTerm(t)) { + PUSH_UP(stack_args, t, stack_vars); + } else if (YAP_IsPairTerm(t)) { + if (t == PairEndTag) { + if (CURRENT_TRIE_MODE == TRIE_MODE_STANDARD) { + t = YAP_MkAtomTerm(YAP_LookupAtom("[]")); + PUSH_UP(stack_args, t, stack_vars); + node = TrNode_parent(node); + t = get_entry(node, &stack_args[1], &node); + } else { /* TRIE_MODE_REVERSE */ + node = TrNode_parent(node); + t = get_entry(node, stack_args, &node); + } + PUSH_UP(stack_args, t, stack_vars); + } else if (t == PairInitTag) { + YAP_Term t2; + if (CURRENT_TRIE_MODE == 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); + } + stack_args = stack_mark; + } else { /* TRIE_MODE_REVERSE */ + t = YAP_MkAtomTerm(YAP_LookupAtom("[]")); + while (STACK_NOT_EMPTY(stack_args, stack_mark)) { + t2 = POP_DOWN(stack_args); + t = YAP_MkPairTerm(t2, t); + } + } + *cur_node = node; + return t; + } else if (t == CommaEndTag) { + node = TrNode_parent(node); + t = get_entry(node, stack_args, &node); + PUSH_UP(stack_args, t, stack_vars); + } else if (t == CommaInitTag) { + YAP_Term *stack_aux = stack_mark; + stack_aux--; + while (STACK_NOT_EMPTY(stack_aux, stack_args)) { + t = YAP_MkApplTerm(FunctorComma, 2, stack_aux); + *stack_aux = t; + stack_aux--; + } + stack_args = stack_mark; + *cur_node = node; + return t; + } else if (t == FloatEndTag) { + volatile double f; + volatile YAP_Term *p; + p = (YAP_Term *)((void *) &f); /* to avoid gcc warning */ +#ifdef TAG_LOW_BITS_32 + node = TrNode_parent(node); + *(p + 1) = TrNode_entry(node); +#endif /* TAG_LOW_BITS_32 */ + node = TrNode_parent(node); + *p = TrNode_entry(node); + node = TrNode_parent(node); /* ignore FloatInitTag */ + t = YAP_MkFloatTerm(f); + PUSH_UP(stack_args, t, stack_vars); + } else if (t == FloatInitTag) { + } + } else if (ApplTag & t) { + YAP_Functor f = (YAP_Functor)(~ApplTag & t); + int arity = YAP_ArityOfFunctor(f); + t = YAP_MkApplTerm(f, arity, &stack_args[1]); + stack_args += arity; + PUSH_UP(stack_args, t, stack_vars); + } else { + fprintf(stderr, "***************************************\n"); + fprintf(stderr, " Tries core module: unknown type tag\n"); + fprintf(stderr, "***************************************\n"); + } + node = TrNode_parent(node); + } + *cur_node = node; + return t; +} + + +static +void remove_entry(TrNode node) { + TrNode parent = TrNode_parent(node); + while (parent) { + if (TrNode_previous(node)) { + if (IS_HASH_NODE(TrNode_child(parent))) { + TrHash hash = (TrHash) TrNode_child(parent); + TrHash_num_nodes(hash)--; + if (TrHash_num_nodes(hash)) { + if (TrNode_next(node)) { + TrNode_next(TrNode_previous(node)) = TrNode_next(node); + TrNode_previous(TrNode_next(node)) = TrNode_previous(node); + } else { + TrNode_next(TrNode_previous(node)) = NULL; + } + free_trie_node(node); + return; + } + free_hash_buckets(TrHash_buckets(hash), TrHash_num_buckets(hash)); + free_trie_hash(hash); + } else { + if (TrNode_next(node)) { + TrNode_next(TrNode_previous(node)) = TrNode_next(node); + TrNode_previous(TrNode_next(node)) = TrNode_previous(node); + } else { + TrNode_next(TrNode_previous(node)) = NULL; + } + free_trie_node(node); + return; + } + } else if (TrNode_next(node)) { + TrNode_child(parent) = TrNode_next(node); + TrNode_previous(TrNode_next(node)) = NULL; + free_trie_node(node); + return; + } + free_trie_node(node); + node = parent; + parent = TrNode_parent(node); + } + TrNode_child(node) = NULL; + return; +} + + +static +void remove_child_nodes(TrNode 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); + do { + if (*--bucket) + remove_child_nodes(*bucket); + } while (bucket != first_bucket); + free_hash_buckets(first_bucket, TrHash_num_buckets(hash)); + free_trie_hash(hash); + return; + } + if (TrNode_next(node)) + remove_child_nodes(TrNode_next(node)); + if (!IS_LEAF_TRIE_NODE(node)) + remove_child_nodes(TrNode_child(node)); + else { + if (DATA_DESTRUCT_FUNCTION) + (*DATA_DESTRUCT_FUNCTION)(node); + DECREMENT_ENTRIES(CURRENT_TRIE_ENGINE); + } + free_trie_node(node); + return; +} + + +static +TrNode copy_child_nodes(TrNode parent_dest, TrNode child_source) { + TrNode child_dest, next_dest; + + if (IS_HASH_NODE(child_source)) { + TrNode *bucket_dest, *first_bucket_source, *bucket_source; + TrHash hash_dest, hash_source; + hash_source = (TrHash) child_source; + first_bucket_source = TrHash_buckets(hash_source); + bucket_source = first_bucket_source + TrHash_num_buckets(hash_source); + new_trie_hash(hash_dest, TrHash_num_nodes(hash_source), TrHash_num_buckets(hash_source)); + bucket_dest = TrHash_buckets(hash_dest) + TrHash_num_buckets(hash_dest); + do { + bucket_dest--; + if (*--bucket_source) { + *bucket_dest = copy_child_nodes(parent_dest, *bucket_source); + TrNode_previous(*bucket_dest) = AS_TR_NODE_NEXT(bucket_dest); + } else + *bucket_dest = NULL; + } while (bucket_source != first_bucket_source); + return (TrNode) hash_dest; + } + + if (TrNode_next(child_source)) + next_dest = copy_child_nodes(parent_dest, TrNode_next(child_source)); + else + next_dest = NULL; + new_trie_node(child_dest, TrNode_entry(child_source), parent_dest, NULL, next_dest, NULL); + if (next_dest) + TrNode_previous(next_dest) = child_dest; + if (IS_LEAF_TRIE_NODE(child_source)) { + MARK_AS_LEAF_TRIE_NODE(child_dest); + INCREMENT_ENTRIES(CURRENT_TRIE_ENGINE); + if (DATA_COPY_FUNCTION) + (*DATA_COPY_FUNCTION)(child_dest, child_source); + } else + TrNode_child(child_dest) = copy_child_nodes(child_dest, TrNode_child(child_source)); + return child_dest; +} + + +static +void traverse_and_add(TrNode parent_dest, TrNode parent_source) { + TrNode child_dest, child_source; + + /* parent_source is not a leaf node */ + child_source = TrNode_child(parent_source); + if (IS_HASH_NODE(child_source)) { + TrNode *first_bucket_source, *bucket_source; + TrHash hash_source; + hash_source = (TrHash) child_source; + first_bucket_source = TrHash_buckets(hash_source); + bucket_source = first_bucket_source + TrHash_num_buckets(hash_source); + do { + child_source = *--bucket_source; + while (child_source) { + /* parent_dest is not a leaf node */ + child_dest = trie_node_check(parent_dest, TrNode_entry(child_source)); + if (child_dest) { + if (IS_LEAF_TRIE_NODE(child_dest)) { + /* child_source is a leaf node */ + if (DATA_ADD_FUNCTION) + (*DATA_ADD_FUNCTION)(child_dest, child_source); + } else + /* child_dest and child_source are not leaf nodes */ + traverse_and_add(child_dest, child_source); + } + child_source = TrNode_next(child_source); + } + } while (bucket_source != first_bucket_source); + return; + } + while (child_source) { + /* parent_dest is not a leaf node */ + child_dest = trie_node_check(parent_dest, TrNode_entry(child_source)); + if (child_dest) { + if (IS_LEAF_TRIE_NODE(child_dest)) { + /* child_source is a leaf node */ + if (DATA_ADD_FUNCTION) + (*DATA_ADD_FUNCTION)(child_dest, child_source); + } else + /* child_dest and child_source are not leaf nodes */ + traverse_and_add(child_dest, child_source); + } + child_source = TrNode_next(child_source); + } + return; +} + + +static +void traverse_and_join(TrNode parent_dest, TrNode parent_source) { + TrNode child_dest, child_source; + + /* parent_source is not a leaf node */ + child_source = TrNode_child(parent_source); + if (IS_HASH_NODE(child_source)) { + TrNode *first_bucket_source, *bucket_source; + TrHash hash_source; + hash_source = (TrHash) child_source; + first_bucket_source = TrHash_buckets(hash_source); + bucket_source = first_bucket_source + TrHash_num_buckets(hash_source); + do { + child_source = *--bucket_source; + while (child_source) { + /* parent_dest is not a leaf node */ + child_dest = trie_node_check(parent_dest, TrNode_entry(child_source)); + if (child_dest) { + if (IS_LEAF_TRIE_NODE(child_dest)) { + /* child_source is a leaf node */ + if (DATA_ADD_FUNCTION) + (*DATA_ADD_FUNCTION)(child_dest, child_source); + } else + /* child_dest and child_source are not leaf nodes */ + traverse_and_join(child_dest, child_source); + } else { + child_dest = trie_node_check_insert(parent_dest, TrNode_entry(child_source)); + if (IS_LEAF_TRIE_NODE(child_source)) { + MARK_AS_LEAF_TRIE_NODE(child_dest); + INCREMENT_ENTRIES(CURRENT_TRIE_ENGINE); + if (DATA_COPY_FUNCTION) + (*DATA_COPY_FUNCTION)(child_dest, child_source); + } else + TrNode_child(child_dest) = copy_child_nodes(child_dest, TrNode_child(child_source)); + } + child_source = TrNode_next(child_source); + } + } while (bucket_source != first_bucket_source); + return; + } + while (child_source) { + /* parent_dest is not a leaf node */ + child_dest = trie_node_check(parent_dest, TrNode_entry(child_source)); + if (child_dest) { + if (IS_LEAF_TRIE_NODE(child_dest)) { + /* child_source is a leaf node */ + if (DATA_ADD_FUNCTION) + (*DATA_ADD_FUNCTION)(child_dest, child_source); + } else + /* child_dest and child_source are not leaf nodes */ + traverse_and_join(child_dest, child_source); + } else { + child_dest = trie_node_check_insert(parent_dest, TrNode_entry(child_source)); + if (IS_LEAF_TRIE_NODE(child_source)) { + MARK_AS_LEAF_TRIE_NODE(child_dest); + INCREMENT_ENTRIES(CURRENT_TRIE_ENGINE); + if (DATA_COPY_FUNCTION) + (*DATA_COPY_FUNCTION)(child_dest, child_source); + } else + TrNode_child(child_dest) = copy_child_nodes(child_dest, TrNode_child(child_source)); + } + child_source = TrNode_next(child_source); + } + return; +} + + +static +void traverse_and_intersect(TrNode parent_dest, TrNode parent_source) { + TrNode child_dest, child_source, child_next; + + /* parent_dest is not a leaf node */ + child_dest = TrNode_child(parent_dest); + if (IS_HASH_NODE(child_dest)) { + TrNode *first_bucket_dest, *bucket_dest; + TrHash hash_dest; + hash_dest = (TrHash) child_dest; + first_bucket_dest = TrHash_buckets(hash_dest); + bucket_dest = first_bucket_dest + TrHash_num_buckets(hash_dest); + do { + child_dest = *--bucket_dest; + while (child_dest) { + child_next = TrNode_next(child_dest); + /* parent_source is not a leaf node */ + child_source = trie_node_check(parent_source, TrNode_entry(child_dest)); + if (child_source) { + if (IS_LEAF_TRIE_NODE(child_dest)) { + /* child_source is a leaf node */ + if (DATA_ADD_FUNCTION) + (*DATA_ADD_FUNCTION)(child_dest, child_source); + } else + /* child_dest and child_source are not leaf nodes */ + traverse_and_intersect(child_dest, child_source); + } else { + if (IS_LEAF_TRIE_NODE(child_dest)) { + if (DATA_DESTRUCT_FUNCTION) + (*DATA_DESTRUCT_FUNCTION)(child_dest); + DECREMENT_ENTRIES(CURRENT_TRIE_ENGINE); + } else + remove_child_nodes(TrNode_child(child_dest)); + remove_entry(child_dest); + } + child_dest = child_next; + } + } while (bucket_dest != first_bucket_dest); + return; + } + while (child_dest) { + child_next = TrNode_next(child_dest); + /* parent_source is not a leaf node */ + child_source = trie_node_check(parent_source, TrNode_entry(child_dest)); + if (child_source) { + if (IS_LEAF_TRIE_NODE(child_dest)) { + /* child_source is a leaf node */ + if (DATA_ADD_FUNCTION) + (*DATA_ADD_FUNCTION)(child_dest, child_source); + } else + /* child_dest and child_source are not leaf nodes */ + traverse_and_intersect(child_dest, child_source); + } else { + if (IS_LEAF_TRIE_NODE(child_dest)) { + if (DATA_DESTRUCT_FUNCTION) + (*DATA_DESTRUCT_FUNCTION)(child_dest); + DECREMENT_ENTRIES(CURRENT_TRIE_ENGINE); + } else + remove_child_nodes(TrNode_child(child_dest)); + remove_entry(child_dest); + } + child_dest = child_next; + } + return; +} + + +static +YAP_Int traverse_and_count_common_entries(TrNode parent1, TrNode parent2) { + TrNode child1, child2; + YAP_Int count = 0; + + /* parent1 is not a leaf node */ + child1 = TrNode_child(parent1); + if (IS_HASH_NODE(child1)) { + TrNode *first_bucket, *bucket; + TrHash hash; + hash = (TrHash) child1; + first_bucket = TrHash_buckets(hash); + bucket = first_bucket + TrHash_num_buckets(hash); + do { + child1 = *--bucket; + while (child1) { + /* parent2 is not a leaf node */ + child2 = trie_node_check(parent2, TrNode_entry(child1)); + if (child2) { + if (IS_LEAF_TRIE_NODE(child1)) + /* child2 is a leaf node */ + count++; + else + /* child1 and child2 are not leaf nodes */ + count += traverse_and_count_common_entries(child1, child2); + } + child1 = TrNode_next(child1); + } + } while (bucket != first_bucket); + return count; + } + while (child1) { + /* parent2 is not a leaf node */ + child2 = trie_node_check(parent2, TrNode_entry(child1)); + if (child2) { + if (IS_LEAF_TRIE_NODE(child1)) + /* child2 is a leaf node */ + count++; + else + /* child1 and child2 are not leaf nodes */ + count += traverse_and_count_common_entries(child1, child2); + } + child1 = TrNode_next(child1); + } + return count; +} + + +static +YAP_Int traverse_and_count_entries(TrNode node) { + YAP_Int count = 0; + + if (IS_HASH_NODE(node)) { + TrNode *first_bucket, *bucket; + TrHash hash; + hash = (TrHash) node; + first_bucket = TrHash_buckets(hash); + bucket = first_bucket + TrHash_num_buckets(hash); + do { + if (*--bucket) { + node = *bucket; + count += traverse_and_count_entries(node); + } + } while (bucket != first_bucket); + return count; + } + + if (TrNode_next(node)) + count += traverse_and_count_entries(TrNode_next(node)); + if (!IS_LEAF_TRIE_NODE(node)) + count += traverse_and_count_entries(TrNode_child(node)); + else + count++; + return count; +} + + +static +void traverse_and_get_usage(TrNode node, YAP_Int depth) { + if (IS_HASH_NODE(node)) { + TrNode *first_bucket, *bucket; + TrHash hash; + hash = (TrHash) node; + first_bucket = TrHash_buckets(hash); + bucket = first_bucket + TrHash_num_buckets(hash); + do { + if (*--bucket) { + node = *bucket; + traverse_and_get_usage(node, depth); + } + } while (bucket != first_bucket); + return; + } + + USAGE_NODES++; + if (TrNode_next(node)) + traverse_and_get_usage(TrNode_next(node), depth); + depth++; + if (!IS_LEAF_TRIE_NODE(node)) { + traverse_and_get_usage(TrNode_child(node), depth); + } else { + USAGE_ENTRIES++; + USAGE_VIRTUAL_NODES+= depth; + } + return; +} + + +static +void traverse_and_save(TrNode node, FILE *file, int float_block) { + YAP_Term t; + + if (IS_HASH_NODE(node)) { + TrNode *first_bucket, *bucket; + TrHash hash; + hash = (TrHash) node; + fprintf(file, "%lu %d ", HASH_SAVE_MARK, TrHash_num_buckets(hash)); + first_bucket = TrHash_buckets(hash); + bucket = first_bucket + TrHash_num_buckets(hash); + do { + if (*--bucket) { + node = *bucket; + traverse_and_save(node, file, float_block); + } + } while (bucket != first_bucket); + return; + } + + if (TrNode_next(node)) + traverse_and_save(TrNode_next(node), file, float_block); + + t = TrNode_entry(node); + if (float_block) { + float_block--; + fprintf(file, "%lu %lu ", FLOAT_SAVE_MARK, t); + } else if (YAP_IsPairTerm(t)) { + if (t == FloatInitTag) { +#ifdef TAG_LOW_BITS_32 + float_block++; +#endif /* TAG_LOW_BITS_32 */ + float_block ++; + } + fprintf(file, "%lu ", t); + } else if (YAP_IsVarTerm(t) || YAP_IsIntTerm(t)) + fprintf(file, "%lu ", t); + else { + int index; + for (index = 0; index <= CURRENT_INDEX; index++) + if (AUXILIARY_TERM_STACK[index] == t) + break; + if (index > CURRENT_INDEX) { + CURRENT_INDEX = index; + if (CURRENT_INDEX == CURRENT_AUXILIARY_TERM_STACK_SIZE) + expand_auxiliary_term_stack(); + AUXILIARY_TERM_STACK[CURRENT_INDEX] = t; + if (YAP_IsAtomTerm(t)) + fprintf(file, "%lu %d %s%c ", ATOM_SAVE_MARK, index, YAP_AtomName(YAP_AtomOfTerm(t)), '\0'); + else /* (ApplTag & t) */ + fprintf(file, "%lu %d %s %d ", FUNCTOR_SAVE_MARK, index, + YAP_AtomName(YAP_NameOfFunctor((YAP_Functor)(~ApplTag & t))), + YAP_ArityOfFunctor((YAP_Functor)(~ApplTag & t))); + } else + if (YAP_IsAtomTerm(t)) + fprintf(file, "%lu %d ", ATOM_SAVE_MARK, index); + else + fprintf(file, "%lu %d ", FUNCTOR_SAVE_MARK, index); + } + if (IS_LEAF_TRIE_NODE(node)) { + fprintf(file, "- "); + if (DATA_SAVE_FUNCTION) + (*DATA_SAVE_FUNCTION)(node, file); + } + else { + traverse_and_save(TrNode_child(node), file, float_block); + fprintf(file, "- "); + } + return; +} + + +static +void traverse_and_load(TrNode parent, FILE *file) { + TrHash hash = NULL; + YAP_Term t; + + if (!fscanf(file, "%lu", &t)) { + MARK_AS_LEAF_TRIE_NODE(parent); + INCREMENT_ENTRIES(CURRENT_TRIE_ENGINE); + if (DATA_LOAD_FUNCTION) + (*DATA_LOAD_FUNCTION)(parent, CURRENT_DEPTH, file); + CURRENT_DEPTH--; + return; + } + if (t == HASH_SAVE_MARK) { + /* alloc a new trie hash */ + int num_buckets; + fscanf(file, "%d", &num_buckets); + new_trie_hash(hash, 0, num_buckets); + TrNode_child(parent) = (TrNode) hash; + fscanf(file, "%lu", &t); + } + do { + TrNode child; + if (t == ATOM_SAVE_MARK) { + int index; + fscanf(file, "%d", &index); + if (index > CURRENT_INDEX) { + char atom[1000]; + if (CURRENT_LOAD_VERSION == 2) { + char *ptr, ch; + ptr = atom; + fgetc(file); /* skip the first empty space */ + while ((ch = fgetc(file))) + *ptr++ = ch; + *ptr = '\0'; + } else if (CURRENT_LOAD_VERSION == 1) { + fscanf(file, "%s", atom); + } + CURRENT_INDEX = index; + if (CURRENT_INDEX == CURRENT_AUXILIARY_TERM_STACK_SIZE) + expand_auxiliary_term_stack(); + AUXILIARY_TERM_STACK[CURRENT_INDEX] = YAP_MkAtomTerm(YAP_LookupAtom(atom)); + } + t = AUXILIARY_TERM_STACK[index]; + } else if (t == FUNCTOR_SAVE_MARK) { + int index; + fscanf(file, "%d", &index); + if (index > CURRENT_INDEX) { + char atom[1000]; + int arity; + fscanf(file, "%s %d", atom, &arity); + CURRENT_INDEX = index; + if (CURRENT_INDEX == CURRENT_AUXILIARY_TERM_STACK_SIZE) + expand_auxiliary_term_stack(); + AUXILIARY_TERM_STACK[CURRENT_INDEX] = ApplTag | ((YAP_Term) YAP_MkFunctor(YAP_LookupAtom(atom), arity)); + } + t = AUXILIARY_TERM_STACK[index]; + } else if (t == FLOAT_SAVE_MARK) + fscanf(file, "%lu", &t); + child = trie_node_insert(parent, t, hash); + traverse_and_load(child, file); + } while (fscanf(file, "%lu", &t)); + CURRENT_DEPTH--; + return; +} + + +static +void traverse_and_print(TrNode node, YAP_Int *arity, char *str, int str_index, int mode) { + YAP_Term t; + YAP_Int new_arity[100]; + + if (IS_HASH_NODE(node)) { + TrNode *first_bucket, *bucket; + TrHash hash; + hash = (TrHash) node; + first_bucket = TrHash_buckets(hash); + bucket = first_bucket + TrHash_num_buckets(hash); + do { + if (*--bucket) { + node = *bucket; + memcpy(new_arity, arity, sizeof(YAP_Int) * 100); + traverse_and_print(node, new_arity, str, str_index, mode); + } + } while (bucket != first_bucket); + return; + } + + if (TrNode_next(node)) { + memcpy(new_arity, arity, sizeof(YAP_Int) * 100); + traverse_and_print(TrNode_next(node), new_arity, str, str_index, mode); + } + + t = TrNode_entry(node); + if (mode == TRIE_PRINT_FLOAT) { +#ifdef TAG_LOW_BITS_32 + arity[arity[0]] = (YAP_Int) t; + mode = TRIE_PRINT_FLOAT2; + } else if (mode == TRIE_PRINT_FLOAT2) { + volatile double f; + volatile YAP_Term *p; + p = (YAP_Term *)((void *) &f); /* to avoid gcc warning */ + *(p + 1) = t; + *p = (YAP_Term) arity[arity[0]]; +#else /* TAG_64BITS */ + volatile double f; + volatile YAP_Term *p; + p = (YAP_Term *)((void *) &f); /* to avoid gcc warning */ + *p = t; +#endif /* TAG_SCHEME */ + str_index += sprintf(& str[str_index], "%.10f", f); + mode = TRIE_PRINT_FLOAT_END; + } else if (mode == TRIE_PRINT_FLOAT_END) { + arity[0]--; + while (arity[0]) { + arity[arity[0]]--; + if (arity[arity[0]] == 0) { + str_index += sprintf(& str[str_index], ")"); + arity[0]--; + } else { + str_index += sprintf(& str[str_index], ","); + break; + } + } + mode = TRIE_PRINT_NORMAL; + } else if (YAP_IsVarTerm(t)) { + str_index += sprintf(& str[str_index], "VAR%ld", TrieVarIndex(t)); + while (arity[0]) { + arity[arity[0]]--; + if (arity[arity[0]] == 0) { + str_index += sprintf(& str[str_index], ")"); + arity[0]--; + } else { + str_index += sprintf(& str[str_index], ","); + break; + } + } + } else if (YAP_IsAtomTerm(t)) { + str_index += sprintf(& str[str_index], "%s", YAP_AtomName(YAP_AtomOfTerm(t))); + while (arity[0]) { + arity[arity[0]]--; + if (arity[arity[0]] == 0) { + str_index += sprintf(& str[str_index], ")"); + arity[0]--; + } else { + str_index += sprintf(& str[str_index], ","); + break; + } + } + } else if (YAP_IsIntTerm(t)) { + str_index += sprintf(& str[str_index], "%ld", YAP_IntOfTerm(t)); + while (arity[0]) { + arity[arity[0]]--; + if (arity[arity[0]] == 0) { + str_index += sprintf(& str[str_index], ")"); + arity[0]--; + } else { + str_index += sprintf(& str[str_index], ","); + break; + } + } + } else if (YAP_IsPairTerm(t)) { + if (t == FloatInitTag) { + mode = TRIE_PRINT_FLOAT; + arity[0]++; + arity[arity[0]] = -1; + } else if (t == PairInitTag) { + str_index += sprintf(& str[str_index], "["); + arity[0]++; + arity[arity[0]] = -1; + } else if (t == CommaInitTag) { + str_index += sprintf(& str[str_index], "("); + arity[0]++; + arity[arity[0]] = -1; + } else { + if (t == PairEndTag) + str[str_index - 1] = ']'; + else /* (t == CommaEndTag) */ + str[str_index - 1] = ')'; + arity[0]--; + while (arity[0]) { + arity[arity[0]]--; + if (arity[arity[0]] == 0) { + str_index += sprintf(& str[str_index], ")"); + arity[0]--; + } else { + str_index += sprintf(& str[str_index], ","); + break; + } + } + if (arity[0]) { + traverse_and_print(TrNode_child(node), arity, str, str_index, mode); + } else { + str[str_index] = 0; + fprintf(stdout, "%s\n", str); + if (DATA_PRINT_FUNCTION) + (*DATA_PRINT_FUNCTION)(node); + } + str[str_index - 1] = ','; + return; + } + } else if (ApplTag & t) { + str_index += sprintf(& str[str_index], "%s(", YAP_AtomName(YAP_NameOfFunctor((YAP_Functor)(~ApplTag & t)))); + arity[0]++; + arity[arity[0]] = YAP_ArityOfFunctor((YAP_Functor)(~ApplTag & t)); + } else { + fprintf(stderr, "***************************************\n"); + fprintf(stderr, " Tries core module: unknown type tag\n"); + fprintf(stderr, "***************************************\n"); + } + + if (arity[0]) { + traverse_and_print(TrNode_child(node), arity, str, str_index, mode); + } else { + str[str_index] = 0; + fprintf(stdout, "%s\n", str); + if (DATA_PRINT_FUNCTION) + (*DATA_PRINT_FUNCTION)(node); + } + return; +} diff --git a/library/Tries/core_tries.h b/library/Tries/core_tries.h new file mode 100644 index 000000000..81e7dc224 --- /dev/null +++ b/library/Tries/core_tries.h @@ -0,0 +1,301 @@ +/********************************************* + File: core_tries.h + Author: Ricardo Rocha + Comments: Tries core module for Yap Prolog + version: $ID$ +*********************************************/ + + + +/* -------------------------------------- */ +/* Yap Tagging Scheme */ +/* -------------------------------------- */ + +#include "config.h" +#if SIZEOF_INT_P==4 +#define TAG_LOW_BITS_32 /* 'Tags_32LowTag.h' tagging scheme */ +#elif SIZEOF_INT_P==8 +#define TAG_64BITS /* 'Tags_64bits.h' tagging scheme */ +#else +#error Unknown tagging scheme +#endif /* YAP_SCHEME */ + + + +/* --------------------------- */ +/* Defines */ +/* --------------------------- */ + +#ifdef TAG_LOW_BITS_32 +#define ApplTag 1 /* 0x01 */ +#else /* TAG_64BITS */ +#define ApplTag 5 /* 0x05 */ +#endif /* TAG_SCHEME */ +#define PairInitTag 3 /* 0x03 */ +#define PairEndTag 19 /* 0x13 */ +#define CommaInitTag 35 /* 0x23 */ +#define CommaEndTag 51 /* 0x33 */ +#define FloatInitTag 67 /* 0x43 */ +#define FloatEndTag 83 /* 0x53 */ + +#define TRIE_MODE_STANDARD 0 +#define TRIE_MODE_REVERSE 1 + +#define TRIE_PRINT_NORMAL 0 +#define TRIE_PRINT_FLOAT 1 +#define TRIE_PRINT_FLOAT2 2 +#define TRIE_PRINT_FLOAT_END 3 + +#define BASE_AUXILIARY_TERM_STACK_SIZE 1000 + + + +/* --------------------------- */ +/* Structs */ +/* --------------------------- */ + +typedef struct trie_engine { + struct trie_node *first_trie; + /* in use */ + YAP_Int memory_in_use; + YAP_Int tries_in_use; + YAP_Int entries_in_use; + YAP_Int nodes_in_use; + /* max used */ + YAP_Int memory_max_used; + YAP_Int tries_max_used; + YAP_Int entries_max_used; + YAP_Int nodes_max_used; +} *TrEngine; + +#define TrEngine_trie(X) ((X)->first_trie) +#define TrEngine_memory(X) ((X)->memory_in_use) +#define TrEngine_tries(X) ((X)->tries_in_use) +#define TrEngine_entries(X) ((X)->entries_in_use) +#define TrEngine_nodes(X) ((X)->nodes_in_use) +#define TrEngine_memory_max(X) ((X)->memory_max_used) +#define TrEngine_tries_max(X) ((X)->tries_max_used) +#define TrEngine_entries_max(X) ((X)->entries_max_used) +#define TrEngine_nodes_max(X) ((X)->nodes_max_used) + +typedef struct trie_node { + struct trie_node *parent; + struct trie_node *child; + struct trie_node *next; + struct trie_node *previous; + YAP_Term entry; +} *TrNode; + +#define TrNode_parent(X) ((X)->parent) +#define TrNode_child(X) ((X)->child) +#define TrNode_next(X) ((X)->next) +#define TrNode_previous(X) ((X)->previous) +#define TrNode_entry(X) ((X)->entry) + +typedef struct trie_hash { + struct trie_node *parent; /* for compatibility with the trie_node data structure */ + struct trie_node **buckets; + int number_of_buckets; + int number_of_nodes; +} *TrHash; + +#define TrHash_mark(X) ((X)->parent) +#define TrHash_buckets(X) ((X)->buckets) +#define TrHash_bucket(X,N) ((X)->buckets + N) +#define TrHash_num_buckets(X) ((X)->number_of_buckets) +#define TrHash_seed(X) ((X)->number_of_buckets - 1) +#define TrHash_num_nodes(X) ((X)->number_of_nodes) + +#define TYPE_TR_ENGINE struct trie_engine +#define TYPE_TR_NODE struct trie_node +#define TYPE_TR_HASH struct trie_hash +#define SIZEOF_TR_ENGINE sizeof(TYPE_TR_ENGINE) +#define SIZEOF_TR_NODE sizeof(TYPE_TR_NODE) +#define SIZEOF_TR_HASH sizeof(TYPE_TR_HASH) +#define SIZEOF_TR_BUCKET sizeof(TYPE_TR_NODE *) + +#define AS_TR_NODE_NEXT(ADDR) (TrNode)((unsigned long int)(ADDR) - 2 * sizeof(struct trie_node *)) + + + +/* --------------------------- */ +/* Macros */ +/* --------------------------- */ + +#define TAG_ADDR(ADDR) ((unsigned long int)(ADDR) | 0x1) +#define UNTAG_ADDR(ADDR) ((unsigned long int)(ADDR) & ~(0x1)) +#define PUT_DATA_IN_LEAF_TRIE_NODE(TR_NODE, DATA) TrNode_child(TR_NODE) = (TrNode)TAG_ADDR(DATA) +#define GET_DATA_FROM_LEAF_TRIE_NODE(TR_NODE) UNTAG_ADDR(TrNode_child(TR_NODE)) +#define MARK_AS_LEAF_TRIE_NODE(TR_NODE) PUT_DATA_IN_LEAF_TRIE_NODE(TR_NODE, TrNode_child(TR_NODE)) +#define IS_LEAF_TRIE_NODE(TR_NODE) ((unsigned long int)(TrNode_child(TR_NODE)) & 0x1) + +#define IsTrieVar(TERM, STACK, STACK_BASE) ((YAP_Term *)(TERM) > STACK && (YAP_Term *)(TERM) <= STACK_BASE) +#define MkTrieVar(INDEX) ((INDEX) << 4) +#define TrieVarIndex(TERM) ((TERM) >> 4) + +#define BASE_HASH_BUCKETS 64 +#define MAX_NODES_PER_TRIE_LEVEL 8 +#define MAX_NODES_PER_BUCKET (MAX_NODES_PER_TRIE_LEVEL / 2) +#define HASH_TERM(TERM, SEED) (((TERM) >> 4) & (SEED)) +#define IS_HASH_NODE(NODE) (TrHash_mark(NODE) == NULL) + +#define BASE_SAVE_MARK 1000 /* could lead to errors if the number of different variables in a term is greater than it */ +#define HASH_SAVE_MARK ((YAP_Term) MkTrieVar(BASE_SAVE_MARK)) +#define ATOM_SAVE_MARK ((YAP_Term) MkTrieVar(BASE_SAVE_MARK + 1)) +#define FUNCTOR_SAVE_MARK ((YAP_Term) MkTrieVar(BASE_SAVE_MARK + 2)) +#define FLOAT_SAVE_MARK ((YAP_Term) MkTrieVar(BASE_SAVE_MARK + 3)) + +#define STACK_NOT_EMPTY(STACK, STACK_BASE) STACK != STACK_BASE +#define POP_UP(STACK) *--STACK +#define POP_DOWN(STACK) *++STACK +#define PUSH_UP(STACK, ITEM, STACK_TOP) \ + { if (STACK < STACK_TOP) { \ + fprintf(stderr, "**************************************\n"); \ + fprintf(stderr, " Tries core module: term stack full\n"); \ + fprintf(stderr, "**************************************\n"); \ + } \ + *STACK = (YAP_Term)(ITEM); \ + STACK--; \ + } +#define PUSH_DOWN(STACK, ITEM, STACK_TOP) \ + { if (STACK > STACK_TOP) { \ + fprintf(stderr, "**************************************\n"); \ + fprintf(stderr, " Tries core module: term stack full\n"); \ + fprintf(stderr, "**************************************\n"); \ + } \ + *STACK = (YAP_Term)(ITEM); \ + STACK++; \ + } + + + +#define new_struct(STR, STR_TYPE, STR_SIZE) \ + STR = (STR_TYPE *) YAP_AllocSpaceFromYap(STR_SIZE) +#define new_trie_engine(TR_ENGINE) \ + { new_struct(TR_ENGINE, TYPE_TR_ENGINE, SIZEOF_TR_ENGINE); \ + TrEngine_trie(TR_ENGINE) = NULL; \ + TrEngine_memory(TR_ENGINE) = 0; \ + TrEngine_tries(TR_ENGINE) = 0; \ + TrEngine_entries(TR_ENGINE) = 0; \ + TrEngine_nodes(TR_ENGINE) = 0; \ + TrEngine_memory_max(TR_ENGINE) = 0; \ + TrEngine_tries_max(TR_ENGINE) = 0; \ + TrEngine_entries_max(TR_ENGINE) = 0; \ + TrEngine_nodes_max(TR_ENGINE) = 0; \ + } +#define new_trie_node(TR_NODE, ENTRY, PARENT, CHILD, NEXT, PREVIOUS) \ + { new_struct(TR_NODE, TYPE_TR_NODE, SIZEOF_TR_NODE); \ + TrNode_entry(TR_NODE) = ENTRY; \ + TrNode_parent(TR_NODE) = PARENT; \ + TrNode_child(TR_NODE) = CHILD; \ + TrNode_next(TR_NODE) = NEXT; \ + TrNode_previous(TR_NODE) = PREVIOUS; \ + INCREMENT_NODES(CURRENT_TRIE_ENGINE); \ + INCREMENT_MEMORY(CURRENT_TRIE_ENGINE, SIZEOF_TR_NODE); \ + } +#define new_trie_hash(TR_HASH, NUM_NODES, NUM_BUCKETS) \ + { new_struct(TR_HASH, TYPE_TR_HASH, SIZEOF_TR_HASH); \ + TrHash_mark(TR_HASH) = NULL; \ + TrHash_num_buckets(TR_HASH) = NUM_BUCKETS; \ + new_hash_buckets(TR_HASH, NUM_BUCKETS); \ + TrHash_num_nodes(TR_HASH) = NUM_NODES; \ + INCREMENT_MEMORY(CURRENT_TRIE_ENGINE, SIZEOF_TR_HASH); \ + } +#define new_hash_buckets(TR_HASH, NUM_BUCKETS) \ + { int i; void **ptr; \ + new_struct(ptr, void *, NUM_BUCKETS * sizeof(void *)); \ + TrHash_buckets(TR_HASH) = (TYPE_TR_NODE **) ptr; \ + for (i = NUM_BUCKETS; i != 0; i--) \ + *ptr++ = NULL; \ + INCREMENT_MEMORY(CURRENT_TRIE_ENGINE, (NUM_BUCKETS) * SIZEOF_TR_BUCKET); \ + } + + + +#define expand_auxiliary_term_stack() \ + { YAP_Term *aux_stack; \ + YAP_Int aux_size = CURRENT_AUXILIARY_TERM_STACK_SIZE * sizeof(YAP_Term); \ + new_struct(aux_stack, YAP_Term, aux_size * 2); \ + memcpy(aux_stack, AUXILIARY_TERM_STACK, aux_size); \ + free_struct(AUXILIARY_TERM_STACK); \ + AUXILIARY_TERM_STACK = aux_stack; \ + CURRENT_AUXILIARY_TERM_STACK_SIZE *= 2; \ + } + + + +#define free_struct(STR) \ + YAP_FreeSpaceFromYap((char *) (STR)) +#define free_trie_node(STR) \ + { free_struct(STR); \ + DECREMENT_NODES(CURRENT_TRIE_ENGINE); \ + DECREMENT_MEMORY(CURRENT_TRIE_ENGINE, SIZEOF_TR_NODE); \ + } +#define free_trie_hash(STR) \ + { free_struct(STR); \ + DECREMENT_MEMORY(CURRENT_TRIE_ENGINE, SIZEOF_TR_HASH); \ + } +#define free_hash_buckets(STR, NUM_BUCKETS) \ + { free_struct(STR); \ + DECREMENT_MEMORY(CURRENT_TRIE_ENGINE, (NUM_BUCKETS) * SIZEOF_TR_BUCKET); \ + } + + + +#define INCREMENT_MEMORY(TR_ENGINE, SIZE) \ + { TrEngine_memory(TR_ENGINE) += SIZE; \ + if (TrEngine_memory(TR_ENGINE) > TrEngine_memory_max(TR_ENGINE)) \ + TrEngine_memory_max(TR_ENGINE) = TrEngine_memory(TR_ENGINE); \ + } +#define INCREMENT_TRIES(TR_ENGINE) \ + { TrEngine_tries(TR_ENGINE)++; \ + if (TrEngine_tries(TR_ENGINE) > TrEngine_tries_max(TR_ENGINE)) \ + TrEngine_tries_max(TR_ENGINE) = TrEngine_tries(TR_ENGINE); \ + } +#define INCREMENT_ENTRIES(TR_ENGINE) \ + { TrEngine_entries(TR_ENGINE)++; \ + if (TrEngine_entries(TR_ENGINE) > TrEngine_entries_max(TR_ENGINE)) \ + TrEngine_entries_max(TR_ENGINE) = TrEngine_entries(TR_ENGINE); \ + } +#define INCREMENT_NODES(TR_ENGINE) \ + { TrEngine_nodes(TR_ENGINE)++; \ + if (TrEngine_nodes(TR_ENGINE) > TrEngine_nodes_max(TR_ENGINE)) \ + TrEngine_nodes_max(TR_ENGINE) = TrEngine_nodes(TR_ENGINE); \ + } +#define DECREMENT_MEMORY(TR_ENGINE, SIZE) \ + TrEngine_memory(TR_ENGINE) -= SIZE +#define DECREMENT_TRIES(TR_ENGINE) \ + TrEngine_tries(TR_ENGINE)-- +#define DECREMENT_ENTRIES(TR_ENGINE) \ + TrEngine_entries(TR_ENGINE)-- +#define DECREMENT_NODES(TR_ENGINE) \ + TrEngine_nodes(TR_ENGINE)-- + + + +/* --------------------------- */ +/* API */ +/* --------------------------- */ + +inline TrEngine core_trie_init_module(void); +inline TrNode core_trie_open(TrEngine engine); +inline void core_trie_close(TrEngine engine, TrNode node, void (*destruct_function)(TrNode)); +inline void core_trie_close_all(TrEngine engine, void (*destruct_function)(TrNode)); +inline void core_trie_set_mode(YAP_Int mode); +inline YAP_Int core_trie_get_mode(void); +inline TrNode core_trie_put_entry(TrEngine engine, TrNode node, YAP_Term entry, YAP_Int *depth); +inline TrNode core_trie_check_entry(TrNode node, YAP_Term entry); +inline YAP_Term core_trie_get_entry(TrNode node); +inline void core_trie_remove_entry(TrEngine engine, TrNode node, void (*destruct_function)(TrNode)); +inline void core_trie_remove_subtree(TrEngine engine, TrNode node, void (*destruct_function)(TrNode)); +inline void core_trie_add(TrNode node_dest, TrNode node_source, void (*add_function)(TrNode, TrNode)); +inline void core_trie_join(TrEngine engine, TrNode node_dest, TrNode node_source, void (*add_function)(TrNode, TrNode), void (*copy_function)(TrNode, TrNode)); +inline void core_trie_intersect(TrEngine engine, TrNode node_dest, TrNode node_source, void (*add_function)(TrNode, TrNode), void (*destruct_function)(TrNode)); +inline YAP_Int core_trie_count_join(TrNode node1, TrNode node2); +inline YAP_Int core_trie_count_intersect(TrNode node1, TrNode node2); +inline void core_trie_save(TrNode node, FILE *file, void (*save_function)(TrNode, FILE *)); +inline TrNode core_trie_load(TrEngine engine, FILE *file, void (*load_function)(TrNode, YAP_Int, FILE *)); +inline void core_trie_stats(TrEngine engine, YAP_Int *memory, YAP_Int *tries, YAP_Int *entries, YAP_Int *nodes); +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)); diff --git a/library/Tries/itries.c b/library/Tries/itries.c index 22d4a040c..07559d9d1 100644 --- a/library/Tries/itries.c +++ b/library/Tries/itries.c @@ -14,7 +14,7 @@ #include #include #include -#include "base_tries.h" +#include "core_tries.h" #include "base_itries.h" @@ -45,6 +45,7 @@ static int p_itrie_intersect(void); static int p_itrie_count_join(void); static int p_itrie_count_intersect(void); static int p_itrie_save(void); +static int p_itrie_save_as_trie(void); static int p_itrie_load(void); static int p_itrie_stats(void); static int p_itrie_max_stats(void); @@ -80,6 +81,7 @@ void init_itries(void) { YAP_UserCPredicate("itrie_count_join", p_itrie_count_join, 3); YAP_UserCPredicate("itrie_count_intersect", p_itrie_count_intersect, 3); YAP_UserCPredicate("itrie_save", p_itrie_save, 2); + YAP_UserCPredicate("itrie_save_as_trie", p_itrie_save_as_trie, 2); YAP_UserCPredicate("itrie_load", p_itrie_load, 2); YAP_UserCPredicate("itrie_stats", p_itrie_stats, 4); YAP_UserCPredicate("itrie_max_stats", p_itrie_max_stats, 4); @@ -526,6 +528,34 @@ static int p_itrie_save(void) { #undef arg_file +/* itrie_save_as_trie(-Itrie,-FileName) */ +#define arg_itrie YAP_ARG1 +#define arg_file YAP_ARG2 +static int p_itrie_save_as_trie(void) { + const char *file_str; + FILE *file; + + /* check args */ + if (!YAP_IsIntTerm(arg_itrie)) + return FALSE; + if (!YAP_IsAtomTerm(arg_file)) + return FALSE; + + /* open file */ + file_str = YAP_AtomName(YAP_AtomOfTerm(arg_file)); + if (!(file = fopen(file_str, "w"))) + return FALSE; + + /* save itrie as trie and close file */ + itrie_save_as_trie((TrEntry) YAP_IntOfTerm(arg_itrie), file); + if (fclose(file)) + return FALSE; + return TRUE; +} +#undef arg_itrie +#undef arg_file + + /* itrie_load(+Itrie,-FileName) */ #define arg_itrie YAP_ARG1 #define arg_file YAP_ARG2 diff --git a/library/Tries/tries.c b/library/Tries/tries.c index 502fc5fd9..b11a46949 100644 --- a/library/Tries/tries.c +++ b/library/Tries/tries.c @@ -14,18 +14,11 @@ #include #include #include +#include "core_tries.h" #include "base_tries.h" -/* -------------------------- */ -/* Local Variables */ -/* -------------------------- */ - -static TrEngine TRIE_ENGINE; - - - /* -------------------------- */ /* Procedures */ /* -------------------------- */ @@ -38,6 +31,8 @@ static int p_trie_mode(void); static int p_trie_put_entry(void); static int p_trie_check_entry(void); static int p_trie_get_entry(void); +static int p_trie_traverse_init(void); +static int p_trie_traverse_cont(void); static int p_trie_remove_entry(void); static int p_trie_remove_subtree(void); static int p_trie_join(void); @@ -66,7 +61,7 @@ static int p_print_trie(void); /* -------------------------- */ void init_tries(void) { - TRIE_ENGINE = trie_init_module(); + trie_init_module(); YAP_UserCPredicate("trie_open", p_trie_open, 1); YAP_UserCPredicate("trie_close", p_trie_close, 1); @@ -75,6 +70,7 @@ void init_tries(void) { YAP_UserCPredicate("trie_put_entry", p_trie_put_entry, 3); YAP_UserCPredicate("trie_check_entry", p_trie_check_entry, 3); YAP_UserCPredicate("trie_get_entry", p_trie_get_entry, 2); + YAP_UserBackCPredicate("trie_traverse", p_trie_traverse_init, p_trie_traverse_cont, 2, 0); YAP_UserCPredicate("trie_remove_entry", p_trie_remove_entry, 1); YAP_UserCPredicate("trie_remove_subtree", p_trie_remove_subtree, 1); YAP_UserCPredicate("trie_join", p_trie_join, 2); @@ -128,7 +124,7 @@ static int p_close_all_tries(void) { #define arg_entry YAP_ARG3 #define arg_ref YAP_ARG4 static int p_put_trie_entry(void) { - TrNode node; + TrData data; const char *mode_str; YAP_Int mode, current_mode; @@ -146,9 +142,9 @@ static int p_put_trie_entry(void) { /* put trie entry */ current_mode = trie_get_mode(); trie_set_mode(mode); - node = trie_put_entry(TRIE_ENGINE, (TrNode) YAP_IntOfTerm(arg_trie), arg_entry, NULL); + data = trie_put_entry((TrEntry) YAP_IntOfTerm(arg_trie), arg_entry); trie_set_mode(current_mode); - return YAP_Unify(arg_ref, YAP_MkIntTerm((YAP_Int) node)); + return YAP_Unify(arg_ref, YAP_MkIntTerm((YAP_Int) data)); } #undef arg_mode #undef arg_trie @@ -179,7 +175,7 @@ static int p_get_trie_entry(void) { /* get trie entry */ current_mode = trie_get_mode(); trie_set_mode(mode); - entry = trie_get_entry((TrNode) YAP_IntOfTerm(arg_ref)); + entry = trie_get_entry((TrData) YAP_IntOfTerm(arg_ref)); trie_set_mode(current_mode); return YAP_Unify(arg_entry, entry); } @@ -208,15 +204,15 @@ static int p_print_trie(void) { /* trie_open(+Trie) */ #define arg_trie YAP_ARG1 static int p_trie_open(void) { - TrNode node; + TrEntry trie; /* check arg */ if (!YAP_IsVarTerm(arg_trie)) return FALSE; /* open trie */ - node = trie_open(TRIE_ENGINE); - return YAP_Unify(arg_trie, YAP_MkIntTerm((YAP_Int) node)); + trie = trie_open(); + return YAP_Unify(arg_trie, YAP_MkIntTerm((YAP_Int) trie)); } #undef arg_trie @@ -229,7 +225,7 @@ static int p_trie_close(void) { return FALSE; /* close trie */ - trie_close(TRIE_ENGINE, (TrNode) YAP_IntOfTerm(arg_trie), NULL); + trie_close((TrEntry) YAP_IntOfTerm(arg_trie)); return TRUE; } #undef arg_trie @@ -237,7 +233,7 @@ static int p_trie_close(void) { /* trie_close_all() */ static int p_trie_close_all(void) { - trie_close_all(TRIE_ENGINE, NULL); + trie_close_all(); return TRUE; } @@ -280,15 +276,15 @@ static int p_trie_mode(void) { #define arg_entry YAP_ARG2 #define arg_ref YAP_ARG3 static int p_trie_put_entry(void) { - TrNode node; + TrData data; /* check args */ if (!YAP_IsIntTerm(arg_trie)) return FALSE; /* put trie entry */ - node = trie_put_entry(TRIE_ENGINE, (TrNode) YAP_IntOfTerm(arg_trie), arg_entry, NULL); - return YAP_Unify(arg_ref, YAP_MkIntTerm((YAP_Int) node)); + data = trie_put_entry((TrEntry) YAP_IntOfTerm(arg_trie), arg_entry); + return YAP_Unify(arg_ref, YAP_MkIntTerm((YAP_Int) data)); } #undef arg_trie #undef arg_entry @@ -300,16 +296,16 @@ static int p_trie_put_entry(void) { #define arg_entry YAP_ARG2 #define arg_ref YAP_ARG3 static int p_trie_check_entry(void) { - TrNode node; + TrData data; /* check args */ if (!YAP_IsIntTerm(arg_trie)) return FALSE; /* check trie entry */ - if (!(node = trie_check_entry((TrNode) YAP_IntOfTerm(arg_trie), arg_entry))) + if (!(data = trie_check_entry((TrEntry) YAP_IntOfTerm(arg_trie), arg_entry))) return FALSE; - return YAP_Unify(arg_ref, YAP_MkIntTerm((YAP_Int) node)); + return YAP_Unify(arg_ref, YAP_MkIntTerm((YAP_Int) data)); } #undef arg_trie #undef arg_entry @@ -327,13 +323,51 @@ static int p_trie_get_entry(void) { return FALSE; /* get trie entry */ - entry = trie_get_entry((TrNode) YAP_IntOfTerm(arg_ref)); + entry = trie_get_entry((TrData) YAP_IntOfTerm(arg_ref)); return YAP_Unify(arg_entry, entry); } #undef arg_ref #undef arg_entry +/* trie_traverse(-Trie,+Ref) */ +#define arg_trie YAP_ARG1 +#define arg_ref YAP_ARG2 +static int p_trie_traverse_init(void) { + TrData data; + + /* check arg */ + if (!YAP_IsIntTerm(arg_trie)) + return FALSE; + + /* traverse trie */ + if (!(data = trie_traverse_init((TrEntry) YAP_IntOfTerm(arg_trie)))) { + YAP_cut_fail(); + return FALSE; + } + return YAP_Unify(arg_ref, YAP_MkIntTerm((YAP_Int) data)); +} +#undef arg_trie +#undef arg_ref + + +/* trie_traverse(-Trie,+Ref) */ +#define arg_trie YAP_ARG1 +#define arg_ref YAP_ARG2 +static int p_trie_traverse_cont(void) { + TrData data; + + /* traverse trie */ + if (!(data = trie_traverse_cont((TrEntry) YAP_IntOfTerm(arg_trie)))) { + YAP_cut_fail(); + return FALSE; + } + return YAP_Unify(arg_ref, YAP_MkIntTerm((YAP_Int) data)); +} +#undef arg_trie +#undef arg_ref + + /* trie_remove_entry(-Ref) */ #define arg_ref YAP_ARG1 static int p_trie_remove_entry(void) { @@ -342,7 +376,7 @@ static int p_trie_remove_entry(void) { return FALSE; /* remove trie entry */ - trie_remove_entry(TRIE_ENGINE, (TrNode) YAP_IntOfTerm(arg_ref), NULL); + trie_remove_entry((TrData) YAP_IntOfTerm(arg_ref)); return TRUE; } #undef arg_ref @@ -356,7 +390,7 @@ static int p_trie_remove_subtree(void) { return FALSE; /* remove trie subtree */ - trie_remove_subtree(TRIE_ENGINE, (TrNode) YAP_IntOfTerm(arg_ref), NULL); + trie_remove_subtree((TrData) YAP_IntOfTerm(arg_ref)); return TRUE; } #undef arg_ref @@ -373,7 +407,7 @@ static int p_trie_join(void) { return FALSE; /* join trie */ - trie_join(TRIE_ENGINE, (TrNode) YAP_IntOfTerm(arg_trie_dest), (TrNode) YAP_IntOfTerm(arg_trie_source), NULL, NULL); + trie_join((TrEntry) YAP_IntOfTerm(arg_trie_dest), (TrEntry) YAP_IntOfTerm(arg_trie_source)); return TRUE; } #undef arg_trie_dest @@ -391,7 +425,7 @@ static int p_trie_intersect(void) { return FALSE; /* intersect trie */ - trie_intersect(TRIE_ENGINE, (TrNode) YAP_IntOfTerm(arg_trie_dest), (TrNode) YAP_IntOfTerm(arg_trie_source), NULL, NULL); + trie_intersect((TrEntry) YAP_IntOfTerm(arg_trie_dest), (TrEntry) YAP_IntOfTerm(arg_trie_source)); return TRUE; } #undef arg_trie_dest @@ -412,7 +446,7 @@ static int p_trie_count_join(void) { return FALSE; /* count join trie */ - entries = trie_count_join((TrNode) YAP_IntOfTerm(arg_trie1), (TrNode) YAP_IntOfTerm(arg_trie2)); + entries = trie_count_join((TrEntry) YAP_IntOfTerm(arg_trie1), (TrEntry) YAP_IntOfTerm(arg_trie2)); return YAP_Unify(arg_entries, YAP_MkIntTerm(entries)); } #undef arg_trie1 @@ -434,7 +468,7 @@ static int p_trie_count_intersect(void) { return FALSE; /* count intersect trie */ - entries = trie_count_intersect((TrNode) YAP_IntOfTerm(arg_trie1), (TrNode) YAP_IntOfTerm(arg_trie2)); + entries = trie_count_intersect((TrEntry) YAP_IntOfTerm(arg_trie1), (TrEntry) YAP_IntOfTerm(arg_trie2)); return YAP_Unify(arg_entries, YAP_MkIntTerm(entries)); } #undef arg_trie1 @@ -461,7 +495,7 @@ static int p_trie_save(void) { return FALSE; /* save trie and close file */ - trie_save((TrNode) YAP_IntOfTerm(arg_trie), file, NULL); + trie_save((TrEntry) YAP_IntOfTerm(arg_trie), file); if (fclose(file)) return FALSE; return TRUE; @@ -474,7 +508,7 @@ static int p_trie_save(void) { #define arg_trie YAP_ARG1 #define arg_file YAP_ARG2 static int p_trie_load(void) { - TrNode node; + TrEntry data; const char *file_str; FILE *file; @@ -490,10 +524,10 @@ static int p_trie_load(void) { return FALSE; /* load trie and close file */ - node = trie_load(TRIE_ENGINE, file, NULL); + data = trie_load(file); if (fclose(file)) return FALSE; - return YAP_Unify(arg_trie, YAP_MkIntTerm((YAP_Int) node)); + return YAP_Unify(arg_trie, YAP_MkIntTerm((YAP_Int) data)); } #undef arg_trie #undef arg_file @@ -508,7 +542,7 @@ static int p_trie_stats(void) { YAP_Int memory, tries, entries, nodes; /* get stats */ - trie_stats(TRIE_ENGINE, &memory, &tries, &entries, &nodes); + trie_stats(&memory, &tries, &entries, &nodes); if (!YAP_Unify(arg_memory, YAP_MkIntTerm(memory))) return FALSE; if (!YAP_Unify(arg_tries, YAP_MkIntTerm(tries))) @@ -534,7 +568,7 @@ static int p_trie_max_stats(void) { YAP_Int memory, tries, entries, nodes; /* get stats */ - trie_max_stats(TRIE_ENGINE, &memory, &tries, &entries, &nodes); + trie_max_stats(&memory, &tries, &entries, &nodes); if (!YAP_Unify(arg_memory, YAP_MkIntTerm(memory))) return FALSE; if (!YAP_Unify(arg_tries, YAP_MkIntTerm(tries))) @@ -564,7 +598,7 @@ static int p_trie_usage(void) { return FALSE; /* get trie usage */ - trie_usage((TrNode) YAP_IntOfTerm(arg_trie), &entries, &nodes, &virtualnodes); + trie_usage((TrEntry) YAP_IntOfTerm(arg_trie), &entries, &nodes, &virtualnodes); if (!YAP_Unify(arg_entries, YAP_MkIntTerm(entries))) return FALSE; if (!YAP_Unify(arg_nodes, YAP_MkIntTerm(nodes))) @@ -587,7 +621,7 @@ static int p_trie_print(void) { return FALSE; /* print trie */ - trie_print((TrNode) YAP_IntOfTerm(arg_trie), NULL); + trie_print((TrEntry) YAP_IntOfTerm(arg_trie)); return TRUE; } #undef arg_trie