From bd25c61fbf986643e7d8e4081e3da4a2f09ec911 Mon Sep 17 00:00:00 2001 From: David Vaz Date: Mon, 17 Dec 2012 20:23:03 +0000 Subject: [PATCH] New work on UDI --- .gitmodules | 3 + C/udi.c | 266 +++++++++++-------- H/utarray.h | 233 +++++++++++++++++ Makefile.in | 11 +- include/rtree_udi.h | 24 -- include/udi.h | 8 +- packages/udi | 1 + packages/udi/README | 7 - packages/udi/rtree.c | 524 ------------------------------------- packages/udi/rtree.h | 63 ----- packages/udi/rtree_udi.c | 179 ------------- packages/udi/rtree_udi_i.h | 20 -- pl/udi.yap | 6 +- 13 files changed, 409 insertions(+), 936 deletions(-) create mode 100644 H/utarray.h delete mode 100644 include/rtree_udi.h create mode 160000 packages/udi delete mode 100644 packages/udi/README delete mode 100644 packages/udi/rtree.c delete mode 100644 packages/udi/rtree.h delete mode 100644 packages/udi/rtree_udi.c delete mode 100644 packages/udi/rtree_udi_i.h diff --git a/.gitmodules b/.gitmodules index 367eac449..dc9ffa933 100644 --- a/.gitmodules +++ b/.gitmodules @@ -43,3 +43,6 @@ [submodule "packages/odbc"] path = packages/odbc url = git://yap.git.sourceforge.net/gitroot/yap/odbc +[submodule "packages/udi"] + path = packages/udi + url = https://github.com/davidvaz/yap-udi-indexers.git diff --git a/C/udi.c b/C/udi.c index 7091df6d4..7a5b04566 100644 --- a/C/udi.c +++ b/C/udi.c @@ -1,169 +1,229 @@ - +#include #include "Yap.h" +#include "YapInterface.h" #include "clause.h" #include "udi.h" +#include "utarray.h" +/* to keep a vector of udi indexers */ +UT_icd udicb_icd = {sizeof(UdiControlBlock), NULL, NULL, NULL}; +UT_array *indexing_structures; -#include "rtree_udi.h" +/* + * New user indexed predicate: + * first argument is the decl term. + * second argument is the init call with the structure + */ +void +Yap_UdiRegister(UdiControlBlock cb){ + /*TODO: check structure integrity and duplicates */ + utarray_push_back(indexing_structures, &cb); +} -/* we can have this stactic because it is written once */ -static struct udi_control_block RtreeCmd; +struct udi_p_args { + void *idxstr; //user indexing structure + UdiControlBlock control; //user indexing structure functions +}; + +/* a pointer utarray list + * This is a hack, becouse I do no know the real type of clauses*/ +UT_icd ptr_icd = {sizeof(void *), NULL, NULL, NULL }; + +#define UDI_MI 10 /****** - All the info we need to enter user indexed code: - predicate - the user control block - functions used, in case we have different schema (maybe should part of previous) + All the info we need to enter user indexed code: right now, this is just a linked list.... ******/ typedef struct udi_info { - PredEntry *p; - void *cb; - UdiControlBlock functions; + PredEntry *p; //predicate (need to identify asserts) + UT_array *clauselist; //clause list used on returns + struct udi_p_args args[UDI_MI]; //indexed args only the first UDI_MI struct udi_info *next; } *UdiInfo; +int Yap_udi_args_init(Term spec, int arity, UdiInfo blk); + /****** we now have one extra user indexed predicate. We assume these are few, so we can do with a linked list. ******/ -static int -add_udi_block(void *info, PredEntry *p, UdiControlBlock cmd) -{ - UdiInfo blk = (UdiInfo)Yap_AllocCodeSpace(sizeof(struct udi_info)); - if (!blk) - return FALSE; - blk->next = UdiControlBlocks; - UdiControlBlocks = blk; - blk->p = p; - blk->functions = cmd; - blk->cb = info; - return TRUE; -} +//static int +//add_udi_block(PredEntry *p, void *info, UdiControlBlock cmd) +//{ +// UdiInfo blk = (UdiInfo) Yap_AllocCodeSpace(sizeof(struct udi_info)); +// if (!blk) +// return FALSE; +// blk->next = UdiControlBlocks; +// UdiControlBlocks = blk; +// blk->p = p; +// blk->functions = cmd; +// blk->cb = info; +// return TRUE; +//} -/****** - new user indexed predicate; - the type right now is just rtrees, but in the future we'll have more. - the second argument is the term. -******/ +/* + * New user indexed predicate: + * the first argument is the term. + */ static Int p_new_udi( USES_REGS1 ) { - Term spec = Deref(ARG2), udi_type = Deref(ARG1); - PredEntry *p; - UdiControlBlock cmd; - Atom udi_t; - void *info; + Term spec = Deref(ARG1); + + PredEntry *p; +// UdiControlBlock cmd; +// Atom udi_t; + UdiInfo blk; + int info; + + fprintf(stderr,"new pred\n"); -/* fprintf(stderr,"new pred babe\n");*/ /* get the predicate from the spec, copied from cdmgr.c */ if (IsVarTerm(spec)) { - Yap_Error(INSTANTIATION_ERROR,spec,"new user index/1"); - return FALSE; + Yap_Error(INSTANTIATION_ERROR,spec,"new user index/1"); + return FALSE; } else if (!IsApplTerm(spec)) { - Yap_Error(TYPE_ERROR_COMPOUND,spec,"new user index/1"); - return FALSE; + Yap_Error(TYPE_ERROR_COMPOUND,spec,"new user index/1"); + return FALSE; } else { - Functor fun = FunctorOfTerm(spec); - Term tmod = CurrentModule; + Functor fun = FunctorOfTerm(spec); + Term tmod = CurrentModule; - while (fun == FunctorModule) { - tmod = ArgOfTerm(1,spec); - if (IsVarTerm(tmod) ) { - Yap_Error(INSTANTIATION_ERROR, spec, "new user index/1"); - return FALSE; - } - if (!IsAtomTerm(tmod) ) { - Yap_Error(TYPE_ERROR_ATOM, spec, "new user index/1"); - return FALSE; - } - spec = ArgOfTerm(2, spec); - fun = FunctorOfTerm(spec); - } - p = RepPredProp(PredPropByFunc(fun, tmod)); + while (fun == FunctorModule) { + tmod = ArgOfTerm(1,spec); + if (IsVarTerm(tmod) ) { + Yap_Error(INSTANTIATION_ERROR, spec, "new user index/1"); + return FALSE; + } + if (!IsAtomTerm(tmod) ) { + Yap_Error(TYPE_ERROR_ATOM, spec, "new user index/1"); + return FALSE; + } + spec = ArgOfTerm(2, spec); + fun = FunctorOfTerm(spec); + } + p = RepPredProp(PredPropByFunc(fun, tmod)); } if (!p) - return FALSE; + return FALSE; /* boring, boring, boring! */ - if ((p->PredFlags & (DynamicPredFlag|LogUpdatePredFlag|UserCPredFlag|CArgsPredFlag|NumberDBPredFlag|AtomDBPredFlag|TestPredFlag|AsmPredFlag|CPredFlag|BinaryPredFlag)) || - (p->ModuleOfPred == PROLOG_MODULE)) { - Yap_Error(PERMISSION_ERROR_MODIFY_STATIC_PROCEDURE, spec, "udi/2"); - return FALSE; + if ((p->PredFlags + & (DynamicPredFlag|LogUpdatePredFlag|UserCPredFlag|CArgsPredFlag|NumberDBPredFlag|AtomDBPredFlag|TestPredFlag|AsmPredFlag|CPredFlag|BinaryPredFlag)) + || (p->ModuleOfPred == PROLOG_MODULE)) { + Yap_Error(PERMISSION_ERROR_MODIFY_STATIC_PROCEDURE, spec, "udi/2"); + return FALSE; } if (p->PredFlags & (DynamicPredFlag|LogUpdatePredFlag|TabledPredFlag)) { - Yap_Error(PERMISSION_ERROR_ACCESS_PRIVATE_PROCEDURE, spec, "udi/2"); - return FALSE; - } - /* just make sure we're looking at the right user type! */ - if (IsVarTerm(udi_type)) { - Yap_Error(INSTANTIATION_ERROR,spec,"new user index/1"); - return FALSE; - } else if (!IsAtomTerm(udi_type)) { - Yap_Error(TYPE_ERROR_ATOM,spec,"new user index/1"); - return FALSE; - } - udi_t = AtomOfTerm(udi_type); - if (udi_t == AtomRTree) { - cmd = &RtreeCmd; - } else { - Yap_Error(TYPE_ERROR_ATOM,spec,"new user index/1"); - return FALSE; + Yap_Error(PERMISSION_ERROR_ACCESS_PRIVATE_PROCEDURE, spec, "udi/2"); + return FALSE; } + /* TODO: remove AtomRTree from atom list */ + /* this is the real work */ - info = cmd->init(spec, (void *)p, p->ArityOfPE); + blk = (UdiInfo) Yap_AllocCodeSpace(sizeof(struct udi_info)); + if (!blk) { + Yap_Error(OUT_OF_HEAP_ERROR, spec, "new user index/1"); + return FALSE; + } + blk->next = UdiControlBlocks; + blk->clauselist = NULL; + blk->p = p; + + info = Yap_udi_args_init(spec, p->ArityOfPE, blk); if (!info) return FALSE; - /* add to table */ - if (!add_udi_block(info, p, cmd)) { - Yap_Error(OUT_OF_HEAP_ERROR, spec, "new user index/1"); - return FALSE; - } + p->PredFlags |= UDIPredFlag; return TRUE; } +/* + * Here we initialize the arguments indexing + */ +int +Yap_udi_args_init(Term spec, int arity, UdiInfo blk) +{ + int i; + Term arg; + Atom idxtype; + UdiControlBlock *p; + + fprintf(stderr,"udi init\n"); + for (i = 1; i <= arity && i <= UDI_MI ; i++) { + blk->args[i-1].idxstr = NULL; + blk->args[i-1].control = NULL; + fprintf(stderr,"%d\n",i); + arg = ArgOfTerm(i,spec); + if (IsAtomTerm(arg)) { + idxtype = AtomOfTerm(arg); + fprintf(stderr,"%p-%s %p-%s\n",idxtype, YAP_AtomName(idxtype), + AtomMinus, YAP_AtomName(AtomMinus)); + if (idxtype == AtomMinus) + continue; + p = NULL; + while ((p = (UdiControlBlock *) utarray_next(indexing_structures, p))) { + fprintf(stderr,"cb: %p %p-%s\n", *p, (*p)->decl, YAP_AtomName((*p)->decl)); + if (idxtype == (*p)->decl){ + blk->args[i-1].idxstr = NULL; + blk->args[i-1].control = *p; + } + } + if (blk->args[i-1].control == NULL){ /* not "-" and not found*/ + fprintf(stderr, "Invalid Spec (%s)\n", AtomName(idxtype)); + return FALSE; + } + } + } + return TRUE; +} + /* just pass info to user, called from cdmgr.c */ int Yap_new_udi_clause(PredEntry *p, yamop *cl, Term t) { - struct udi_info *info = UdiControlBlocks; - while (info->p != p && info) - info = info->next; - if (!info) - return FALSE; - info->cb = info->functions->insert(t, info->cb, (void *)cl); - return TRUE; + /* find our structure*/ + struct udi_info *info = UdiControlBlocks; + while (info->p != p && info) + info = info->next; + if (!info) + return FALSE; + + /* do the actual insertion */ + fprintf(stderr,"udi insert\n"); +// info->cb = info->functions->insert(t, info->cb, (void *)cl); + return TRUE; } /* index, called from absmi.c */ yamop * Yap_udi_search(PredEntry *p) { - struct udi_info *info = UdiControlBlocks; - while (info->p != p && info) - info = info->next; - if (!info) - return NULL; - return info->functions->search(info->cb); + struct udi_info *info = UdiControlBlocks; + while (info->p != p && info) + info = info->next; + if (!info) + return NULL; + return NULL; /*info->functions->search(info->cb);*/ } /* index, called from absmi.c */ void Yap_udi_abolish(PredEntry *p) { - /* tell the predicate destroy */ + /* tell the predicate destroy */ } void Yap_udi_init(void) { UdiControlBlocks = NULL; - /* to be filled in by David */ - RtreeCmd.init = RtreeUdiInit; - RtreeCmd.insert = RtreeUdiInsert; - RtreeCmd.search = RtreeUdiSearch; - RtreeCmd.destroy = RtreeUdiDestroy; - Yap_InitCPred("$udi_init", 2, p_new_udi, 0); + + /*init indexing structures array*/ + utarray_new(indexing_structures, &udicb_icd); + + Yap_InitCPred("$udi_init", 1, p_new_udi, 0); + /* TODO: decide if yap.udi should be loaded automaticaly in init.yap */ } diff --git a/H/utarray.h b/H/utarray.h new file mode 100644 index 000000000..0c1e59b5b --- /dev/null +++ b/H/utarray.h @@ -0,0 +1,233 @@ +/* +Copyright (c) 2008-2013, Troy D. Hanson http://uthash.sourceforge.net +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* a dynamic array implementation using macros + * see http://uthash.sourceforge.net/utarray + */ +#ifndef UTARRAY_H +#define UTARRAY_H + +#define UTARRAY_VERSION 1.9.7 + +#ifdef __GNUC__ +#define _UNUSED_ __attribute__ ((__unused__)) +#else +#define _UNUSED_ +#endif + +#include /* size_t */ +#include /* memset, etc */ +#include /* exit */ + +#define oom() exit(-1) + +typedef void (ctor_f)(void *dst, const void *src); +typedef void (dtor_f)(void *elt); +typedef void (init_f)(void *elt); +typedef struct { + size_t sz; + init_f *init; + ctor_f *copy; + dtor_f *dtor; +} UT_icd; + +typedef struct { + unsigned i,n;/* i: index of next available slot, n: num slots */ + UT_icd icd; /* initializer, copy and destructor functions */ + char *d; /* n slots of size icd->sz*/ +} UT_array; + +#define utarray_init(a,_icd) do { \ + memset(a,0,sizeof(UT_array)); \ + (a)->icd=*_icd; \ +} while(0) + +#define utarray_done(a) do { \ + if ((a)->n) { \ + if ((a)->icd.dtor) { \ + size_t _ut_i; \ + for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \ + (a)->icd.dtor(utarray_eltptr(a,_ut_i)); \ + } \ + } \ + free((a)->d); \ + } \ + (a)->n=0; \ +} while(0) + +#define utarray_new(a,_icd) do { \ + a=(UT_array*)malloc(sizeof(UT_array)); \ + utarray_init(a,_icd); \ +} while(0) + +#define utarray_free(a) do { \ + utarray_done(a); \ + free(a); \ +} while(0) + +#define utarray_reserve(a,by) do { \ + if (((a)->i+by) > ((a)->n)) { \ + while(((a)->i+by) > ((a)->n)) { (a)->n = ((a)->n ? (2*(a)->n) : 8); } \ + if ( ((a)->d=(char*)realloc((a)->d, (a)->n*(a)->icd.sz)) == NULL) oom(); \ + } \ +} while(0) + +#define utarray_push_back(a,p) do { \ + utarray_reserve(a,1); \ + if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,(a)->i++), p); } \ + else { memcpy(_utarray_eltptr(a,(a)->i++), p, (a)->icd.sz); }; \ +} while(0) + +#define utarray_pop_back(a) do { \ + if ((a)->icd.dtor) { (a)->icd.dtor( _utarray_eltptr(a,--((a)->i))); } \ + else { (a)->i--; } \ +} while(0) + +#define utarray_extend_back(a) do { \ + utarray_reserve(a,1); \ + if ((a)->icd.init) { (a)->icd.init(_utarray_eltptr(a,(a)->i)); } \ + else { memset(_utarray_eltptr(a,(a)->i),0,(a)->icd.sz); } \ + (a)->i++; \ +} while(0) + +#define utarray_len(a) ((a)->i) + +#define utarray_eltptr(a,j) (((j) < (a)->i) ? _utarray_eltptr(a,j) : NULL) +#define _utarray_eltptr(a,j) ((char*)((a)->d + ((a)->icd.sz*(j) ))) + +#define utarray_insert(a,p,j) do { \ + utarray_reserve(a,1); \ + if (j > (a)->i) break; \ + if ((j) < (a)->i) { \ + memmove( _utarray_eltptr(a,(j)+1), _utarray_eltptr(a,j), \ + ((a)->i - (j))*((a)->icd.sz)); \ + } \ + if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,j), p); } \ + else { memcpy(_utarray_eltptr(a,j), p, (a)->icd.sz); }; \ + (a)->i++; \ +} while(0) + +#define utarray_inserta(a,w,j) do { \ + if (utarray_len(w) == 0) break; \ + if (j > (a)->i) break; \ + utarray_reserve(a,utarray_len(w)); \ + if ((j) < (a)->i) { \ + memmove(_utarray_eltptr(a,(j)+utarray_len(w)), \ + _utarray_eltptr(a,j), \ + ((a)->i - (j))*((a)->icd.sz)); \ + } \ + if ((a)->icd.copy) { \ + size_t _ut_i; \ + for(_ut_i=0;_ut_i<(w)->i;_ut_i++) { \ + (a)->icd.copy(_utarray_eltptr(a,j+_ut_i), _utarray_eltptr(w,_ut_i)); \ + } \ + } else { \ + memcpy(_utarray_eltptr(a,j), _utarray_eltptr(w,0), \ + utarray_len(w)*((a)->icd.sz)); \ + } \ + (a)->i += utarray_len(w); \ +} while(0) + +#define utarray_resize(dst,num) do { \ + size_t _ut_i; \ + if (dst->i > (size_t)(num)) { \ + if ((dst)->icd.dtor) { \ + for(_ut_i=num; _ut_i < dst->i; _ut_i++) { \ + (dst)->icd.dtor(utarray_eltptr(dst,_ut_i)); \ + } \ + } \ + } else if (dst->i < (size_t)(num)) { \ + utarray_reserve(dst,num-dst->i); \ + if ((dst)->icd.init) { \ + for(_ut_i=dst->i; _ut_i < num; _ut_i++) { \ + (dst)->icd.init(utarray_eltptr(dst,_ut_i)); \ + } \ + } else { \ + memset(_utarray_eltptr(dst,dst->i),0,(dst)->icd.sz*(num-dst->i)); \ + } \ + } \ + dst->i = num; \ +} while(0) + +#define utarray_concat(dst,src) do { \ + utarray_inserta((dst),(src),utarray_len(dst)); \ +} while(0) + +#define utarray_erase(a,pos,len) do { \ + if ((a)->icd.dtor) { \ + size_t _ut_i; \ + for(_ut_i=0; _ut_i < len; _ut_i++) { \ + (a)->icd.dtor(utarray_eltptr((a),pos+_ut_i)); \ + } \ + } \ + if ((a)->i > (pos+len)) { \ + memmove( _utarray_eltptr((a),pos), _utarray_eltptr((a),pos+len), \ + (((a)->i)-(pos+len))*((a)->icd.sz)); \ + } \ + (a)->i -= (len); \ +} while(0) + +#define utarray_renew(a,u) do { \ + if (a) utarray_clear(a); \ + else utarray_new((a),(u)); \ +} while(0) + +#define utarray_clear(a) do { \ + if ((a)->i > 0) { \ + if ((a)->icd.dtor) { \ + size_t _ut_i; \ + for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \ + (a)->icd.dtor(utarray_eltptr(a,_ut_i)); \ + } \ + } \ + (a)->i = 0; \ + } \ +} while(0) + +#define utarray_sort(a,cmp) do { \ + qsort((a)->d, (a)->i, (a)->icd.sz, cmp); \ +} while(0) + +#define utarray_find(a,v,cmp) bsearch((v),(a)->d,(a)->i,(a)->icd.sz,cmp) + +#define utarray_front(a) (((a)->i) ? (_utarray_eltptr(a,0)) : NULL) +#define utarray_next(a,e) (((e)==NULL) ? utarray_front(a) : ((((a)->i) > (utarray_eltidx(a,e)+1)) ? _utarray_eltptr(a,utarray_eltidx(a,e)+1) : NULL)) +#define utarray_prev(a,e) (((e)==NULL) ? utarray_back(a) : ((utarray_eltidx(a,e) > 0) ? _utarray_eltptr(a,utarray_eltidx(a,e)-1) : NULL)) +#define utarray_back(a) (((a)->i) ? (_utarray_eltptr(a,(a)->i-1)) : NULL) +#define utarray_eltidx(a,e) (((char*)(e) >= (char*)((a)->d)) ? (((char*)(e) - (char*)((a)->d))/(a)->icd.sz) : -1) + +/* last we pre-define a few icd for common utarrays of ints and strings */ +static void utarray_str_cpy(void *dst, const void *src) { + char **_src = (char**)src, **_dst = (char**)dst; + *_dst = (*_src == NULL) ? NULL : strdup(*_src); +} +static void utarray_str_dtor(void *elt) { + char **eltc = (char**)elt; + if (*eltc) free(*eltc); +} +static const UT_icd ut_str_icd _UNUSED_ = {sizeof(char*),NULL,utarray_str_cpy,utarray_str_dtor}; +static const UT_icd ut_int_icd _UNUSED_ = {sizeof(int),NULL,NULL,NULL}; +static const UT_icd ut_ptr_icd _UNUSED_ = {sizeof(void*),NULL,NULL,NULL}; + + +#endif /* UTARRAY_H */ diff --git a/Makefile.in b/Makefile.in index d999ed46b..8e8ecf18d 100755 --- a/Makefile.in +++ b/Makefile.in @@ -111,7 +111,6 @@ INTERFACE_HEADERS = \ $(srcdir)/include/clause_list.h \ $(srcdir)/include/dswiatoms.h \ $(srcdir)/include/udi.h \ - $(srcdir)/include/rtree_udi.h \ $(srcdir)/include/yap_structs.h \ $(srcdir)/include/YapInterface.h \ $(srcdir)/include/SWI-Prolog.h \ @@ -262,8 +261,6 @@ C_SOURCES= \ $(srcdir)/C/threads.c \ $(srcdir)/C/tracer.c $(srcdir)/C/unify.c $(srcdir)/C/userpreds.c \ $(srcdir)/C/udi.c \ - $(srcdir)/packages/udi/rtree.c \ - $(srcdir)/packages/udi/rtree_udi.c \ $(srcdir)/C/utilpreds.c $(srcdir)/C/write.c $(srcdir)/console/yap.c \ $(srcdir)/C/yap-args.c \ $(srcdir)/C/ypstdio.c \ @@ -370,7 +367,7 @@ ENGINE_OBJECTS = \ parser.o qlyr.o qlyw.o range.o \ save.o scanner.o sort.o stdpreds.o \ sysbits.o threads.o tracer.o \ - udi.o rtree.o rtree_udi.o\ + udi.o\ unify.o userpreds.o utilpreds.o \ yap-args.o write.o \ blobs.o swi.o ypstdio.o $(IOLIB_OBJECTS) @MPI_OBJS@ @@ -474,12 +471,6 @@ sysbits.o: $(srcdir)/C/sysbits.c config.h udi.o: $(srcdir)/C/udi.c config.h $(CC) -c $(C_INTERF_FLAGS) $(srcdir)/C/udi.c -o $@ -rtree.o: $(srcdir)/packages/udi/rtree.c config.h - $(CC) -c $(C_INTERF_FLAGS) $(srcdir)/packages/udi/rtree.c -o $@ - -rtree_udi.o: $(srcdir)/packages/udi/rtree_udi.c config.h - $(CC) -c $(C_INTERF_FLAGS) $(srcdir)/packages/udi/rtree_udi.c -o $@ - yap.o: $(srcdir)/console/yap.c config.h $(CC) -c $(CFLAGS) -I$(srcdir)/include $(srcdir)/console/yap.c -o $@ diff --git a/include/rtree_udi.h b/include/rtree_udi.h deleted file mode 100644 index d701212f6..000000000 --- a/include/rtree_udi.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef _RTREE_UDI_ -#define _RTREE_UDI_ - -#ifndef _RTREE_ -typedef void control_t; -#endif - -/*Prolog term from :- udi(a(-,+,+)). - User defined index announce -*/ -extern control_t *RtreeUdiInit (Term spec, - void *pred, - int arity); - -/*this is called in each asserted term that was declared to udi_init*/ -extern control_t *RtreeUdiInsert (Term term, /*asserted term*/ - control_t *control, - void *clausule); /*to store in tree and return - in search*/ - -extern void *RtreeUdiSearch (control_t *control); -extern int RtreeUdiDestroy(control_t *control); - -#endif /* _RTREE_UDI_ */ diff --git a/include/udi.h b/include/udi.h index d97a9cdc9..566e90348 100644 --- a/include/udi.h +++ b/include/udi.h @@ -1,4 +1,3 @@ - /*chamada a cada index/2 controi estrutura de control, para definir a indexação, contem a rtree p.e. @@ -6,13 +5,13 @@ */ typedef void * (* Yap_UdiInit)( - Term spec, /* mode spec */ + YAP_Term spec, /* mode spec */ void *pred, /* pass predicate information */ int arity); /*chamada a cada assert*/ typedef void * -(* Yap_UdiInsert)(Term t, /* termo asserted */ +(* Yap_UdiInsert)(YAP_Term t, /* termo asserted */ void *control, /* estrutura de control*/ void *clausule); /* valor a guardar na arvore, para retornar na pesquisa */ @@ -37,9 +36,12 @@ typedef int (* Yap_UdiDestroy)(void * control); typedef struct udi_control_block { + YAP_Atom decl; //atom that triggers this indexing structure Yap_UdiInit init; Yap_UdiInsert insert; Yap_UdiSearch search; Yap_UdiDestroy destroy; } *UdiControlBlock; +/* used to register the new indexing structure */ +void Yap_UdiRegister(UdiControlBlock); diff --git a/packages/udi b/packages/udi new file mode 160000 index 000000000..10522b20e --- /dev/null +++ b/packages/udi @@ -0,0 +1 @@ +Subproject commit 10522b20e6b061d9f68a8e08e800ff0eb9814755 diff --git a/packages/udi/README b/packages/udi/README deleted file mode 100644 index f63b5294d..000000000 --- a/packages/udi/README +++ /dev/null @@ -1,7 +0,0 @@ -This directory contains support for user defined indexers, currently: - -- RTrees - -For Examples and Tests proceed as follows: - -git clone git://yap.dcc.fc.up.pt/udi-examples diff --git a/packages/udi/rtree.c b/packages/udi/rtree.c deleted file mode 100644 index 90bd5b219..000000000 --- a/packages/udi/rtree.c +++ /dev/null @@ -1,524 +0,0 @@ -#include -#include -#include -#include -#include - -#include "rtree.h" - -static node_t RTreeNewNode (void); -static void RTreeDestroyNode (node_t); -static void RTreeNodeInit (node_t); - -static int RTreeSearchNode (node_t, rect_t, SearchHitCallback, void *); -static int RTreeInsertNode (node_t, int, rect_t,void *,node_t *); - -static int RTreePickBranch (rect_t, node_t); -static int RTreeAddBranch(node_t, branch_t, node_t *); -static void RTreeSplitNode (node_t, branch_t, node_t *); - -static void RTreePickSeeds(partition_t *, node_t, node_t); -static void RTreeNodeAddBranch(rect_t *, node_t, branch_t); -static void RTreePickNext(partition_t *, node_t, node_t); - -static rect_t RTreeNodeCover(node_t); - -static double RectArea (rect_t); -static rect_t RectCombine (rect_t, rect_t); -static int RectOverlap (rect_t, rect_t); -static void RectPrint (rect_t); - -static partition_t PartitionNew (void); -static void PartitionPush (partition_t *, branch_t); -static branch_t PartitionPop (partition_t *); -static branch_t PartitionGet (partition_t *, int); - -rtree_t RTreeNew (void) -{ - rtree_t t; - t = RTreeNewNode(); - t->level = 0; /*leaf*/ - return t; -} - -void RTreeDestroy (rtree_t t) -{ - if (t) - RTreeDestroyNode (t); -} - -static node_t RTreeNewNode (void) -{ - node_t n; - - n = (node_t) malloc (sizeof(*n)); - assert(n); - RTreeNodeInit(n); - return n; -} - -static void RTreeDestroyNode (node_t node) -{ - int i; - - if (node->level == 0) /* leaf level*/ - { - for (i = 0; i < MAXCARD; i++) - if (node->branch[i].child) - ;/* allow user free data*/ - else - break; - } - else - { - for (i = 0; i < MAXCARD; i++) - if (node->branch[i].child) - RTreeDestroyNode (node->branch[i].child); - else - break; - } - free (node); -} - -static void RTreeNodeInit (node_t n) -{ - memset((void *) n,0, sizeof(*n)); - n->level = -1; -} - -int RTreeSearch (rtree_t t, rect_t s, SearchHitCallback f, void *arg) -{ - assert(t); - return RTreeSearchNode(t,s,f,arg); -} - -static int RTreeSearchNode (node_t n, rect_t s, SearchHitCallback f, void *arg) -{ - int i; - int c = 0; - - if (n->level > 0) - { - for (i = 0; i < MAXCARD; i++) - if (n->branch[i].child && - RectOverlap (s,n->branch[i].mbr)) - c += RTreeSearchNode ((node_t) n->branch[i].child, s, f, arg); - } - else - { - for (i = 0; i < MAXCARD; i++) - if (n->branch[i].child && - RectOverlap (s,n->branch[i].mbr)) - { - c ++; - if (f) - if ( !f(n->branch[i].mbr,n->branch[i].child,arg)) - return c; - } - } - return c; -} - -void RTreeInsert (rtree_t *t, rect_t r, void *data) -{ - node_t n2; - node_t new_root; - branch_t b; - assert(t && *t); - - if (RTreeInsertNode(*t, 0, r, data, &n2)) - /* deal with root split */ - { - new_root = RTreeNewNode(); - new_root->level = (*t)->level + 1; - b.mbr = RTreeNodeCover(*t); - b.child = (void *) *t; - RTreeAddBranch(new_root, b, NULL); - b.mbr = RTreeNodeCover(n2); - b.child = (void *) n2; - RTreeAddBranch(new_root, b, NULL); - *t = new_root; - } -} - -static int RTreeInsertNode (node_t n, int level, - rect_t r, void *data, - node_t *new_node) -{ - int i; - node_t n2; - branch_t b; - - assert(n && new_node); - assert(level >= 0 && level <= n->level); - - if (n->level > level) - { - i = RTreePickBranch(r,n); - if (!RTreeInsertNode((node_t) n->branch[i].child, level, - r, data,&n2)) /* not split */ - { - n->branch[i].mbr = RectCombine(r,n->branch[i].mbr); - return FALSE; - } - else /* node split */ - { - n->branch[i].mbr = RTreeNodeCover(n->branch[i].child); - b.child = n2; - b.mbr = RTreeNodeCover(n2); - return RTreeAddBranch(n, b, new_node); - } - } - else /*insert level*/ - { - b.mbr = r; - b.child = data; - return RTreeAddBranch(n, b, new_node); - } -} - -static int RTreeAddBranch(node_t n, branch_t b, node_t *new_node) -{ - int i; - - assert(n); - - if (n->count < MAXCARD) /*split not necessary*/ - { - for (i = 0; i < MAXCARD; i++) - if (n->branch[i].child == NULL) - { - n->branch[i] = b; - n->count ++; - break; - } - return FALSE; - } - else /*needs to split*/ - { - assert(new_node); - RTreeSplitNode (n, b, new_node); - return TRUE; - } -} - -static int RTreePickBranch (rect_t r, node_t n) -{ - int i; - double area; - double inc_area; - rect_t tmp; - int best_i; - double best_inc; - double best_i_area; - - best_i = 0; - best_inc = DBL_MAX; /* double Max value */ - best_i_area = DBL_MAX; - - for (i = 0; i < MAXCARD; i++) - if (n->branch[i].child) - { - area = RectArea (n->branch[i].mbr); - tmp = RectCombine (r, n->branch[i].mbr); - inc_area = RectArea (tmp) - area; - - if (inc_area < best_inc) - { - best_inc = inc_area; - best_i = i; - best_i_area = area; - } - else if (inc_area == best_inc && best_i_area > area) - { - best_inc = inc_area; - best_i = i; - best_i_area = area; - } - } - else - break; - return best_i; -} - -static void RTreeSplitNode (node_t n, branch_t b, node_t *new_node) -{ - partition_t p; - int level; - int i; - - assert(n); - assert(new_node); - - p = PartitionNew(); - - for (i = 0; i < MAXCARD; i ++) - PartitionPush(&p,n->branch[i]); - PartitionPush(&p,b); - - level = n->level; - RTreeNodeInit(n); - n->level = level; - *new_node = RTreeNewNode(); - (*new_node)->level = level; - - RTreePickSeeds(&p, n, *new_node); - - while (p.n) - if (n->count + p.n <= MINCARD) - /* first group (n) needs all entries */ - RTreeNodeAddBranch(&(p.cover[0]), n, PartitionPop(&p)); - else if ((*new_node)->count + p.n <= MINCARD) - /* second group (new_node) needs all entries */ - RTreeNodeAddBranch(&(p.cover[1]), *new_node, PartitionPop(&p)); - else - RTreePickNext(&p, n, *new_node); -} - -static void RTreePickNext(partition_t *p, node_t n1, node_t n2) -/* linear version */ -{ - branch_t b; - double area[2], inc_area[2]; - rect_t tmp; - - b = PartitionPop(p); - - area[0] = RectArea (p->cover[0]); - tmp = RectCombine (p->cover[0], b.mbr); - inc_area[0] = RectArea (tmp) - area[0]; - - area[1] = RectArea (p->cover[1]); - tmp = RectCombine (p->cover[1], b.mbr); - inc_area[1] = RectArea (tmp) - area[1]; - - if (inc_area[0] < inc_area[1] || - (inc_area[0] == inc_area[1] && area[0] < area[1])) - RTreeNodeAddBranch(&(p->cover[0]),n1,b); - else - RTreeNodeAddBranch(&(p->cover[1]),n2,b); -} - -static void RTreePickSeeds(partition_t *p, node_t n1, node_t n2) -/* puts in index 0 of each node the resulting entry, forming the two - groups - This is the linear version -*/ -{ - int dim,high, i; - int highestLow[NUMDIMS], lowestHigh[NUMDIMS]; - double width[NUMDIMS]; - int seed0, seed1; - double sep, best_sep; - - assert(p->n == MAXCARD + 1); - - for (dim = 0; dim < NUMDIMS; dim++) - { - high = dim + NUMDIMS; - highestLow[dim] = lowestHigh[dim] = 0; - for (i = 1; i < MAXCARD +1; i++) - { - if (p->buffer[i].mbr.coords[dim] > - p->buffer[highestLow[dim]].mbr.coords[dim]) - highestLow[dim] = i; - if (p->buffer[i].mbr.coords[high] < - p->buffer[lowestHigh[dim]].mbr.coords[high]) - lowestHigh[dim] = i; - } - width[dim] = p->cover_all.coords[high] - p->cover_all.coords[dim]; - assert(width[dim] >= 0); - } - - seed0 = lowestHigh[0]; - seed1 = highestLow[0]; - best_sep = 0; - for (dim = 0; dim < NUMDIMS; dim ++) - { - high = dim + NUMDIMS; - - sep = (p->buffer[highestLow[dim]].mbr.coords[dim] - - p->buffer[lowestHigh[dim]].mbr.coords[high]) / width[dim]; - if (sep > best_sep) - { - seed0 = lowestHigh[dim]; - seed1 = highestLow[dim]; - best_sep = sep; - } - } -/* assert (seed0 != seed1); */ - if (seed0 > seed1) - { - RTreeNodeAddBranch(&(p->cover[0]),n1,PartitionGet(p,seed0)); - RTreeNodeAddBranch(&(p->cover[1]),n2,PartitionGet(p,seed1)); - } - else if (seed0 < seed1) - { - RTreeNodeAddBranch(&(p->cover[0]),n1,PartitionGet(p,seed1)); - RTreeNodeAddBranch(&(p->cover[1]),n2,PartitionGet(p,seed0)); - } -} - -static void RTreeNodeAddBranch(rect_t *r, node_t n, branch_t b) -{ - int i; - - assert(n); - assert(n->count < MAXCARD); - - for (i = 0; i < MAXCARD; i++) - if (n->branch[i].child == NULL) - { - n->branch[i] = b; - n->count ++; - break; - } - *r = RectCombine(*r,b.mbr); -} - - -void RTreePrint(node_t t) -{ - int i; - - /* printf("rtree([_,_,_,_,_]).\n"); */ - printf("rtree(%p,%d,[",t,t->level); - for (i = 0; i < MAXCARD; i++) - { - if (t->branch[i].child != NULL) - { - printf("(%p,",t->branch[i].child); - RectPrint(t->branch[i].mbr); - printf(")"); - } - else - { - printf("nil"); - } - if (i < MAXCARD-1) - printf(","); - } - printf("]).\n"); - - if (t->level != 0) - for (i = 0; i < MAXCARD; i++) - if (t->branch[i].child != NULL) - RTreePrint((node_t) t->branch[i].child); - else - break; -} - -/* - * Partition related - */ - -static partition_t PartitionNew (void) -{ - partition_t p; - memset((void *) &p,0, sizeof(p)); - p.cover[0] = p.cover[1] = p.cover_all = RectInit(); - return p; -} - -static void PartitionPush (partition_t *p, branch_t b) -{ - assert(p->n < MAXCARD + 1); - p->buffer[p->n] = b; - p->n ++; - p->cover_all = RectCombine(p->cover_all,b.mbr); -} - -static branch_t PartitionPop (partition_t *p) -{ - assert(p->n > 0); - p->n --; - return p->buffer[p->n]; -} - -static branch_t PartitionGet (partition_t *p, int n) -{ - branch_t b; - assert (p->n > n); - b = p->buffer[n]; - p->buffer[n] = PartitionPop(p); - return b; -} - -/* - * Rect related - */ - -rect_t RectInit (void) -{ - rect_t r = {{DBL_MAX, DBL_MAX, DBL_MIN, DBL_MIN}}; - return (r); -} - -static double RectArea (rect_t r) -{ - int i; - double area; - - for (i = 0,area = 1; i < NUMDIMS; i++) - area *= r.coords[i+NUMDIMS] - r.coords[i]; - -/* area = (r.coords[1] - r.coords[0]) * */ -/* (r.coords[3] - r.coords[2]); */ - - return area; -} - -static rect_t RectCombine (rect_t r, rect_t s) -{ - int i; - rect_t new_rect; - - for (i = 0; i < NUMDIMS; i++) - { - new_rect.coords[i] = MIN(r.coords[i],s.coords[i]); - new_rect.coords[i+NUMDIMS] = MAX(r.coords[i+NUMDIMS],s.coords[i+NUMDIMS]); - } - - return new_rect; -} - -static int RectOverlap (rect_t r, rect_t s) -{ - int i; - - for (i = 0; i < NUMDIMS; i++) - if (r.coords[i] > s.coords[i + NUMDIMS] || - s.coords[i] > r.coords[i + NUMDIMS]) - return FALSE; - return TRUE; -} - -static rect_t RTreeNodeCover(node_t n) -{ - int i; - rect_t r = RectInit(); - - for (i = 0; i < MAXCARD; i++) - if (n->branch[i].child) - { - r = RectCombine (r, n->branch[i].mbr); - } - else - break; - - return r; -} - -static void RectPrint (rect_t r) -{ - int i; - - printf("["); - for (i = 0; i < 2*NUMDIMS; i++) - { - printf("%f",r.coords[i]); - if ( i < 2*NUMDIMS - 1) - printf(","); - } - printf("]"); -} diff --git a/packages/udi/rtree.h b/packages/udi/rtree.h deleted file mode 100644 index f05ae86e8..000000000 --- a/packages/udi/rtree.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef _RTREE_ -#define _RTREE_ - -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef TRUE -#define TRUE !FALSE -#endif - -#define NUMDIMS 2 /* 2d */ - -struct Rect -{ - double coords[2*NUMDIMS]; /* x1min, y1min, ... , x1max, y1max, ...*/ -}; -typedef struct Rect rect_t; - -struct Branch -{ - rect_t mbr; - void * child; /*void * so user can store whatever he needs, in case - of non-leaf ndes it stores the child-pointer*/ -}; -typedef struct Branch branch_t; - -#define PGSIZE 196 -#define MAXCARD (int)((PGSIZE-(2*sizeof(int)))/ sizeof(struct Branch)) -#define MINCARD (MAXCARD / 2) - -struct Node -{ - int count; - int level; - branch_t branch[MAXCARD]; -}; -typedef struct Node * node_t; - -typedef node_t rtree_t; - -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define MAX(a, b) ((a) > (b) ? (a) : (b)) - -/* CallBack to search function */ -typedef int (*SearchHitCallback)(rect_t r, void *data, void *arg); - -extern rtree_t RTreeNew (void); -extern void RTreeInsert (rtree_t *, rect_t, void *); -extern int RTreeSearch (rtree_t, rect_t, SearchHitCallback, void *); -extern void RTreeDestroy (rtree_t); -extern void RTreePrint(node_t); -extern rect_t RectInit (void); - -struct Partition -{ - branch_t buffer[MAXCARD+1]; - int n; - rect_t cover_all; - rect_t cover[2]; -}; -typedef struct Partition partition_t; - -#endif /* _RTREE_ */ diff --git a/packages/udi/rtree_udi.c b/packages/udi/rtree_udi.c deleted file mode 100644 index e9c092c98..000000000 --- a/packages/udi/rtree_udi.c +++ /dev/null @@ -1,179 +0,0 @@ -#include -#include -#include -#include - -#include - -#include "Yap.h" - -#include "rtree.h" -#include "clause_list.h" -#include "rtree_udi_i.h" -#include "rtree_udi.h" - -static int YAP_IsNumberTermToFloat (Term term, YAP_Float *n) -{ - if (YAP_IsIntTerm (term) != FALSE) - { - if (n != NULL) - *n = (YAP_Float) YAP_IntOfTerm (term); - return (TRUE); - } - if (YAP_IsFloatTerm (term) != FALSE) - { - if (n != NULL) - *n = YAP_FloatOfTerm (term); - return (TRUE); - } - return (FALSE); -} - -static rect_t RectOfTerm (Term term) -{ - YAP_Term tmp; - rect_t rect; - int i; - - if (!YAP_IsPairTerm(term)) - return (RectInit()); - - for (i = 0; YAP_IsPairTerm(term) && i < 4; i++) - { - tmp = YAP_HeadOfTerm (term); - if (!YAP_IsNumberTermToFloat(tmp,&(rect.coords[i]))) - return (RectInit()); - term = YAP_TailOfTerm (term); - } - - return (rect); -} - -control_t *RtreeUdiInit (Term spec, - void * pred, - int arity){ - control_t *control; - YAP_Term arg; - int i, c; - /* YAP_Term mod; */ - - /* spec = Yap_StripModule(spec, &mod); */ - if (! YAP_IsApplTerm(spec)) - return (NULL); - - control = (control_t *) malloc (sizeof(*control)); - assert(control); - memset((void *) control,0, sizeof(*control)); - - c = 0; - for (i = 1; i <= arity; i ++) - { - arg = YAP_ArgOfTerm(i,spec); - if (YAP_IsAtomTerm(arg) - && strcmp("+",YAP_AtomName(YAP_AtomOfTerm(arg))) == 0) - { - - (*control)[c].pred = pred; - (*control)[c++].arg = i; - - } - } - -/* for (i = 0; i < NARGS; i++) - printf("%d,%p\t",(*control)[i].arg,(*control)[i].tree); - printf("\n"); */ - - return control; -} - -control_t *RtreeUdiInsert (Term term,control_t *control,void *clausule) -{ - int i; - rect_t r; - - assert(control); - - for (i = 0; i < NARGS && (*control)[i].arg != 0 ; i++) - { - r = RectOfTerm(YAP_ArgOfTerm((*control)[i].arg,term)); - if (!(*control)[i].tree) - (*control)[i].tree = RTreeNew(); - RTreeInsert(&(*control)[i].tree,r,clausule); - } - - /* printf("insert %p\n", clausule); */ - - return (control); -} - -static int callback(rect_t r, void *data, void *arg) -{ - callback_m_t x; - x = (callback_m_t) arg; - return Yap_ClauseListExtend(x->cl,data,x->pred); -} - -/*ARGS ARE AVAILABLE*/ -void *RtreeUdiSearch (control_t *control) -{ - rect_t r; - int i; - struct ClauseList clauselist; - struct CallbackM cm; - callback_m_t c; - YAP_Term Constraints; - - /*RTreePrint ((*control)[0].tree);*/ - - for (i = 0; i < NARGS && (*control)[i].arg != 0 ; i++) { - YAP_Term t = YAP_A((*control)[i].arg); - if (YAP_IsAttVar(t)) - { - fprintf(stderr,"i=%ld\n",i); - /*get the constraits rect*/ - Constraints = YAP_AttsOfVar(t); - /* Yap_DebugPlWrite(Constraints); */ - r = RectOfTerm(YAP_ArgOfTerm(2,Constraints)); - - c = &cm; - c->cl = Yap_ClauseListInit(&clauselist); - c->pred = (*control)[i].pred; - if (!c->cl) - return NULL; /*? or fail*/ - RTreeSearch((*control)[i].tree, r, callback, c); - Yap_ClauseListClose(c->cl); - - if (Yap_ClauseListCount(c->cl) == 0) - { - Yap_ClauseListDestroy(c->cl); - return Yap_FAILCODE(); - } - - if (Yap_ClauseListCount(c->cl) == 1) - { - return Yap_ClauseListToClause(c->cl); - } - - return Yap_ClauseListCode(c->cl); - } - } - return NULL; /*YAP FALLBACK*/ -} - -int RtreeUdiDestroy(control_t *control) -{ - int i; - - assert(control); - - for (i = 0; i < NARGS && (*control)[i].arg != 0; i++) - { - if ((*control)[i].tree) - RTreeDestroy((*control)[i].tree); - } - - free(control); - control = NULL; - - return TRUE; -} diff --git a/packages/udi/rtree_udi_i.h b/packages/udi/rtree_udi_i.h deleted file mode 100644 index d16aeb04e..000000000 --- a/packages/udi/rtree_udi_i.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _RTREE_UDI_I_ -#define _RTREE_UDI_I_ - -#define NARGS 5 -struct Control -{ - int arg; - void *pred; - rtree_t tree; -}; -typedef struct Control control_t[NARGS]; - -struct CallbackM -{ - clause_list_t cl; - void * pred; -}; -typedef struct CallbackM * callback_m_t; - -#endif /* _RTREE_UDI_I_ */ diff --git a/pl/udi.yap b/pl/udi.yap index a1e177174..b0da6c65b 100644 --- a/pl/udi.yap +++ b/pl/udi.yap @@ -9,7 +9,7 @@ ************************************************************************** * * * File: udi.yap * -* Last rev: 8/2/88 * +* Last rev: 17/12/2012 * * mods: * * comments: support user defined indexing * * * @@ -22,5 +22,5 @@ ******************/ udi(Pred) :- - '$udi_init'(rtree, Pred). - + writeln(('udi.yap ',Pred)), + '$udi_init'(Pred).