New work on UDI
This commit is contained in:
		
							
								
								
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							@@ -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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										266
									
								
								C/udi.c
									
									
									
									
									
								
							
							
						
						
									
										266
									
								
								C/udi.c
									
									
									
									
									
								
							@@ -1,169 +1,229 @@
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#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 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										233
									
								
								H/utarray.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										233
									
								
								H/utarray.h
									
									
									
									
									
										Normal file
									
								
							@@ -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 <stddef.h>  /* size_t */
 | 
			
		||||
#include <string.h>  /* memset, etc */
 | 
			
		||||
#include <stdlib.h>  /* 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 */
 | 
			
		||||
							
								
								
									
										11
									
								
								Makefile.in
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								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 $@
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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_ */
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								packages/udi
									
									
									
									
									
										Submodule
									
								
							
							
								
								
								
								
								
							
						
						
									
										1
									
								
								packages/udi
									
									
									
									
									
										Submodule
									
								
							 Submodule packages/udi added at 10522b20e6
									
								
							@@ -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 
 | 
			
		||||
@@ -1,524 +0,0 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <float.h>
 | 
			
		||||
 | 
			
		||||
#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("]");
 | 
			
		||||
}
 | 
			
		||||
@@ -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_ */
 | 
			
		||||
@@ -1,179 +0,0 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
 | 
			
		||||
#include <YapInterface.h>
 | 
			
		||||
 | 
			
		||||
#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;
 | 
			
		||||
}
 | 
			
		||||
@@ -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_ */
 | 
			
		||||
@@ -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).
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user