[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