[SCM] Gerris Flow Solver branch, upstream, updated. b3aa46814a06c9cb2912790b23916ffb44f1f203
Stephane Popinet
popinet at users.sf.net
Fri May 15 02:55:11 UTC 2009
The following commit has been merged in the upstream branch:
commit 918763e2fddb67877139af6e46ce4fe1e4292c8b
Author: Stephane Popinet <popinet at users.sf.net>
Date: Thu Apr 10 18:32:54 2008 +1000
R*-tree implementation of Norbert Beckmann
This is the original implementation as unpacked from http://www.rtreeportal.org.
darcs-hash:20080410083254-d4795-eb1eaa09348c570bb8f659a3c09e57a39dd72757.gz
diff --git a/modules/RStarTree/Makefile b/modules/RStarTree/Makefile
new file mode 100644
index 0000000..14a83f8
--- /dev/null
+++ b/modules/RStarTree/Makefile
@@ -0,0 +1,131 @@
+# Make RStarTree C-Version R2.0
+
+# Cflags = -g -ansi -pedantic -Wall
+# Cflags = -g -ansi -pedantic
+Cflags = -O -ansi -pedantic -Wall
+# Cflags = -O -ansi -pedantic
+
+CC = gcc
+
+
+compile = $(CC) $(Cflags) -c
+link = $(CC) $(Cflags) -o
+
+
+RSTos = RStarTree.o RSTInterUtil.o RSTInOut.o RSTInstDel.o RSTUtil.o \
+ RSTQuery.o RSTJoin.o
+
+
+libraries = libcSmRST.a
+programs = trst
+
+
+ RANLIB = ranlib $(libraries) # Berkely
+# RANLIB = @ echo 'skipping ranlib' # SVR4
+
+
+all: $(libraries) $(programs)
+
+
+#
+# Libraries
+#
+libcSmRST.a: $(RSTos)
+ ar rcv libcSmRST.a $(RSTos)
+ $(RANLIB)
+ mv README ..
+ mv libcSmRST.a ..
+ cp RStarTree.h ..
+ cp RSTBase.h ..
+
+#
+# Main Programs
+#
+trst: trst.o \
+ libcSmRST.a \
+ Set.o
+ $(link) trst trst.o Set.o -L.. -lcSmRST
+
+trst.o: trst.c \
+ RStarTree.h \
+ Set.h
+ $(compile) trst.c
+
+#
+# compile the modules.
+#
+RStarTree.o: RStarTree.c \
+ RStarTree.h \
+ RSTInterUtil.h \
+ RSTInOut.h \
+ RSTInstDel.h \
+ RSTQuery.h \
+ RSTJoin.h
+ $(compile) RStarTree.c
+
+RSTInterUtil.o: RSTInterUtil.c \
+ RSTInterUtil.h \
+ RStarTree.h
+ $(compile) RSTInterUtil.c
+
+RSTInOut.o: RSTInOut.c \
+ RSTInOut.h \
+ RStarTree.h
+ $(compile) RSTInOut.c
+
+RSTInstDel.o: RSTInstDel.c \
+ RSTInstDel.h \
+ RStarTree.h \
+ RSTUtil.h \
+ RSTInOut.h
+ $(compile) RSTInstDel.c
+
+RSTUtil.o: RSTUtil.c \
+ RSTUtil.h \
+ RStarTree.h
+ $(compile) RSTUtil.c
+
+RSTQuery.o: RSTQuery.c \
+ RSTQuery.h \
+ RStarTree.h \
+ RSTUtil.h \
+ RSTInOut.h
+ $(compile) RSTQuery.c
+
+RSTJoin.o: RSTJoin.c \
+ RSTJoin.h \
+ RStarTree.h \
+ RSTUtil.h \
+ RSTInOut.h
+ $(compile) RSTJoin.c
+
+Set.o: Set.c \
+ Set.h
+ $(compile) Set.c
+
+#
+# interface dependencies
+#
+RStarTree.h: RSTBase.h
+ touch RStarTree.h
+
+RSTInterUtil.h: RStarTree.h
+ touch RSTInterUtil.h
+
+RSTInOut.h: RStarTree.h
+ touch RSTInOut.h
+
+RSTInstDel.h: RStarTree.h
+ touch RSTInstDel.h
+
+RSTUtil.h: RStarTree.h
+ touch RSTUtil.h
+
+RSTQuery.h: RStarTree.h
+ touch RSTQuery.h
+
+RSTJoin.h: RStarTree.h
+ touch RSTJoin.h
+
+Set.h: SetDef.h
+ touch Set.h
diff --git a/modules/RStarTree/README b/modules/RStarTree/README
new file mode 100644
index 0000000..672da83
--- /dev/null
+++ b/modules/RStarTree/README
@@ -0,0 +1,20 @@
+User guide for RStarTree Version R2.xx (VR2.xx)
+-----------------------------------------------
+
+The files "RStarTree.h", "RSTBase.h" and "libcSmRST.a" should reside in the
+directory, where this README file resides. We will call this directory "dest".
+RStarTree.h is the user interface. RSTBase.h is a private header file included
+by RStarTree.h. Provided that, RSTREE is a typed pointer (not a void).
+
+SYNOPSYS
+
+Compilation:
+#include "dest/RStarTree.h"
+
+Linking:
+-Ldest -lcSmRST
+
+The usage of the RStarTree implementation is explained in RStarTree.h.
+You might have a look at dest/src/trst.c as an example as well. trst uses a
+little set implementation also located in dest/src.
+Installation hints you'll find in dest/src/READMEInstall.
diff --git a/modules/RStarTree/RSTBase.h b/modules/RStarTree/RSTBase.h
new file mode 100644
index 0000000..d4cb113
--- /dev/null
+++ b/modules/RStarTree/RSTBase.h
@@ -0,0 +1,211 @@
+/* ----- RSTBase.h ----- */
+#ifndef __RSTBase_h
+#define __RSTBase_h
+
+
+/*** Begin ----- naming rules for structured types ----- **********/
+/*
+Non vector types are always called "typ<..>",
+ Exceptions:
+ Side, rstree.
+References to non vector types are always called "ref<..>".
+ Exceptions:
+ RSTREE.
+Vector types are always called <..>Array.
+ Exceptions:
+ RSTName, typpoint, typrect, typfixblock,
+ and the internal arrays of the R*-tree as
+ typpath, typentrynumbs, typpagenrs, typflagarray, typpagecountarr.
+*/
+/*** End ----- naming rules for structured types ----- **********/
+
+
+/* constants */
+
+#define SIZEfixblock 512
+#define maxnum (((SIZEfixblock-2*sizeof(int)) / sizeof(int))-1)
+#define maxentries MaxNumbOfEntriesPerPage
+#define EntryRange (maxentries+sizeof(int))
+
+#define chainlen 42 /* 3^ 40 = 12,157,665,459,056,928,801 */
+
+#define datasuffix ".Data"
+#define dirPDsuffix ".DirPD"
+#define dataPDsuffix ".DataPD"
+
+#define STDMODE 0644
+
+#define paramblocknumb 0
+#define firstPDblocknumb (paramblocknumb+1)
+#define rootblocknumb 0
+
+
+/* types */
+
+typedef typinterval *refinterval;
+
+typedef char RSTName[MaxNameLength];
+typedef double typpoint[NumbOfDim];
+
+typedef double ValueArray[EntryRange];
+typedef int IndexArray[EntryRange];
+typedef byte ByteArray[EntryRange];
+typedef typrect RectArray[EntryRange];
+typedef typrect NbrsArray[EntryRange];
+typedef typpoint PointArray[EntryRange];
+
+typedef enum {
+ low,
+ high
+ } Side;
+
+typedef struct {
+ typrect rect;
+ int ptrtosub;
+ } typDIRent, *refDIRent; /* inner entry */
+typedef struct {
+ typrect rect;
+ typinfo info;
+ } typDATAent, *refDATAent; /* data entry */
+typedef union {
+ typDIRent DIR;
+ typDATAent DATA;
+ } typentry, *refentry; /* universal entry */
+ /* If typentry v; Then */
+ /* every access to rect by v.DIR.rect */
+ /* End */
+ /* hope the compiler-designers agree. */
+
+
+typedef typDIRent typDIRentries[EntryRange];
+typedef typDATAent typDATAentries[EntryRange];
+
+
+typedef struct {
+ int nofentries;
+ typDIRentries entries; /* 0 .. nofentries-1 !! */
+ } typDIRnode, *refDIRnode; /* inner node */
+typedef struct {
+ int nofentries;
+ typDATAentries entries; /* 0 .. nofentries-1 !! */
+ } typDATAnode, *refDATAnode; /* data node */
+typedef union {
+ typDIRnode DIR;
+ typDATAnode DATA;
+ } typnode, *refnode; /* universal node */
+ /* If typnode v; Then */
+ /* every access to nofentries by v.DIR.nofentries */
+ /* End */
+ /* hope the compiler-designers agree. */
+
+
+typedef refnode typpath[chainlen+1]; /* 1 .. height !! */
+typedef int typentrynumbs[chainlen+1]; /* 1 .. height !! */
+typedef int typpagenrs[chainlen+1]; /* 1 .. height !! */
+typedef boolean typflagarray[chainlen+1]; /* 1 .. height !! */
+
+typedef byte typfixblock[SIZEfixblock];
+
+typedef struct {
+ int childnr;
+ int nofnumbers;
+ int number[maxnum+1]; /* 0 + [1 .. maxnum] !! */
+ } typpagedir, *refpagedir;
+
+typedef union {
+ typpagedir _; /* call the intrinsics "_" */
+ typfixblock fixblock; /* adjust to SIZEfixblock */
+ } typPDblock, *refPDblock;
+
+typedef int typpagecountarr[chainlen+1]; /* 1 .. height !! */
+
+typedef struct {
+ boolean unique;
+ int height;
+ int SIZE_DIRnofentries, SIZE_DATAnofentries;
+ int SIZEinfo;
+ int direntrylen, dataentrylen;
+ int nbrsexam;
+ int reinstpercent;
+ int minfillpercent;
+ int dirreinsertqty, datareinsertqty;
+ int pagelen;
+ int dirM, dirMwords, dirm;
+ int dataM, dataMwords, datam;
+ int maxdim;
+ int dirpagecount, datapagecount, recordcount;
+ typpagecountarr pagecountarr;
+ } typparameters, *refparameters;
+
+typedef union {
+ typparameters _; /* call the intrinsics "_" */
+ typfixblock fixblock; /* adjust to SIZEfixblock */
+ } typparamblock, *refparamblock;
+
+typedef struct {
+ boolean countflag;
+ int dirvisitcount, datavisitcount;
+ int dirreadcount, datareadcount;
+ int dirmodifycount, datamodifycount;
+ int dirwritecount, datawritecount;
+ } typcount, *refcount;
+
+typedef struct {
+ File f;
+ int bl;
+ } typfiledesc;
+
+typedef struct {
+ int dirnodelen, datanodelen;
+ typpath N, NInst, NDel;
+ typentrynumbs E, EInst;
+ typpagenrs P;
+ typflagarray Nmodified, ReInsert;
+ typPDblock dirpagedir, datapagedir;
+ typparamblock parameters;
+ typcount count;
+ boolean RSTDone;
+ refnode helpdirnode, helpdatanode, Ntosplit, Nsibling;
+ typfiledesc dir, data, dirPD, dataPD;
+ RSTName dirname;
+ } rstree;
+
+
+/****************************************************************/
+/* begin **** --- types to check for alignment problems --- *****/
+
+typedef
+ typDIRent typ2DIRentries[2];
+typedef
+ typDATAent typ2DATAentries[2];
+typedef
+ struct {
+ int nofentries;
+ typ2DIRentries entries;
+ } typDIRnodeOf2; /* inner node containing 2 entries */
+typedef
+ struct {
+ int nofentries;
+ typ2DATAentries entries;
+ } typDATAnodeOf2; /* data node containing 2 entries */
+
+typedef
+ typDIRent typ3DIRentries[3];
+typedef
+ typDATAent typ3DATAentries[3];
+typedef
+ struct {
+ int nofentries;
+ typ3DIRentries entries;
+ } typDIRnodeOf3; /* inner node containing 3 entries */
+typedef
+ struct {
+ int nofentries;
+ typ3DATAentries entries;
+ } typDATAnodeOf3; /* data node containing 3 entries */
+
+/* end **** --- types to check for alignment problems --- *****/
+/****************************************************************/
+
+
+#endif /* !__RSTBase_h */
diff --git a/modules/RStarTree/RSTInOut.c b/modules/RStarTree/RSTInOut.c
new file mode 100644
index 0000000..35cb963
--- /dev/null
+++ b/modules/RStarTree/RSTInOut.c
@@ -0,0 +1,226 @@
+/* ----- RSTInOut.c ----- */
+
+
+#include "RStarTree.h"
+#include "RSTInOut.h"
+
+
+/* declarations */
+
+/************************************************************************/
+
+void PutNode(RSTREE R,
+ refnode nodeptr,
+ int pagenr,
+ int depth)
+
+{
+ refparameters par;
+ refcount c;
+
+ par= &(*R).parameters._;
+
+ if (depth == (*par).height) {
+ WritePage(R,(*R).data,pagenr,nodeptr);
+
+ c= &(*R).count;
+ if ((*c).countflag) {
+ (*c).datawritecount++;
+ }
+ }
+ else {
+ WritePage(R,(*R).dir,pagenr,nodeptr);
+
+ c= &(*R).count;
+ if ((*c).countflag) {
+ (*c).dirwritecount++;
+ }
+ }
+}
+
+/************************************************************************/
+
+void GetNode(RSTREE R,
+ refnode nodeptr,
+ int pagenr,
+ int depth)
+
+{
+ refparameters par;
+ refcount c;
+
+ par= &(*R).parameters._;
+
+ if (depth == (*par).height) {
+ ReadPage(R,(*R).data,pagenr,nodeptr);
+
+ c= &(*R).count;
+ if ((*c).countflag) {
+ (*c).datareadcount++;
+ }
+ }
+ else {
+ ReadPage(R,(*R).dir,pagenr,nodeptr);
+
+ c= &(*R).count;
+ if ((*c).countflag) {
+ (*c).dirreadcount++;
+ }
+ }
+}
+
+/************************************************************************/
+
+void NewNode(RSTREE R,
+ int depth)
+
+{
+ if ((*R).Nmodified[depth]) {
+ PutNode(R,(*R).N[depth],(*R).P[depth],depth);
+ (*R).Nmodified[depth]= FALSE;
+ }
+ (*R).P[depth]= (*(*R).N[depth-1]).DIR.entries[(*R).E[depth-1]].ptrtosub;
+ GetNode(R,(*R).N[depth],(*R).P[depth],depth);
+}
+
+/************************************************************************/
+
+void ReadPage(RSTREE R,
+ typfiledesc fd,
+ int pagenr,
+ void *block)
+
+{
+ int pnb; /* position or nbytes */
+
+ pnb= lseek(fd.f,pagenr*fd.bl,L_SET);
+ if (pnb != -1) {
+ pnb= read(fd.f,block,fd.bl);
+ }
+ if (pnb <= 0) {
+ (*R).RSTDone= FALSE;
+ }
+}
+
+/************************************************************************/
+
+void WritePage(RSTREE R,
+ typfiledesc fd,
+ int pagenr,
+ void *block)
+
+{
+ int pnb; /* position or nbytes */
+
+ pnb= lseek(fd.f,pagenr*fd.bl,L_SET);
+ if (pnb != -1) {
+ pnb= write(fd.f,block,fd.bl);
+ }
+ if (pnb <= 0) {
+ (*R).RSTDone= FALSE;
+ }
+}
+
+/************************************************************************/
+
+void GetPageNr(RSTREE R, int *pagenr, int depth)
+
+{
+ refparameters par;
+ refpagedir dpd;
+
+ par= &(*R).parameters._;
+
+ if (depth == (*par).height) {
+
+ dpd= &(*R).datapagedir._;
+
+ if ((*dpd).nofnumbers == 0) {
+ if ((*dpd).childnr == firstPDblocknumb) {
+ (*dpd).number[0]++;
+ *pagenr= (*dpd).number[0];
+ }
+ else {
+ ReadPage(R,(*R).dataPD,(*dpd).childnr,&(*R).datapagedir._);
+ (*dpd).childnr--;
+ *pagenr= (*dpd).number[maxnum];
+ (*dpd).nofnumbers= maxnum - 1;
+ }
+ }
+ else {
+ *pagenr= (*dpd).number[(*dpd).nofnumbers];
+ (*dpd).nofnumbers--;
+ }
+ (*par).datapagecount++;
+ }
+ else {
+
+ dpd= &(*R).dirpagedir._;
+
+ if ((*dpd).nofnumbers == 0) {
+ if ((*dpd).childnr == firstPDblocknumb) {
+ (*dpd).number[0]++;
+ *pagenr= (*dpd).number[0];
+ }
+ else {
+ ReadPage(R,(*R).dirPD,(*dpd).childnr,&(*R).dirpagedir._);
+ (*dpd).childnr--;
+ *pagenr= (*dpd).number[maxnum];
+ (*dpd).nofnumbers= maxnum - 1;
+ }
+ }
+ else {
+ *pagenr= (*dpd).number[(*dpd).nofnumbers];
+ (*dpd).nofnumbers--;
+ }
+ (*par).dirpagecount++;
+ }
+ (*par).pagecountarr[depth]++;
+}
+
+/************************************************************************/
+
+void PutPageNr(RSTREE R, int pagenr, int depth)
+
+{
+ refparameters par;
+ refpagedir dpd;
+
+ par= &(*R).parameters._;
+
+ if (depth == (*par).height) {
+
+ dpd= &(*R).datapagedir._;
+
+ if ((*dpd).nofnumbers == maxnum) {
+ (*dpd).childnr++;
+ WritePage(R,(*R).dataPD,(*dpd).childnr,&(*R).datapagedir._);
+ (*dpd).nofnumbers= 1;
+ (*dpd).number[1]= pagenr;
+ }
+ else {
+ (*dpd).nofnumbers++;
+ (*dpd).number[(*dpd).nofnumbers]= pagenr;
+ }
+ (*par).datapagecount--;
+ }
+ else {
+
+ dpd= &(*R).dirpagedir._;
+
+ if ((*dpd).nofnumbers == maxnum) {
+ (*dpd).childnr++;
+ WritePage(R,(*R).dirPD,(*dpd).childnr,&(*R).dirpagedir._);
+ (*dpd).nofnumbers= 1;
+ (*dpd).number[1]= pagenr;
+ }
+ else {
+ (*dpd).nofnumbers++;
+ (*dpd).number[(*dpd).nofnumbers]= pagenr;
+ }
+ (*par).dirpagecount--;
+ }
+ (*par).pagecountarr[depth]--;
+}
+
+/************************************************************************/
diff --git a/modules/RStarTree/RSTInOut.h b/modules/RStarTree/RSTInOut.h
new file mode 100644
index 0000000..33ea1b9
--- /dev/null
+++ b/modules/RStarTree/RSTInOut.h
@@ -0,0 +1,43 @@
+/* ----- RSTInOut.h ----- */
+#ifndef __RSTInOut_h
+#define __RSTInOut_h
+
+
+#include "RStarTree.h"
+
+
+/* declarations */
+
+void PutNode(RSTREE R,
+ refnode nodeptr,
+ int pagenr,
+ int depth);
+
+void GetNode(RSTREE R,
+ refnode nodeptr,
+ int pagenr,
+ int depth);
+
+void NewNode(RSTREE R,
+ int depth);
+
+void ReadPage(RSTREE R,
+ typfiledesc fd,
+ int pagenr,
+ void *block);
+
+void WritePage(RSTREE R,
+ typfiledesc fd,
+ int pagenr,
+ void *block);
+
+void GetPageNr(RSTREE R,
+ int *pagenr,
+ int depth);
+
+void PutPageNr(RSTREE R,
+ int pagenr,
+ int depth);
+
+
+#endif /* !__RSTInOut_h */
diff --git a/modules/RStarTree/RSTInstDel.c b/modules/RStarTree/RSTInstDel.c
new file mode 100644
index 0000000..2962798
--- /dev/null
+++ b/modules/RStarTree/RSTInstDel.c
@@ -0,0 +1,1176 @@
+/* ----- RSTInstDel.c ----- */
+
+
+#include "RStarTree.h"
+#include "RSTInstDel.h"
+#include "RSTUtil.h"
+#include "RSTInOut.h"
+
+
+/* declarations */
+
+static void ExcludeDataEntries(RSTREE R,
+ refDATAent newentry,
+ typrect newrect,
+ int depth,
+ int M,
+ int reinsertqty);
+static void ExcludeDirEntries(RSTREE R,
+ refDIRent newentry,
+ typrect newrect,
+ int depth,
+ int M,
+ int reinsertqty);
+static void Split(RSTREE R,
+ refentry newentry,
+ int *depth,
+ int M,
+ int m);
+static void SplitAndDistributDir(RSTREE R,
+ int depth,
+ refDIRent newentry,
+ int M,
+ int m);
+static void SplitAndDistributData(RSTREE R,
+ int depth,
+ refDATAent newentry,
+ int M,
+ int m);
+static void UnDistributData(RSTREE R,
+ refDATAent newentry);
+static void GetInstChain(RSTREE R,
+ typrect newrect,
+ int depth);
+static void NtoNDel(RSTREE R,
+ int depth);
+static void ShrinkTree(RSTREE R);
+
+
+/***********************************************************************/
+
+static void GetInstChain(RSTREE R,
+ typrect newrect,
+ int depth)
+
+{
+ int i;
+ refcount c;
+
+ i= 1;
+ while (i < depth) {
+ if ((*R).NInst[i+1] != NULL) {
+ /* already in path */
+ (*R).E[i]= (*R).EInst[i]; (*R).EInst[i]= -1;
+ i++;
+ if ((*R).N[i] != (*R).NInst[i]) {
+ (*R).P[i]= (*(*R).N[i-1]).DIR.entries[(*R).E[i-1]].ptrtosub;
+ free((*R).N[i]); (*R).N[i]= NULL;
+ (*R).N[i]= (*R).NInst[i];
+ }
+ (*R).NInst[i]= NULL;
+ }
+ else if ((*R).EInst[i] != -1) {
+ /* known ... */
+ (*R).E[i]= (*R).EInst[i]; (*R).EInst[i]= -1;
+ i++;
+ if ((*(*R).N[i-1]).DIR.entries[(*R).E[i-1]].ptrtosub != (*R).P[i]) {
+ /* but not in path */
+ NewNode(R,i);
+ }
+ }
+ else {
+ /* not known */
+ ChooseSubtree(R,newrect,i,&(*(*R).N[i]).DIR,&(*R).E[i]);
+ i++;
+ if ((*(*R).N[i-1]).DIR.entries[(*R).E[i-1]].ptrtosub != (*R).P[i]) {
+ /* and not in path */
+ NewNode(R,i);
+ }
+ }
+ }
+
+ c= &(*R).count;
+ if ((*c).countflag) {
+ if (depth == (*R).parameters._.height) {
+ (*c).dirvisitcount+= depth - 1;
+ (*c).datavisitcount++;
+ }
+ else {
+ (*c).dirvisitcount+= depth;
+ }
+ }
+}
+
+/***********************************************************************/
+
+void Insert(RSTREE R, typentry *newentry, int depth)
+
+{
+ typrect newrect;
+ int M, m;
+ int reinsertqty, heightbefore;
+ refparameters par;
+ refDIRnode DIN, DINdel;
+ refDATAnode DAN, DANdel;
+ refcount c;
+ int j;
+
+ CopyRect(R,(*newentry).DIR.rect,newrect); /* see RSTBase.h "hope ..." */
+ GetInstChain(R,newrect,depth);
+
+ par= &(*R).parameters._;
+
+ for (;;) {
+ if (depth == (*par).height) {
+ M= (*par).dataM; m= (*par).datam;
+
+ DAN= &(*(*R).N[depth]).DATA;
+
+ if ((*DAN).nofentries < M) {
+ (*DAN).entries[(*DAN).nofentries]= (*newentry).DATA; /* 0.. */
+ (*DAN).nofentries++;
+ (*R).Nmodified[depth]= TRUE;
+
+ c= &(*R).count;
+ if ((*c).countflag) {
+ (*c).datamodifycount++;
+ }
+
+ depth--;
+ AdjustChain(R,depth,newrect);
+ break;
+ }
+ }
+ else {
+ M= (*par).dirM; m= (*par).dirm;
+
+ DIN= &(*(*R).N[depth]).DIR;
+
+ if ((*DIN).nofentries < M) {
+ (*DIN).entries[(*DIN).nofentries]= (*newentry).DIR; /* 0.. */
+ (*DIN).nofentries++;
+ (*R).Nmodified[depth]= TRUE;
+
+ c= &(*R).count;
+ if ((*c).countflag) {
+ (*c).dirmodifycount++;
+ }
+
+ depth--;
+ AdjustChain(R,depth,newrect);
+ break;
+ }
+ }
+
+ /*** --- LOOP not EXITed by direct insert --- ***/
+
+ if ((*R).ReInsert[depth] && depth != 1 && M > 1) {
+ if (depth == (*par).height) {
+ reinsertqty= (*par).datareinsertqty;
+ (*R).NDel[depth]= (refnode)malloc((*R).datanodelen);
+ ExcludeDataEntries(R,&(*newentry).DATA,newrect,depth,M,reinsertqty);
+ }
+ else {
+ reinsertqty= (*par).dirreinsertqty;
+ (*R).NDel[depth]= (refnode)malloc((*R).dirnodelen);
+ ExcludeDirEntries(R,&(*newentry).DIR,newrect,depth,M,reinsertqty);
+ }
+ heightbefore= (*par).height;
+ (*R).ReInsert[depth]= FALSE;
+ (*R).ReInsert[depth-1]= TRUE;
+ (*R).Nmodified[depth]= TRUE;
+ AdjustChainAfterDeletion(R,depth);
+
+ if (depth == (*par).height) {
+
+ DANdel= &(*(*R).NDel[depth]).DATA;
+
+ for (j= reinsertqty; j >= 0; j--) {
+ Insert(R,(refentry)&(*DANdel).entries[j],depth);
+ if ((*par).height > heightbefore) {
+ depth+= (*par).height - heightbefore;
+ heightbefore= (*par).height;
+ }
+ }
+ }
+ else {
+
+ DINdel= &(*(*R).NDel[depth]).DIR;
+
+ for (j= reinsertqty; j >= 0; j--) {
+ Insert(R,(refentry)&(*DINdel).entries[j],depth);
+ if ((*par).height > heightbefore) {
+ depth+= (*par).height - heightbefore;
+ heightbefore= (*par).height;
+ }
+ }
+ }
+ free((*R).NDel[depth]); (*R).NDel[depth]= NULL;
+ if (depth != 1) {
+ (*R).ReInsert[depth-1]= FALSE;
+ /* ReInitialisation for the case, that the LOOP
+ did not call ReInsert in the next higher level */
+ }
+ break;
+ }
+ else {
+ Split(R,newentry,&depth,M,m);
+ }
+ }
+}
+
+/***********************************************************************/
+
+static void ExcludeDataEntries(RSTREE R,
+ typDATAent *newentry,
+ typrect newrect,
+ int depth,
+ int M,
+ int reinsertqty)
+
+{
+ refparameters par;
+ typpoint allcenter, newrectcenter, center;
+ refDATAnode n, nd;
+ ValueArray distarr;
+ IndexArray I;
+ ByteArray chosen;
+ int j, k, sortind;
+
+ par= &(*R).parameters._;
+
+ EvalCenter(R,(*(*R).N[depth-1]).DIR.entries[(*R).E[depth-1]].rect,allcenter);
+ EvalCenter(R,newrect,newrectcenter);
+
+ n= &(*(*R).N[depth]).DATA;
+
+ for (j= 0; j < M; j++) {
+ EvalCenter(R,(*n).entries[j].rect,center);
+ distarr[j]= RSTDistance(R,allcenter,center);
+ I[j]= j;
+ }
+ distarr[M]= RSTDistance(R,allcenter,newrectcenter);
+ I[M]= M;
+ QuickSortValArr(0,M,distarr,I);
+
+ nd= &(*(*R).NDel[depth]).DATA;
+
+ FalseArray((int *)chosen,(*par).dataMwords);
+ j= 0; k= M;
+ while (j < reinsertqty) {
+ sortind= I[k];
+ chosen[sortind]= 1;
+ if (sortind != M) {
+ (*nd).entries[j]= (*n).entries[sortind];
+ }
+ else {
+ (*nd).entries[j]= *newentry;
+ }
+ j++;
+ k--;
+ }
+ /* entry referenced by distarr[I[M]], [I[M-1]], ...
+ becomes NDel[depth]->entries[0], [1], ... */
+
+ if (chosen[M] == 1) {
+ (*nd).entries[reinsertqty]= (*n).entries[I[M-reinsertqty]];
+ chosen[I[M-reinsertqty]]= 1;
+ }
+ else {
+ (*nd).entries[reinsertqty]= *newentry;
+ }
+ /* entry referenced by I[M-reinsertqty] or newentry (referenced
+ by I[?] == 0) becomes NDel[depth]->entries[reinsertqty] */
+ /* Entries to reinsert now in NDel[depth] sorted by */
+ /* decreasing distances to the midpoint. */
+ /* !!! newentry is reinserted in any case !!! */
+
+ (*n).nofentries= M - reinsertqty;
+ j= 0; k= M - 1;
+ do {
+ if (chosen[j] == 1) {
+ while (chosen[k] == 1) {
+ k--;
+ }
+ (*n).entries[j]= (*n).entries[k];
+ chosen[k]= 1;
+ }
+ j++;
+ } while (j < (*n).nofentries);
+}
+
+/***********************************************************************/
+
+static void ExcludeDirEntries(RSTREE R,
+ typDIRent *newentry,
+ typrect newrect,
+ int depth,
+ int M,
+ int reinsertqty)
+
+{
+ refparameters par;
+ typpoint allcenter, newrectcenter, center;
+ refDIRnode n, nd;
+ ValueArray distarr;
+ IndexArray I;
+ ByteArray chosen;
+ int j, k, sortind;
+
+ par= &(*R).parameters._;
+
+ EvalCenter(R,(*(*R).N[depth-1]).DIR.entries[(*R).E[depth-1]].rect,allcenter);
+ EvalCenter(R,newrect,newrectcenter);
+
+ n= &(*(*R).N[depth]).DIR;
+
+ for (j= 0; j < M; j++) {
+ EvalCenter(R,(*n).entries[j].rect,center);
+ distarr[j]= RSTDistance(R,allcenter,center);
+ I[j]= j;
+ }
+ distarr[M]= RSTDistance(R,allcenter,newrectcenter);
+ I[M]= M;
+ QuickSortValArr(0,M,distarr,I);
+
+ nd= &(*(*R).NDel[depth]).DIR;
+
+ FalseArray((int *)chosen,(*par).dirMwords);
+ j= 0; k= M;
+ while (j < reinsertqty) {
+ sortind= I[k];
+ chosen[sortind]= 1;
+ if (sortind != M) {
+ (*nd).entries[j]= (*n).entries[sortind];
+ }
+ else {
+ (*nd).entries[j]= *newentry;
+ }
+ j++;
+ k--;
+ }
+ /* entry referenced by distarr[I[M]], [I[M-1]], ...
+ becomes NDel[depth]->entries[0], [1], ... */
+
+ if (chosen[M] == 1) {
+ (*nd).entries[reinsertqty]= (*n).entries[I[M-reinsertqty]];
+ chosen[I[M-reinsertqty]]= 1;
+ }
+ else {
+ (*nd).entries[reinsertqty]= *newentry;
+ }
+ /* entry referenced by I[M-reinsertqty] or newentry (referenced
+ by I[?] == 0) becomes NDel[depth]->entries[reinsertqty] */
+ /* Entries to reinsert now in NDel[depth] sorted by */
+ /* decreasing distances to the midpoint. */
+ /* !!! newentry is reinserted in any case !!! */
+
+ (*n).nofentries= M - reinsertqty;
+ j= 0; k= M - 1;
+ do {
+ if (chosen[j] == 1) {
+ while (chosen[k] == 1) {
+ k--;
+ }
+ (*n).entries[j]= (*n).entries[k];
+ chosen[k]= 1;
+ }
+ j++;
+ } while (j < (*n).nofentries);
+}
+
+/***********************************************************************/
+
+static void Split(RSTREE R,
+ typentry *newentry,
+ int *depth,
+ int M,
+ int m)
+
+{
+ refparameters par;
+ refcount c;
+ int pagenr;
+ boolean isdata;
+ int i;
+
+ par= &(*R).parameters._;
+
+ if (*depth == (*par).height) {
+ if (M == 1) {
+ UnDistributData(R,&(*newentry).DATA);
+ }
+ else
+ {
+ SplitAndDistributData(R,*depth,&(*newentry).DATA,M,m);
+ }
+ }
+ else {
+ SplitAndDistributDir(R,*depth,&(*newentry).DIR,M,m);
+ }
+ if (*depth == 1) {
+ (*par).height++;
+ *depth= 2;
+ for (i= (*par).height; i >= 2; i--) {
+ (*R).N[i]= (*R).N[i-1];
+ (*R).NDel[i]= (*R).NDel[i-1]; /* for ReInsert */
+ (*R).ReInsert[i]= (*R).ReInsert[i-1]; /* for ReInsert */
+ /* following assignments not necessary for i=2: */
+ (*R).P[i]= (*R).P[i-1]; /* set(i=2) */
+ (*R).Nmodified[i]= (*R).Nmodified[i-1]; /* set(i=2) */
+ (*par).pagecountarr[i]= (*par).pagecountarr[i-1];
+ }
+ (*R).N[1]= (refnode)malloc((*R).dirnodelen);
+ /* R->P[1] is RSTBase.rootblocknumb forever */
+ /* R->Nmodified[1] set inserting the sibling */
+ (*R).NDel[1]= NULL; /* for ReInsert */
+ (*R).ReInsert[1]= FALSE; /* for ReInsert */
+ /* initiate first root entry: */
+ (*(*R).N[1]).DIR.nofentries= 1;
+ (*R).E[1]= 0;
+ GetPageNr(R,&pagenr,*depth);
+ (*(*R).N[1]).DIR.entries[0].ptrtosub= pagenr;
+ (*R).P[2]= pagenr;
+ }
+ isdata= *depth == (*par).height;
+ (*R).Nmodified[*depth]= TRUE;
+ GetPageNr(R,&pagenr,*depth);
+ (*newentry).DIR.ptrtosub= pagenr;
+
+ if (isdata) {
+ EvalDataEnclRect(R,&(*(*R).Nsibling).DATA,(*newentry).DIR.rect);
+ EvalDataEnclRect(R,&(*(*R).N[*depth]).DATA,
+ (*(*R).N[*depth-1]).DIR.entries[(*R).E[*depth-1]].rect);
+ c= &(*R).count;
+ if ((*c).countflag) {
+ (*c).datamodifycount+= 2;
+ }
+ }
+ else {
+ EvalDirEnclRect(R,&(*(*R).Nsibling).DIR,(*newentry).DIR.rect);
+ EvalDirEnclRect(R,&(*(*R).N[*depth]).DIR,
+ (*(*R).N[*depth-1]).DIR.entries[(*R).E[*depth-1]].rect);
+ c= &(*R).count;
+ if ((*c).countflag) {
+ (*c).dirmodifycount+= 2;
+ }
+ }
+ PutNode(R,(*R).Nsibling,pagenr,*depth);
+ (*depth)--;
+}
+
+/***********************************************************************/
+
+static void SplitAndDistributDir(RSTREE R,
+ int depth,
+ typDIRent *newentry,
+ int M,
+ int m)
+
+{
+ ValueArray edgearray, spacearray;
+ RectArray rectarray;
+ refparameters par;
+ refDIRnode n;
+ refinterval re;
+
+ IndexArray I;
+ Side sortside, currsortside, axsortside;
+ int axis;
+ int mlow, mhigh,
+ index, backind,
+ axisindex;
+ typrect leftrect, rightrect;
+ double leftspace, rightspace,
+ leftedge, rightedge, edge, validedge, backvaledge, axisedge,
+ ovlp,
+ value, validvalue, backvalvalue;
+ int i, j, ii;
+
+ par= &(*R).parameters._;
+
+ (*R).Ntosplit= (*R).N[depth];
+ (*R).N[depth]= (*R).helpdirnode;
+ (*R).helpdirnode= (*R).Ntosplit;
+ for (j= 0; j <= M; j++) {
+ I[j]= j;
+ }
+ mhigh= M-m+1;
+ mlow= m-1;
+
+ n= &(*(*R).Ntosplit).DIR;
+
+ (*n).entries[M]= *newentry;
+ for (i= 0; i <= (*par).maxdim; i++) {
+ sortside= low;
+ currsortside= low;
+ QuickSortDirEnt(0,M,i,low,(*n).entries,I);
+ CopyRect(R,(*n).entries[I[M]].rect,rightrect);
+ rightrect[i].l= (*n).entries[I[mhigh]].rect[i].l;
+ for (j= M-1; j >= m; j--) {
+ for (ii= 0; ii <= (*par).maxdim; ii++) {
+
+ re= &(*n).entries[I[j]].rect[ii];
+
+ if ((*re).l < rightrect[ii].l) {
+ rightrect[ii].l= (*re).l;
+ }
+ if ((*re).h > rightrect[ii].h) {
+ rightrect[ii].h= (*re).h;
+ }
+ }
+ if (j <= mhigh) {
+ rightedge= 0.0; rightspace= 1.0;
+ for (ii= 0; ii <= (*par).maxdim; ii++) {
+ rightedge+= rightrect[ii].h - rightrect[ii].l;
+ rightspace*= rightrect[ii].h - rightrect[ii].l;
+ }
+ CopyRect(R,rightrect,rectarray[j]);
+ edgearray[j]= rightedge;
+ spacearray[j]= rightspace;
+ }
+ }
+ /* fill array from M-m+1 down to m
+ with rightrect, rightedge, rightspace */
+ CopyRect(R,(*n).entries[I[0]].rect,leftrect);
+ for (j= 1; j < mhigh; j++) {
+ for (ii= 0; ii <= (*par).maxdim; ii++) {
+
+ re= &(*n).entries[I[j]].rect[ii];
+
+ if ((*re).l < leftrect[ii].l) {
+ leftrect[ii].l= (*re).l;
+ }
+ if ((*re).h > leftrect[ii].h) {
+ leftrect[ii].h= (*re).h;
+ }
+ }
+ if (j >= mlow) {
+ leftedge= 0.0;
+ for (ii= 0; ii <= (*par).maxdim; ii++) {
+ leftedge+= leftrect[ii].h - leftrect[ii].l;
+ }
+ if (Overlaps(R,leftrect,rectarray[j+1])) {
+ GetOverlap(R,leftrect,rectarray[j+1],&ovlp);
+ if (j == mlow) {
+ validedge= leftedge+edgearray[j+1];
+ validvalue= ovlp;
+ index= m;
+ }
+ else {
+ edge= leftedge+edgearray[j+1];
+ validedge= validedge+edge;
+ value= ovlp;
+ if (value < validvalue) {
+ validvalue= value;
+ index= j+1;
+ }
+ }
+ }
+ else {
+ leftspace= 1.0;
+ for (ii= 0; ii <= (*par).maxdim; ii++) {
+ leftspace*= leftrect[ii].h - leftrect[ii].l;
+ }
+ if (j == mlow) {
+ validedge= leftedge+edgearray[j+1];
+ validvalue= -1.0/(leftspace+spacearray[j+1]);
+ index= m;
+ }
+ else {
+ edge= leftedge+edgearray[j+1];
+ validedge= validedge+edge;
+ value= -1.0/(leftspace+spacearray[j+1]);
+ if (value < validvalue) {
+ validvalue= value;
+ index= j+1;
+ }
+ }
+ }
+ }
+ }
+ /* Compute sum of the edges
+ from leftedge[m-1]+rightedge[m]
+ up to leftedge[M-m]+rightedge[M-m+1], -> axis;
+ minimal area resp. overlap, -> index. */
+ currsortside= high;
+ QuickSortDirEnt(0,M,i,high,(*n).entries,I);
+ CopyRect(R,(*n).entries[I[0]].rect,leftrect);
+ leftrect[i].h= (*n).entries[I[mlow]].rect[i].h;
+ for (j= 1; j < mhigh; j++) {
+ for (ii= 0; ii <= (*par).maxdim; ii++) {
+
+ re= &(*n).entries[I[j]].rect[ii];
+
+ if ((*re).l < leftrect[ii].l) {
+ leftrect[ii].l= (*re).l;
+ }
+ if ((*re).h > leftrect[ii].h) {
+ leftrect[ii].h= (*re).h;
+ }
+ }
+ if (j >= mlow) {
+ leftedge= 0.0; leftspace= 1.0;
+ for (ii= 0; ii <= (*par).maxdim; ii++) {
+ leftedge+= leftrect[ii].h - leftrect[ii].l;
+ leftspace*= leftrect[ii].h - leftrect[ii].l;
+ }
+ CopyRect(R,leftrect,rectarray[j]);
+ edgearray[j]= leftedge;
+ spacearray[j]= leftspace;
+ }
+ }
+ /* fill array from m-1 up to M-m
+ with leftrect, leftedge, leftspace */
+ CopyRect(R,(*n).entries[I[M]].rect,rightrect);
+ for (j= M-1; j >= m; j--) {
+ for (ii= 0; ii <= (*par).maxdim; ii++) {
+
+ re = &(*n).entries[I[j]].rect[ii];
+
+ if ((*re).l < rightrect[ii].l) {
+ rightrect[ii].l= (*re).l;
+ }
+ if ((*re).h > rightrect[ii].h) {
+ rightrect[ii].h= (*re).h;
+ }
+ }
+ if (j <= mhigh) {
+ rightedge= 0.0;
+ for (ii= 0; ii <= (*par).maxdim; ii++) {
+ rightedge+= rightrect[ii].h- rightrect[ii].l;
+ }
+ if (Overlaps(R,rightrect,rectarray[j-1])) {
+ GetOverlap(R,rightrect,rectarray[j-1],&ovlp);
+ if (j == mhigh) {
+ backvaledge= rightedge+edgearray[j-1];
+ backvalvalue= ovlp;
+ backind= j;
+ }
+ else {
+ edge= rightedge+edgearray[j-1];
+ backvaledge= backvaledge+edge;
+ value= ovlp;
+ if (value < backvalvalue) {
+ backvalvalue= value;
+ backind= j;
+ }
+ }
+ }
+ else {
+ rightspace= 1.0;
+ for (ii= 0; ii <= (*par).maxdim; ii++) {
+ rightspace*= rightrect[ii].h - rightrect[ii].l;
+ }
+ if (j == mhigh) {
+ backvaledge= rightedge+edgearray[j-1];
+ backvalvalue= -1.0/(rightspace+spacearray[j-1]);
+ backind= j;
+ }
+ else {
+ edge= rightedge+edgearray[j-1];
+ backvaledge= backvaledge+edge;
+ value= -1.0/(rightspace+spacearray[j-1]);
+ if (value < backvalvalue) {
+ backvalvalue= value;
+ backind= j;
+ }
+ }
+ }
+ }
+ }
+ /* Compute sum of the edges
+ from rightedge[M-m+1]+leftedge[M-m]
+ down to rightedge[m] +leftedge[m-1], -> axis;
+ minimal area resp. overlap, -> index. */
+ if (backvalvalue <= validvalue) {
+ sortside= high;
+ index= backind;
+ }
+ validedge= validedge+backvaledge;
+ if (i == 0) {
+ axsortside= sortside;
+ axis= i;
+ axisedge= validedge;
+ axisindex= index;
+ }
+ else if (validedge < axisedge) {
+ axsortside= sortside;
+ axis= i;
+ axisedge= validedge;
+ axisindex= index;
+ }
+
+ }
+ if (axis != (*par).maxdim || axsortside != currsortside) {
+ QuickSortDirEnt(0,M,axis,axsortside,(*n).entries,I);
+ }
+
+ n= &(*(*R).N[depth]).DIR;
+
+ (*n).nofentries= axisindex;
+ for (j= 0; j < (*n).nofentries; j++) {
+ (*n).entries[j]= (*(*R).Ntosplit).DIR.entries[I[j]];
+ }
+ /* printf("%3d",axisindex); */
+ /* N[depth] gets entries 0 up to axisindex-1 */
+
+ n= &(*(*R).Nsibling).DIR;
+
+ (*n).nofentries= M-axisindex+1;
+ for (j= 0; j < (*n).nofentries; j++) {
+ (*n).entries[j]= (*(*R).Ntosplit).DIR.entries[I[axisindex+j]];
+ }
+ /* printf("%3d",M-axisindex+1); */
+ /* printf("%3d\n",M+1); */
+}
+
+/***********************************************************************/
+
+static void SplitAndDistributData(RSTREE R,
+ int depth,
+ typDATAent *newentry,
+ int M,
+ int m)
+
+{
+ ValueArray edgearray, spacearray;
+ RectArray rectarray;
+ refparameters par;
+ refDATAnode n;
+ refinterval re;
+
+ IndexArray I;
+ Side sortside, currsortside, axsortside;
+ int axis;
+ int mlow, mhigh,
+ index, backind,
+ axisindex;
+ typrect leftrect, rightrect;
+ double leftspace, rightspace,
+ leftedge, rightedge, edge, validedge, backvaledge, axisedge,
+ ovlp,
+ value, validvalue, backvalvalue;
+ int i, j, ii;
+
+ par= &(*R).parameters._;
+
+ (*R).Ntosplit= (*R).N[depth];
+ (*R).N[depth]= (*R).helpdatanode;
+ (*R).helpdatanode= (*R).Ntosplit;
+ for (j= 0; j <= M; j++) {
+ I[j]= j;
+ }
+ mhigh= M-m+1;
+ mlow= m-1;
+
+ n= &(*(*R).Ntosplit).DATA;
+
+ (*n).entries[M]= *newentry;
+ for (i= 0; i <= (*par).maxdim; i++) {
+ sortside= low;
+ currsortside= low;
+ QuickSortDataEnt(0,M,i,low,(*n).entries,I);
+ CopyRect(R,(*n).entries[I[M]].rect,rightrect);
+ rightrect[i].l= (*n).entries[I[mhigh]].rect[i].l;
+ for (j= M-1; j >= m; j--) {
+ for (ii= 0; ii <= (*par).maxdim; ii++) {
+
+ re= &(*n).entries[I[j]].rect[ii];
+
+ if ((*re).l < rightrect[ii].l) {
+ rightrect[ii].l= (*re).l;
+ }
+ if ((*re).h > rightrect[ii].h) {
+ rightrect[ii].h= (*re).h;
+ }
+ }
+ if (j <= mhigh) {
+ rightedge= 0.0; rightspace= 1.0;
+ for (ii= 0; ii <= (*par).maxdim; ii++) {
+ rightedge+= rightrect[ii].h - rightrect[ii].l;
+ rightspace*= rightrect[ii].h - rightrect[ii].l;
+ }
+ CopyRect(R,rightrect,rectarray[j]);
+ edgearray[j]= rightedge;
+ spacearray[j]= rightspace;
+ }
+ }
+ /* fill array from M-m+1 down to m
+ with rightrect, rightedge, rightspace */
+ CopyRect(R,(*n).entries[I[0]].rect,leftrect);
+ for (j= 1; j < mhigh; j++) {
+ for (ii= 0; ii <= (*par).maxdim; ii++) {
+
+ re= &(*n).entries[I[j]].rect[ii];
+
+ if ((*re).l < leftrect[ii].l) {
+ leftrect[ii].l= (*re).l;
+ }
+ if ((*re).h > leftrect[ii].h) {
+ leftrect[ii].h= (*re).h;
+ }
+ }
+ if (j >= mlow) {
+ leftedge= 0.0;
+ for (ii= 0; ii <= (*par).maxdim; ii++) {
+ leftedge+= leftrect[ii].h - leftrect[ii].l;
+ }
+ if (Overlaps(R,leftrect,rectarray[j+1])) {
+ GetOverlap(R,leftrect,rectarray[j+1],&ovlp);
+ if (j == mlow) {
+ validedge= leftedge+edgearray[j+1];
+ validvalue= ovlp;
+ index= m;
+ }
+ else {
+ edge= leftedge+edgearray[j+1];
+ validedge= validedge+edge;
+ value= ovlp;
+ if (value < validvalue) {
+ validvalue= value;
+ index= j+1;
+ }
+ }
+ }
+ else {
+ leftspace= 1.0;
+ for (ii= 0; ii <= (*par).maxdim; ii++) {
+ leftspace*= leftrect[ii].h - leftrect[ii].l;
+ }
+ if (j == mlow) {
+ validedge= leftedge+edgearray[j+1];
+ validvalue= -1.0/(leftspace+spacearray[j+1]);
+ index= m;
+ }
+ else {
+ edge= leftedge+edgearray[j+1];
+ validedge= validedge+edge;
+ value= -1.0/(leftspace+spacearray[j+1]);
+ if (value < validvalue) {
+ validvalue= value;
+ index= j+1;
+ }
+ }
+ }
+ }
+ }
+ /* Compute sum of the edges
+ from leftedge[m-1]+rightedge[m]
+ up to leftedge[M-m]+rightedge[M-m+1], -> axis;
+ minimal area resp. overlap, -> index. */
+ currsortside= high;
+ QuickSortDataEnt(0,M,i,high,(*n).entries,I);
+ CopyRect(R,(*n).entries[I[0]].rect,leftrect);
+ leftrect[i].h= (*n).entries[I[mlow]].rect[i].h;
+ for (j= 1; j < mhigh; j++) {
+ for (ii= 0; ii <= (*par).maxdim; ii++) {
+
+ re= &(*n).entries[I[j]].rect[ii];
+
+ if ((*re).l < leftrect[ii].l) {
+ leftrect[ii].l= (*re).l;
+ }
+ if ((*re).h > leftrect[ii].h) {
+ leftrect[ii].h= (*re).h;
+ }
+ }
+ if (j >= mlow) {
+ leftedge= 0.0; leftspace= 1.0;
+ for (ii= 0; ii <= (*par).maxdim; ii++) {
+ leftedge+= leftrect[ii].h - leftrect[ii].l;
+ leftspace*= leftrect[ii].h - leftrect[ii].l;
+ }
+ CopyRect(R,leftrect,rectarray[j]);
+ edgearray[j]= leftedge;
+ spacearray[j]= leftspace;
+ }
+ }
+ /* fill array from m-1 up to M-m
+ with leftrect, leftedge, leftspace */
+ CopyRect(R,(*n).entries[I[M]].rect,rightrect);
+ for (j= M-1; j >= m; j--) {
+ for (ii= 0; ii <= (*par).maxdim; ii++) {
+
+ re = &(*n).entries[I[j]].rect[ii];
+
+ if ((*re).l < rightrect[ii].l) {
+ rightrect[ii].l= (*re).l;
+ }
+ if ((*re).h > rightrect[ii].h) {
+ rightrect[ii].h= (*re).h;
+ }
+ }
+ if (j <= mhigh) {
+ rightedge= 0.0;
+ for (ii= 0; ii <= (*par).maxdim; ii++) {
+ rightedge+= rightrect[ii].h- rightrect[ii].l;
+ }
+ if (Overlaps(R,rightrect,rectarray[j-1])) {
+ GetOverlap(R,rightrect,rectarray[j-1],&ovlp);
+ if (j == mhigh) {
+ backvaledge= rightedge+edgearray[j-1];
+ backvalvalue= ovlp;
+ backind= j;
+ }
+ else {
+ edge= rightedge+edgearray[j-1];
+ backvaledge= backvaledge+edge;
+ value= ovlp;
+ if (value < backvalvalue) {
+ backvalvalue= value;
+ backind= j;
+ }
+ }
+ }
+ else {
+ rightspace= 1.0;
+ for (ii= 0; ii <= (*par).maxdim; ii++) {
+ rightspace*= rightrect[ii].h - rightrect[ii].l;
+ }
+ if (j == mhigh) {
+ backvaledge= rightedge+edgearray[j-1];
+ backvalvalue= -1.0/(rightspace+spacearray[j-1]);
+ backind= j;
+ }
+ else {
+ edge= rightedge+edgearray[j-1];
+ backvaledge= backvaledge+edge;
+ value= -1.0/(rightspace+spacearray[j-1]);
+ if (value < backvalvalue) {
+ backvalvalue= value;
+ backind= j;
+ }
+ }
+ }
+ }
+ }
+ /* Compute sum of the edges
+ from rightedge[M-m+1]+leftedge[M-m]
+ down to rightedge[m] +leftedge[m-1], -> axis;
+ minimal area resp. overlap, -> index. */
+ if (backvalvalue <= validvalue) {
+ sortside= high;
+ index= backind;
+ }
+ validedge= validedge+backvaledge;
+ if (i == 0) {
+ axsortside= sortside;
+ axis= i;
+ axisedge= validedge;
+ axisindex= index;
+ }
+ else if (validedge < axisedge) {
+ axsortside= sortside;
+ axis= i;
+ axisedge= validedge;
+ axisindex= index;
+ }
+
+ }
+ if (axis != (*par).maxdim || axsortside != currsortside) {
+ QuickSortDataEnt(0,M,axis,axsortside,(*n).entries,I);
+ }
+
+ n= &(*(*R).N[depth]).DATA;
+
+ (*n).nofentries= axisindex;
+ for (j= 0; j < (*n).nofentries; j++) {
+ (*n).entries[j]= (*(*R).Ntosplit).DATA.entries[I[j]];
+ }
+ /* printf("%3d",axisindex); */
+ /* N[depth] gets entries 0 up to axisindex-1 */
+
+ n= &(*(*R).Nsibling).DATA;
+
+ (*n).nofentries= M-axisindex+1;
+ for (j= 0; j < (*n).nofentries; j++) {
+ (*n).entries[j]= (*(*R).Ntosplit).DATA.entries[I[axisindex+j]];
+ }
+ /* printf("%3d",M-axisindex+1); */
+ /* printf("%3d\n",M+1); */
+}
+
+/***********************************************************************/
+
+static void UnDistributData(RSTREE R,
+ typDATAent *newentry)
+
+{
+ refDATAnode DAN;
+
+ DAN= &(*(*R).Nsibling).DATA;
+
+ (*DAN).nofentries= 1;
+ (*DAN).entries[0]= *newentry;
+ /* printf(" Un\n"); */
+}
+
+/***********************************************************************/
+
+void DeleteOneRec(RSTREE R)
+
+{
+ refparameters par;
+ refDIRnode DIN;
+ refDATAnode DAN;
+ refcount c;
+ int depth, heightbefore;
+ int i, j;
+
+ par = &(*R).parameters._;
+
+ depth= (*par).height;
+ for (;;) {
+ if (depth == (*par).height) {
+
+ DAN= &(*(*R).N[depth]).DATA;
+
+ (*DAN).nofentries--;
+ (*DAN).entries[(*R).E[depth]]= (*DAN).entries[(*DAN).nofentries];
+ if ((*DAN).nofentries >= (*par).datam || depth == 1) {
+ (*R).Nmodified[depth]= TRUE;
+
+ c= &(*R).count;
+ if ((*c).countflag) {
+ (*c).datamodifycount++;
+ }
+
+ AdjustChainAfterDeletion(R,depth);
+ break;
+ }
+ }
+ else {
+
+ DIN= &(*(*R).N[depth]).DIR;
+
+ (*DIN).nofentries--;
+ (*DIN).entries[(*R).E[depth]]= (*DIN).entries[(*DIN).nofentries];
+ if ((*DIN).nofentries >= (*par).dirm || depth == 1) {
+ (*R).Nmodified[depth]= TRUE;
+
+ c= &(*R).count;
+ if ((*c).countflag) {
+ (*c).dirmodifycount++;
+ }
+
+ AdjustChainAfterDeletion(R,depth);
+ break;
+ }
+ }
+ /*** --- LOOP not EXITed by deletion without underflow --- ***/
+ NtoNDel(R,depth);
+ depth--;
+ }
+ /*** --- ReInsertion --- ***/
+ i= 2; heightbefore= (*par).height;
+ while (i <= (*par).height) {
+ if ((*R).NDel[i] != NULL) {
+
+ c= &(*R).count;
+ if ((*c).countflag) {
+ if (i == (*par).height) {
+ (*c).datavisitcount++;
+ }
+ else {
+ (*c).dirvisitcount++;
+ }
+ }
+ if (i == (*par).height) {
+
+ DAN= &(*(*R).NDel[i]).DATA;
+
+ for (j= 0; j < (*DAN).nofentries; j++) {
+ Insert(R,(refentry)&(*DAN).entries[j],i);
+ if ((*par).height > heightbefore) {
+ i++; heightbefore++;
+ }
+ }
+ }
+ else {
+
+ DIN= &(*(*R).NDel[i]).DIR;
+
+ for (j= 0; j < (*DIN).nofentries; j++) {
+ Insert(R,(refentry)&(*DIN).entries[j],i);
+ if ((*par).height > heightbefore) {
+ i++; heightbefore++;
+ }
+ }
+ }
+ free((*R).NDel[i]); (*R).NDel[i]= NULL;
+ }
+ i++;
+ }
+ /*** --- Shrink the tree --- ***/
+ if ((*par).height != 1 && (*(*R).N[1]).DIR.nofentries == 1) {
+ ShrinkTree(R);
+ }
+}
+
+/***********************************************************************/
+
+static void NtoNDel(RSTREE R,
+ int depth)
+
+{
+ refparameters par;
+
+ par= &(*R).parameters._;
+
+ if ((*(*R).N[depth]).DIR.nofentries != 0) { /* see RSTBase.h "hope ..." */
+ (*R).NDel[depth]= (*R).N[depth];
+ if (depth == (*par).height) {
+ (*R).N[depth]= (refnode)malloc((*R).datanodelen);
+ }
+ else {
+ (*R).N[depth]= (refnode)malloc((*R).dirnodelen);
+ }
+ }
+ else {
+ /* this is only possible for data nodes. NDel[height] stays NULL. */
+ /* ==> no ReInsertion(height). P[height] set to 0 in any case. */
+ /* if height == 2 and shrink is done NewNode(R,2) is called. */
+ }
+ PutPageNr(R,(*R).P[depth],depth);
+ (*R).P[depth]= 0;
+ (*R).Nmodified[depth]= FALSE;
+}
+
+/***********************************************************************/
+
+static void ShrinkTree(RSTREE R)
+
+{
+ refparameters par;
+ refcount c;
+ int i;
+
+ par= &(*R).parameters._;
+
+ if ((*R).P[2] == 0) {
+ (*R).E[1]= 0;
+ NewNode(R,2);
+ }
+ free((*R).N[1]);
+ for (i= 1; i <= (*par).height; i++) {
+ (*R).N[i]= (*R).N[i+1];
+ }
+ (*R).Nmodified[1]= TRUE;
+
+ c= &(*R).count;
+ if ((*c).countflag) {
+ (*c).dirmodifycount++;
+ }
+
+ PutPageNr(R,(*R).P[2],2);
+ for (i= 2; i <= (*par).height; i++) {
+ (*R).P[i]= (*R).P[i+1];
+ (*R).Nmodified[i]= (*R).Nmodified[i+1];
+ (*par).pagecountarr[i]= (*par).pagecountarr[i+1];
+ }
+ (*R).E[(*par).height]= -1;
+ (*par).height--;
+}
+
+/***********************************************************************/
diff --git a/modules/RStarTree/RSTInstDel.h b/modules/RStarTree/RSTInstDel.h
new file mode 100644
index 0000000..4779160
--- /dev/null
+++ b/modules/RStarTree/RSTInstDel.h
@@ -0,0 +1,15 @@
+/* ----- RSTInstDel.h ----- */
+#ifndef __RSTInstDel_h
+#define __RSTInstDel_h
+
+
+#include "RStarTree.h"
+
+
+/* declarations */
+
+void Insert(RSTREE R, refentry newentry, int depth);
+void DeleteOneRec(RSTREE R);
+
+
+#endif /* !__RSTInstDel_h */
diff --git a/modules/RStarTree/RSTInterUtil.c b/modules/RStarTree/RSTInterUtil.c
new file mode 100644
index 0000000..f23d52e
--- /dev/null
+++ b/modules/RStarTree/RSTInterUtil.c
@@ -0,0 +1,428 @@
+/* ----- RSTInterUtil.c ----- */
+
+
+#include "RStarTree.h"
+#include "RSTInterUtil.h"
+
+
+/* ----- declarations ----- */
+
+/***********************************************************************/
+
+void CreateRSFiles(RSTREE R)
+
+{
+ RSTName SufName;
+ int O_MODE= O_RDWR | O_CREAT | O_EXCL;
+ /* int O_MODE= O_RDWR | O_CREAT | O_TRUNC; "forced Creation" */
+
+ (*R).dir.f= open((*R).dirname,O_MODE,STDMODE);
+ if ((*R).dir.f == -1) {
+ (*R).RSTDone= FALSE;
+ return;
+ }
+ strcpy(SufName,(*R).dirname);
+ strcat(SufName,datasuffix);
+ (*R).data.f= open(SufName,O_MODE,STDMODE);
+ if ((*R).data.f == -1) {
+ (*R).RSTDone= FALSE;
+ return;
+ }
+ strcpy(SufName,(*R).dirname);
+ strcat(SufName,dirPDsuffix);
+ (*R).dirPD.f= open(SufName,O_MODE,STDMODE);
+ if ((*R).dirPD.f == -1) {
+ (*R).RSTDone= FALSE;
+ return;
+ }
+ strcpy(SufName,(*R).dirname);
+ strcat(SufName,dataPDsuffix);
+ (*R).dataPD.f= open(SufName,O_MODE,STDMODE);
+ if ((*R).dataPD.f == -1) {
+ (*R).RSTDone= FALSE;
+ return;
+ }
+}
+
+/***********************************************************************/
+
+void OpenRSFiles(RSTREE R)
+
+{
+ RSTName SufName;
+ int O_MODE= O_RDWR;
+
+ (*R).dir.f= open((*R).dirname,O_MODE,STDMODE);
+ if ((*R).dir.f == -1) {
+ (*R).RSTDone= FALSE;
+ return;
+ }
+ strcpy(SufName,(*R).dirname);
+ strcat(SufName,datasuffix);
+ (*R).data.f= open(SufName,O_MODE,STDMODE);
+ if ((*R).data.f == -1) {
+ (*R).RSTDone= FALSE;
+ return;
+ }
+ strcpy(SufName,(*R).dirname);
+ strcat(SufName,dirPDsuffix);
+ (*R).dirPD.f= open(SufName,O_MODE,STDMODE);
+ if ((*R).dirPD.f == -1) {
+ (*R).RSTDone= FALSE;
+ return;
+ }
+ strcpy(SufName,(*R).dirname);
+ strcat(SufName,dataPDsuffix);
+ (*R).dataPD.f= open(SufName,O_MODE,STDMODE);
+ if ((*R).dataPD.f == -1) {
+ (*R).RSTDone= FALSE;
+ return;
+ }
+}
+
+/***********************************************************************/
+
+void FastCloseRSFiles(RSTREE R)
+
+{
+ close((*R).dir.f);
+ close((*R).data.f);
+ close((*R).dirPD.f);
+ close((*R).dataPD.f);
+}
+
+/***********************************************************************/
+
+void CloseRSFiles(RSTREE R)
+
+{
+ if (close((*R).dir.f) == -1) {
+ (*R).RSTDone= FALSE;
+ }
+ if (close((*R).data.f) == -1) {
+ (*R).RSTDone= FALSE;
+ }
+ if (close((*R).dirPD.f) == -1) {
+ (*R).RSTDone= FALSE;
+ }
+ if (close((*R).dataPD.f) == -1) {
+ (*R).RSTDone= FALSE;
+ }
+}
+
+/***********************************************************************/
+
+void SetBase(RSTREE R, int pagelen, boolean unique)
+
+{
+ refparameters par;
+ refpagedir dpd;
+ int dirminfill, dataminfill;
+ int i;
+
+ par= &(*R).parameters._;
+
+ (*par).minfillpercent= minimumFillPercentage;
+ (*par).reinstpercent= ReInsertPercentage;
+ (*par).nbrsexam= maximumNeighborsToExamine;
+ (*par).maxdim= NumbOfDim-1;
+ (*par).SIZEinfo= sizeof(typinfo);
+ (*par).unique= unique;
+ (*par).pagelen= pagelen;
+
+ /* ----- set directory level parameters ----- */
+ SetCheckDir(R,TRUE);
+ (*par).dirM= ((*par).pagelen-(*par).SIZE_DIRnofentries) / (*par).direntrylen;
+ if ((*par).dirM > maxentries) {
+ (*R).RSTDone= FALSE;
+ return;
+ }
+ if ((*par).dirM < 3) {
+ (*R).RSTDone= FALSE;
+ return;
+ }
+ if ((*par).dirM < 5) {
+ dirminfill= minFillPercSmallFanout;
+ }
+ else {
+ dirminfill= minimumFillPercentage;
+ }
+ (*par).dirMwords= (*par).dirM / sizeof(int) + 1;
+ (*par).dirm= (dirminfill * (*par).dirM + 50) / 100;
+ (*par).dirreinsertqty= ((*par).reinstpercent * (*par).dirM + 50) / 100;
+
+ /* ----- set data level parameters ----- */
+ SetCheckData(R,TRUE);
+ (*par).dataM= ((*par).pagelen-(*par).SIZE_DATAnofentries) /
+ (*par).dataentrylen;
+ if ((*par).dataM > maxentries) {
+ (*R).RSTDone= FALSE;
+ return;
+ }
+ if ((*par).dataM < 1) {
+ (*R).RSTDone= FALSE;
+ return;
+ }
+ if ((*par).dataM < 5) {
+ dataminfill= minFillPercSmallFanout;
+ }
+ else {
+ dataminfill= minimumFillPercentage;
+ }
+ (*par).dataMwords= (*par).dataM / sizeof(int) + 1;
+ (*par).datam= (dataminfill * (*par).dataM + 50) / 100;
+ (*par).datareinsertqty=
+ ((*par).reinstpercent * (*par).dataM + 50) / 100;
+
+ /* ----- set defaults ----- */
+ (*par).height= 1;
+ (*par).dirpagecount= 1;
+ (*par).datapagecount= 0;
+ for (i= 0; i < chainlen; i++) {
+ (*par).pagecountarr[i]= 0;
+ }
+ (*par).recordcount= 0;
+
+ dpd= &(*R).dirpagedir._;
+
+ (*dpd).childnr= firstPDblocknumb;
+ (*dpd).nofnumbers= 0;
+ (*dpd).number[0]= rootblocknumb;
+
+ dpd= &(*R).datapagedir._;
+
+ (*dpd).childnr= firstPDblocknumb;
+ (*dpd).nofnumbers= 0;
+ (*dpd).number[0]= rootblocknumb;
+}
+
+/***********************************************************************/
+
+void SetCheckDir(RSTREE R, boolean creation)
+
+{
+ /* Alignment and compatibility checks */
+
+ refparameters par;
+ int SIZE_DIRnodeOf3, SIZE_DIRnodeOf2,
+ PACKEDdirentrylen, REALdirentrylen,
+ PACKEDSIZE_DIRnofentries, REALSIZE_DIRnofentries;
+
+ par= &(*R).parameters._;
+
+ if (creation) {
+ (*par).direntrylen= sizeof(typDIRent); /* set */
+ PACKEDdirentrylen= sizeof(typrect) + sizeof(int);
+ if (PACKEDdirentrylen != (*par).direntrylen) {
+ printf("\n%s\n"," ----- WARNING -----");
+ printf("%s\n","Directory entries are not packed!");
+ printf("%s %d\n","Packed directory entry length:",PACKEDdirentrylen);
+ printf("%s %d\n"," Real space needed:",(*par).direntrylen);
+ printf("%s\n",/* implicitly */"Applying the latter!");
+ }
+ }
+
+ SIZE_DIRnodeOf3= sizeof(typDIRnodeOf3);
+ SIZE_DIRnodeOf2= sizeof(typDIRnodeOf2);
+ REALdirentrylen= SIZE_DIRnodeOf3 - SIZE_DIRnodeOf2;
+ if (creation) {
+ if (REALdirentrylen != (*par).direntrylen) {
+ printf("\n%s\n"," ----- WARNING -----");
+ printf("%s\n","Directory nodes are not packed!");
+ printf("%s %d\n","Directory entry length:",(*par).direntrylen);
+ printf("%s %d\n","Space needed in a node:",REALdirentrylen);
+ printf("%s\n",/* explicitly */"Applying the latter!");
+ (*par).direntrylen= REALdirentrylen; /* reset */
+ }
+ }
+ else {
+ if ((*par).direntrylen != REALdirentrylen) { /* check */
+ printf("\n%s\n","FATAL ERROR:");
+ printf("%s\n","Incompatible R*-tree file!");
+ printf("%s %d\n","Size of a directory entry:",(*par).direntrylen);
+ printf("%s %d\n"," Expecting:",REALdirentrylen);
+ }
+ }
+
+ PACKEDSIZE_DIRnofentries= sizeof(int);
+ REALSIZE_DIRnofentries= SIZE_DIRnodeOf3 - 3 * (*par).direntrylen;
+ (*par).SIZE_DIRnofentries= REALSIZE_DIRnofentries; /* set */
+ if (creation) {
+ if (PACKEDSIZE_DIRnofentries != (*par).SIZE_DIRnofentries) {
+ printf("\n%s\n"," ----- WARNING -----");
+ printf("%s\n","Gap before directory entries!");
+ }
+ }
+ else {
+ if ((*par).SIZE_DIRnofentries != REALSIZE_DIRnofentries) {
+ printf("\n%s\n","FATAL ERROR:");
+ printf("%s\n","Incompatible R*-tree file!");
+ printf("%s %d\n","Offset for entries:",(*par).SIZE_DIRnofentries);
+ printf("%s %d\n"," Expecting:",REALSIZE_DIRnofentries);
+ }
+ }
+
+ if (! creation) {
+ if ((*par).maxdim+1 != NumbOfDim) {
+ printf("\n%s\n","FATAL ERROR:");
+ printf("%s\n","Incompatible R*-tree file!");
+ printf("%s %d\n","Number of dimensions:",(*par).maxdim+1);
+ printf("%s %d\n"," Expecting:",NumbOfDim);
+ }
+ }
+
+ (*R).dirnodelen= (*par).pagelen + (*par).direntrylen;
+}
+
+/***********************************************************************/
+
+void SetCheckData(RSTREE R, boolean creation)
+
+{
+ /* Alignment and compatibility checks */
+
+ refparameters par;
+ int SIZE_DATAnodeOf3, SIZE_DATAnodeOf2,
+ PACKEDdataentrylen, REALdataentrylen,
+ PACKEDSIZE_DATAnofentries, REALSIZE_DATAnofentries;
+
+ par= &(*R).parameters._;
+
+ if (creation) {
+ (*par).dataentrylen= sizeof(typDATAent); /* set */
+ PACKEDdataentrylen= sizeof(typrect) + sizeof(typinfo);
+ if (PACKEDdataentrylen != (*par).dataentrylen) {
+ printf("\n%s\n"," ----- WARNING -----");
+ printf("%s\n","Data entries are not packed!");
+ printf("%s %d\n","Packed data entry length:",PACKEDdataentrylen);
+ printf("%s %d\n"," Real space needed:",(*par).dataentrylen);
+ printf("%s\n",/* implicitly */"Applying the latter!");
+ }
+ }
+
+ SIZE_DATAnodeOf3= sizeof(typDATAnodeOf3);
+ SIZE_DATAnodeOf2= sizeof(typDATAnodeOf2);
+ REALdataentrylen= SIZE_DATAnodeOf3 - SIZE_DATAnodeOf2;
+ if (creation) {
+ if (REALdataentrylen != (*par).dataentrylen) {
+ printf("\n%s\n"," ----- WARNING -----");
+ printf("%s\n","Data nodes are not packed!");
+ printf("%s %d\n"," Data entry length:",(*par).dataentrylen);
+ printf("%s %d\n","Space needed in a node:",REALdataentrylen);
+ printf("%s\n",/* explicitly */"Applying the latter!");
+ (*par).dataentrylen= REALdataentrylen; /* reset */
+ }
+ }
+ else {
+ if ((*par).dataentrylen != REALdataentrylen) { /* check */
+ printf("\n%s\n","FATAL ERROR:");
+ printf("%s\n","Incompatible R*-tree file!");
+ printf("%s %d\n","Size of a data entry:",(*par).dataentrylen);
+ printf("%s %d\n"," Expecting:",REALdataentrylen);
+ }
+ }
+
+ PACKEDSIZE_DATAnofentries= sizeof(int);
+ REALSIZE_DATAnofentries= SIZE_DATAnodeOf3 - 3 * (*par).dataentrylen;
+ (*par).SIZE_DATAnofentries= REALSIZE_DATAnofentries; /* set */
+ if (creation) {
+ if (PACKEDSIZE_DATAnofentries != (*par).SIZE_DATAnofentries) {
+ printf("\n%s\n"," ----- WARNING -----");
+ printf("%s\n","Gap before data entries!");
+ }
+ }
+ else {
+ if ((*par).SIZE_DATAnofentries != REALSIZE_DATAnofentries) {
+ printf("\n%s\n","FATAL ERROR:");
+ printf("%s\n","Incompatible R*-tree file!");
+ printf("%s %d\n","Offset for entries:",(*par).SIZE_DATAnofentries);
+ printf("%s %d\n"," Expecting:",REALSIZE_DATAnofentries);
+ }
+ }
+
+ if (! creation) {
+ if ((*par).SIZEinfo != sizeof(typinfo)) {
+ printf("\n%s\n","FATAL ERROR:");
+ printf("%s %d\n","Size of an info part:",(*par).SIZEinfo);
+ printf("%s %d\n"," Expecting:",sizeof(typinfo));
+ }
+ }
+
+ (*R).datanodelen= (*par).pagelen + (*par).dataentrylen;
+}
+
+/***********************************************************************/
+
+void InitChainFlags(RSTREE R)
+
+{
+ int i;
+
+ for (i= 1; i <= chainlen; i++) {
+ (*R).N[i]= NULL; (*R).NInst[i]= NULL; (*R).NDel[i]= NULL;
+ (*R).E[i]= -1; (*R).EInst[i]= -1;
+ (*R).P[i]= 0;
+ (*R).Nmodified[i]= FALSE;
+ (*R).ReInsert[i]= FALSE;
+ }
+}
+
+/***********************************************************************/
+
+void AllocBuffers(RSTREE R)
+
+{
+ refparameters par;
+ int i;
+
+ par= &(*R).parameters._;
+
+ for (i= 1; i < (*par).height; i++) {
+ (*R).N[i]= (refnode)malloc((*R).dirnodelen);
+ }
+ (*R).N[(*par).height]= (refnode)malloc((*R).datanodelen);
+ if ((*R).dirnodelen > (*R).datanodelen) {
+ (*R).Nsibling= (refnode)malloc((*R).dirnodelen);
+ }
+ else {
+ (*R).Nsibling= (refnode)malloc((*R).datanodelen);
+ }
+ (*R).helpdirnode= (refnode)malloc((*R).dirnodelen);
+ (*R).helpdatanode= (refnode)malloc((*R).datanodelen);
+}
+
+/***********************************************************************/
+
+void DeallocBuffers(RSTREE R)
+
+{
+ refparameters par;
+ int i;
+
+ par= &(*R).parameters._;
+
+ for (i= 1; i < (*par).height; i++) {
+ free((*R).N[i]); (*R).N[i]= NULL;
+ }
+ free((*R).N[(*par).height]); (*R).N[(*par).height]= NULL;
+ free((*R).Nsibling);
+ free((*R).helpdirnode);
+ free((*R).helpdatanode);
+}
+
+/***********************************************************************/
+
+void InitCount(RSTREE R)
+
+{
+ refcount c;
+
+ c= &(*R).count;
+ (*c).countflag= FALSE;
+ (*c).dirvisitcount= 0; (*c).datavisitcount= 0;
+ (*c).dirreadcount= 0; (*c).datareadcount= 0;
+ (*c).dirmodifycount= 0; (*c).datamodifycount= 0;
+ (*c).dirwritecount= 0; (*c).datawritecount= 0;
+}
+
+/***********************************************************************/
diff --git a/modules/RStarTree/RSTInterUtil.h b/modules/RStarTree/RSTInterUtil.h
new file mode 100644
index 0000000..38db446
--- /dev/null
+++ b/modules/RStarTree/RSTInterUtil.h
@@ -0,0 +1,32 @@
+/* ----- RSTInterUtil.h ----- */
+#ifndef __RSTInterUtil_h
+#define __RSTInterUtil_h
+
+
+#include "RStarTree.h"
+
+
+/* constants */
+
+#define minimumFillPercentage 40
+#define minFillPercSmallFanout 50
+#define ReInsertPercentage 30
+#define maximumNeighborsToExamine 32
+
+
+/* declarations */
+
+void CreateRSFiles(RSTREE R);
+void OpenRSFiles(RSTREE R);
+void FastCloseRSFiles(RSTREE R);
+void CloseRSFiles(RSTREE R);
+void SetBase(RSTREE R, int pagelen, boolean unique);
+void SetCheckDir(RSTREE R, boolean creation);
+void SetCheckData(RSTREE R, boolean creation);
+void InitChainFlags(RSTREE R);
+void AllocBuffers(RSTREE R);
+void DeallocBuffers(RSTREE R);
+void InitCount(RSTREE R);
+
+
+#endif /* !__RSTInterUtil_h */
diff --git a/modules/RStarTree/RSTJoin.c b/modules/RStarTree/RSTJoin.c
new file mode 100644
index 0000000..86669e6
--- /dev/null
+++ b/modules/RStarTree/RSTJoin.c
@@ -0,0 +1,514 @@
+/* ----- RSTJoin.c ----- */
+
+
+#include "RStarTree.h"
+#include "RSTJoin.h"
+#include "RSTUtil.h"
+#include "RSTInOut.h"
+
+
+/* declarations */
+
+static void JnRgnCntNv(RSTREE R, RSTREE Rx,
+ boolean order,
+ int depth,
+ typrect dataqueryrect1,
+ typrect dataqueryrect2,
+ typrect joinrect,
+ DataQueryProc DataQuery,
+ DirQueryProc DirJoin,
+ DataQueryProc DataJoin,
+ int *keysqualifying);
+
+static void JnRgnQueryNv(RSTREE R, RSTREE Rx,
+ boolean order,
+ int depth,
+ typrect dataqueryrect1,
+ typrect dataqueryrect2,
+ typrect joinrect,
+ refinfo ptr_to_info_of_other_tree,
+ DataQueryProc DataQuery,
+ DirQueryProc DirJoin,
+ DataQueryProc DataJoin,
+ JoinManageProc Manage,
+ void *buf1,
+ void *buf2,
+ boolean *finish);
+
+
+/************************************************************************/
+
+void JnCntNv(RSTREE R1, RSTREE R2,
+ int depth,
+ typrect R1rectangle1,
+ typrect R1rectangle2,
+ typrect R2rectangle1,
+ typrect R2rectangle2,
+ DirQueryProc Dir1Query,
+ DataQueryProc Data1Query,
+ DirQueryProc Dir2Query,
+ DataQueryProc Data2Query,
+ DirQueryProc DirJoin,
+ DataQueryProc DataJoin,
+ int *keysqualifying,
+ int *mark)
+
+{
+ refDATAnode n;
+ refcount c;
+ boolean istoread1, istoread2;
+ int downqualifying;
+ typrect unused;
+ int i, j;
+
+ boolean verbosejoincount= TRUE;
+
+ if (depth != (*R1).parameters._.height && depth !=
+ (*R2).parameters._.height) {
+ for (i= 0; i < (*(*R1).N[depth]).DIR.nofentries; i++) {
+ for (j= 0; j < (*(*R2).N[depth]).DIR.nofentries; j++) {
+ if ( Dir1Query(R1,(*(*R1).N[depth]).DIR.entries[i].rect,
+ R1rectangle1,R1rectangle2) &&
+ Dir2Query(R2,(*(*R2).N[depth]).DIR.entries[j].rect,
+ R2rectangle1,R2rectangle2) ) {
+ if (DirJoin(R1,(*(*R1).N[depth]).DIR.entries[i].rect,
+ (*(*R2).N[depth]).DIR.entries[j].rect,unused)) {
+ /* R1 sets the number of dimensions and type */
+ (*R1).E[depth]= i; (*R2).E[depth]= j;
+ istoread1= (*(*R1).N[depth]).DIR.entries[i].ptrtosub !=
+ (*R1).P[depth+1];
+ if ( istoread1 ) {
+ NewNode(R1,depth+1);
+ }
+ istoread2= (*(*R2).N[depth]).DIR.entries[j].ptrtosub !=
+ (*R2).P[depth+1];
+ if ( istoread2 ) {
+ NewNode(R2,depth+1);
+ }
+ JnCntNv(R1,R2,
+ depth+1,
+ R1rectangle1,R1rectangle2,R2rectangle1,R2rectangle2,
+ Dir1Query,Data1Query,Dir2Query,Data2Query,DirJoin,DataJoin,
+ keysqualifying,
+ mark);
+ }
+ }
+ }
+ }
+
+ c= &(*R1).count;
+ if ((*c).countflag) {
+ (*c).dirvisitcount++;
+ }
+
+ c= &(*R2).count;
+ if ( (*c).countflag ) {
+ (*c).dirvisitcount++;
+ }
+ }
+ else {
+ if (depth == (*R1).parameters._.height) {
+
+ n= &(*(*R1).N[depth]).DATA;
+
+ for (i= 0; i < (*n).nofentries; i++) {
+ downqualifying= 0;
+ if (Data1Query(R1,(*n).entries[i].rect,R1rectangle1,R1rectangle2)) {
+ JnRgnCntNv(R2,R1,FALSE,depth,
+ R2rectangle1,R2rectangle2,
+ (*n).entries[i].rect,
+ Data2Query,
+ DirJoin,DataJoin,
+ &downqualifying);
+ *keysqualifying+= downqualifying;
+ if (verbosejoincount) {
+ if (*keysqualifying > *mark) {
+ printf("%s%10d%s\n","More than",*mark," record pairs.");
+ if (*mark < 1000) {
+ *mark+= 100;
+ }
+ else if (*mark < 10000) {
+ *mark+= 1000;
+ }
+ else {
+ *mark+= 10000;
+ }
+ }
+ }
+ }
+ }
+
+ c= &(*R1).count;
+ if ((*c).countflag) {
+ (*c).datavisitcount++;
+ }
+ }
+ else {
+
+ n= &(*(*R2).N[depth]).DATA;
+
+ for (i= 0; i < (*n).nofentries; i++) {
+ downqualifying= 0;
+ if (Data2Query(R2,(*n).entries[i].rect,R2rectangle1,R2rectangle2)) {
+ JnRgnCntNv(R1,R2,TRUE,depth,
+ R1rectangle1,R1rectangle2,
+ (*n).entries[i].rect,
+ Data1Query,
+ DirJoin,DataJoin,
+ &downqualifying);
+ *keysqualifying+= downqualifying;
+ if (verbosejoincount) {
+ if (*keysqualifying > *mark) {
+ printf("%s%10d%s\n","More than",*mark," record pairs.");
+ if (*mark < 1000) {
+ *mark+= 100;
+ }
+ else if (*mark < 10000) {
+ *mark+= 1000;
+ }
+ else {
+ *mark+= 10000;
+ }
+ }
+ }
+ }
+ }
+
+ c= &(*R2).count;
+ if ((*c).countflag) {
+ (*c).datavisitcount++;
+ }
+
+ }
+ }
+}
+
+/************************************************************************/
+
+static void JnRgnCntNv(RSTREE R, RSTREE Rx,
+ boolean order,
+ int depth,
+ typrect dataqueryrect1,
+ typrect dataqueryrect2,
+ typrect joinrect,
+ DataQueryProc DataQuery,
+ DirQueryProc DirJoin,
+ DataQueryProc DataJoin,
+ int *keysqualifying)
+
+{
+ refDIRnode DIN;
+ refDATAnode DAN;
+ refcount c;
+ boolean istoread;
+ typrect unused;
+ int i;
+
+
+ if (depth != (*R).parameters._.height) {
+
+ DIN= &(*(*R).N[depth]).DIR;
+
+ if (order) {
+ for (i= 0; i < (*DIN).nofentries; i++) {
+ if (DirJoin(R,(*DIN).entries[i].rect,joinrect,unused)) {
+ (*R).E[depth]= i;
+ istoread= (*DIN).entries[i].ptrtosub != (*R).P[depth+1];
+ if ( istoread ) {
+ NewNode(R,depth+1);
+ }
+ JnRgnCntNv(R,Rx,order,depth+1,
+ dataqueryrect1,dataqueryrect2,joinrect,
+ DataQuery,DirJoin,DataJoin,
+ keysqualifying);
+ }
+ }
+ }
+ else {
+ for (i= 0; i < (*DIN).nofentries; i++) {
+ if (DirJoin(Rx,joinrect,(*DIN).entries[i].rect,unused)) {
+ (*R).E[depth]= i;
+ istoread= (*DIN).entries[i].ptrtosub != (*R).P[depth+1];
+ if (istoread) {
+ NewNode(R,depth+1);
+ }
+ JnRgnCntNv(R,Rx,order,depth+1,
+ dataqueryrect1,dataqueryrect2,joinrect,
+ DataQuery,DirJoin,DataJoin,
+ keysqualifying);
+ }
+ }
+ }
+
+ c= &(*R).count;
+ if ((*c).countflag) {
+ (*c).dirvisitcount++;
+ }
+ }
+ else {
+
+ DAN= &(*(*R).N[depth]).DATA;
+
+ if (order) {
+ for (i= 0; i < (*DAN).nofentries; i++) {
+ if (DataQuery(R,(*DAN).entries[i].rect,dataqueryrect1,dataqueryrect2)) {
+ if (DataJoin(R,(*DAN).entries[i].rect,joinrect,unused)) {
+ (*R).E[depth]= i;
+ (*keysqualifying)++;
+ }
+ }
+ }
+ }
+ else {
+ for (i= 0; i < (*DAN).nofentries; i++) {
+ if (DataQuery(R,(*DAN).entries[i].rect,dataqueryrect1,dataqueryrect2)) {
+ if (DataJoin(Rx,joinrect,(*DAN).entries[i].rect,unused)) {
+ (*R).E[depth]= i;
+ (*keysqualifying)++;
+ }
+ }
+ }
+ }
+
+ c= &(*R).count;
+ if ((*c).countflag) {
+ (*c).datavisitcount++;
+ }
+
+ }
+}
+
+/************************************************************************/
+
+void JnNv(RSTREE R1, RSTREE R2,
+ int depth,
+ typrect R1rectangle1,
+ typrect R1rectangle2,
+ typrect R2rectangle1,
+ typrect R2rectangle2,
+ DirQueryProc Dir1Query,
+ DataQueryProc Data1Query,
+ DirQueryProc Dir2Query,
+ DataQueryProc Data2Query,
+ DirQueryProc DirJoin,
+ DataQueryProc DataJoin,
+ JoinManageProc Manage,
+ void *buf1,
+ void *buf2,
+ boolean *finish)
+
+{
+ refDATAnode n;
+ refcount c;
+ boolean istoread1, istoread2;
+ typrect unused;
+ int i, j;
+
+ if (depth != (*R1).parameters._.height && depth !=
+ (*R2).parameters._.height) {
+ c= &(*R1).count;
+ if ((*c).countflag) {
+ (*c).dirvisitcount++;
+ }
+ c= &(*R2).count;
+ if ( (*c).countflag ) {
+ (*c).dirvisitcount++;
+ }
+
+ for (i= 0; i < (*(*R1).N[depth]).DIR.nofentries; i++) {
+ if (*finish) {return;}
+ for (j= 0; j < (*(*R2).N[depth]).DIR.nofentries; j++) {
+ if (*finish) {return;}
+ if ( Dir1Query(R1,(*(*R1).N[depth]).DIR.entries[i].rect,
+ R1rectangle1,R1rectangle2) &&
+ Dir2Query(R2,(*(*R2).N[depth]).DIR.entries[j].rect,
+ R2rectangle1,R2rectangle2) ) {
+ if (DirJoin(R1,(*(*R1).N[depth]).DIR.entries[i].rect,
+ (*(*R2).N[depth]).DIR.entries[j].rect,unused)) {
+ /* R1 sets the number of dimensions and type */
+ (*R1).E[depth]= i; (*R2).E[depth]= j;
+ istoread1= (*(*R1).N[depth]).DIR.entries[i].ptrtosub !=
+ (*R1).P[depth+1];
+ if ( istoread1 ) {
+ NewNode(R1,depth+1);
+ }
+ istoread2= (*(*R2).N[depth]).DIR.entries[j].ptrtosub !=
+ (*R2).P[depth+1];
+ if ( istoread2 ) {
+ NewNode(R2,depth+1);
+ }
+ JnNv(R1,R2,
+ depth+1,
+ R1rectangle1,R1rectangle2,R2rectangle1,R2rectangle2,
+ Dir1Query,Data1Query,Dir2Query,Data2Query,DirJoin,DataJoin,
+ Manage,buf1,buf2,finish);
+ }
+ }
+ }
+ }
+ }
+ else {
+ if (depth == (*R1).parameters._.height) {
+
+ c= &(*R1).count;
+ if ((*c).countflag) {
+ (*c).datavisitcount++;
+ }
+
+ n= &(*(*R1).N[depth]).DATA;
+
+ for (i= 0; i < (*n).nofentries; i++) {
+ if (*finish) {return;}
+ if (Data1Query(R1,(*n).entries[i].rect,R1rectangle1,R1rectangle2)) {
+ JnRgnQueryNv(R2,R1,FALSE,depth,
+ R2rectangle1,R2rectangle2,
+ (*n).entries[i].rect,
+ &(*n).entries[i].info,
+ Data2Query,
+ DirJoin,DataJoin,
+ Manage,buf1,buf2,finish);
+ }
+ }
+ }
+ else {
+
+ c= &(*R2).count;
+ if ((*c).countflag) {
+ (*c).datavisitcount++;
+ }
+
+ n= &(*(*R2).N[depth]).DATA;
+
+ for (i= 0; i < (*n).nofentries; i++) {
+ if (*finish) {return;}
+ if (Data2Query(R2,(*n).entries[i].rect,R2rectangle1,R2rectangle2)) {
+ JnRgnQueryNv(R1,R2,TRUE,depth,
+ R1rectangle1,R1rectangle2,
+ (*n).entries[i].rect,
+ &(*n).entries[i].info,
+ Data1Query,
+ DirJoin,DataJoin,
+ Manage,buf1,buf2,finish);
+ }
+ }
+ }
+ }
+}
+
+/************************************************************************/
+
+static void JnRgnQueryNv(RSTREE R, RSTREE Rx,
+ boolean order,
+ int depth,
+ typrect dataqueryrect1,
+ typrect dataqueryrect2,
+ typrect joinrect,
+ typinfo *joininfo,
+ DataQueryProc DataQuery,
+ DirQueryProc DirJoin,
+ DataQueryProc DataJoin,
+ JoinManageProc Manage,
+ void *buf1,
+ void *buf2,
+ boolean *finish)
+{
+ refDIRnode DIN;
+ refDATAnode DAN;
+ refcount c;
+ boolean istoread;
+ typrect rectR1, rectR2, unused;
+ int i;
+
+ if (depth != (*R).parameters._.height) {
+
+ c= &(*R).count;
+ if ((*c).countflag) {
+ (*c).dirvisitcount++;
+ }
+
+ DIN= &(*(*R).N[depth]).DIR;
+
+ if (order) {
+ for (i= 0; i < (*DIN).nofentries; i++) {
+ if (*finish) {return;}
+ if (DirJoin(R,(*DIN).entries[i].rect,joinrect,unused)) {
+ (*R).E[depth]= i;
+ istoread= (*DIN).entries[i].ptrtosub != (*R).P[depth+1];
+ if ( istoread ) {
+ NewNode(R,depth+1);
+ }
+ JnRgnQueryNv(R,Rx,order,depth+1,
+ dataqueryrect1,dataqueryrect2,
+ joinrect,
+ joininfo,
+ DataQuery,DirJoin,DataJoin,
+ Manage,buf1,buf2,finish);
+ }
+ }
+ }
+ else {
+ for (i= 0; i < (*DIN).nofentries; i++) {
+ if (*finish) {return;}
+ if (DirJoin(Rx,joinrect,(*DIN).entries[i].rect,unused)) {
+ (*R).E[depth]= i;
+ istoread= (*DIN).entries[i].ptrtosub != (*R).P[depth+1];
+ if (istoread) {
+ NewNode(R,depth+1);
+ }
+ JnRgnQueryNv(R,Rx,order,depth+1,
+ dataqueryrect1,dataqueryrect2,
+ joinrect,
+ joininfo,
+ DataQuery,DirJoin,DataJoin,
+ Manage,buf1,buf2,finish);
+ }
+ }
+ }
+ }
+ else {
+
+ c= &(*R).count;
+ if ((*c).countflag) {
+ (*c).datavisitcount++;
+ }
+
+ DAN= &(*(*R).N[depth]).DATA;
+
+ if (order) {
+ for (i= 0; i < (*DAN).nofentries; i++) {
+ if (*finish) {return;}
+ if (DataQuery(R,(*DAN).entries[i].rect,dataqueryrect1,dataqueryrect2)) {
+ if (DataJoin(R,(*DAN).entries[i].rect,joinrect,unused)) {
+ (*R).E[depth]= i;
+ CopyRect(R,(*DAN).entries[i].rect,rectR1);
+ CopyRect(R,joinrect,rectR2);
+ Manage(R,Rx,
+ rectR1,rectR2,
+ &(*DAN).entries[i].info,joininfo,
+ buf1,buf2,
+ finish);
+ }
+ }
+ }
+ }
+ else {
+ for (i= 0; i < (*DAN).nofentries; i++) {
+ if (*finish) {return;}
+ if (DataQuery(R,(*DAN).entries[i].rect,dataqueryrect1,dataqueryrect2)) {
+ if (DataJoin(Rx,joinrect,(*DAN).entries[i].rect,unused)) {
+ (*R).E[depth]= i;
+ CopyRect(Rx,joinrect,rectR1);
+ CopyRect(Rx,(*DAN).entries[i].rect,rectR2);
+ Manage(Rx,R,
+ rectR1,rectR2,
+ joininfo,&(*DAN).entries[i].info,
+ buf1,buf2,
+ finish);
+ }
+ }
+ }
+ }
+ }
+}
+
+/************************************************************************/
diff --git a/modules/RStarTree/RSTJoin.h b/modules/RStarTree/RSTJoin.h
new file mode 100644
index 0000000..075fee5
--- /dev/null
+++ b/modules/RStarTree/RSTJoin.h
@@ -0,0 +1,46 @@
+/* ----- RSTJoin.h ----- */
+#ifndef __RSTJoin_h
+#define __RSTJoin_h
+
+
+#include "RStarTree.h"
+
+
+/* declarations */
+
+void JnCntNv(RSTREE R1, RSTREE R2,
+ int depth,
+ typrect R1rectangle1,
+ typrect R1rectangle2,
+ typrect R2rectangle1,
+ typrect R2rectangle2,
+ DirQueryProc Dir1Query,
+ DataQueryProc Data1Query,
+ DirQueryProc Dir2Query,
+ DataQueryProc Data2Query,
+ DirQueryProc DirJoin,
+ DataQueryProc DataJoin,
+ int *keysqualifying,
+ int *mark);
+
+
+void JnNv(RSTREE R1, RSTREE R2,
+ int depth,
+ typrect R1rectangle1,
+ typrect R1rectangle2,
+ typrect R2rectangle1,
+ typrect R2rectangle2,
+ DirQueryProc Dir1Query,
+ DataQueryProc Data1Query,
+ DirQueryProc Dir2Query,
+ DataQueryProc Data2Query,
+ DirQueryProc DirJoin,
+ DataQueryProc DataJoin,
+ JoinManageProc Manage,
+ void *buf1,
+ void *buf2,
+ boolean *finish);
+
+
+#endif /* !__RSTJoin_h */
+
diff --git a/modules/RStarTree/RSTQuery.c b/modules/RStarTree/RSTQuery.c
new file mode 100644
index 0000000..5ebb949
--- /dev/null
+++ b/modules/RStarTree/RSTQuery.c
@@ -0,0 +1,340 @@
+/* ----- RSTQuery.c ----- */
+
+
+#include "RStarTree.h"
+#include "RSTQuery.h"
+#include "RSTUtil.h"
+#include "RSTInOut.h"
+
+
+/* declarations */
+
+/************************************************************************/
+
+boolean FoundRect(RSTREE R,
+ int depth,
+ typrect rectangle,
+ boolean isinsert,
+ refinfo *infoadr)
+
+{
+ refparameters par;
+ refcount c;
+ refDATAnode n;
+ int instind;
+ boolean found;
+ int i;
+
+ i= -1; instind= -1; found= FALSE;
+
+ par= &(*R).parameters._;
+
+ if (depth != (*par).height) {
+ if (isinsert) {
+ ChooseSubtree(R,rectangle,depth,&(*(*R).N[depth]).DIR,&instind);
+ (*R).EInst[depth]= instind;
+ }
+ do {
+ i++;
+ if (Covers(R,(*(*R).N[depth]).DIR.entries[i].rect,rectangle)) {
+ (*R).E[depth]= i;
+ depth++;
+ if ((*R).N[depth] == (*R).NInst[depth]) {
+ if ((*R).Nmodified[depth]) {
+ PutNode(R,(*R).N[depth],(*R).P[depth],depth);
+ (*R).Nmodified[depth]= FALSE;
+ }
+ if (depth == (*par).height) {
+ (*R).N[depth]= (refnode)malloc((*R).datanodelen);
+ }
+ else {
+ (*R).N[depth]= (refnode)malloc((*R).dirnodelen);
+ }
+ (*R).P[depth]= (*(*R).N[depth-1]).DIR.entries[i].ptrtosub;
+ GetNode(R,(*R).N[depth],(*R).P[depth],depth);
+ }
+ else if ((*(*R).N[depth-1]).DIR.entries[i].ptrtosub != (*R).P[depth]) {
+ NewNode(R,depth);
+ }
+ if ( i == instind) {
+ (*R).NInst[depth]= (*R).N[depth];
+ }
+ found= FoundRect(R,depth,rectangle,i==instind,infoadr);
+ depth--;
+ }
+ } while (! found && i != (*(*R).N[depth]).DIR.nofentries - 1);
+
+ c = &(*R).count;
+
+ if ((*c).countflag) {
+ (*c).dirvisitcount++;
+ }
+ }
+ else {
+
+ n= &(*(*R).N[depth]).DATA;
+
+ while (! found && i != (*n).nofentries - 1) {
+ i++;
+ found= RSTEqual(R,(*n).entries[i].rect,rectangle);
+ if (found) {
+ (*R).E[depth]= i;
+ *infoadr= &(*n).entries[i].info;
+ }
+ }
+
+ c = &(*R).count;
+ if ((*c).countflag) {
+ (*c).datavisitcount++;
+ }
+ }
+ if (found) {
+ (*R).EInst[depth]= -1;
+ depth++;
+ if ((*R).NInst[depth] != NULL) {
+ if ((*R).NInst[depth] != (*R).N[depth]) {
+ free((*R).NInst[depth]);
+ }
+ (*R).NInst[depth]= NULL;
+ }
+ depth--;
+ }
+ return found;
+}
+
+/************************************************************************/
+
+void XstsRgn(RSTREE R,
+ int depth,
+ typrect rectangle1,
+ typrect rectangle2,
+ DirQueryProc DirQuery,
+ DataQueryProc DataQuery,
+ boolean *found)
+
+{
+ refcount c;
+ refDIRnode DIN;
+ refDATAnode DAN;
+ boolean istoread;
+ int i;
+
+ if (depth != (*R).parameters._.height) {
+
+ DIN= &(*(*R).N[depth]).DIR;
+
+ i= -1;
+ do {
+ i++;
+ if (DirQuery(R,(*DIN).entries[i].rect,rectangle1,rectangle2)) {
+ (*R).E[depth]= i;
+ istoread= (*DIN).entries[i].ptrtosub != (*R).P[depth+1];
+ if (istoread) {
+ NewNode(R,depth+1);
+ }
+ XstsRgn(R,depth+1,rectangle1,rectangle2,DirQuery,DataQuery,found);
+ }
+ } while (! *found && i != (*DIN).nofentries - 1);
+
+ c= &(*R).count;
+ if ((*c).countflag) {
+ (*c).dirvisitcount++;
+ }
+ }
+ else {
+
+ DAN= &(*(*R).N[depth]).DATA;
+
+ i= -1;
+ while (! *found && i != (*DAN).nofentries - 1) {
+ i++;
+ if (DataQuery(R,(*DAN).entries[i].rect,rectangle1,rectangle2)) {
+ (*R).E[depth]= i;
+ *found= TRUE;
+ }
+ }
+
+ c= &(*R).count;
+ if ((*c).countflag) {
+ (*c).datavisitcount++;
+ }
+ }
+}
+
+/************************************************************************/
+
+void RgnCnt(RSTREE R,
+ int depth,
+ typrect rectangle1,
+ typrect rectangle2,
+ DirQueryProc DirQuery,
+ DataQueryProc DataQuery,
+ int *keysqualifying)
+
+{
+ refcount c;
+ refDIRnode DIN;
+ refDATAnode DAN;
+ boolean istoread;
+ int i;
+
+ if (depth != (*R).parameters._.height) {
+
+ DIN= &(*(*R).N[depth]).DIR;
+
+ for (i= 0; i < (*DIN).nofentries; i++) {
+ if (DirQuery(R,(*DIN).entries[i].rect,rectangle1,rectangle2)) {
+ (*R).E[depth]= i;
+ istoread= (*DIN).entries[i].ptrtosub != (*R).P[depth+1];
+ if (istoread) {
+ NewNode(R,depth+1);
+ }
+ RgnCnt(R,depth+1,rectangle1,rectangle2,
+ DirQuery, DataQuery,keysqualifying);
+ }
+ }
+
+ c= &(*R).count;
+ if ((*c).countflag) {
+ (*c).dirvisitcount++;
+ }
+ }
+ else {
+
+ DAN= &(*(*R).N[depth]).DATA;
+
+ for (i= 0; i < (*DAN).nofentries; i++) {
+ if (DataQuery(R,(*DAN).entries[i].rect,rectangle1,rectangle2)) {
+ (*R).E[depth]= i;
+ (*keysqualifying)++;
+ }
+ }
+
+ c= &(*R).count;
+ if ((*c).countflag) {
+ (*c).datavisitcount++;
+ }
+
+ }
+}
+
+/************************************************************************/
+
+void RgnQuery(RSTREE R,
+ int depth,
+ typrect rectangle1,
+ typrect rectangle2,
+ DirQueryProc DirQuery,
+ DataQueryProc DataQuery,
+ QueryManageProc Manage,
+ void *buf,
+ boolean *finish)
+
+{
+ refcount c;
+ refDIRnode DIN;
+ refDATAnode DAN;
+ boolean istoread;
+ typrect rectfound;
+ int i;
+
+ if (depth != (*R).parameters._.height) {
+
+ c= &(*R).count;
+ if ((*c).countflag) {
+ (*c).dirvisitcount++;
+ }
+
+ DIN= &(*(*R).N[depth]).DIR;
+
+ for (i= 0; i < (*DIN).nofentries; i++) {
+ if (*finish) {return;}
+
+ if (DirQuery(R,(*DIN).entries[i].rect,rectangle1,rectangle2)) {
+ (*R).E[depth]= i;
+ istoread= (*DIN).entries[i].ptrtosub != (*R).P[depth+1];
+ if (istoread) {
+ NewNode(R,depth+1);
+ }
+ RgnQuery(R,depth+1,rectangle1,rectangle2,
+ DirQuery,DataQuery,
+ Manage,buf,finish);
+ }
+ }
+ }
+ else {
+
+ c= &(*R).count;
+ if ((*c).countflag) {
+ (*c).datavisitcount++;
+ }
+
+ DAN= &(*(*R).N[depth]).DATA;
+
+ for (i= 0; i < (*DAN).nofentries; i++) {
+ if (*finish) {return;}
+
+ if (DataQuery(R,(*DAN).entries[i].rect,rectangle1,rectangle2)) {
+ (*R).E[depth]= i;
+
+ CopyRect(R,(*DAN).entries[i].rect,rectfound); /* avoid modification */
+ Manage(R,rectfound,
+ &(*DAN).entries[i].info,
+ buf,
+ &(*R).Nmodified[depth],
+ finish);
+
+ }
+ }
+ }
+}
+
+/************************************************************************/
+
+void All(RSTREE R,
+ int depth,
+ QueryManageProc Manage,
+ void *buf,
+ boolean *finish)
+
+{
+ refDIRnode DIN;
+ refDATAnode DAN;
+ typrect rectfound;
+ int i;
+
+ if (depth != (*R).parameters._.height) {
+
+ DIN= &(*(*R).N[depth]).DIR;
+
+ for (i= 0; i < (*DIN).nofentries; i++) {
+ if (*finish) {return;}
+
+ (*R).E[depth]= i;
+ if ((*DIN).entries[i].ptrtosub != (*R).P[depth+1]) {
+ NewNode(R,depth+1);
+ }
+ All(R,depth+1,Manage,buf,finish);
+ }
+ }
+ else {
+
+ DAN= &(*(*R).N[depth]).DATA;
+
+ for (i= 0; i < (*DAN).nofentries; i++) {
+ if (*finish) {return;}
+
+ (*R).E[depth]= i;
+
+ CopyRect(R,(*DAN).entries[i].rect,rectfound); /* avoid modification */
+ Manage(R,rectfound,
+ &(*DAN).entries[i].info,
+ buf,
+ &(*R).Nmodified[depth],
+ finish);
+
+ }
+ }
+}
+
+/************************************************************************/
diff --git a/modules/RStarTree/RSTQuery.h b/modules/RStarTree/RSTQuery.h
new file mode 100644
index 0000000..dfa1d72
--- /dev/null
+++ b/modules/RStarTree/RSTQuery.h
@@ -0,0 +1,54 @@
+/* ----- RSTQuery.h ----- */
+#ifndef __RSTQuery_h
+#define __RSTQuery_h
+
+
+#include "RStarTree.h"
+
+
+/* declarations */
+
+boolean FoundRect(RSTREE R,
+ int depth,
+ typrect rectangle,
+ boolean isinsert,
+ refinfo *infoadr);
+
+void XstsRgn(RSTREE R,
+ int depth,
+ typrect rectangle1,
+ typrect rectangle2,
+ DirQueryProc DirQuery,
+ DataQueryProc DataQuery,
+ boolean *found);
+
+
+void RgnCnt(RSTREE R,
+ int depth,
+ typrect rectangle1,
+ typrect rectangle2,
+ DirQueryProc DirQuery,
+ DataQueryProc DataQuery,
+ int *keysqualifying);
+
+
+void RgnQuery(RSTREE R,
+ int depth,
+ typrect rectangle1,
+ typrect rectangle2,
+ DirQueryProc DirQuery,
+ DataQueryProc DataQuery,
+ QueryManageProc Manage,
+ void *buf,
+ boolean *finish);
+
+
+void All(RSTREE R,
+ int depth,
+ QueryManageProc Manage,
+ void *buf,
+ boolean *finish);
+
+
+#endif /* !__RSTQuery_h */
+
diff --git a/modules/RStarTree/RSTUtil.c b/modules/RStarTree/RSTUtil.c
new file mode 100644
index 0000000..6763c58
--- /dev/null
+++ b/modules/RStarTree/RSTUtil.c
@@ -0,0 +1,843 @@
+/* ----- RSTUtil.c ----- */
+
+
+#include "RStarTree.h"
+#include "RSTUtil.h"
+
+
+/* declarations */
+
+static void ExChange(int *x, int *y);
+static void CSWorkAround(RSTREE R,
+ typrect newrect,
+ refDIRnode node,
+ int index,
+ double space,
+ double newspace);
+
+
+/***********************************************************************/
+
+void FalseArray(int *ptr, int wordsqty)
+
+{
+ int i;
+
+ i= 1;
+ while (i <= wordsqty) {
+ *ptr= FALSE;
+ ptr++;
+ i++;
+ }
+}
+
+/***********************************************************************/
+
+void CopyRect(RSTREE R,
+ typrect from,
+ typrect to)
+
+{
+ int d;
+ for (d= 0; d <= (*R).parameters._.maxdim; d++) {
+ to[d]= from[d];
+ }
+}
+
+/***********************************************************************/
+
+void EvalCenter(RSTREE R, typrect rectangle, typpoint center)
+
+{
+ int i;
+
+ for (i= 0; i <= (*R).parameters._.maxdim; i++) {
+ center[i]= (rectangle[i].l + rectangle[i].h) / 2.0;
+ }
+}
+
+/***********************************************************************/
+
+double RSTDistance(RSTREE R, typpoint point1, typpoint point2)
+
+{
+ double sum, factor;
+ int i;
+
+ sum= 0.0;
+ for (i= 0; i <= (*R).parameters._.maxdim; i++) {
+ factor= point1[i] - point2[i];
+ sum= sum+factor*factor;
+ }
+ return sum; /* relativ distance (sqrt avoided) */
+}
+
+/***********************************************************************/
+
+void EvalDirEnclRect(RSTREE R, typDIRnode *node, typrect rectangle)
+
+{
+ int maxdim;
+ refinterval re;
+ int i, j;
+
+ maxdim= (*R).parameters._.maxdim;
+ CopyRect(R,(*node).entries[0].rect,rectangle);
+ for (i= 0; i < (*node).nofentries; i++) {
+ for (j= 0; j <= maxdim; j++) {
+
+ re= &(*node).entries[i].rect[j];
+
+ if (rectangle[j].l > (*re).l) {
+ rectangle[j].l= (*re).l;
+ }
+ if (rectangle[j].h < (*re).h) {
+ rectangle[j].h= (*re).h;
+ }
+ }
+ }
+}
+
+/***********************************************************************/
+
+void EvalDataEnclRect(RSTREE R, typDATAnode *node, typrect rectangle)
+
+{
+ int maxdim;
+ refinterval re;
+ int i, j;
+
+ maxdim= (*R).parameters._.maxdim;
+ CopyRect(R,(*node).entries[0].rect,rectangle);
+ for (i= 0; i < (*node).nofentries; i++) {
+ for (j= 0; j <= maxdim; j++) {
+
+ re= &(*node).entries[i].rect[j];
+
+ if (rectangle[j].l > (*re).l) {
+ rectangle[j].l= (*re).l;
+ }
+ if (rectangle[j].h < (*re).h) {
+ rectangle[j].h= (*re).h;
+ }
+ }
+ }
+}
+
+/***********************************************************************/
+
+boolean Overlaps(RSTREE R,
+ typrect rect1,
+ typrect rect2)
+
+{
+ boolean ovlp;
+ int maxdim;
+ int d;
+
+ maxdim= (*R).parameters._.maxdim;
+ d= -1;
+ do {
+ d++;
+ ovlp= rect1[d].l <= rect2[d].h &&
+ rect1[d].h >= rect2[d].l;
+ } while (ovlp && d != maxdim);
+ return ovlp;
+}
+
+/***********************************************************************/
+
+void GetOverlap(RSTREE R,
+ typrect r1,
+ typrect r2,
+ double *spc)
+
+{
+ double low, high;
+ int i;
+
+ *spc= 1.0;
+ for (i= 0; i <= (*R).parameters._.maxdim; i++) {
+ if (r1[i].l < r2[i].l) {
+ low= r2[i].l;
+ }
+ else {
+ low= r1[i].l;
+ }
+ if (r1[i].h < r2[i].h) {
+ high= r1[i].h;
+ }
+ else {
+ high= r2[i].h;
+ }
+ *spc= *spc * (high-low);
+ }
+}
+
+/***********************************************************************/
+
+boolean RSTEqual(RSTREE R,
+ typrect rect1,
+ typrect rect2)
+
+{
+ boolean eql;
+ int d;
+
+ d= -1;
+ do {
+ d++;
+ eql= rect1[d].l == rect2[d].l &&
+ rect1[d].h == rect2[d].h;
+ } while (eql && d != (*R).parameters._.maxdim);
+ return eql;
+}
+
+/***********************************************************************/
+
+boolean Covers(RSTREE R,
+ typrect crect,
+ typrect rect)
+
+{
+ boolean cov;
+ int maxdim;
+ int d;
+
+ maxdim= (*R).parameters._.maxdim;
+ d= -1;
+ do {
+ d++;
+ cov= crect[d].l <= rect[d].l &&
+ crect[d].h >= rect[d].h;
+ } while (cov && d != (*R).parameters._.maxdim);
+ return cov;
+}
+
+/***********************************************************************/
+
+void QuickSortValArr(int begin,
+ int end,
+ ValueArray value,
+ IndexArray I)
+/* Sorts I
+ by value[I[i]]. */
+
+{
+ double midelem;
+ int i, j;
+
+ i= begin; j= end;
+ midelem= value[I[(i+j) / 2]];
+ do {
+ while (value[I[i]] < midelem) {
+ i++;
+ }
+ while (value[I[j]]>midelem) {
+ j--;
+ }
+ if (i < j) {
+ ExChange(&I[i],&I[j]);
+ i++; j--;
+ }
+ else if (i == j) {
+ i++; j--;
+ }
+ } while (i <= j);
+ if (begin < j) {
+ if (j - begin > 1) {
+ QuickSortValArr(begin,j,value,I);
+ }
+ else {
+ if (value[I[begin]] > value[I[j]]) {
+ ExChange(&I[begin],&I[j]);
+ }
+ }
+ }
+ if (i < end) {
+ if (end - i > 1) {
+ QuickSortValArr(i,end,value,I);
+ }
+ else {
+ if (value[I[i]] > value[I[end]]) {
+ ExChange(&I[i],&I[end]);
+ }
+ }
+ }
+}
+
+/***********************************************************************/
+
+void QuickSortDirEnt(int begin,
+ int end,
+ int dim,
+ Side side,
+ typDIRentries Ntosort,
+ IndexArray I)
+/* Sorts I
+ primarily by Ntosort[I[i]].rect[dim].side,
+ secondarily by Ntosort[I[i]].rect[dim]."otherside". */
+
+{
+ refinterval re;
+ typatomkey midlow, midhigh;
+ typinterval int1, int2;
+ int i, j;
+
+ i= begin; j= end;
+ if (side == low) {
+
+ re = &Ntosort[I[(i+j) / 2]].rect[dim];
+
+ midlow= (*re).l;
+ midhigh= (*re).h;
+ do {
+ while ( Ntosort[I[i]].rect[dim].l < midlow ||
+ ( Ntosort[I[i]].rect[dim].l == midlow &&
+ Ntosort[I[i]].rect[dim].h < midhigh ) ) {
+ i++;
+ }
+ while ( Ntosort[I[j]].rect[dim].l > midlow ||
+ ( Ntosort[I[j]].rect[dim].l == midlow &&
+ Ntosort[I[j]].rect[dim].h > midhigh ) ) {
+ j--;
+ }
+ if (i < j) {
+ ExChange(&I[i],&I[j]);
+ i++; j--;
+ }
+ else if (i == j) {
+ i++; j--;
+ }
+ } while (i <= j);
+ if (begin < j) {
+ if (j - begin > 1) {
+ QuickSortDirEnt(begin,j,dim,low,Ntosort,I);
+ }
+ else {
+ int1= Ntosort[I[begin]].rect[dim];
+ int2= Ntosort[I[j]].rect[dim];
+ if ( int1.l > int2.l ||
+ ( int1.l == int2.l &&
+ int1.h > int2.h ) ) {
+ ExChange(&I[begin],&I[j]);
+ }
+ }
+ }
+ if (i < end) {
+ if (end - i > 1) {
+ QuickSortDirEnt(i,end,dim,low,Ntosort,I);
+ }
+ else {
+ int1= Ntosort[I[i]].rect[dim];
+ int2= Ntosort[I[end]].rect[dim];
+ if ( int1.l > int2.l ||
+ ( int1.l == int2.l &&
+ int1.h > int2.h ) ) {
+ ExChange(&I[i],&I[end]);
+ }
+ }
+ }
+ }
+ else {
+
+ re = &Ntosort[I[(i+j) / 2]].rect[dim];
+
+ midhigh= (*re).h;
+ midlow= (*re).l;
+ do {
+ while ( Ntosort[I[i]].rect[dim].h < midhigh ||
+ ( Ntosort[I[i]].rect[dim].h == midhigh &&
+ Ntosort[I[i]].rect[dim].l < midlow ) ) {
+ i++;
+ };
+ while ( Ntosort[I[j]].rect[dim].h > midhigh ||
+ ( Ntosort[I[j]].rect[dim].h == midhigh &&
+ Ntosort[I[j]].rect[dim].l > midlow ) ) {
+ j--;
+ };
+ if (i < j) {
+ ExChange(&I[i],&I[j]);
+ i++; j--;
+ }
+ else if (i == j) {
+ i++; j--;
+ }
+ } while (i <= j);
+ if (begin < j) {
+ if (j - begin > 1) {
+ QuickSortDirEnt(begin,j,dim,high,Ntosort,I);
+ }
+ else {
+ int1= Ntosort[I[begin]].rect[dim];
+ int2= Ntosort[I[j]].rect[dim];
+ if ( int1.h > int2.h ||
+ ( int1.h == int2.h &&
+ int1.l > int2.l ) ) {
+ ExChange(&I[begin],&I[j]);
+ }
+ }
+ }
+ if (i < end) {
+ if (end - i > 1) {
+ QuickSortDirEnt(i,end,dim,high,Ntosort,I);
+ }
+ else {
+ int1= Ntosort[I[i]].rect[dim];
+ int2= Ntosort[I[end]].rect[dim];
+ if ( int1.h > int2.h ||
+ ( int1.h == int2.h &&
+ int1.l > int2.l ) ) {
+ ExChange(&I[i],&I[end]);
+ }
+ }
+ }
+ }
+}
+
+/***********************************************************************/
+
+void QuickSortDataEnt(int begin,
+ int end,
+ int dim,
+ Side side,
+ typDATAentries Ntosort,
+ IndexArray I)
+/* Sorts I
+ primarily by Ntosort[I[i]].rect[dim].side,
+ secondarily by Ntosort[I[i]].rect[dim]."otherside". */
+
+{
+ refinterval re;
+ typatomkey midlow, midhigh;
+ typinterval int1, int2;
+ int i, j;
+
+ i= begin; j= end;
+ if (side == low) {
+
+ re = &Ntosort[I[(i+j) / 2]].rect[dim];
+
+ midlow= (*re).l;
+ midhigh= (*re).h;
+ do {
+ while ( Ntosort[I[i]].rect[dim].l < midlow ||
+ ( Ntosort[I[i]].rect[dim].l == midlow &&
+ Ntosort[I[i]].rect[dim].h < midhigh ) ) {
+ i++;
+ }
+ while ( Ntosort[I[j]].rect[dim].l > midlow ||
+ ( Ntosort[I[j]].rect[dim].l == midlow &&
+ Ntosort[I[j]].rect[dim].h > midhigh ) ) {
+ j--;
+ }
+ if (i < j) {
+ ExChange(&I[i],&I[j]);
+ i++; j--;
+ }
+ else if (i == j) {
+ i++; j--;
+ }
+ } while (i <= j);
+ if (begin < j) {
+ if (j - begin > 1) {
+ QuickSortDataEnt(begin,j,dim,low,Ntosort,I);
+ }
+ else {
+ int1= Ntosort[I[begin]].rect[dim];
+ int2= Ntosort[I[j]].rect[dim];
+ if ( int1.l > int2.l ||
+ ( int1.l == int2.l &&
+ int1.h > int2.h ) ) {
+ ExChange(&I[begin],&I[j]);
+ }
+ }
+ }
+ if (i < end) {
+ if (end - i > 1) {
+ QuickSortDataEnt(i,end,dim,low,Ntosort,I);
+ }
+ else {
+ int1= Ntosort[I[i]].rect[dim];
+ int2= Ntosort[I[end]].rect[dim];
+ if ( int1.l > int2.l ||
+ ( int1.l == int2.l &&
+ int1.h > int2.h ) ) {
+ ExChange(&I[i],&I[end]);
+ }
+ }
+ }
+ }
+ else {
+
+ re = &Ntosort[I[(i+j) / 2]].rect[dim];
+
+ midhigh= (*re).h;
+ midlow= (*re).l;
+ do {
+ while ( Ntosort[I[i]].rect[dim].h < midhigh ||
+ ( Ntosort[I[i]].rect[dim].h == midhigh &&
+ Ntosort[I[i]].rect[dim].l < midlow ) ) {
+ i++;
+ };
+ while ( Ntosort[I[j]].rect[dim].h > midhigh ||
+ ( Ntosort[I[j]].rect[dim].h == midhigh &&
+ Ntosort[I[j]].rect[dim].l > midlow ) ) {
+ j--;
+ };
+ if (i < j) {
+ ExChange(&I[i],&I[j]);
+ i++; j--;
+ }
+ else if (i == j) {
+ i++; j--;
+ }
+ } while (i <= j);
+ if (begin < j) {
+ if (j - begin > 1) {
+ QuickSortDataEnt(begin,j,dim,high,Ntosort,I);
+ }
+ else {
+ int1= Ntosort[I[begin]].rect[dim];
+ int2= Ntosort[I[j]].rect[dim];
+ if ( int1.h > int2.h ||
+ ( int1.h == int2.h &&
+ int1.l > int2.l ) ) {
+ ExChange(&I[begin],&I[j]);
+ }
+ }
+ }
+ if (i < end) {
+ if (end - i > 1) {
+ QuickSortDataEnt(i,end,dim,high,Ntosort,I);
+ }
+ else {
+ int1= Ntosort[I[i]].rect[dim];
+ int2= Ntosort[I[end]].rect[dim];
+ if ( int1.h > int2.h ||
+ ( int1.h == int2.h &&
+ int1.l > int2.l ) ) {
+ ExChange(&I[i],&I[end]);
+ }
+ }
+ }
+ }
+}
+
+/***********************************************************************/
+
+static void ExChange(int *x, int *y)
+
+{
+ int z;
+
+ z= *x; *x= *y; *y= z;
+}
+
+/***********************************************************************/
+
+void ChooseSubtree(RSTREE R,
+ typrect newrect,
+ int depth,
+ typDIRnode *node,
+ int *found)
+
+{
+ int maxexam, inv;
+ typatomkey low, high;
+ double space, newspace,
+ enlarge,
+ validspace, ovlpspc, overlap, leastovlp;
+ boolean didfit, first, ok;
+ ValueArray enlarr;
+ IndexArray I;
+ typrect enlargedrect;
+ int maxdim;
+ refparameters par;
+ refinterval re;
+ refDIRent e;
+ int i, j, k;
+
+ didfit= FALSE; ok= TRUE;
+ maxdim= (*R).parameters._.maxdim;
+ for (i= 0; i < (*node).nofentries; i++) {
+ space= 1.0; newspace= 1.0;
+ for (j= 0; j <= maxdim; j++) {
+
+ re= &(*node).entries[i].rect[j];
+
+ low= (*re).l;
+ high= (*re).h;
+ space= space * (high - low);
+
+ re= &newrect[j];
+
+ if (low > (*re).l) {
+ low= (*re).l;
+ }
+ if (high < (*re).h) {
+ high= (*re).h;
+ }
+ newspace= newspace * (high - low);
+ }
+ if (space == 0.0) {
+ CSWorkAround(R,newrect,node,i,space,newspace);
+ ok= FALSE;
+ } /* trap degenerated rectangles */
+ if (didfit) {
+ if (newspace == space) { /* it fits */
+ if (space < validspace) {
+ validspace= space;
+ *found= i;
+ }
+ }
+ }
+ else {
+ enlarge= newspace - space;
+ if (enlarge == 0.0) {
+ validspace= space;
+ *found= i;
+ didfit= TRUE;
+ }
+ else {
+ enlarr[i]= enlarge;
+ }
+ }
+ }
+ if (! didfit) {
+ for (i= 0; i < (*node).nofentries; i++) {
+ I[i]= i;
+ }
+ QuickSortValArr(0,(*node).nofentries - 1,enlarr,I);
+ if (ok && depth == (*R).parameters._.height - 1) { /* Subtrees are leafs */
+
+ par = &(*R).parameters._;
+
+ if ((*node).nofentries < (*par).nbrsexam) {
+ maxexam= (*node).nofentries;
+ }
+ else {
+ maxexam= (*par).nbrsexam;
+ }
+
+/* maxexam= (*node).nofentries; *//* <- all *) */
+
+ first= TRUE;
+ for (i= 0; i < maxexam; i++) {
+ for (j= 0; j <= maxdim; j++) {
+
+ re= &(*node).entries[I[i]].rect[j];
+
+ low= (*re).l;
+ high= (*re).h;
+
+ re= &enlargedrect[j];
+
+ (*re).l= low;
+ (*re).h= high;
+ if (low > newrect[j].l) {
+ (*re).l= newrect[j].l;
+ }
+ if (high < newrect[j].h) {
+ (*re).h= newrect[j].h;
+ }
+ } /* Create enlargedrect */
+ overlap= 0.0;
+ for (k= 0; k < (*node).nofentries; k++) {
+ if (k != i) {
+
+ e= &(*node).entries[I[k]];
+
+ if (Overlaps(R,enlargedrect,(*e).rect)) {
+ GetOverlap(R,enlargedrect,(*e).rect,&ovlpspc);
+ overlap= overlap+ovlpspc;
+ if (Overlaps(R,(*node).entries[I[i]].rect,(*e).rect)) {
+ GetOverlap(R,(*node).entries[I[i]].rect,(*e).rect,&ovlpspc);
+ overlap= overlap-ovlpspc;
+ }
+ }
+ }
+ }
+ if (first) {
+ leastovlp= overlap;
+ *found= I[0];
+ inv= 1;
+ first= FALSE;
+ }
+ else {
+ if (overlap < leastovlp) {
+ leastovlp= overlap;
+ *found= I[i];
+ inv= i;
+ }
+ }
+ }
+ }
+ else { /* Subtrees are not leafs */
+ *found= I[0];
+ }
+ }
+}
+
+/***********************************************************************/
+
+static void CSWorkAround(RSTREE R,
+ typrect newrect,
+ typDIRnode *node,
+ int index,
+ double space,
+ double newspace)
+
+{
+#define epsilon (1.0e-100)
+
+ typatomkey low, high;
+ double distance;
+ refinterval re;
+ int j;
+
+ space= 1.0; newspace= 1.0;
+ for (j= 0; j <= (*R).parameters._.maxdim; j++) {
+
+ re= &(*node).entries[index].rect[j];
+
+ low= (*re).l;
+ high= (*re).h;
+ distance= high - low;
+ if (distance == 0.0) {
+ distance= epsilon;
+ }
+ space= space * distance;
+
+ re= &newrect[j];
+
+ if (low > (*re).l) {
+ low= (*re).l;
+ }
+ if (high < (*re).h) {
+ high= (*re).h;
+ }
+ distance= high - low;
+ if (distance == 0.0) {
+ distance= epsilon;
+ }
+ newspace= newspace * distance;
+ }
+
+#undef epsilon
+}
+
+/***********************************************************************/
+
+void AdjustChain(RSTREE R,
+ int depth,
+ typrect newrect)
+
+{
+ refinterval re;
+ refcount c;
+ int maxdim;
+ boolean adjusting;
+ int j;
+
+ c= &(*R).count;
+ maxdim= (*R).parameters._.maxdim;
+
+ adjusting= TRUE;
+
+ if (depth == (*R).parameters._.height) {
+ adjusting= FALSE;
+ for (j= 0; j <= maxdim; j++) {
+
+ re = &(*(*R).N[depth]).DATA.entries[(*R).E[depth]].rect[j];
+
+ if ((*re).l > newrect[j].l) {
+ (*re).l= newrect[j].l;
+ adjusting= TRUE;
+ }
+ if ((*re).h < newrect[j].h) {
+ (*re).h= newrect[j].h;
+ adjusting= TRUE;
+ }
+ }
+ if (adjusting) {
+ (*R).Nmodified[depth]= TRUE;
+ if ((*c).countflag) {
+ (*c).dirmodifycount++;
+ }
+ }
+ depth--;
+ }
+ while (depth != 0 && adjusting) {
+ adjusting= FALSE;
+ for (j= 0; j <= maxdim; j++) {
+
+ re = &(*(*R).N[depth]).DIR.entries[(*R).E[depth]].rect[j];
+
+ if ((*re).l > newrect[j].l) {
+ (*re).l= newrect[j].l;
+ adjusting= TRUE;
+ }
+ if ((*re).h < newrect[j].h) {
+ (*re).h= newrect[j].h;
+ adjusting= TRUE;
+ }
+ }
+ if (adjusting) {
+ (*R).Nmodified[depth]= TRUE;
+ if ((*c).countflag) {
+ (*c).dirmodifycount++;
+ }
+ }
+ depth--;
+ }
+}
+
+/***********************************************************************/
+
+void AdjustChainAfterDeletion(RSTREE R,
+ int depth)
+
+{
+ refDIRent e;
+ refcount c;
+ boolean changed;
+ typrect helprect;
+
+ c= &(*R).count;
+
+ changed= TRUE;
+
+ if (depth == (*R).parameters._.height && depth != 1) {
+ EvalDataEnclRect(R,&(*(*R).N[depth]).DATA,helprect);
+ depth--;
+
+ e = &(*(*R).N[depth]).DIR.entries[(*R).E[depth]];
+
+ changed= ! RSTEqual(R,helprect,(*e).rect);
+ if (changed) {
+ CopyRect(R,helprect,(*e).rect);
+ (*R).Nmodified[depth]= TRUE;
+ if ((*c).countflag) {
+ (*c).dirmodifycount++;
+ }
+ }
+ }
+ while (depth != 1 && changed) {
+ EvalDirEnclRect(R,&(*(*R).N[depth]).DIR,helprect);
+ depth--;
+
+ e = &(*(*R).N[depth]).DIR.entries[(*R).E[depth]];
+
+ changed= ! RSTEqual(R,helprect,(*e).rect);
+ if (changed) {
+ CopyRect(R,helprect,(*e).rect);
+ (*R).Nmodified[depth]= TRUE;
+ if ((*c).countflag) {
+ (*c).dirmodifycount++;
+ }
+ }
+ }
+}
+
+/***********************************************************************/
diff --git a/modules/RStarTree/RSTUtil.h b/modules/RStarTree/RSTUtil.h
new file mode 100644
index 0000000..6e00213
--- /dev/null
+++ b/modules/RStarTree/RSTUtil.h
@@ -0,0 +1,84 @@
+/* ----- RSTUtil.h ----- */
+#ifndef __RSTUtil_h
+#define __RSTUtil_h
+
+
+#include "RStarTree.h"
+
+
+/* declarations */
+
+void FalseArray(int *ptr,
+ int wordsqty);
+
+void CopyRect(RSTREE,
+ typrect from,
+ typrect to);
+
+void EvalCenter(RSTREE R,
+ typrect rectangle,
+ typpoint center);
+
+double RSTDistance(RSTREE R,
+ typpoint point1,
+ typpoint point2);
+
+void EvalDirEnclRect(RSTREE R,
+ refDIRnode node,
+ typrect rect);
+
+void EvalDataEnclRect(RSTREE R,
+ refDATAnode node,
+ typrect rect);
+
+boolean Overlaps(RSTREE R,
+ typrect rect1,
+ typrect rect2);
+
+boolean RSTEqual(RSTREE R,
+ typrect rect1,
+ typrect rect2);
+
+boolean Covers(RSTREE R,
+ typrect crect,
+ typrect rect);
+
+void GetOverlap(RSTREE R,
+ typrect r1,
+ typrect r2,
+ double *spc);
+
+void QuickSortValArr(int begin,
+ int end,
+ ValueArray value,
+ IndexArray I);
+
+void QuickSortDirEnt(int begin,
+ int end,
+ int dim,
+ Side side,
+ typDIRentries Ntosort,
+ IndexArray I);
+
+void QuickSortDataEnt(int begin,
+ int end,
+ int dim,
+ Side side,
+ typDATAentries Ntosort,
+ IndexArray I);
+
+void ChooseSubtree(RSTREE R,
+ typrect newrect,
+ int depth,
+ refDIRnode node,
+ int *found);
+
+void AdjustChain(RSTREE R,
+ int depth,
+ typrect newrect);
+
+void AdjustChainAfterDeletion(RSTREE R,
+ int depth);
+
+
+#endif /* !__RSTUtil_h */
diff --git a/modules/RStarTree/RStarTree.c b/modules/RStarTree/RStarTree.c
new file mode 100644
index 0000000..ed17cb7
--- /dev/null
+++ b/modules/RStarTree/RStarTree.c
@@ -0,0 +1,859 @@
+/* ----- RStarTree.c ----- */
+
+
+#include "RStarTree.h"
+#include "RSTInterUtil.h"
+#include "RSTInOut.h"
+#include "RSTInstDel.h"
+#include "RSTQuery.h"
+#include "RSTJoin.h"
+
+
+/* constants */
+
+
+/* types */
+
+
+/* declarations */
+
+static void BasicCheck(void);
+/*** --- Begin --- unused ***
+static boolean InternEqual(RSTREE rst,
+ typrect RSTrect,
+ typrect qrect1,
+ typrect qrect2);
+static boolean InternEncloses(RSTREE rst,
+ typrect RSTrect,
+ typrect qrect1,
+ typrect qrect2);
+ *** --- End --- unused ***/
+
+/************************************************************************/
+
+void NoRSTree(RSTREE *r)
+
+{
+ *r= NULL;
+}
+
+/************************************************************************/
+
+boolean CreateRST(char *name,
+ int pagelen,
+ boolean unique)
+
+{
+ RSTREE R;
+ refparameters par;
+
+ BasicCheck();
+
+ R= (RSTREE)malloc(sizeof(rstree));
+ strcpy((*R).dirname,name);
+ (*R).RSTDone= TRUE;
+ CreateRSFiles(R);
+ if (! (*R).RSTDone) {
+ free(R); R= NULL;
+ return FALSE;
+ }
+ SetBase(R,pagelen,unique);
+ if (! (*R).RSTDone) {
+ free(R); R= NULL;
+ return FALSE;
+ }
+ (*R).dirPD.bl= SIZEfixblock;
+
+ par= &(*R).parameters._;
+
+ WritePage(R,(*R).dirPD,paramblocknumb,par);
+ WritePage(R,(*R).dirPD,firstPDblocknumb,&(*R).dirpagedir);
+ (*R).dataPD.bl= SIZEfixblock;
+ WritePage(R,(*R).dataPD,paramblocknumb,par); /* -- unused -- */
+ WritePage(R,(*R).dataPD,firstPDblocknumb,&(*R).datapagedir);
+ (*R).data.bl= (*par).pagelen;
+ (*R).N[1]= (refnode)malloc((*R).datanodelen);
+ (*(*R).N[1]).DATA.nofentries= 0;
+ PutNode(R,(*R).N[1],rootblocknumb,1);
+ free((*R).N[1]);
+ if (! (*R).RSTDone) {
+ free(R); R= NULL;
+ return FALSE;
+ }
+ CloseRSFiles(R);
+ if (! (*R).RSTDone) {
+ free(R); R= NULL;
+ return FALSE;
+ }
+ free(R); R= NULL;
+ return TRUE;
+}
+
+/************************************************************************/
+
+boolean RemoveRST(char *name)
+
+{
+ RSTName SufName;
+ boolean success= TRUE;
+
+ if (unlink(name) != 0) {
+ success= FALSE;
+ }
+ strcpy(SufName,name);
+ strcat(SufName,datasuffix);
+ if (unlink(SufName) != 0) {
+ success= FALSE;
+ }
+ strcpy(SufName,name);
+ strcat(SufName,dirPDsuffix);
+ if (unlink(SufName) != 0) {
+ success= FALSE;
+ }
+ strcpy(SufName,name);
+ strcat(SufName,dataPDsuffix);
+ if (unlink(SufName) != 0) {
+ success= FALSE;
+ }
+ return success;
+}
+
+/************************************************************************/
+
+boolean OpenRST(RSTREE *r,
+ char *name)
+
+{
+ RSTREE R;
+ refparameters par;
+
+ if (*r != NULL) {
+ return FALSE;
+ }
+ *r= (RSTREE)malloc(sizeof(rstree));
+ R= *r;
+ strcpy((*R).dirname,name);
+ (*R).RSTDone= TRUE;
+ OpenRSFiles(R);
+ if (! (*R).RSTDone) {
+ free(R); *r= NULL;
+ return FALSE;
+ }
+ InitChainFlags(R);
+ (*R).dirPD.bl= SIZEfixblock;
+
+ par= &(*R).parameters._;
+
+ ReadPage(R,(*R).dirPD,paramblocknumb,par);
+ ReadPage(R,(*R).dirPD,firstPDblocknumb,&(*R).dirpagedir);
+ (*R).dataPD.bl= SIZEfixblock;
+ ReadPage(R,(*R).dataPD,firstPDblocknumb,&(*R).datapagedir);
+ if (! (*R).RSTDone) {
+ FastCloseRSFiles(R);
+ free(R); *r= NULL;
+ return FALSE;
+ }
+ SetCheckDir(R,FALSE);
+ SetCheckData(R,FALSE);
+ AllocBuffers(R);
+ (*R).dir.bl= (*par).pagelen;
+ (*R).data.bl= (*par).pagelen;
+ GetNode(R,(*R).N[1],rootblocknumb,1); (*R).P[1]= rootblocknumb;
+ InitCount(R);
+ if (! (*R).RSTDone) {
+ FastCloseRSFiles(R);
+ DeallocBuffers(R);
+ free(R); *r= NULL;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/************************************************************************/
+
+boolean CloseRST(RSTREE *r)
+
+{
+ RSTREE R;
+ refparameters par;
+ boolean success;
+ int i;
+
+ if (*r == NULL) {
+ return FALSE;
+ }
+ R= *r;
+ (*R).RSTDone= TRUE;
+
+ par= &(*R).parameters._;
+ WritePage(R,(*R).dirPD,paramblocknumb,par);
+ WritePage(R,(*R).dirPD,firstPDblocknumb,&(*R).dirpagedir);
+ WritePage(R,(*R).dataPD,paramblocknumb,par); /* -- unused -- */
+ WritePage(R,(*R).dataPD,firstPDblocknumb,&(*R).datapagedir);
+ for (i= 1; i <= (*par).height; i++) {
+ if ((*R).Nmodified[i]) {
+ PutNode(R,(*R).N[i],(*R).P[i],i);
+ }
+ }
+ if (! (*R).RSTDone) {
+ return (*R).RSTDone;
+ }
+ CloseRSFiles(R);
+ if (! (*R).RSTDone) {
+ return (*R).RSTDone;
+ }
+ DeallocBuffers(R);
+ success= (*R).RSTDone;
+ free(R); *r= NULL;
+ return success;
+}
+
+/************************************************************************/
+
+boolean SetUnique(RSTREE R,
+ boolean mode)
+
+{
+ if (R == NULL) {
+ return FALSE;
+ }
+ (*R).parameters._.unique= mode;
+ return TRUE;
+}
+
+/************************************************************************/
+
+boolean InsertRecord(RSTREE R,
+ typrect rectangle,
+ typinfo *info,
+ boolean *inserted)
+
+{
+ refparameters par;
+ typentry entry;
+ refinfo infoadr;
+ int d;
+
+ if (R == NULL) {
+ *inserted= FALSE;
+ return FALSE;
+ }
+
+ (*R).RSTDone= TRUE;
+
+ par= &(*R).parameters._;
+
+ if ((*par).unique) {
+ *inserted= ! FoundRect(R,1,rectangle,TRUE,&infoadr);
+ }
+ else {
+ *inserted= TRUE;
+ }
+ if (*inserted) {
+ for (d= 0; d <= (*par).maxdim; d++) {
+ entry.DATA.rect[d]= rectangle[d];
+ }
+ entry.DATA.info= *info;
+ (*R).ReInsert[(*par).height]= TRUE; /* general switch for Forced ReInsert */
+ Insert(R,&entry,(*par).height);
+ (*R).ReInsert[(*par).height]= FALSE;
+ *inserted= (*R).RSTDone;
+ if (*inserted) {
+ (*par).recordcount++;
+ }
+ }
+ return (*R).RSTDone;
+}
+
+/************************************************************************/
+
+boolean DeleteRecord(RSTREE R,
+ typrect rectangle,
+ boolean *deleted)
+
+{
+ refinfo infoadr;
+
+ if (R == NULL) {
+ *deleted= FALSE;
+ return FALSE;
+ }
+
+ (*R).RSTDone= TRUE;
+
+ *deleted= FoundRect(R,1,rectangle,FALSE,&infoadr);
+ if (*deleted) {
+ DeleteOneRec(R);
+ *deleted= (*R).RSTDone;
+ if (*deleted) {
+ (*R).parameters._.recordcount--;
+ }
+ }
+ return (*R).RSTDone;
+}
+
+/************************************************************************/
+
+boolean ExistsRegion(RSTREE R,
+ typrect rectangle1,
+ typrect rectangle2,
+ DirQueryProc DirQuery,
+ DataQueryProc DataQuery,
+ boolean *regionfound)
+
+{
+ int i;
+
+ if (R == NULL) {
+ *regionfound= FALSE;
+ return FALSE;
+ }
+ /**/
+ for (i= 2; i <= (*R).parameters._.height; i++) {
+ if ((*R).Nmodified[i]) {
+ PutNode(R,(*R).N[i],(*R).P[i],i);
+ (*R).Nmodified[i]= FALSE;
+ }
+ (*R).P[i]= 0;
+ }
+ /**//* to be inserted, if main memory path shall be initialized
+ for test purpose */
+
+ (*R).RSTDone= TRUE;
+ *regionfound= FALSE;
+ XstsRgn(R,1,rectangle1,rectangle2,DirQuery,DataQuery,regionfound);
+ return (*R).RSTDone;
+}
+
+/************************************************************************/
+
+boolean RegionCount(RSTREE R,
+ typrect rectangle1,
+ typrect rectangle2,
+ DirQueryProc DirQuery,
+ DataQueryProc DataQuery,
+ int *recordcount)
+
+{
+ int i;
+
+ if (R == NULL) {
+ *recordcount= 0;
+ return FALSE;
+ }
+ /**/
+ for (i= 2; i <= (*R).parameters._.height; i++) {
+ if ((*R).Nmodified[i]) {
+ PutNode(R,(*R).N[i],(*R).P[i],i);
+ (*R).Nmodified[i]= FALSE;
+ }
+ (*R).P[i]= 0;
+ }
+ /**//* to be inserted, if main memory path shall be initialized
+ for test purpose */
+
+ (*R).RSTDone= TRUE;
+ *recordcount= 0;
+ RgnCnt(R,1,rectangle1,rectangle2,DirQuery,DataQuery,recordcount);
+ return (*R).RSTDone;
+}
+
+/************************************************************************/
+
+boolean RegionQuery(RSTREE R,
+ typrect rectangle1,
+ typrect rectangle2,
+ DirQueryProc DirQuery,
+ DataQueryProc DataQuery,
+ QueryManageProc ManageProc,
+ void *buf)
+
+{
+ boolean finish;
+ int i;
+
+ if (R == NULL) {
+ return FALSE;
+ }
+ /**/
+ for (i= 2; i <= (*R).parameters._.height; i++) {
+ if ((*R).Nmodified[i]) {
+ PutNode(R,(*R).N[i],(*R).P[i],i);
+ (*R).Nmodified[i]= FALSE;
+ }
+ (*R).P[i]= 0;
+ }
+ /**//* to be inserted, if main memory path shall be initialized
+ for test purpose */
+
+ (*R).RSTDone= TRUE;
+ finish= FALSE;
+ RgnQuery(R,1,rectangle1,rectangle2,DirQuery,DataQuery,
+ ManageProc,buf,&finish);
+ return (*R).RSTDone;
+}
+
+/************************************************************************/
+
+boolean AllQuery(RSTREE R,
+ QueryManageProc ManageProc,
+ void *buf)
+
+{
+ boolean finish;
+ int i;
+
+ if (R == NULL) {
+ return FALSE;
+ }
+ /**/
+ for (i= 2; i <= (*R).parameters._.height; i++) {
+ if ((*R).Nmodified[i]) {
+ PutNode(R,(*R).N[i],(*R).P[i],i);
+ (*R).Nmodified[i]= FALSE;
+ }
+ (*R).P[i]= 0;
+ }
+ /**//* to be inserted, if main memory path shall be initialized
+ for test purpose */
+
+ (*R).RSTDone= TRUE;
+ finish= FALSE;
+ All(R,1,ManageProc,buf,&finish);
+ return (*R).RSTDone;
+}
+/************************************************************************/
+
+boolean JoinCountNv(RSTREE R1, RSTREE R2,
+ typrect R1rectangle1,
+ typrect R1rectangle2,
+ typrect R2rectangle1,
+ typrect R2rectangle2,
+ DirQueryProc Dir1Query,
+ DataQueryProc Data1Query,
+ DirQueryProc Dir2Query,
+ DataQueryProc Data2Query,
+ DirQueryProc DirJoin,
+ DataQueryProc DataJoin,
+ int *paircount)
+
+{
+ int mark;
+ boolean twiceopen, success;
+ int i;
+
+ if (R1 == NULL || R2 == NULL) {
+ *paircount= 0;
+ return FALSE;
+ }
+ twiceopen= R1 == R2;
+ if (twiceopen) {
+ for (i= 1; i <= (*R1).parameters._.height; i++) {
+ if ((*R1).Nmodified[i]) {
+ PutNode(R1,(*R1).N[i],(*R1).P[i],i);
+ (*R1).Nmodified[i]= FALSE;
+ }
+ } /* syncronize R1 */
+ R2= NULL;
+ success= OpenRST(&R2,(*R1).dirname); /* NEW(R2) */
+ if (! success) {
+ printf("%s\n","FATAL INTERNAL ERROR");
+ printf("%s\n","JoinCountNv 1");
+ abort();
+ }
+ }
+ /**/
+ for (i= 2; i <= (*R1).parameters._.height; i++) {
+ if ((*R1).Nmodified[i]) {
+ PutNode(R1,(*R1).N[i],(*R1).P[i],i);
+ (*R1).Nmodified[i]= FALSE;
+ }
+ (*R1).P[i]= 0;
+ }
+ for (i= 2; i <= (*R2).parameters._.height; i++) {
+ if ((*R2).Nmodified[i]) {
+ PutNode(R2,(*R2).N[i],(*R2).P[i],i);
+ (*R2).Nmodified[i]= FALSE;
+ }
+ (*R2).P[i]= 0;
+ }
+ /**//* to be inserted, if main memory path shall be initialized
+ for test purpose */
+
+ if (! ((*R1).RSTDone && (*R2).RSTDone) ) {
+ *paircount= 0;
+ return FALSE;
+ }
+ *paircount= 0;
+ mark= 0;
+ JnCntNv(R1,R2,
+ 1,
+ R1rectangle1,R1rectangle2,R2rectangle1,R2rectangle2,
+ Dir1Query,Data1Query,Dir2Query,Data2Query,DirJoin,DataJoin,
+ paircount,
+ &mark);
+ success= (*R1).RSTDone && (*R2).RSTDone;
+ if (twiceopen) {
+ success= success && CloseRST(&R2);
+ }
+ return success;
+}
+
+/************************************************************************/
+
+boolean JoinNv(RSTREE R1, RSTREE R2,
+ typrect R1rectangle1,
+ typrect R1rectangle2,
+ typrect R2rectangle1,
+ typrect R2rectangle2,
+ DirQueryProc Dir1Query,
+ DataQueryProc Data1Query,
+ DirQueryProc Dir2Query,
+ DataQueryProc Data2Query,
+ DirQueryProc DirJoin,
+ DataQueryProc DataJoin,
+ JoinManageProc Manage,
+ void *buf1,
+ void *buf2)
+
+{
+ boolean twiceopen, success;
+ boolean finish;
+ int i;
+
+ if (R1 == NULL || R2 == NULL) {
+ return FALSE;
+ }
+ twiceopen= R1 == R2;
+ if (twiceopen) {
+ for (i= 1; i <= (*R1).parameters._.height; i++) {
+ if ((*R1).Nmodified[i]) {
+ PutNode(R1,(*R1).N[i],(*R1).P[i],i);
+ (*R1).Nmodified[i]= FALSE;
+ }
+ } /* syncronize R1 */
+ R2= NULL;
+ success= OpenRST(&R2,(*R1).dirname); /* NEW(R2) */
+ if (! success) {
+ printf("%s\n","FATAL INTERNAL ERROR");
+ printf("%s\n","JoinCountNv 1");
+ abort();
+ }
+ }
+ /**/
+ for (i= 2; i <= (*R1).parameters._.height; i++) {
+ if ((*R1).Nmodified[i]) {
+ PutNode(R1,(*R1).N[i],(*R1).P[i],i);
+ (*R1).Nmodified[i]= FALSE;
+ }
+ (*R1).P[i]= 0;
+ }
+ for (i= 2; i <= (*R2).parameters._.height; i++) {
+ if ((*R2).Nmodified[i]) {
+ PutNode(R2,(*R2).N[i],(*R2).P[i],i);
+ (*R2).Nmodified[i]= FALSE;
+ }
+ (*R2).P[i]= 0;
+ }
+ /**//* to be inserted, if main memory path shall be initialized
+ for test purpose */
+
+ if (! ((*R1).RSTDone && (*R2).RSTDone) ) {
+ return FALSE;
+ }
+ finish= FALSE;
+ JnNv(R1,R2,
+ 1,
+ R1rectangle1,R1rectangle2,R2rectangle1,R2rectangle2,
+ Dir1Query,Data1Query,Dir2Query,Data2Query,DirJoin,DataJoin,
+ Manage,buf1,buf2,&finish);
+ success= (*R1).RSTDone && (*R2).RSTDone;
+ if (twiceopen) {
+ success= success && CloseRST(&R2);
+ }
+ return success;
+}
+
+/************************************************************************/
+
+boolean InquireRSTDesc(RSTREE R,
+ char *name,
+ int *numbofdim,
+ int *pagesize,
+ int *sizedirentry,
+ int *sizedataentry,
+ int *sizeinfo,
+ int *maxdirfanout,
+ int *maxdatafanout,
+ int *numbofdirpages,
+ int *numbofdatapages,
+ int pagesperlevel[],
+ int *numbofrecords,
+ int *height,
+ boolean *unique)
+
+{
+ refparameters par;
+ int i;
+
+ if (R == NULL) {
+ return FALSE;
+ }
+
+ strcpy(name,(*R).dirname);
+
+ par= &(*R).parameters._;
+
+ *numbofdim= (*par).maxdim+1;
+ *pagesize= (*par).pagelen;
+ *sizedirentry= (*par).direntrylen;
+ *sizedataentry= (*par).dataentrylen;
+ *sizeinfo= (*par).SIZEinfo;
+ *maxdirfanout= (*par).dirM;
+ *maxdatafanout= (*par).dataM;
+ *numbofdirpages= (*par).dirpagecount;
+ *numbofdatapages= (*par).datapagecount;
+ pagesperlevel[0]= 1;
+ for (i= 1; i < (*par).height; i++) {
+ pagesperlevel[i]= (*par).pagecountarr[i+1];
+ }
+ *numbofrecords= (*par).recordcount;
+ *height= (*par).height;
+ *unique= (*par).unique;
+ return TRUE;
+}
+
+/************************************************************************/
+
+boolean CountsOn0(RSTREE R)
+
+{
+ refcount c;
+
+ if (R == NULL) {
+ return FALSE;
+ }
+ c= &(*R).count;
+ (*c).countflag= TRUE;
+ (*c).dirvisitcount= 0; (*c).datavisitcount= 0;
+ (*c).dirreadcount= 0; (*c).datareadcount= 0;
+ (*c).dirmodifycount= 0; (*c).datamodifycount= 0;
+ (*c).dirwritecount= 0; (*c).datawritecount= 0;
+ return TRUE;
+}
+
+/************************************************************************/
+
+boolean CountsOn(RSTREE R)
+
+{
+ if (R == NULL) {
+ return FALSE;
+ }
+ (*R).count.countflag= TRUE;
+ return TRUE;
+}
+
+/************************************************************************/
+
+boolean CountsOff(RSTREE R)
+
+{
+ if (R == NULL) {
+ return FALSE;
+ }
+ (*R).count.countflag= FALSE;
+ return TRUE;
+}
+
+/************************************************************************/
+
+boolean GetCountRead(RSTREE R,
+ int *dirvis, int *datavis,
+ int *dirread, int *dataread)
+
+{
+ refcount c;
+
+ if (R == NULL) {
+ *dirvis= 0;
+ *datavis= 0;
+ *dirread= 0;
+ *dataread= 0;
+ return FALSE;
+ }
+ c= &(*R).count;
+ *dirvis= (*c).dirvisitcount;
+ *datavis= (*c).datavisitcount;
+ *dirread= (*c).dirreadcount;
+ *dataread= (*c).datareadcount;
+ return TRUE;
+}
+
+/************************************************************************/
+
+boolean GetCountWrite(RSTREE R,
+ int *dirmod, int *datamod,
+ int *dirwrite, int *datawrite)
+
+{
+ refcount c;
+
+ if (R == NULL) {
+ *dirmod= 0;
+ *datamod= 0;
+ *dirwrite= 0;
+ *datawrite= 0;
+ return FALSE;
+ }
+ c= &(*R).count;
+ *dirmod= (*c).dirmodifycount;
+ *datamod= (*c).datamodifycount;
+ *dirwrite= (*c).dirwritecount;
+ *datawrite= (*c).datawritecount;
+ return TRUE;
+}
+
+/************************************************************************/
+
+boolean GetMemory(RSTREE R,
+ int *dirpages, int *datapages)
+
+{
+ refparameters par;
+
+ if (R == NULL) {
+ *dirpages= 0;
+ *datapages= 0;
+ return FALSE;
+ }
+ par= &(*R).parameters._;
+ *dirpages= (*par).dirpagecount;
+ *datapages= (*par).datapagecount;
+ return TRUE;
+}
+
+/************************************************************************/
+
+boolean GetHeight(RSTREE R,
+ int *height)
+
+{
+ if (R == NULL) {
+ *height= 0;
+ return FALSE;
+ }
+ *height= (*R).parameters._.height;
+ return TRUE;
+}
+
+/************************************************************************/
+
+static void BasicCheck()
+{
+ if (sizeof(byte) != 1) {
+ printf("%s\n","FATAL ERROR:");
+ printf("%s\n","BasicCheck 1");
+ printf("%s\n","sizeof(byte) != 1");
+ printf("%s %d\n","sizeof(byte):",sizeof(byte));
+ abort();
+ /* concerning application of type ByteArray */
+ }
+ if (sizeof(int) < 4) {
+ printf("%s\n","BasicCheck 2");
+ printf("%s\n","sizeof(int) < 4");
+ printf("%s %d\n","sizeof(int):",sizeof(int));
+ printf("%s\n","WARNING: bigger int range assumed.");
+ }
+ if (sizeof(typinfo) < sizeof(int)) {
+ printf("%s\n","FATAL ERROR:");
+ printf("%s\n","BasicCheck 3");
+ printf("%s\n","sizeof(typinfo) < sizeof(int)");
+ printf("%s %d\n","sizeof(typinfo):",sizeof(typinfo));
+ printf("%s %d\n"," sizeof(int):",sizeof(int));
+ abort();
+ }
+ if (sizeof(typpagedir) > sizeof(typfixblock)) {
+ printf("%s\n","FATAL ERROR:");
+ printf("%s\n","BasicCheck 4");
+ printf("%s\n","sizeof(typpagedir) > sizeof(typfixblock)");
+ printf("%s %d\n"," sizeof(typpagedir):",sizeof(typpagedir));
+ printf("%s %d\n","sizeof(typfixblock):",sizeof(typfixblock));
+ abort();
+ }
+ if (sizeof(typparameters) > sizeof(typfixblock)) {
+ printf("%s\n","FATAL ERROR:");
+ printf("%s\n","BasicCheck 5");
+ printf("%s\n","sizeof(typparameters) > sizeof(typfixblock)");
+ printf("%s %d\n","sizeof(typparameters):",sizeof(typparameters));
+ printf("%s %d\n"," sizeof(typfixblock):",sizeof(typfixblock));
+ abort();
+ }
+}
+
+/************************************************************************/
+/*** --- Begin --- unused ***
+
+static boolean InternEqual(RSTREE R,
+ typrect RSTrect,
+ typrect queryrect,
+ typrect unused)
+
+{
+ boolean eql;
+ int d;
+
+ d= -1;
+ do {
+ d++;
+ eql= RSTrect[d].l == queryrect[d].l &&
+ RSTrect[d].h == queryrect[d].h;
+ } while (eql && d != (*R).parameters._.maxdim);
+ return eql;
+}
+
+static boolean InternEncloses(RSTREE R,
+ typrect RSTrect,
+ typrect queryrect,
+ typrect unused)
+
+{
+ int maxdim;
+ boolean encl;
+ int d;
+
+ maxdim= (*R).parameters._.maxdim;
+ d= -1;
+ do {
+ d++;
+ encl= RSTrect[d].l <= queryrect[d].l &&
+ RSTrect[d].h >= queryrect[d].h;
+ } while (encl && d != maxdim);
+ return encl;
+}
+
+ *** --- End --- unused ***/
+/***********************************************************************/
+
+boolean Find(RSTREE R,
+ typrect rectangle,
+ boolean *found,
+ void *buf,
+ int nbytes)
+
+{
+ refinfo infoadr;
+
+ if (R == NULL) {
+ *found= FALSE;
+ return FALSE;
+ }
+
+ *found= FoundRect(R,1,rectangle,FALSE,&infoadr);
+ if (*found) {
+ memcpy(buf,infoadr,nbytes);
+ }
+ return (*R).RSTDone;
+}
+
+/************************************************************************/
diff --git a/modules/RStarTree/RStarTree.h b/modules/RStarTree/RStarTree.h
new file mode 100644
index 0000000..e9d13d2
--- /dev/null
+++ b/modules/RStarTree/RStarTree.h
@@ -0,0 +1,752 @@
+/* ----- RStarTree.h ----- */
+#ifndef __RStarTree_h
+#define __RStarTree_h
+
+
+
+/** R*-tree
+ ======= **/
+
+
+/** Implementation: Norbert Beckmann
+ Version: R.2.0
+ Date: 6/93 **/
+
+
+/** Praktische Informatik,
+ Universitaet Bremen, D-2800 Bremen 33, Germany **/
+
+
+
+/* ---------------------- operating system version --------------------- */
+/*
+#ifndef SVR4
+# define SVR4
+#endif
+*/
+#include <stddef.h>
+#include <sys/file.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <string.h>
+#include <stdio.h>
+#include <values.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#ifdef SVR4
+# include <fcntl.h>
+# include <sys/fcntl.h>
+#else
+# include <sys/fcntlcom.h>
+# include <sys/fcntl.h>
+#endif
+
+
+/* ----------------------------- constants ----------------------------- */
+
+#define byte unsigned char
+#define boolean int
+#define FALSE 0
+#define TRUE 1
+
+#define int int /**V**/ /* large data sets require a 32 bit int */
+
+#define MaxNameLength 160 /* including less than 10 bytes for a suffix */
+
+#define MaxNumbOfEntriesPerPage 512 /**V**/
+
+#define NumbOfDim 2 /**V**/
+
+
+/* ------------------------------- types ------------------------------- */
+
+typedef int File;
+
+
+typedef float typatomkey; /**V**/
+
+ /* typatomkey may be of any type as far as the standard comparisons
+ apply */
+
+
+typedef struct {
+ typatomkey l, h;
+ } typinterval;
+
+
+typedef typinterval typrect[NumbOfDim];
+
+ /* A typrect is the key type an R*-tree handles. The smallest
+ entity which may be used as a key is an interval,
+ i.e. a typrect[1]. */
+
+
+typedef struct {
+ int contents; /**V**/
+ } typinfo, *refinfo;
+
+ /* A typinfo is a struct which may contain arbitrary information
+ associated with a data record.
+ RESTRICTION: sizeof(typinfo) >= sizeof(int) must hold! */
+
+
+/* ------------------------- private includes -------------------------- */
+
+#include "RSTBase.h"
+
+
+/* ----------------------------- R*-tree ------------------------------- */
+
+typedef rstree *RSTREE; /* R*-tree identifier */
+
+
+/* ------------------------- procedure types --------------------------- */
+
+typedef boolean (*DirQueryProc) (RSTREE /* rst */,
+ typrect /* dirrect */,
+ typrect /* queryrect1 */,
+ typrect /* queryrect2 */);
+
+ /* rst:
+ contains the R*-tree identifier as passed to the procedures
+ RegionQuery, ExistsRegion and RegionCount respectively.
+
+ dirrect:
+ contains a multidimensional directory rectangle.
+
+ queryrect1, queryrect2:
+ contain queryrect1 and queryrect2 as passed to the procedures
+ RegionQuery, ExistsRegion and RegionCount respectively.
+
+ This type is also used in the JoinXX procedures to perform the
+ join. Then the parameters will have a slightly different
+ contents, see the JoinXX procedures. */
+
+
+typedef boolean (*DataQueryProc) (RSTREE /* rst */,
+ typrect /* datarect */,
+ typrect /* queryrect1 */,
+ typrect /* queryrect2 */);
+
+ /* rst:
+ contains the R*-tree identifier as passed to the procedures
+ RegionQuery, ExistsRegion and RegionCount respectively.
+
+ datarect:
+ contains a multidimensional data rectangle.
+
+ queryrect1, queryrect2:
+ contain queryrect1 and queryrect2 as passed to the procedures
+ RegionQuery, ExistsRegion and RegionCount respectively.
+
+ This type is also used in the JoinXX procedures to perform the
+ join. Then the parameters will have a slightly different
+ contents, see the JoinXX procedures. */
+
+
+typedef void (*QueryManageProc) (RSTREE /* rst */,
+ typrect /* rectangle */,
+ refinfo /* info */,
+ void* /* pointer */,
+ boolean* /* modify */,
+ boolean* /* finish */);
+
+ /* rst:
+ contains the R*-tree identifier as passed to the procedure
+ RegionQuery.
+
+ rectangle:
+ contains the multidimensional data rectangle currently found.
+
+ info:
+ points to the concerning information part.
+
+ pointer:
+ is an arbitrary pointer as passed to the procedure RegionQuery.
+ It may be used as a pointer to a buffer structure.
+
+ modify:
+ points to a flag labeling the node to be written back.
+ BEWARE:
+ record modified | modify | result
+ --------------------------------------------------------
+ no | FALSE | record is not modified
+ no | TRUE | undefined
+ yes | FALSE | undefined
+ yes | TRUE | record is modified
+ (See also RegionQuery)
+
+ finish:
+ points to a flag labeling the query to be finished when the
+ procedure is left. */
+
+
+typedef void (*JoinManageProc) (RSTREE /* rst1 */,
+ RSTREE /* rst2 */,
+ typrect /* rectangle1 */,
+ typrect /* rectangle2 */,
+ refinfo /* info1 */ ,
+ refinfo /* info2 */,
+ void* /* pointer1 */,
+ void* /* pointer2 */,
+ boolean* /* finish */);
+
+ /* rst1, rst2:
+ contain the R*-tree identifiers as passed to the JoinXX
+ procedures.
+
+ rectangle1, rectangle2:
+ contain the two rectangles currently found by the join.
+
+ info1, info2:
+ point to the concerning information parts.
+
+ pointer1, pointer2:
+ are arbitrary pointers as passed to the JoinXX procedures.
+ They may be used as pointers to buffer structures.
+
+ finish:
+ points to a flag labeling the join to be finished when the
+ procedure is left. */
+
+
+/* ---------------------- procedure declarations ----------------------- */
+
+/*
+ Almost all procedures return a boolean result.
+ If a procedure returns FALSE an error has occured. The implementation
+ attempts to detect errors before any update operations are performed.
+*/
+
+
+void NoRSTree(RSTREE *rst);
+
+ /* Initializes an R*-tree identifier (at least sets *rst to NULL).
+ Each procedure which requires an R*-tree identifier checks the
+ value of this identifier at its entry.
+ OpenRST for example demands a NULL identifier while CloseRST
+ demands a non NULL identifier. */
+
+
+boolean CreateRST(char *name,
+ int pagesize,
+ boolean unique);
+
+ /* CreateRST creates an R*-tree on secondary memory.
+ To work on it, it has to be opened by the procedure OpenRST.
+
+ name:
+ is the main filename under which the created R*-tree will be
+ stored, additionally a few files named filename.suffix with
+ different suffixes will be created. name is not fixed in the
+ internal parameter table, thus after renaming the files, the
+ R*-tree may be opened under another name.
+
+ pagesize:
+ is the size in bytes, a page (directory or data) will occupy.
+
+ unique:
+ if unique is set TRUE the procedure InsertRecord will not store
+ more than one record with the same rectangle (key) in the
+ R*-tree (rectangles will be real keys).
+ The unique flag may be reset with the procedure SetUnique
+ without further internal tests. */
+
+
+boolean RemoveRST(char *name);
+
+ /* RemoveRST removes all files corresponding to an R*-tree. */
+
+
+boolean OpenRST(RSTREE *rst,
+ char *name);
+
+ /* OpenRST opens the R*-tree named name. */
+
+
+boolean CloseRST(RSTREE *rst);
+
+ /* CloseRST closes the R*-tree referenced by rst. */
+
+
+boolean SetUnique(RSTREE rst,
+ boolean mode);
+
+ /* The unique state, defined in procedure CreateRST may be reset
+ by this procedure (see also CreateRST). The unique flag is set
+ without internal checks (even to TRUE). */
+
+
+boolean InquireRSTDesc(RSTREE rst,
+ char *name,
+ int *numbofdim,
+ int *sizedirentry,
+ int *sizedataentry,
+ int *sizeinfo,
+ int *maxdirfanout,
+ int *maxdatafanout,
+ int *pagesize,
+ int *numbofdirpages,
+ int *numbofdatapages,
+ int pagesperlevel[],
+ int *numbofrecords,
+ int *height,
+ boolean *unique);
+
+ /* InquireRSTDesc provides some useful information about the
+ R*-tree referenced by rst.
+
+ name: see CreateRST.
+
+ numbofdim:
+ contains the number of dimensions of the R*-tree referenced by
+ rst, i.e. the value the constant NumbOfDim was set to when it
+ was created.
+
+ sizedirentry, sizedataentry:
+ contain the size (in bytes) of a directory and data entry
+ respectively.
+
+ sizeinfo:
+ contains the size (in bytes) of an information part.
+
+ maxdirfanout, maxdatafanout:
+ contain the maximum possible number of entries a directory
+ and data node respectively can store.
+
+ pagesize: see CreateRST.
+
+ numbofdirpages, numbofdatapages:
+ total number of directory and data pages respectively in use.
+
+ pagesperlevel:
+ For each level i, beginning at the root, pagesperlevel[i]
+ contains the number of pages in use.
+
+ numbofrecords:
+ total number of data records stored in the R*-tree.
+
+ height:
+ height of the tree, the lowest height is "1" (only the root
+ exists).
+
+ unique: see CreateRST. */
+
+
+boolean InsertRecord(RSTREE rst,
+ typrect rectangle,
+ typinfo *info,
+ boolean *inserted);
+
+ /* InsertRecord inserts a new record in the R*-tree.
+ If the unique flag is set TRUE (see CreateRST) a new record is
+ not inserted if a record with the same rectangle is found. In
+ this case inserted yields FALSE, but the return value is TRUE
+ (if no error occurred).
+
+ rectangle:
+ is the rectangle part of the new record.
+
+ info:
+ is the information part of the new record. */
+
+
+boolean DeleteRecord(RSTREE rst,
+ typrect rectangle,
+ boolean *deleted);
+
+ /* DeleteRecord deletes the first record with the given rectangle
+ it finds. It provides a fast deletion in trees where entries
+ are unique and may be used in trees where entries are not
+ unique, to delete iteratively all entries with the same
+ rectangle as passed. */
+
+
+boolean ExistsRegion(RSTREE rst,
+ typrect queryrect1,
+ typrect queryrect2,
+ DirQueryProc DirQuery,
+ DataQueryProc DataQuery,
+ boolean *recordfound);
+
+ /* ExistsRegion performs a RegionQuery on the R*-tree referenced
+ by rst. It stops after the first record satisfying the query
+ condition is found.
+ See also RegionQuery.
+
+ recordfound:
+ is set to TRUE if a record satisfying the query condition
+ exists, otherwise FALSE. */
+
+
+boolean RegionCount(RSTREE rst,
+ typrect queryrect1,
+ typrect queryrect2,
+ DirQueryProc DirQuery,
+ DataQueryProc DatQuery,
+ int *recordcount);
+
+ /* RegionCount performs a RegionQuery on the R*-tree referenced
+ by rst. It does not return records but only counts the number
+ of records found.
+ See also RegionQuery.
+
+ recordcount:
+ is set to the number of records satisfying the query
+ condition. */
+
+
+boolean RegionQuery(RSTREE rst,
+ typrect queryrect1,
+ typrect queryrect2,
+ DirQueryProc DirQuery,
+ DataQueryProc DatQuery,
+ QueryManageProc Manage,
+ void *pointer);
+
+ /* RegionQuery performs a RegionQuery on the R*-tree referenced
+ by rst. Up to two query rectangles may be passed by queryrect1
+ and queryrect2. Two different procedures have two be provided
+ (DirQuery, DataQuery) which perform the query in the directory
+ and the data level respectively. A third procedure (Manage) must
+ be provided to deal with the records successively found.
+ A query is closed either if it did not find an additional
+ record satisfying the query condition or if the finish flag is
+ set by the procedure Manage.
+ See also DirQueryProc, DataQueryProc, QueryManageProc.
+
+ queryrect1, queryrect2:
+ query rectangles to be compared with directory rectangles and
+ data rectangles respectively.
+
+ DirQuery, DataQuery:
+ Procedure parameters passing comparison procedures of type
+ boolean.
+
+ Manage:
+ Procedure parameter passing a management procedure.
+ Manage is called each time a new data rectangle satisfying the
+ query condition is found.
+ Procedures of type QueryManageProc may provide the following
+ facilities:
+ Inspection of the data records rectangle and info part.
+ Communication to another structure, pointed to by pointer.
+ To modify the info part (the rectangle cannot be modified), and
+ label the node to be written back.
+ To finish the query.
+
+ pointer:
+ Arbitrary pointer passed through to the procedure Manage. */
+
+
+boolean AllQuery(RSTREE rst,
+ QueryManageProc Manage,
+ void *pointer);
+
+ /* AllQuery performs a fast query which returns all records stored
+ in the R*-tree referenced by rst.
+
+ Manage:
+ Procedure parameter passing a management procedure.
+ Manage is called each time a new data rectangle satisfying the
+ query condition is found.
+ The type QueryManageProc provides the following functions:
+ To inspect a data records rectangle and info part.
+ To copy a record to the location pointer points to.
+ To modify the info part (the rectangle cannot be modified),
+ and label the node to be written back.
+ To finish the query.
+
+ pointer:
+ Arbitrary pointer passed through to the procedure Manage.
+
+ Since AllQuery is designed to be fast it does not support the
+ complete counting facility.
+
+ See also RegionQuery. */
+
+
+boolean JoinCountNv(RSTREE rst1,
+ RSTREE rst2,
+ typrect R1queryrect1,
+ typrect R1queryrect2,
+ typrect R2queryrect1,
+ typrect R2queryrect2,
+ DirQueryProc Dir1Query,
+ DataQueryProc Data1Query,
+ DirQueryProc Dir2Query,
+ DataQueryProc Data2Query,
+ DirQueryProc DirJoin,
+ DataQueryProc DataJoin,
+ int *paircount);
+
+ /* JoinCountNv performs a Join on the two R*-trees referenced by
+ rst1 and rst2. It does not return record pairs but only counts
+ the number of record pairs found.
+ See also JoinNv.
+
+ paircount:
+ is set to the number of recordpairs satisfying the join
+ condition. */
+
+
+boolean JoinNv(RSTREE rst1,
+ RSTREE rst2,
+ typrect rst1queryrect1,
+ typrect rst1queryrect2,
+ typrect rst2queryrect1,
+ typrect rst2queryrect2,
+ DirQueryProc Dir1Query,
+ DataQueryProc Data1Query,
+ DirQueryProc Dir2Query,
+ DataQueryProc Data2Query,
+ DirQueryProc DirJoin,
+ DataQueryProc DataJoin,
+ JoinManageProc Manage,
+ void *pointer1,
+ void *pointer2);
+
+ /* The functionality of the join can be considered as follows:
+ On each of the two R*-trees to be joined a query is performed.
+ On the resulting restricted sets of records of the two R*-trees
+ the join is applied depending on the given join condition.
+
+ Join performs a join on the two R*-trees referenced by rst1 and
+ rst2. A join is closed either if it did not find an additional
+ pair of records satisfying the join condition or if the finish
+ flag is set by the procedure Manage.
+ See also DirQueryProc, DataQueryProc, JoinManageProc.
+
+ rst1queryrect1, rst1queryrect2:
+ Used in connection with the pre-query on rst1;
+ query rectangles to be compared with directory and data
+ rectangles respectively of rst1.
+
+ rst2queryrect1, rst2queryrect2:
+ Used in connection with the pre-query on rst2;
+ query rectangles to be compared with directory and data
+ rectangles respectively of rst2.
+
+ Dir1Query, Data1Query:
+ Procedure parameters passing comparison procedures of type
+ boolean.
+ The two procedures have to perform the pre-query on rst1.
+ See also DirQueryProc, DataQueryProc and RegionQuery.
+
+ Dir2Query, Data2Query:
+ Procedure parameters passing comparison procedures of type
+ boolean.
+ The two procedures have to perform the pre-query on rst2.
+ See also DirQueryProc, DataQueryProc and RegionQuery.
+
+ DirJoin, DataJoin:
+ Procedure parameters passing comparison procedures of type
+ boolean.
+ DirJoin has to determine if two directory rectangles, one of
+ rst1 the other of rst2 have to be joined,
+ DataJoin has to determine if two data rectangles, one of
+ rst1 the other of rst2 have to be joined.
+ Here the types DirQueryProc and DataQueryProc are used as
+ follows:
+ DQP(RSTREE rst1,
+ typrect rst1rect,
+ typrect rst2rect,
+ typrect unused);
+ rst1 contains rst1.
+ rst1rect contains a directory or data rectangle respectively
+ of rst1.
+ rst2rect contains a directory or data rectangle respectively
+ of rst2.
+ The last parameter is unused.
+
+ Manage:
+ Procedure parameter passing a management procedure.
+ Manage is called each time a new pair of data rectangles
+ satisfying the join condition is found.
+ Procedures of type JoinManageProc may provide the following
+ facilities:
+ Inspection of the data records' rectangles and info parts.
+ Communication to two other structures, pointed to by pointer1
+ and pointer2.
+ To finish the join.
+
+ pointer1, pointer2:
+ Arbitrary pointers passed through to the procedure Manage. */
+
+
+/*************** ----- Performance Controll Routines ----- ***************/
+
+/* ------ Counts-Switch: */
+
+boolean CountsOn0(RSTREE rst);
+ /* put ON, set 0 */
+
+boolean CountsOn(RSTREE rst);
+ /* put ON */
+
+boolean CountsOff(RSTREE rst);
+ /* put OFF */
+
+ /* the Counts-Switch applies to the variables set by the
+ procedures GetCountRead, GetCountWrite.
+
+ The procedure OpenRST initializes counting:
+ the count variables are set to 0, the count switch is set to
+ OFF. */
+
+
+boolean GetCountRead(RSTREE rst,
+ int *DirVisitCount,
+ int *DataVisitCount,
+ int *DirReadCount,
+ int *DataReadCount);
+
+ /* DirVisitCount is set to the number of directory nodes visited
+ traversing the tree.
+ DataVisitCount is set to the number of data nodes visited
+ traversing the tree.
+ DirReadCount directory nodes and DataReadCount data nodes had
+ actually to be read from secondary memory.
+
+ If the function returns FALSE these variables are set to 0.
+ DirVisitCount, DataVisitCount is counted:
+ for all query, join and update procedures.
+ DirReadCount, DataReadCount is counted:
+ whenever a read occurs. */
+
+
+boolean GetCountWrite(RSTREE rst,
+ int *DirModifyCount,
+ int *DataModifyCount,
+ int *DirWriteCount,
+ int *DataWriteCount);
+
+ /* DirModifyCount is set to the number of directory nodes
+ modified.
+ DataModifyCount is set to the number of data nodes modified.
+ DirWriteCount is set to the number of directory nodes written
+ to secondary memory.
+ DataWriteCount is set to the number of data nodes written to
+ secondary memory.
+ If the function returns FALSE these variables are set to 0.
+ DirModifyCount, DataModifyCount is counted:
+ for all update procedures.
+ DirWriteCount, DataWriteCount is counted:
+ whenever a write occurs. */
+
+
+boolean GetMemory(RSTREE rst,
+ int *numbofdirpages,
+ int *numbofdatapages);
+
+ /* numbofdirpages and numbofdatapages are set to the number of
+ pages in use for the directory and the data level respectively.
+ If the function returns FALSE these variables are set to 0. */
+
+
+boolean GetHeight(RSTREE rst,
+ int *height);
+
+ /* height is set to the height of the tree, the lowest height
+ is "1" (only the root exists).
+ If the function returns FALSE these variables are set to 0. */
+
+
+/*************************************************************************/
+
+/* Layout of a directory and data node respectively (pidgin C)
+ -----------------------------------------------------------
+
+ directory node layout:
+
+ struct {
+ typrect rectangle;
+ int subtree_pointer;
+ } directory_entry;
+
+ struct {
+ int n;
+ directory_entry entries[M];
+ } directory_node;
+
+ The maximum number of entries M varies with different page sizes. The
+ minimum is M = 3.
+ The minimum number of entries m is calculated as max(round(0.4 * M), 2).
+
+ data node layout:
+
+ struct {
+ typrect rectangle;
+ typinfo information_part;
+ } data_entry;
+
+ struct {
+ int n;
+ data_entry entries[M];
+ } data_node;
+
+ The maximum number of entries M varies with different page sizes. The
+ minimum is M = 1.
+ The minimum number of entries m is calculated as max(round(0.4 * M), 1).
+*/
+
+/*************************************************************************/
+
+/* BUGS:
+
+ The implementation does not provide packing, thus depending on the
+ design of the machine and the compiler, and the choice of typatomkey and
+ typinfo nodes may have gaps, i.e. the fanout may be smaller than you
+ expect.
+ Alignment problems, i.e. gaps between the entities stored in the nodes
+ cause warning messages on stdout (with one restriction):
+ The implementation does not know the internal structure of typinfo (it
+ only knows its size). Thus, if typinfo intrinsically contains gaps, this
+ cannot be detected. Information about the actual values of important
+ parameters may be obtained by calling InquireRSTDesc.
+
+ R*-tree identifiers are only checked for NULL and non NULL. Though
+ passing a non NULL invalid identifier is not detected as an error.
+
+ To open an R*-tree twice may damage consistency. But the implementation
+ does not detect this mistake.
+
+ Early detection of memory limitations is not available. If accidentally
+ the file system fills up during an update operation, the tree may be
+ left in an inconsistent state.
+
+ Although (aside from the lacks mentioned above) internal error detection
+ is nearly exhaustive, all you get is a boolean return value.
+
+ Passing the same R*-tree identifier twice to the JoinXX procedures is
+ save. If a join is performed on one and the same R*-tree, a second
+ R*-tree is opened virtually, but the performance control parameters are
+ only available for one of them. Since the join internally does not work
+ symmetrically this information generally is useless.
+
+ If deletions are performed the files holding the directory and data
+ pages will not shrink. Free pages are reoccupied by following
+ insertions. A file reorganization algorithm is not implemented.
+
+ The procedures of type QueryManageProc and JoinManageProc permit
+ unprotected access to parts of the internal data structure of the
+ R*-tree. This avoids copying but is unsafe of course.
+
+ The implementation restricts the informational part of a data record to
+ contain at least an integer sized contents.
+
+*/
+
+
+/*************************************************************************/
+/*************** ----- For Private Test Purpose Only ----- ***************/
+
+boolean Find(RSTREE rst,
+ typrect rectangle,
+ boolean *found,
+ void *buf,
+ int nbytes);
+
+
+#endif /* !__RStarTree_h */
diff --git a/modules/RStarTree/Set.c b/modules/RStarTree/Set.c
new file mode 100644
index 0000000..1e30d61
--- /dev/null
+++ b/modules/RStarTree/Set.c
@@ -0,0 +1,149 @@
+/* ----- Set.c ----- */
+
+
+#include "Set.h"
+
+
+/* declarations */
+
+Set AddLeft(Set set, Set branch);
+void OutputSet(Set set, int *cardcount);
+
+
+/*********************************************************************/
+
+Set EmptySet()
+
+{
+ return NULL;
+}
+
+/*********************************************************************/
+
+Set IncludeSet(Set set, int value)
+
+{
+ Set newson;
+
+ if (set == NULL) {
+ newson= (Set)malloc(sizeof(SetRec));
+ (*newson).value= value;
+ (*newson).lson= NULL;
+ (*newson).rson= NULL;
+ return newson;
+ }
+ else {
+ if (value < (*set).value) {
+ (*set).lson= IncludeSet((*set).lson,value);
+ }
+ else if (value > (*set).value) {
+ (*set).rson= IncludeSet((*set).rson,value);
+ }
+ }
+ return set;
+}
+
+/*********************************************************************/
+
+Set ExcludeSet(Set set, int value)
+
+{
+ Set help;
+
+ if (set != NULL) {
+ if (value == (*set).value) {
+ if ((*set).rson == NULL) {
+ help= (*set).lson;
+ free(set);
+ set= help;
+ }
+ else {
+ (*set).rson= AddLeft((*set).rson,(*set).lson);
+ help= (*set).rson;
+ free(set);
+ set= help;
+ }
+ }
+ else {
+ if (value < (*set).value) {
+ (*set).lson= ExcludeSet((*set).lson,value);
+ }
+ else {
+ (*set).rson= ExcludeSet((*set).rson,value);
+ }
+ }
+ }
+ return set;
+}
+
+/*********************************************************************/
+
+Set AddLeft(Set set, Set branch)
+
+{
+ if ((*set).lson == NULL) {
+ (*set).lson= branch;
+ }
+ else {
+ (*set).lson= AddLeft((*set).lson,branch);
+ }
+ return set;
+}
+
+/*********************************************************************/
+
+int Cardinality(Set set)
+
+{
+ if (set == NULL) {
+ return 0;
+ }
+ else {
+ return 1+Cardinality((*set).lson)+Cardinality((*set).rson);
+ }
+}
+
+/*********************************************************************/
+
+void WriteSet(Set set)
+
+{
+ int cardcount;
+
+ cardcount= 0;
+ OutputSet(set,&cardcount);
+}
+
+/*********************************************************************/
+
+void OutputSet(Set set, int *cardcount)
+
+{
+ if (set != NULL) {
+ OutputSet((*set).lson,cardcount);
+ printf("%5d",(*set).value);
+ (*cardcount)++;
+ if (*cardcount % 10 == 0)
+ printf("\n");
+ OutputSet((*set).rson,cardcount);
+ }
+}
+
+/*********************************************************************/
+
+void WriteTree(Set set)
+
+{
+ if (set == 0) {
+ printf(".");
+ }
+ else {
+ printf("[");
+ WriteTree((*set).lson);
+ printf("%d",(*set).value);
+ WriteTree((*set).rson);
+ printf("]");
+ }
+}
+
+/*********************************************************************/
diff --git a/modules/RStarTree/Set.h b/modules/RStarTree/Set.h
new file mode 100644
index 0000000..903978e
--- /dev/null
+++ b/modules/RStarTree/Set.h
@@ -0,0 +1,36 @@
+/* ----- Set.h ----- */
+#ifndef __Set_h
+#define __Set_h
+
+
+#include <stdio.h>
+#include <math.h>
+#include <malloc.h>
+
+
+/* private includes */
+
+#include "SetDef.h"
+
+
+/* ----- types ----- */
+
+typedef SetRec *Set;
+
+
+/* ----- procedure declarations ----- */
+
+Set EmptySet(void);
+
+Set IncludeSet(Set set, int value);
+
+Set ExcludeSet(Set set, int value);
+
+int Cardinality(Set set);
+
+void WriteSet(Set set);
+
+void WriteTree(Set set);
+
+
+#endif /* !__Set_h */
diff --git a/modules/RStarTree/SetDef.h b/modules/RStarTree/SetDef.h
new file mode 100644
index 0000000..7e485f6
--- /dev/null
+++ b/modules/RStarTree/SetDef.h
@@ -0,0 +1,14 @@
+/* ----- SetDef.h ----- */
+#ifndef __SetDef_h
+#define __SetDef_h
+
+
+typedef struct BinTree {
+ int value;
+ struct BinTree *lson;
+ struct BinTree *rson;
+ } SetRec;
+
+
+#endif /* !__SetDef_h */
+
diff --git a/modules/RStarTree/rdata b/modules/RStarTree/rdata
new file mode 100644
index 0000000..706716a
Binary files /dev/null and b/modules/RStarTree/rdata differ
diff --git a/modules/RStarTree/trst.c b/modules/RStarTree/trst.c
new file mode 100644
index 0000000..7d4997c
--- /dev/null
+++ b/modules/RStarTree/trst.c
@@ -0,0 +1,1346 @@
+/* ----- trst.c ----- */
+
+
+#include "RStarTree.h"
+#include "Set.h"
+
+/* constants */
+
+#define STDMODE 0644
+#define RSTsuffix ".RSF"
+
+
+/* types */
+
+typedef
+ struct {
+ typatomkey center[NumbOfDim], ext[NumbOfDim];
+ } data;
+
+
+/* declarations */
+
+ int GetLOF(File f);
+ void getname(char *name);
+ void DataAndTreeName(void);
+ void QueryName(void);
+ void DisplErr(char *name);
+boolean opendata(void);
+ void closedata(void);
+boolean openquery(void);
+ void closequery(void);
+ void exeCreate(void);
+ void exeRemove(void);
+ void exeOpen(RSTREE *RST);
+ void exeClose(void);
+ void GetTestParameters(File file,
+ char *name);
+ void exeInsert(void);
+ void exeDelete(void);
+ void exeSearch(void);
+ void exeExistsRegion(void);
+ void exeRegionCount(void);
+ void exeRegionQueries(void);
+ void exeJoinCountNv(void);
+ void exeJoinNv(void);
+ void exeJoinCountX(void);
+ void exeJoinX(void);
+ void exeInquire(void);
+ void exeComputeNodeLengths(void);
+ void ShortInstruction(void);
+boolean Equal(RSTREE rst,
+ typrect RSTrect,
+ typrect qrect1,
+ typrect qrect2);
+boolean Intersects(RSTREE rst,
+ typrect RSTrect,
+ typrect qrect1,
+ typrect qrect2);
+boolean Encloses(RSTREE rst,
+ typrect RSTrect,
+ typrect qrect1,
+ typrect qrect2);
+boolean IsContained(RSTREE rst,
+ typrect RSTrect,
+ typrect qrect1,
+ typrect qrect2);
+boolean AlwaysTrue(RSTREE rst,
+ typrect RSTrect,
+ typrect qrect1,
+ typrect qrect2);
+void CompCount0();
+void ManageQuery(RSTREE R,
+ typrect rectangle,
+ refinfo infoptr,
+ void *buf,
+ boolean *modify,
+ boolean *finish);
+void ManageJoin(RSTREE R, RSTREE R2,
+ typrect rectangle, typrect rectangle2,
+ refinfo infoptr, refinfo infoptr2,
+ void *buf, void *buf2,
+ boolean *finish);
+
+
+/* global variables */
+
+char distname[80];
+char quername[80];
+char rfilename[80];
+char ch, dummy;
+
+File datafile, querfile;
+
+int ferr, nbytes, pos;
+int begin, end;
+int constante;
+int height;
+typrect rectangle;
+data datarect;
+boolean notdmsg, donemsg;
+RSTREE R, R2;
+
+int compcount;
+int globnumfound;
+int globpaircount;
+
+int i;
+
+
+/***********************************************************************/
+
+void main(int argc, char *argv[])
+
+{
+ char mainchoose, choose;
+ boolean WorkMenu;
+ NoRSTree(&R);
+ NoRSTree(&R2);
+ ShortInstruction();
+ do {
+ printf("\n");
+ printf("%20s, %20s,\n","(forced)Create = \"c\"","Remove = \"R\"");
+ printf("%20s, %20s,\n","Open = \"o\"","Close = \".\"");
+ printf("%30s,\n","Inquire Description = \"I\"");
+ printf("%30s,\n","Node lenghts computation = \"`\"");
+ printf("%30s,\n","leave this menu = \"-\"");
+ printf("%30s.\n","quit = \"q\"");
+ printf("Input: ");
+ do {
+ mainchoose= getchar();
+ } while ((mainchoose != 'c') && (mainchoose != 'R') &&
+ (mainchoose != 'o') && (mainchoose != '.') &&
+ (mainchoose != 'I') &&
+ (mainchoose != '`') &&
+ (mainchoose != '-') &&
+ (mainchoose != 'q'));
+ dummy= getchar();
+ WorkMenu= mainchoose != '`';
+ if (mainchoose != 'q') {
+ if (mainchoose == '-') {
+ }
+ else if (mainchoose == 'c') {
+ if (R != NULL) {
+ exeClose();
+ }
+ DataAndTreeName();
+ exeCreate();
+ exeOpen(&R);
+ }
+ else if (mainchoose == 'R') {
+ if (R != NULL) {
+ exeClose();
+ }
+ exeRemove();
+ }
+ else if (mainchoose == 'o') {
+ if (R != NULL) {
+ exeClose();
+ }
+ DataAndTreeName();
+ exeOpen(&R);
+ printf("\n ===========================================\n\n");
+ printf("Prepare for Join? (y/n) ");
+ do {
+ ch= getchar();
+ } while ((ch != 'y') && (ch != 'n'));
+ dummy= getchar();
+ if (ch == 'y') {
+ printf("R2=R? (y/n) ");
+ do {
+ ch= getchar();
+ } while ((ch != 'y') && (ch != 'n'));
+ dummy= getchar();
+ if (ch == 'y') {
+ R2= R;
+ }
+ else {
+ DataAndTreeName();
+ exeOpen(&R2);
+ }
+ }
+ }
+ else if (mainchoose == '.') {
+ exeClose();
+ }
+ else if (mainchoose == 'I') {
+ exeInquire();
+ }
+ else if (mainchoose == '`') {
+ exeComputeNodeLengths();
+ }
+ if (WorkMenu) {
+ printf("\n");
+ printf("%20s, %20s,\n","Insert = \"i\"","Delete = \"d\"");
+ printf("%30s,\n","Search = \"s\"");
+ printf("%30s,\n","ExistsRegion = \"e\"");
+ printf("%20s, %20s,\n","RegionCount = \"r\"","RegionQueries = \"[\"");
+ printf("%20s, %20s,\n","JoinCountNv = \"j\"","JoinNv = \"=\"");
+ printf("%20s, %20s,\n","JoinCountX = \"J\"","JoinX = \"#\"");
+ printf("%30s.\n","leave this menu = \"-\"");
+ printf("Input: ");
+ do {
+ choose= getchar();
+ } while ((choose != 'i') && (choose != 'd') &&
+ (choose != 's') &&
+ (choose != 'e') &&
+ (choose != 'r') && (choose != '[') &&
+ (choose != 'j') && (choose != '=') &&
+ (choose != 'J') && (choose != '#') &&
+ (choose != '-'));
+ dummy= getchar();
+ if (choose == '-') {
+ }
+ else if (choose == 'i') {
+ if (opendata()) {
+ exeInsert();
+ closedata();
+ }
+ }
+ else if (choose == 'd') {
+ if (opendata()) {
+ exeDelete();
+ closedata();
+ }
+ }
+ else if (choose == 's') {
+ if (opendata()) {
+ exeSearch();
+ closedata();
+ }
+ }
+ else if (choose == 'e') {
+ QueryName();
+ if (openquery()) {
+ exeExistsRegion();
+ closequery();
+ }
+ }
+ else if (choose == 'r') {
+ QueryName();
+ if (openquery()) {
+ exeRegionCount();
+ closequery();
+ }
+ }
+ else if (choose == '[') {
+ QueryName();
+ if (openquery()) {
+ exeRegionQueries();
+ closequery();
+ }
+ }
+ else if (choose == 'j') {
+ exeJoinCountNv();
+ }
+ else if (choose == '=') {
+ exeJoinNv();
+ }
+ else if (choose == 'J') {
+ exeJoinCountX();
+ }
+ else if (choose == '#') {
+ exeJoinX();
+ }
+ }
+ }
+ else {
+ exeClose();
+ }
+ } while (mainchoose != 'q');
+}
+
+/***********************************************************************/
+
+void ShortInstruction()
+
+{
+ printf("\n --- TestRStarTree ---\n");
+ printf("This testprogram principally works on one \"main\" tree only.\n");
+ printf("Exception: JoinCount.\n");
+ printf("Joins work on the main tree and a secondary tree.\n");
+ printf("Joins are normally initialized by \"Open\".\n");
+ printf("If an error occurs the corresponding procedure does nothing\n");
+ printf("but issuing a message, though actions may be retried.\n");
+ printf("\"Create\", \"Open\" and \"Remove\" automatically perform\n");
+ printf("\"Close\" on the main tree (if it is not NULL)\n");
+ printf("before performing the concerning action.\n");
+ printf("\"quit\" will also try to close the main tree.\n");
+ printf("The secondary tree is automatically closed after the join.\n");
+}
+
+/***********************************************************************/
+
+int GetLOF(File f) /* GetLengthOfFile */
+
+{
+ struct stat *refstatus;
+
+ refstatus= (struct stat *)malloc(sizeof(struct stat));
+ ferr= fstat(f,refstatus);
+ if (ferr == -1) {
+ return 0;
+ }
+ else {
+ return (*refstatus).st_size;
+ }
+}
+
+/***********************************************************************/
+
+void getname(char *name)
+
+{
+ printf("\nData File (without suffix): ");
+ scanf("%s",name);
+}
+
+/***********************************************************************/
+
+void DataAndTreeName()
+
+{
+ getname(distname);
+ strcpy(rfilename,distname);
+ strcat(rfilename,RSTsuffix);
+}
+
+/***********************************************************************/
+
+void QueryName()
+
+{
+ getname(quername);
+}
+
+/***********************************************************************/
+
+void DisplErr(char *name)
+
+{
+ char message[80];
+
+ printf("\n--------------------\n");
+ printf("%s %d\n","FileError:",errno);
+ strcpy(message,"Error handling file:\n");
+ strcat(message,name);
+ perror(message);
+ printf("--------------------\n");
+ errno= 0;
+}
+
+/***********************************************************************/
+
+boolean opendata()
+
+{
+ printf("Open Data File:\n");
+ printf("%s\n",distname);
+ datafile= open(distname,O_RDONLY,STDMODE);
+ if (datafile == -1) {
+ DisplErr(distname);
+ return FALSE;
+ }
+ else {
+ GetTestParameters(datafile,distname);
+ return TRUE;
+ }
+}
+
+/***********************************************************************/
+
+void closedata()
+
+{
+ printf("Close Data File:\n");
+ printf("%s\n",distname);
+ ferr= close(datafile);
+ if (ferr == -1) {
+ DisplErr(distname);
+ }
+}
+
+/***********************************************************************/
+
+boolean openquery()
+
+{
+ printf("Open Query File:\n");
+ printf("%s\n",quername);
+ querfile= open(quername,O_RDONLY,STDMODE);
+ if (querfile == -1) {
+ DisplErr(quername);
+ return FALSE;
+ }
+ else {
+ GetTestParameters(querfile,quername);
+ return TRUE;
+ }
+}
+
+/***********************************************************************/
+
+void closequery()
+
+{
+ printf("Close Query File:\n");
+ printf("%s\n",quername);
+ ferr= close(querfile);
+ if (ferr == -1) {
+ DisplErr(quername);
+ }
+}
+
+/***********************************************************************/
+
+void exeCreate()
+
+{
+ int pagelen;
+ boolean unique;
+
+ printf("Length of a page: ");
+ scanf("%d",&pagelen);
+ printf("Unique?, (y/n): ");
+ do {
+ ch= getchar();
+ } while ((ch != 'y') && (ch != 'n'));
+ dummy= getchar();
+ unique= ch == 'y';
+ printf("%s%s%s","\nRemoveRST(",rfilename,"):\n");
+ if (RemoveRST(rfilename)) {
+ printf("Done\n");
+ }
+ printf("%s%s,%d,%d%s","CreateRST(",rfilename,pagelen,unique,"):\n");
+ if (CreateRST(rfilename,pagelen,unique)) {
+ printf("Done\n");
+ }
+ else {
+ printf("FAILURE\n");
+ }
+}
+
+/***********************************************************************/
+
+void exeRemove()
+
+{
+ printf("%s%s%s","\nRemoveRST(",rfilename,"):\n");
+ if (RemoveRST(rfilename)) {
+ printf("Done\n");
+ }
+ else {
+ printf("FAILURE\n");
+ }
+}
+
+/***********************************************************************/
+
+void exeOpen(RSTREE *r)
+
+{
+ printf("%s%s%s","OpenRST(",rfilename,"):\n");
+ if (OpenRST(r,rfilename)) {
+ printf("Done\n");
+ }
+ else {
+ printf("FAILURE\n");
+ }
+}
+
+/***********************************************************************/
+
+void exeClose()
+
+{
+ printf("%s%s%s","CloseRST(",rfilename,"):\n");
+ if (CloseRST(&R)) {
+ printf("Done\n");
+ }
+ else {
+ printf("FAILURE\n");
+ }
+}
+
+/***********************************************************************/
+
+void GetTestParameters(File file, char *name)
+
+{
+ printf("\nExecution from/up to entrynumber\n");
+ printf("(\"0 0\": Execution on all entries of the file.)\n");
+ printf("Input: ");
+ scanf("%d",&begin); scanf("%d",&end);
+ if (begin != 0) { begin--; }
+ if (end == 0) {
+ end= GetLOF(file) / sizeof(data);
+ }
+ pos= lseek(file,begin*sizeof(data),L_SET);
+ if (pos == -1) {
+ DisplErr(name);
+ }
+ printf("Message if done =\"d\",");
+ printf(" not done =\"n\", message off =\"o\"\n");
+ printf("Input: ");
+ do {
+ ch= getchar();
+ } while ((ch != 'd') && (ch != 'n') && (ch != 'o'));
+ dummy= getchar();
+ notdmsg= ch == 'n';
+ donemsg= ch == 'd';
+ printf("Echo resp. performance-measurement(Insert) at ");
+ printf("entrynumber MOD how much?\n");
+ printf("(\"0\": none, not \"0\": mandatory at the end)\n");
+ printf("Input: ");
+ scanf("%d",&constante);
+ dummy= getchar(); /* scanf leaves trailing white characters */
+ if (constante == 0) {constante= MAXINT;}
+}
+
+/***********************************************************************/
+
+void exeInsert()
+
+{
+ int xdirv, xdatav, xdirr, xdatar,
+ xdirm, xdatam, xdirw, xdataw;
+ boolean inserted, success;
+ int height;
+ int d;
+ typinfo info;
+
+ CountsOn0(R);
+ i= begin;
+ do {
+ nbytes= read(datafile,&datarect,sizeof(data));
+ if (nbytes <= 0) {
+ DisplErr(distname);
+ }
+ i++;
+ for (d= 0; d < NumbOfDim; d++) {
+ rectangle[d].l= datarect.center[d] - datarect.ext[d];
+ rectangle[d].h= datarect.center[d] + datarect.ext[d];
+ }
+ /* Begin set info.contents to record number */
+ /**/
+ info.contents= i;
+ /**/
+ /* End set info.contents to record number */
+ success= InsertRecord(R,rectangle,&info,&inserted);
+ if (notdmsg) {
+ if (! inserted) {
+ printf("%s%d\n"," NOT INSERTED: ",i);
+ }
+ }
+ else if (donemsg) {
+ if (inserted) {
+ printf("%s%d\n"," INSERTED: ",i);
+ }
+ }
+ if ((i % constante == 0) || (i == end)) {
+ printf("%5d%s",i,":: ");
+ GetHeight(R,&height);
+ printf("%s%3d\n","height:",height);
+ }
+ if (! success) {printf("FAILURE\n"); return;}
+ } while (i != end);
+ GetCountRead(R,&xdirv,&xdatav,&xdirr,&xdatar);
+ printf("%s%d\n","dirv: ",xdirv);
+ printf("%s%d\n","datav: ",xdatav);
+ printf("%s%d\n","dirr: ",xdirr);
+ printf("%s%d\n","datar: ",xdatar);
+ GetCountWrite(R,&xdirm,&xdatam,&xdirw,&xdataw);
+ printf("%s%d\n","dirm: ",xdirm);
+ printf("%s%d\n","datam: ",xdatam);
+ printf("%s%d\n","dirw: ",xdirw);
+ printf("%s%d\n","dataw: ",xdataw);
+}
+
+/***********************************************************************/
+
+void exeDelete()
+
+{
+ int xdirv, xdatav, xdirr, xdatar,
+ xdirm, xdatam, xdirw, xdataw;
+ boolean found, success;
+ int d;
+
+ CountsOn0(R);
+ i= begin;
+ do {
+ nbytes= read(datafile,&datarect,sizeof(data));
+ if (nbytes <= 0) {
+ DisplErr(distname);
+ }
+ i++;
+ for (d= 0; d < NumbOfDim; d++) {
+ rectangle[d].l= datarect.center[d] - datarect.ext[d];
+ rectangle[d].h= datarect.center[d] + datarect.ext[d];
+ }
+ success= DeleteRecord(R,rectangle,&found);
+ if (notdmsg) {
+ if (! found) {
+ printf("%s%d\n"," NOT FOUND: ",i);
+ }
+ }
+ else if (donemsg) {
+ if (found) {
+ printf("%s%d\n"," FOUND: ",i);
+ }
+ }
+ if ((i % constante == 0) || (i == end)) {
+ printf("%5d%s",i,":: ");
+ GetHeight(R,&height);
+ printf("%s%3d\n","height:",height);
+ }
+ if (! success) {printf("FAILURE\n"); return;}
+ } while (i != end);
+ GetCountRead(R,&xdirv,&xdatav,&xdirr,&xdatar);
+ printf("%s%d\n","dirv: ",xdirv);
+ printf("%s%d\n","datav: ",xdatav);
+ printf("%s%d\n","dirr: ",xdirr);
+ printf("%s%d\n","datar: ",xdatar);
+ GetCountWrite(R,&xdirm,&xdatam,&xdirw,&xdataw);
+ printf("%s%d\n","dirm: ",xdirm);
+ printf("%s%d\n","datam: ",xdatam);
+ printf("%s%d\n","dirw: ",xdirw);
+ printf("%s%d\n","dataw: ",xdataw);
+}
+
+/***********************************************************************/
+
+void exeSearch()
+
+{
+ int xdirv, xdatav, xdirr, xdatar;
+ int allfound;
+ boolean found, success;
+ typrect unused;
+ typinfo check;
+ int d;
+
+ allfound= 0;
+ CountsOn0(R);
+
+ i= begin;
+ do {
+ nbytes= read(datafile,&datarect,sizeof(data));
+ if (nbytes <= 0) {
+ DisplErr(distname);
+ }
+ i++;
+ for (d= 0; d < NumbOfDim; d++) {
+ rectangle[d].l= datarect.center[d] - datarect.ext[d];
+ rectangle[d].h= datarect.center[d] + datarect.ext[d];
+ }
+ success= Find(R,rectangle,&found,&check,sizeof(check));
+ if (found) {
+ allfound++;
+ }
+ if (notdmsg) {
+ if (! found) {
+ printf("%s%d\n"," NOT FOUND: ",i);
+ }
+ }
+ else if (donemsg) {
+ if (found) {
+ printf("%s%d\n"," FOUND: ",i);
+ }
+ }
+ if (found) {
+ /* Begin check correctness of an integer infopart */
+ /**/
+ if (check.contents != i) {
+ printf("%d%s%d\n",i,
+ ": ODD INFOPART: ",
+ check.contents);
+ }
+ /**/
+ /* End check correctness of an integer infopart */
+ }
+ if ((i % constante == 0) || (i == end)) {
+ printf("%6d%s",i,":: ");
+ GetHeight(R,&height);
+ printf("%s%3d","height:",height);
+ printf("%s%6d\n"," found:",allfound);
+ }
+ if (! success) {printf("FAILURE\n"); return;}
+ } while (i != end);
+ printf("\n");
+ GetCountRead(R,&xdirv,&xdatav,&xdirr,&xdatar);
+ printf("%s%d\n","dirv: ",xdirv);
+ printf("%s%d\n","datav: ",xdatav);
+ printf("%s%d\n","dirr: ",xdirr);
+ printf("%s%d\n","datar: ",xdatar);
+}
+
+/***********************************************************************/
+
+void exeExistsRegion()
+
+{
+ int xdirv, xdatav, xdirr, xdatar;
+ int allfound;
+ boolean found, success;
+ typrect unused;
+ int d;
+
+ allfound= 0;
+ CountsOn0(R);
+ CompCount0();
+
+ i= begin;
+ do {
+ nbytes= read(querfile,&datarect,sizeof(data));
+ if (nbytes <= 0) {
+ DisplErr(quername);
+ }
+ i++;
+ for (d= 0; d < NumbOfDim; d++) {
+ rectangle[d].l= datarect.center[d] - datarect.ext[d];
+ rectangle[d].h= datarect.center[d] + datarect.ext[d];
+ }
+ success= ExistsRegion(R,rectangle,unused,Encloses,Equal,&found);
+ if (found) {
+ allfound++;
+ }
+ if (notdmsg) {
+ if (! found) {
+ printf("%s%d\n"," NOT FOUND: ",i);
+ }
+ }
+ else if (donemsg) {
+ if (found) {
+ printf("%s%d\n"," FOUND: ",i);
+ }
+ }
+ if ((i % constante == 0) || (i == end)) {
+ printf("%5d%s",i,":: ");
+ GetHeight(R,&height);
+ printf("%s%3d","height:",height);
+ printf("%s%6d\n"," found:",allfound);
+ }
+ if (! success) {printf("FAILURE\n"); return;}
+ } while (i != end);
+ printf("\n");
+ printf("%s%d\n","comp: ",compcount);
+ printf("\n");
+ GetCountRead(R,&xdirv,&xdatav,&xdirr,&xdatar);
+ printf("%s%d\n","dirv: ",xdirv);
+ printf("%s%d\n","datav: ",xdatav);
+ printf("%s%d\n","dirr: ",xdirr);
+ printf("%s%d\n","datar: ",xdatar);
+}
+
+/***********************************************************************/
+
+void exeRegionCount()
+
+{
+ int xdirv, xdatav, xdirr, xdatar;
+ int numfound, allfound, emptyquery;
+ typrect unused;
+ boolean success;
+ int d;
+
+ allfound= 0;
+ emptyquery= 0;
+ CountsOn0(R);
+ CompCount0();
+
+ i= begin;
+ do {
+ nbytes= read(querfile,&datarect,sizeof(data));
+ if (nbytes <= 0) {
+ DisplErr(quername);
+ }
+ i++;
+ for (d= 0; d < NumbOfDim; d++) {
+ rectangle[d].l= datarect.center[d] - datarect.ext[d];
+ rectangle[d].h= datarect.center[d] + datarect.ext[d];
+ }
+ success= RegionCount(R,rectangle,unused,Intersects,Intersects,&numfound);
+ if (numfound == 0) {
+ emptyquery++;
+ }
+ else {
+ allfound= allfound+numfound;
+ }
+ if (notdmsg) {
+ if (numfound == 0) {
+ printf("%s%d\n"," NOT FOUND: ",i);
+ }
+ }
+ else if (donemsg) {
+ if (numfound != 0) {
+ printf("%s%d\n"," FOUND: ",i);
+ }
+ }
+ if ((i % constante == 0) || (i == end)) {
+ printf("%5d%s",i,":: ");
+ GetHeight(R,&height);
+ printf("%s%3d","height:",height);
+ printf("%s%6d\n"," found:",allfound);
+ }
+ if (! success) {printf("FAILURE\n"); return;}
+ } while (i != end);
+ printf("\n");
+ printf("%s%d\n","comp: ",compcount);
+ printf("\n");
+ GetCountRead(R,&xdirv,&xdatav,&xdirr,&xdatar);
+ printf("%s%d\n","empty queries: ",emptyquery);
+ printf("%s%d\n","rectangles found: ",allfound);
+ printf("\n");
+ printf("%s%d\n","dirv: ",xdirv);
+ printf("%s%d\n","datav: ",xdatav);
+ printf("%s%d\n","dirr: ",xdirr);
+ printf("%s%d\n","datar: ",xdatar);
+}
+
+/***********************************************************************/
+
+void exeRegionQueries()
+
+{
+ int xdirv, xdatav, xdirr, xdatar;
+ int allfound, emptyquery;
+ typrect unused;
+ boolean success;
+ Set buffer;
+ int d;
+
+ allfound= 0;
+ emptyquery= 0;
+ CountsOn0(R);
+ CompCount0();
+
+ buffer= EmptySet();
+
+ i= begin;
+ do {
+ nbytes= read(querfile,&datarect,sizeof(data));
+ if (nbytes <= 0) {
+ DisplErr(quername);
+ }
+ i++;
+ for (d= 0; d < NumbOfDim; d++) {
+ rectangle[d].l= datarect.center[d] - datarect.ext[d];
+ rectangle[d].h= datarect.center[d] + datarect.ext[d];
+ }
+ globnumfound= 0;
+ success= RegionQuery(R,
+ rectangle,
+ unused,
+ Intersects,
+ Intersects,
+ ManageQuery,
+ &buffer);
+ if (globnumfound == 0) {
+ emptyquery++;
+ }
+ else {
+ allfound= allfound+globnumfound;
+ }
+ if (notdmsg) {
+ if (globnumfound == 0) {
+ printf("%s%d\n"," NOT FOUND: ",i);
+ }
+ }
+ else if (donemsg) {
+ if (globnumfound != 0) {
+ printf("%s%d\n"," FOUND: ",i);
+ }
+ }
+ if ((i % constante == 0) || (i == end)) {
+ printf("%5d%s",i,":: ");
+ GetHeight(R,&height);
+ printf("%s%3d","height:",height);
+ printf("%s%6d\n"," found:",allfound);
+ }
+ if (! success) {printf("FAILURE\n"); return;}
+ } while (i != end);
+ printf("\n");
+ printf("%s%d\n","comp: ",compcount);
+ printf("\n");
+ GetCountRead(R,&xdirv,&xdatav,&xdirr,&xdatar);
+ printf("%s%d\n","empty queries: ",emptyquery);
+ printf("%s%d\n","rectangles found: ",allfound);
+ printf("\n");
+ printf("%s%d\n","dirv: ",xdirv);
+ printf("%s%d\n","datav: ",xdatav);
+ printf("%s%d\n","dirr: ",xdirr);
+ printf("%s%d\n","datar: ",xdatar);
+
+ WriteSet(buffer);
+ printf("\n");
+ WriteTree(buffer);
+ printf("\n");
+}
+
+/***********************************************************************/
+
+void ManageQuery(RSTREE R,
+ typrect rectangle,
+ refinfo infoptr,
+ void *buf,
+ boolean *modify,
+ boolean *finish)
+
+{
+ Set *set;
+ char dummy;
+ int d;
+
+ /***** ----- count ----- *****/
+
+ globnumfound++;
+
+ /***** ----- prompt the user ----- *****/
+
+ printf(">"); dummy= getchar();
+
+ /***** ----- print rectangle ----- *****/
+
+ for (d= 0; d < NumbOfDim; d++) {
+ printf("%25.17f",rectangle[d].l);
+ printf("%25.17f",rectangle[d].h);
+ printf("\n");
+ }
+
+ /***** ----- print info part ----- *****/
+
+ printf("%15d\n",(*infoptr).contents);
+
+ /***** ----- get info part ----- *****/
+
+ set= buf;
+ *set= IncludeSet(*set,(*infoptr).contents);
+
+ /***** ----- modify record ----- *****/
+
+ (*infoptr).contents= 42;
+ *modify= TRUE;
+
+ /***** ----- finish after finding one ----- *****/
+
+ *finish= TRUE;
+
+}
+
+/***********************************************************************/
+
+void exeJoinCountNv()
+
+{
+ int xdirv, xdatav, xdirr, xdatar;
+ int paircount;
+ typrect unused;
+ boolean success;
+
+ CountsOn0(R);
+ CountsOn0(R2);
+ CompCount0();
+
+ globpaircount= 0;
+ success= JoinCountNv(R,R2,
+ unused,unused,unused,unused,
+ AlwaysTrue,AlwaysTrue,AlwaysTrue,AlwaysTrue,
+ Intersects,Intersects,
+ &paircount);
+ if (! success) {printf("FAILURE\n"); return;}
+ printf("\n%s%d\n\n","Number of Pairs found: ",paircount);
+ printf("\n");
+ printf("%s%d\n","comp: ",compcount);
+ printf("\n");
+ GetCountRead(R,&xdirv,&xdatav,&xdirr,&xdatar);
+ printf("%s%d\n","dirv: ",xdirv);
+ printf("%s%d\n","datav: ",xdatav);
+ printf("%s%d\n","dirr: ",xdirr);
+ printf("%s%d\n","datar: ",xdatar);
+ GetCountRead(R2,&xdirv,&xdatav,&xdirr,&xdatar);
+ printf("%s%d\n","dirv: ",xdirv);
+ printf("%s%d\n","datav: ",xdatav);
+ printf("%s%d\n","dirr: ",xdirr);
+ printf("%s%d\n","datar: ",xdatar);
+
+ if (R2 != R) {
+ printf("Close R2:\n");
+ if (CloseRST(&R2)) {
+ printf("Done\n");
+ }
+ else {
+ printf("FAILURE\n");
+ }
+ }
+}
+
+/***********************************************************************/
+
+void exeJoinNv()
+
+{
+ int xdirv, xdatav, xdirr, xdatar;
+ typrect unused;
+ boolean success;
+ void *buffer, *buffer2;
+
+ CountsOn0(R);
+ CountsOn0(R2);
+ CompCount0();
+
+ buffer= malloc(sizeof(typinfo));
+ buffer2= malloc(sizeof(typinfo));
+
+ success= JoinNv(R,R2,
+ unused,unused,unused,unused,
+ AlwaysTrue,AlwaysTrue,AlwaysTrue,AlwaysTrue,
+ Intersects,Intersects,
+ ManageJoin,buffer,buffer2);
+ if (! success) {printf("FAILURE\n"); return;}
+ printf("\n%s%d\n\n","Number of Pairs found: ",globpaircount);
+ printf("\n");
+ printf("%s%d\n","comp: ",compcount);
+ printf("\n");
+ GetCountRead(R,&xdirv,&xdatav,&xdirr,&xdatar);
+ printf("%s%d\n","dirv: ",xdirv);
+ printf("%s%d\n","datav: ",xdatav);
+ printf("%s%d\n","dirr: ",xdirr);
+ printf("%s%d\n","datar: ",xdatar);
+ GetCountRead(R2,&xdirv,&xdatav,&xdirr,&xdatar);
+ printf("%s%d\n","dirv: ",xdirv);
+ printf("%s%d\n","datav: ",xdatav);
+ printf("%s%d\n","dirr: ",xdirr);
+ printf("%s%d\n","datar: ",xdatar);
+
+ if (R2 != R) {
+ printf("Close R2:\n");
+ if (CloseRST(&R2)) {
+ printf("Done\n");
+ }
+ else {
+ printf("FAILURE\n");
+ }
+ }
+}
+
+/***********************************************************************/
+
+void ManageJoin(RSTREE R, RSTREE R2,
+ typrect rectangle, typrect rectangle2,
+ refinfo infoptr, refinfo infoptr2,
+ void *buf, void *buf2,
+ boolean *finish)
+
+{
+# define MAXPAIRS 42
+
+ char dummy;
+ int d;
+
+ /***** ----- count pairs ----- *****/
+
+ globpaircount++;
+
+ /***** ----- prompt the user ----- *****/
+
+ printf(">"); dummy= getchar();
+
+ /***** ----- print rectangle of R ----- *****/
+
+ for (d= 0; d < NumbOfDim; d++) {
+ printf("%25.17f",rectangle[d].l);
+ printf("%25.17f",rectangle[d].h);
+ printf("\n");
+ }
+
+ /***** ----- print info part of R ----- *****/
+
+ printf("%15d\n",(*infoptr).contents);
+
+ /***** ----- print rectangle of R2 ----- *****/
+
+ for (d= 0; d < NumbOfDim; d++) {
+ printf("%25.17f",rectangle2[d].l);
+ printf("%25.17f",rectangle2[d].h);
+ printf("\n");
+ }
+
+ /***** ----- print info part of R2 ----- *****/
+
+ printf("%15d\n",(*infoptr2).contents);
+
+ /***** ----- finish after finding MAXPAIRS pairs ----- *****/
+ /*
+ if (globpaircount == MAXPAIRS) {
+ *finish= TRUE;
+ }
+ */
+
+# undef MAXPAIRS
+}
+
+/***********************************************************************/
+
+void exeJoinCountX()
+
+{
+ printf("\nJoinCountX NOT IMPLEMENTED\n");
+}
+
+/***********************************************************************/
+
+void exeJoinX()
+
+{
+ printf("\nJoinX NOT IMPLEMENTED\n");
+}
+
+/***********************************************************************/
+
+void exeInquire()
+
+{
+ char name[80];
+ int NumberOfDimensions,
+ SIZEdirentry, SIZEdataentry, SIZEinfo,
+ dirM, dataM,
+ PageLength,
+ NumbDirPages, NumbDataPages;
+ int PagesPerLevel[50];
+ int NumbRecords,
+ height;
+ boolean unique;
+ double spaceutil[50];
+ double sumspaceutil;
+ boolean success;
+ int i;
+
+ success= InquireRSTDesc(R,
+ name,
+ &NumberOfDimensions,
+ &PageLength,
+ &SIZEdirentry,
+ &SIZEdataentry,
+ &SIZEinfo,
+ &dirM,
+ &dataM,
+ &NumbDirPages,
+ &NumbDataPages,
+ PagesPerLevel,
+ &NumbRecords,
+ &height,
+ &unique);
+ if (! success) {printf("FAILURE\n"); return;}
+ printf("%20s%s\n","name: ",name);
+ printf("%20s%d\n","NumberOfDimensions: ",NumberOfDimensions);
+ printf("%20s%d\n","PageLength: ",PageLength);
+ printf("%20s%d\n","SIZEdirentry: ",SIZEdirentry);
+ printf("%20s%d\n","SIZEdataentry: ",SIZEdataentry);
+ printf("%20s%d\n","SIZEinfo: ",SIZEinfo);
+ printf("%20s%d\n","dirM: ",dirM);
+ printf("%20s%d\n","dataM: ",dataM);
+ printf("%20s%d\n","NumbDirPages: ",NumbDirPages);
+ printf("%20s%d\n","NumbDataPages: ",NumbDataPages);
+ printf("%20s%d\n","NumbPages: ",NumbDirPages+NumbDataPages);
+ printf("%20s%d\n","NumbRecords: ",NumbRecords);
+ printf("%20s%d\n","height: ",height);
+ printf("%20s%d\n","unique: ",unique);
+ printf("pages per level:\n");
+ for(i= 0; i < height; i++) {
+ printf("%7d",PagesPerLevel[i]);
+ }
+ printf("\n");
+ for (i= 0; i < height-1; i++) {
+ spaceutil[i]= (double)PagesPerLevel[i+1] /
+ (double)(PagesPerLevel[i]*dirM);
+ }
+ spaceutil[height-1]= (double)(NumbRecords) /
+ (double)(PagesPerLevel[height-1]*dataM);
+ printf("space utilization:\n");
+ for(i= 0; i < height; i++) {
+ printf("%.2e ",spaceutil[i]);
+ }
+ printf("\n");
+ sumspaceutil= 0.0;
+ for (i= 1; i < height-1; i++) {
+ sumspaceutil= sumspaceutil+spaceutil[i];
+ }
+ printf("%s%.2e\n"," avg spc util dir (without root): ",
+ sumspaceutil / (double)(height-2));
+ sumspaceutil= sumspaceutil+spaceutil[height-1];
+ printf("%s%.2e\n","avg spc util overall (without root): ",
+ sumspaceutil / (double)(height-1));
+}
+
+/***********************************************************************/
+
+void exeComputeNodeLengths()
+
+{
+ int infolen;
+ int entryqty, bytesqty;
+ int keylen, direntrylen, dataentrylen;
+ int dirlen, datalen;
+ int dirnumb, datanumb;
+ char again;
+ do {
+ printf("Length of the info part: ");
+ scanf("%d",&infolen);
+ printf("Number of entries: ");
+ scanf("%d",&entryqty);
+ printf("Computing from sizeof(data),\n");
+ keylen= sizeof(data);
+ direntrylen= keylen+sizeof(int);
+ dataentrylen= keylen+infolen;
+ dirlen= sizeof(int)+entryqty*direntrylen;
+ datalen= sizeof(int)+entryqty*dataentrylen;
+ printf("directory page length is ");
+ printf("%5d\n",dirlen);
+ printf(" data page length is ");
+ printf("%5d\n",datalen);
+ printf(" Number of bytes: ");
+ scanf("%d",&bytesqty);
+ printf("Computing from sizeof(data),\n");
+ dirnumb= (bytesqty-sizeof(int)) / direntrylen;
+ datanumb= (bytesqty-sizeof(int)) / dataentrylen;
+ printf("number of directory page entries is ");
+ printf("%5d\n",dirnumb);
+ printf(" number of data page entries is ");
+ printf("%5d\n",datanumb);
+ printf("\nagain?, (y/n): ");
+ do {
+ again= getchar();
+ } while ((again != 'y') && (again != 'n'));
+ dummy= getchar();
+ } while (again == 'y');
+}
+
+/***********************************************************************/
+
+boolean Equal(RSTREE R,
+ typrect RSTrect,
+ typrect queryrect,
+ typrect unused)
+
+{
+ int maxdim= NumbOfDim -1;
+ boolean eql;
+ int d;
+
+ compcount++;
+ d= -1;
+ do {
+ d++;
+ eql= RSTrect[d].l == queryrect[d].l &&
+ RSTrect[d].h == queryrect[d].h;
+ } while (eql && d != maxdim);
+ return eql;
+}
+
+/***********************************************************************/
+
+boolean Intersects(RSTREE R,
+ typrect RSTrect,
+ typrect queryrect,
+ typrect unused)
+
+{
+ int maxdim= NumbOfDim -1;
+ boolean inter;
+ int d;
+
+ compcount++;
+ d= -1;
+ do {
+ d++;
+ inter= RSTrect[d].l <= queryrect[d].h &&
+ RSTrect[d].h >= queryrect[d].l;
+ } while (inter && d != maxdim);
+ return inter;
+}
+
+/***********************************************************************/
+
+boolean Encloses(RSTREE R,
+ typrect RSTrect,
+ typrect queryrect,
+ typrect unused)
+
+{
+ int maxdim= NumbOfDim -1;
+ boolean encl;
+ int d;
+
+ compcount++;
+ d= -1;
+ do {
+ d++;
+ encl= RSTrect[d].l <= queryrect[d].l &&
+ RSTrect[d].h >= queryrect[d].h;
+ } while (encl && d != maxdim);
+ return encl;
+}
+
+/***********************************************************************/
+
+boolean IsContained(RSTREE R,
+ typrect RSTrect,
+ typrect queryrect,
+ typrect unused)
+
+{
+ int maxdim= NumbOfDim -1;
+ boolean iscont;
+ int d;
+
+ compcount++;
+ d= -1;
+ do {
+ d++;
+ iscont= RSTrect[d].l >= queryrect[d].l &&
+ RSTrect[d].h <= queryrect[d].h;
+ } while (iscont && d != maxdim);
+ return iscont;
+}
+
+/***********************************************************************/
+
+boolean AlwaysTrue(RSTREE R,
+ typrect unused1,
+ typrect unused2,
+ typrect unused3)
+
+{
+ return TRUE;
+}
+
+/***********************************************************************/
+
+void CompCount0()
+
+{
+ compcount= 0;
+}
+
+/***********************************************************************/
--
Gerris Flow Solver
More information about the debian-science-commits
mailing list