[GRASS-SVN] r42281 - in grass/trunk: include include/Make include/vect lib lib/btree2 lib/segment lib/vector/Vlib lib/vector/diglib raster/r.watershed/ram

svn_grass at osgeo.org svn_grass at osgeo.org
Tue May 18 05:42:15 EDT 2010


Author: mmetz
Date: 2010-05-18 05:42:14 -0400 (Tue, 18 May 2010)
New Revision: 42281

Added:
   grass/trunk/include/rbtree.h
   grass/trunk/lib/btree2/
   grass/trunk/lib/btree2/Makefile
   grass/trunk/lib/btree2/README
   grass/trunk/lib/btree2/rbtree.c
Removed:
   grass/trunk/include/vect/rbtree.h
   grass/trunk/lib/segment/rbtree.c
   grass/trunk/lib/segment/rbtree.h
   grass/trunk/lib/vector/diglib/rbtree.c
   grass/trunk/raster/r.watershed/ram/rbtree.c
   grass/trunk/raster/r.watershed/ram/rbtree.h
Modified:
   grass/trunk/include/Make/Grass.make
   grass/trunk/include/vect/dig_structs.h
   grass/trunk/lib/Makefile
   grass/trunk/lib/segment/Makefile
   grass/trunk/lib/segment/pagein.c
   grass/trunk/lib/segment/release.c
   grass/trunk/lib/segment/setup.c
   grass/trunk/lib/vector/Vlib/break_polygons.c
   grass/trunk/lib/vector/Vlib/snap.c
   grass/trunk/raster/r.watershed/ram/Makefile
   grass/trunk/raster/r.watershed/ram/do_flatarea.c
Log:
add balanced search tree to lib, update Vlib and segment

Modified: grass/trunk/include/Make/Grass.make
===================================================================
--- grass/trunk/include/Make/Grass.make	2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/include/Make/Grass.make	2010-05-18 09:42:14 UTC (rev 42281)
@@ -112,6 +112,7 @@
 	BASIC:basic \
 	BITMAP:bitmap \
 	BTREE:btree \
+	BTREE2:btree2 \
 	CAIRODRIVER:cairodriver \
 	CDHC:cdhc \
 	CCMATH:ccmath \
@@ -213,13 +214,13 @@
 RLIDEPS          = $(RASTERLIB) $(GISLIB) $(MATHLIB)
 ROWIODEPS        = $(GISLIB)
 RTREEDEPS        = $(MATHLIB)
-SEGMENTDEPS      = $(GISLIB)
+SEGMENTDEPS      = $(GISLIB) $(BTREE2LIB)
 #SIMDEPS          = $(VECTLIB) $(BITMAPLIB) $(GMATHLIB) $(LINKMLIB) $(SITESLIB) $(DBMILIB) $(GISLIB)
 SITESDEPS        = $(VECTORLIB) $(DBMILIB) $(GISLIB) $(DATETIMELIB)
 STATSDEPS        = $(RASTERLIB) $(GISLIB) $(MATHLIB)	# NB: doesn't use libgis directly
 SYMBDEPS         = $(GISLIB) $(MATHLIB)
 TRANSDEPS        = $(MATHLIB)
-VECTORDEPS       = $(DBMILIB) $(GRAPHLIB) $(DIG2LIB) $(LINKMLIB) $(RTREELIB) $(GISLIB) $(GEOSLIBS) $(GDALLIBS) $(MATHLIB)
+VECTORDEPS       = $(DBMILIB) $(GRAPHLIB) $(DIG2LIB) $(LINKMLIB) $(RTREELIB) $(GISLIB) $(GEOSLIBS) $(GDALLIBS) $(MATHLIB) $(BTREE2LIB)
 VEDITDEPS        = $(VECTORLIB) $(DBMILIB) $(GISLIB) $(MATHLIB)
 NETADEPS         = $(VECTORDEP) $(DBMIDEP) $(GISDEP)
 
@@ -276,7 +277,7 @@
 
 DBMILIB     = $(DBMICLIENTLIB) $(DBMIBASELIB) $(DBMIEXTRALIB)
 GEOMLIB     = $(OPTRILIB) $(SOSLIB) $(LIALIB) $(BASICLIB)
-VECTLIB     = $(VECTORLIB) $(DIG2LIB) $(GRAPHLIB) $(RTREELIB) $(LINKMLIB) $(DBMILIB)
+VECTLIB     = $(VECTORLIB) $(DIG2LIB) $(GRAPHLIB) $(RTREELIB) $(LINKMLIB) $(DBMILIB) $(BTREE2LIB)
 
 DBMIDEP     = $(DBMICLIENTDEP) $(DBMIBASEDEP)
 GEOMDEP     = $(OPTRIDEP) $(SOSDEP) $(LIADEP) $(BASICDEP)

Added: grass/trunk/include/rbtree.h
===================================================================
--- grass/trunk/include/rbtree.h	                        (rev 0)
+++ grass/trunk/include/rbtree.h	2010-05-18 09:42:14 UTC (rev 42281)
@@ -0,0 +1,112 @@
+/*************************************************************
+ *                          USAGE                            *
+ *************************************************************
+ *
+ * NOTE: duplicates are not supported
+ *
+ * custom compare function
+ * extern int my_compare_fn(const void *, const void *);
+ * int my_compare_fn(const void *a, const void *b) {
+ *   if ((mydatastruct *) a < (mydatastruct *) b)
+ *     return -1;
+ *   else if ((mydatastruct *) a > (mydatastruct *) b)
+ *     return 1;
+ *   else if ((mydatastruct *) a == (mydatastruct *) b)
+ *     return 0;
+ * }
+ * 
+ * create and initialize tree:
+ * struct RB_TREE *mytree = rbtree_create(my_compare_fn, item_size);
+ *
+ * insert items to tree:
+ * struct mydatastruct data = <some data>;
+ * if (rbtree_insert(mytree, &data) == 0)
+ * 	 G_warning("could not insert data");
+ *
+ * find item in tree:
+ * struct mydatastruct data = <some data>;
+ * if (rbtree_find(mytree, &data) == 0)
+ * 	 G_message("data not found");
+ *
+ * delete item from tree:
+ * struct mydatastruct data = <some data>;
+ * if (rbtree_remove(mytree, &data) == 0)
+ * 	  G_warning("could not find data in tree");
+ *
+ * traverse tree (get all items in tree in ascending order):
+ * struct RB_TRAV trav;
+ * rbtree_init_trav(&trav, tree);
+ * while ((data = rbtree_traverse(&trav)) != NULL) {
+ *   if (my_compare_fn(data, threshold_data) == 0) break;
+ * 	   <do something with data>;
+ *  }
+ *
+ * get a selection of items: all data > data1 and < data2
+ * start in tree where data is last smaller or first larger compared to data1
+ * struct RB_TRAV trav;
+ * rbtree_init_trav(&trav, tree);
+ * data = rbtree_traverse_start(&trav, &data1);
+ * 	 <do something with data>;
+ * while ((data = rbtree_traverse(&trav)) != NULL) {
+ *	 if (data > data2) break;
+ *   <do something with data>;
+ * }
+ *
+ * destroy tree:
+ * rbtree_destroy(mytree);
+ *
+ * debug the whole tree with
+ * rbtree_debug(mytree, mytree->root);
+ * 
+ *************************************************************/
+
+#include <stddef.h>
+
+/* maximum RB Tree height */
+#define RBTREE_MAX_HEIGHT 64        /* should be more than enough */
+
+/* routine to compare data items
+ * return -1 if rb_a < rb_b
+ * return  0 if rb_a == rb_b
+ * return  1 if rb_a > rb_b
+ */
+typedef int rb_compare_fn(const void *rb_a, const void *rb_b);
+
+struct RB_NODE
+{
+    unsigned char red;              /* 0 = black, 1 = red */
+    void *data;                     /* any kind of data */
+    struct RB_NODE *link[2];        /* link to children: link[0] for smaller, link[1] for larger */
+};
+ 
+struct RB_TREE
+{
+    struct RB_NODE *root;           /* root node */
+    size_t datasize;                /* item size */
+    size_t count;                   /* number of items in tree. */
+    rb_compare_fn *rb_compare;      /* function to compare data */
+};
+
+struct RB_TRAV
+{
+    struct RB_TREE *tree;           /* tree being traversed */
+    struct RB_NODE *curr_node;      /* current node */
+    struct RB_NODE *up[RBTREE_MAX_HEIGHT];  /* stack of parent nodes */
+    int top;                        /* index for stack */
+    int first;                      /* little helper flag */
+};
+
+/* tree functions */
+struct RB_TREE *rbtree_create(rb_compare_fn *, size_t);
+void rbtree_destroy(struct RB_TREE *);
+int rbtree_insert(struct RB_TREE *, void *);
+int rbtree_remove(struct RB_TREE *, const void *);
+void *rbtree_find(struct RB_TREE *, const void *);
+
+/* tree traversal functions */
+int rbtree_init_trav(struct RB_TRAV *, struct RB_TREE *);
+void* rbtree_traverse(struct RB_TRAV *);
+void *rbtree_traverse_start(struct RB_TRAV *, const void *);
+
+/* debug tree from given node downwards */
+int rbtree_debug(struct RB_TREE *, struct RB_NODE *);

Modified: grass/trunk/include/vect/dig_structs.h
===================================================================
--- grass/trunk/include/vect/dig_structs.h	2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/include/vect/dig_structs.h	2010-05-18 09:42:14 UTC (rev 42281)
@@ -20,7 +20,7 @@
 
 #include <grass/dgl.h>
 #include <grass/shapefil.h>
-#include <grass/btree.h>
+#include <grass/rbtree.h>
 #include <grass/rtree.h>
 
 #ifdef HAVE_OGR
@@ -31,7 +31,7 @@
 
   3.10 changes plus_t to  ints.
   This assumes that any reasonable machine will use 4 bytes to
-  store an int. The mapdev code is not guaranteed to work if
+  store an int. The diglib code is not guaranteed to work if
   plus_t is changed to a type that is larger than an int.
 */
 typedef int plus_t;

Deleted: grass/trunk/include/vect/rbtree.h
===================================================================
--- grass/trunk/include/vect/rbtree.h	2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/include/vect/rbtree.h	2010-05-18 09:42:14 UTC (rev 42281)
@@ -1,112 +0,0 @@
-/*************************************************************
- *                          USAGE                            *
- *************************************************************
- *
- * NOTE: duplicates are not supported
- *
- * custom compare function
- * extern int my_compare_fn(const void *, const void *);
- * int my_compare_fn(const void *a, const void *b) {
- *   if ((mydatastruct *) a < (mydatastruct *) b)
- *     return -1;
- *   else if ((mydatastruct *) a > (mydatastruct *) b)
- *     return 1;
- *   else if ((mydatastruct *) a == (mydatastruct *) b)
- *     return 0;
- * }
- * 
- * create and initialize tree:
- * struct RB_TREE *mytree = rbtree_create(my_compare_fn, item_size);
- *
- * insert items to tree:
- * struct mydatastruct data = <some data>;
- * if (rbtree_insert(mytree, &data) == 0)
- * 	 G_warning("could not insert data");
- *
- * find item in tree:
- * struct mydatastruct data = <some data>;
- * if (rbtree_find(mytree, &data) == 0)
- * 	 G_message("data not found");
- *
- * delete item from tree:
- * struct mydatastruct data = <some data>;
- * if (rbtree_remove(mytree, &data) == 0)
- * 	  G_warning("could not find data in tree");
- *
- * traverse tree (get all items in tree in ascending order):
- * struct RB_TRAV trav;
- * rbtree_init_trav(&trav, tree);
- * while ((data = rbtree_traverse(&trav)) != NULL) {
- *   if (my_compare_fn(data, threshold_data) == 0) break;
- * 	   <do something with data>;
- *  }
- *
- * get a selection of items: all data > data1 and < data2
- * start in tree where data is last smaller or first larger compared to data1
- * struct RB_TRAV trav;
- * rbtree_init_trav(&trav, tree);
- * data = rbtree_traverse_start(&trav, &data1);
- * 	 <do something with data>;
- * while ((data = rbtree_traverse(&trav)) != NULL) {
- *	 if (data > data2) break;
- *   <do something with data>;
- * }
- *
- * destroy tree:
- * rbtree_destroy(mytree);
- *
- * debug the whole tree with
- * rbtree_debug(mytree, mytree->root);
- * 
- *************************************************************/
-
-#include <stddef.h>
-
-/* maximum RB Tree height */
-#define RBTREE_MAX_HEIGHT 64        /* should be more than enough */
-
-/* routine to compare data items
- * return -1 if rb_a < rb_b
- * return  0 if rb_a == rb_b
- * return  1 if rb_a > rb_b
- */
-typedef int rb_compare_fn(const void *rb_a, const void *rb_b);
-
-struct RB_NODE
-{
-    unsigned char red;              /* 0 = black, 1 = red */
-    void *data;                     /* any kind of data */
-    struct RB_NODE *link[2];        /* link to children: link[0] for smaller, link[1] for larger */
-};
- 
-struct RB_TREE
-{
-    struct RB_NODE *root;           /* root node */
-    size_t datasize;                /* item size */
-    size_t count;                   /* number of items in tree. */
-    rb_compare_fn *rb_compare;      /* function to compare data */
-};
-
-struct RB_TRAV
-{
-    struct RB_TREE *tree;           /* tree being traversed */
-    struct RB_NODE *curr_node;      /* current node */
-    struct RB_NODE *up[RBTREE_MAX_HEIGHT];  /* stack of parent nodes */
-    int top;                        /* index for stack */
-    int first;                      /* little helper flag */
-};
-
-/* tree functions */
-struct RB_TREE *rbtree_create(rb_compare_fn *, size_t);
-void rbtree_destroy(struct RB_TREE *);
-int rbtree_insert(struct RB_TREE *, void *);
-int rbtree_remove(struct RB_TREE *, const void *);
-void *rbtree_find(struct RB_TREE *, const void *);
-
-/* tree traversal functions */
-int rbtree_init_trav(struct RB_TRAV *, struct RB_TREE *);
-void* rbtree_traverse(struct RB_TRAV *);
-void *rbtree_traverse_start(struct RB_TRAV *, const void *);
-
-/* debug tree from given node downwards */
-int rbtree_debug(struct RB_TREE *, struct RB_NODE *);

Modified: grass/trunk/lib/Makefile
===================================================================
--- grass/trunk/lib/Makefile	2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/lib/Makefile	2010-05-18 09:42:14 UTC (rev 42281)
@@ -17,6 +17,7 @@
 	cairodriver \
 	bitmap \
 	btree \
+	btree2 \
 	display \
 	db \
 	fonts \

Added: grass/trunk/lib/btree2/Makefile
===================================================================
--- grass/trunk/lib/btree2/Makefile	                        (rev 0)
+++ grass/trunk/lib/btree2/Makefile	2010-05-18 09:42:14 UTC (rev 42281)
@@ -0,0 +1,11 @@
+MODULE_TOPDIR = ../..
+
+include $(MODULE_TOPDIR)/include/Make/Vars.make
+
+MOD_OBJS := $(filter-out try.o,$(AUTO_OBJS))
+
+LIB = BTREE2
+
+include $(MODULE_TOPDIR)/include/Make/Lib.make
+
+default: lib

Added: grass/trunk/lib/btree2/README
===================================================================
--- grass/trunk/lib/btree2/README	                        (rev 0)
+++ grass/trunk/lib/btree2/README	2010-05-18 09:42:14 UTC (rev 42281)
@@ -0,0 +1,75 @@
+
+#include <grass/rbtree.h>
+
+and link to BTREE2LIB
+
+to make use of this binary balanced (Red-Black) search tree
+
+NOTE: duplicates are not supported
+
+
+USAGE
+=====
+
+see also grass/rbtree.h for instructions on how to use it
+  
+/* custom compare function */
+extern int my_compare_fn(const void *, const void *);
+int my_compare_fn(const void *a, const void *b)
+{
+    if ((mydatastruct *) a < (mydatastruct *) b)
+        return -1;
+    else if ((mydatastruct *) a > (mydatastruct *) b)
+        return 1;
+    else if ((mydatastruct *) a == (mydatastruct *) b)
+        return 0;
+}
+
+/* create and initialize tree: */
+struct RB_TREE *mytree = rbtree_create(my_compare_fn, item_size);
+
+/* insert items to tree: */
+    struct mydatastruct data = <some data>;
+    
+    if (rbtree_insert(mytree, &data) == 0)
+        G_warning("could not insert data");
+
+/* find item in tree: */
+    struct mydatastruct data = <some data>;
+    
+    if (rbtree_find(mytree, &data) == 0)
+        G_message("data not found");
+
+/* delete item from tree: */
+    struct mydatastruct data = <some data>;
+    
+    if (rbtree_remove(mytree, &data) == 0)
+        G_warning("could not find data in tree");
+
+/* traverse tree (get all items in tree in ascending order): */
+    struct RB_TRAV trav;
+    
+    rbtree_init_trav(&trav, tree);
+    while ((data = rbtree_traverse(&trav)) != NULL) {
+        if (my_compare_fn(data, threshold_data) == 0) break;
+  	    /* do something with data */
+    }
+
+/* get a selection of items: all data > data1 and < data2
+ * start in tree where data is last smaller or first larger compared to data1 */
+    struct RB_TRAV trav;
+    
+    rbtree_init_trav(&trav, tree);
+    data = rbtree_traverse_start(&trav, &data1);
+  	    /* do something with data */
+    while ((data = rbtree_traverse(&trav)) != NULL) {
+       if (data > data2) break;
+  	    /* do something with data */
+    }
+ 
+/* destroy tree: */
+    rbtree_destroy(mytree);
+ 
+/* debug the whole tree with */
+    rbtree_debug(mytree, mytree->root);
+    

Added: grass/trunk/lib/btree2/rbtree.c
===================================================================
--- grass/trunk/lib/btree2/rbtree.c	                        (rev 0)
+++ grass/trunk/lib/btree2/rbtree.c	2010-05-18 09:42:14 UTC (rev 42281)
@@ -0,0 +1,534 @@
+/*!
+ * \file rbtree.c
+ *
+ * \brief binary search tree 
+ *
+ * Generic balanced binary search tree (Red Black Tree) implementation
+ *
+ * (C) 2009 by the GRASS Development Team
+ *
+ * This program is free software under the GNU General Public License
+ * (>=v2).  Read the file COPYING that comes with GRASS for details.
+ *
+ * \author Original author Julienne Walker 2003, 2008
+ *         GRASS implementation Markus Metz, 2009
+ */
+
+/* balanced binary search tree implementation
+ * 
+ * this one is a Red Black Tree, no parent pointers, no threads
+ * The core code comes from Julienne Walker's tutorials on binary search trees
+ * original license: public domain
+ * http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_rbtree.aspx
+ * some ideas come from libavl (GPL >= 2)
+ *
+ * Red Black Trees are used to maintain a data structure with
+ * search, insertion and deletion in O(log N) time
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <grass/gis.h>
+#include <grass/glocale.h>
+#include <grass/rbtree.h>
+
+/* internal functions */
+void rbtree_destroy2(struct RB_NODE *);
+struct RB_NODE *rbtree_single(struct RB_NODE *, int);
+struct RB_NODE *rbtree_double(struct RB_NODE *, int);
+void *rbtree_first(struct RB_TRAV *);
+void *rbtree_next(struct RB_TRAV *);
+struct RB_NODE *rbtree_make_node(size_t, void *);
+int is_red(struct RB_NODE *);
+
+
+/* create new tree and initialize
+ * returns pointer to new tree, NULL for memory allocation error
+ */
+struct RB_TREE *rbtree_create(rb_compare_fn *compare, size_t rb_datasize)
+{
+    struct RB_TREE *tree = G_malloc(sizeof(*tree));
+
+    if (tree == NULL) {
+	G_warning("RB tree: Out of memory!");
+	return NULL;
+    }
+
+    assert(compare);
+
+    tree->datasize = rb_datasize;
+    tree->rb_compare = compare;
+    tree->count = 0;
+    tree->root = NULL;
+
+    return tree;
+}
+
+/* add an item to a tree
+ * non-recursive top-down insertion
+ * the algorithm does not allow duplicates and also does not warn about a duplicate
+ * returns 1 on success, 0 on failure
+ */
+int rbtree_insert(struct RB_TREE *tree, void *data)
+{
+    assert(tree && data);
+
+    if (tree->root == NULL) {
+	/* create a new root node for tree */
+	tree->root = rbtree_make_node(tree->datasize, data);
+	if (tree->root == NULL)
+	    return 0;
+    }
+    else {
+	struct RB_NODE head = { 0 };	/* False tree root */
+	struct RB_NODE *g, *t;	/* Grandparent & parent */
+	struct RB_NODE *p, *q;	/* Iterator & parent */
+	int dir = 0, last = 0;
+
+	/* Set up helpers */
+	t = &head;
+	g = p = NULL;
+	q = t->link[1] = tree->root;
+
+	/* Search down the tree */
+	for (;;) {
+	    if (q == NULL) {
+		/* Insert new node at the bottom */
+		p->link[dir] = q = rbtree_make_node(tree->datasize, data);
+		if (q == NULL)
+		    return 0;
+	    }
+	    else if (is_red(q->link[0]) && is_red(q->link[1])) {
+		/* Color flip */
+		q->red = 1;
+		q->link[0]->red = 0;
+		q->link[1]->red = 0;
+	    }
+
+	    /* Fix red violation */
+	    if (is_red(q) && is_red(p)) {
+		int dir2 = t->link[1] == g;
+
+		if (q == p->link[last])
+		    t->link[dir2] = rbtree_single(g, !last);
+		else
+		    t->link[dir2] = rbtree_double(g, !last);
+	    }
+
+	    last = dir;
+	    dir = tree->rb_compare(q->data, data);
+
+	    /* Stop if found. This check also disallows duplicates in the tree */
+	    if (dir == 0)
+		break;
+
+	    dir = dir < 0;
+
+	    /* Move the helpers down */
+	    if (g != NULL)
+		t = g;
+
+	    g = p, p = q;
+	    q = q->link[dir];
+	}
+
+	/* Update root */
+	tree->root = head.link[1];
+    }
+
+    /* Make root black */
+    tree->root->red = 0;
+
+    tree->count++;
+
+    return 1;
+}
+
+/* remove an item from a tree that matches given data
+ * non-recursive top-down removal
+ * returns 1 on successful removal
+ * returns 0 if data item was not found
+ */
+int rbtree_remove(struct RB_TREE *tree, const void *data)
+{
+    struct RB_NODE head = { 0 };	/* False tree root */
+    struct RB_NODE *q, *p, *g;	/* Helpers */
+    struct RB_NODE *f = NULL;	/* Found item */
+    int dir = 1, removed = 0;
+
+    assert(tree && data);
+
+    if (tree->root == NULL) {
+	return 0;		/* empty tree, nothing to remove */
+    }
+
+    /* Set up helpers */
+    q = &head;
+    g = p = NULL;
+    q->link[1] = tree->root;
+
+    /* Search and push a red down */
+    while (q->link[dir] != NULL) {
+	int last = dir;
+
+	/* Update helpers */
+	g = p, p = q;
+	q = q->link[dir];
+	dir = tree->rb_compare(q->data, data);
+
+	/* Save found node */
+	if (dir == 0)
+	    f = q;
+
+	dir = dir < 0;
+
+	/* Push the red node down */
+	if (!is_red(q) && !is_red(q->link[dir])) {
+	    if (is_red(q->link[!dir]))
+		p = p->link[last] = rbtree_single(q, dir);
+	    else if (!is_red(q->link[!dir])) {
+		struct RB_NODE *s = p->link[!last];
+
+		if (s != NULL) {
+		    if (!is_red(s->link[!last]) && !is_red(s->link[last])) {
+			/* Color flip */
+			p->red = 0;
+			s->red = 1;
+			q->red = 1;
+		    }
+		    else {
+			int dir2 = g->link[1] == p;
+
+			if (is_red(s->link[last]))
+			    g->link[dir2] = rbtree_double(p, last);
+			else if (is_red(s->link[!last]))
+			    g->link[dir2] = rbtree_single(p, last);
+
+			/* Ensure correct coloring */
+			q->red = g->link[dir2]->red = 1;
+			g->link[dir2]->link[0]->red = 0;
+			g->link[dir2]->link[1]->red = 0;
+		    }
+		}
+	    }
+	}
+    }
+
+    /* Replace and remove if found */
+    if (f != NULL) {
+	G_free(f->data);
+	f->data = q->data;
+	p->link[p->link[1] == q] = q->link[q->link[0] == NULL];
+	G_free(q);
+	tree->count--;
+	removed = 1;
+    }
+    else
+	G_debug(2, "RB tree: data not found in search tree");
+
+    /* Update root and make it black */
+    tree->root = head.link[1];
+    if (tree->root != NULL)
+	tree->root->red = 0;
+
+    return removed;
+}
+
+/* find data item in tree
+ * returns pointer to data item if found else NULL
+ */
+void *rbtree_find(struct RB_TREE *tree, const void *data)
+{
+    struct RB_NODE *curr_node = tree->root;
+    int cmp;
+
+    assert(tree && data);
+
+    while (curr_node != NULL) {
+	cmp = tree->rb_compare(curr_node->data, data);
+	if (cmp == 0)
+	    return curr_node->data;	/* found */
+
+	curr_node = curr_node->link[cmp < 0];
+    }
+    return NULL;
+}
+
+/* initialize tree traversal
+ * (re-)sets trav structure
+ * returns 0
+ */
+int rbtree_init_trav(struct RB_TRAV *trav, struct RB_TREE *tree)
+{
+    assert(trav && tree);
+
+    trav->tree = tree;
+    trav->curr_node = tree->root;
+    trav->first = 1;
+    trav->top = 0;
+
+    return 0;
+}
+
+/* traverse the tree in ascending order
+ * useful to get all items in the tree non-recursively
+ * struct RB_TRAV *trav needs to be initialized first
+ * returns pointer to data, NULL when finished
+ */
+void *rbtree_traverse(struct RB_TRAV *trav)
+{
+    assert(trav);
+
+    if (trav->curr_node == NULL) {
+	if (trav->first)
+	    G_debug(1, "RB tree: empty tree");
+	else
+	    G_debug(1, "RB tree: finished traversing");
+
+	return NULL;
+    }
+
+    if (!trav->first)
+	return rbtree_next(trav);
+    else {
+	trav->first = 0;
+	return rbtree_first(trav);
+    }
+}
+
+/* find start point to traverse the tree in ascending order
+ * useful to get a selection of items in the tree
+ * magnitudes faster than traversing the whole tree
+ * may return first item that's smaller or first item that's larger
+ * struct RB_TRAV *trav needs to be initialized first
+ * returns pointer to data, NULL when finished
+ */
+void *rbtree_traverse_start(struct RB_TRAV *trav, const void *data)
+{
+    int dir = 0;
+
+    assert(trav && data);
+
+    if (trav->curr_node == NULL) {
+	if (trav->first)
+	    G_warning("RB tree: empty tree");
+	else
+	    G_warning("RB tree: finished traversing");
+
+	return NULL;
+    }
+
+    if (!trav->first)
+	return rbtree_next(trav);
+
+    /* else first time, get start node */
+
+    trav->first = 0;
+    trav->top = 0;
+
+    while (trav->curr_node != NULL) {
+	dir = trav->tree->rb_compare(trav->curr_node->data, data);
+	/* exact match, great! */
+	if (dir == 0)
+	    return trav->curr_node->data;
+	else {
+	    dir = dir < 0;
+	    /* end of branch, also reached if
+	     * smallest item is larger than search template or
+	     * largest item is smaller than search template */
+	    if (trav->curr_node->link[dir] == NULL)
+		return trav->curr_node->data;
+
+	    trav->up[trav->top++] = trav->curr_node;
+	    trav->curr_node = trav->curr_node->link[dir];
+	}
+    }
+
+    return NULL;		/* should not happen */
+}
+
+/* two functions needed to fully traverse the tree: initialize and continue
+ * useful to get all items in the tree non-recursively
+ * this one here uses a stack
+ * parent pointers or threads would also be possible
+ * but these would need to be added to RB_NODE
+ * -> more memory needed for standard operations
+ */
+
+/* start traversing the tree
+ * returns pointer to smallest data item
+ */
+void *rbtree_first(struct RB_TRAV *trav)
+{
+    /* get smallest item */
+    while (trav->curr_node->link[0] != NULL) {
+	trav->up[trav->top++] = trav->curr_node;
+	trav->curr_node = trav->curr_node->link[0];
+    }
+
+    return trav->curr_node->data;	/* return smallest item */
+}
+
+/* continue traversing the tree in ascending order
+ * returns pointer to data item, NULL when finished
+ */
+void *rbtree_next(struct RB_TRAV *trav)
+{
+    if (trav->curr_node->link[1] != NULL) {
+	/* something on the right side: larger item */
+	trav->up[trav->top++] = trav->curr_node;
+	trav->curr_node = trav->curr_node->link[1];
+
+	/* go down, find smallest item in this branch */
+	while (trav->curr_node->link[0] != NULL) {
+	    trav->up[trav->top++] = trav->curr_node;
+	    trav->curr_node = trav->curr_node->link[0];
+	}
+    }
+    else {
+	/* at smallest item in this branch, go back up */
+	struct RB_NODE *last;
+
+	do {
+	    if (trav->top == 0) {
+		trav->curr_node = NULL;
+		break;
+	    }
+	    last = trav->curr_node;
+	    trav->curr_node = trav->up[--trav->top];
+	} while (last == trav->curr_node->link[1]);
+    }
+
+    if (trav->curr_node != NULL) {
+	return trav->curr_node->data;
+    }
+    else
+	return NULL;		/* finished traversing */
+}
+
+/* destroy the tree */
+void rbtree_destroy(struct RB_TREE *tree)
+{
+    rbtree_destroy2(tree->root);
+    G_free(tree);
+}
+
+void rbtree_destroy2(struct RB_NODE *root)
+{
+    if (root != NULL) {
+	rbtree_destroy2(root->link[0]);
+	rbtree_destroy2(root->link[1]);
+	G_free(root->data);
+	G_free(root);
+    }
+}
+
+/* used for debugging: check for errors in tree structure */
+int rbtree_debug(struct RB_TREE *tree, struct RB_NODE *root)
+{
+    int lh, rh;
+
+    if (root == NULL)
+	return 1;
+    else {
+	struct RB_NODE *ln = root->link[0];
+	struct RB_NODE *rn = root->link[1];
+	int lcmp = 0, rcmp = 0;
+
+	/* Consecutive red links */
+	if (is_red(root)) {
+	    if (is_red(ln) || is_red(rn)) {
+		G_warning("Red Black Tree debugging: Red violation");
+		return 0;
+	    }
+	}
+
+	lh = rbtree_debug(tree, ln);
+	rh = rbtree_debug(tree, rn);
+
+	if (ln) {
+	    lcmp = tree->rb_compare(ln->data, root->data);
+	}
+
+	if (rn) {
+	    rcmp = tree->rb_compare(rn->data, root->data);
+	}
+
+	/* Invalid binary search tree:
+	 * left node >= parent or right node <= parent */
+	if ((ln != NULL && lcmp > -1)
+	    || (rn != NULL && rcmp < 1)) {
+	    G_warning("Red Black Tree debugging: Binary tree violation");
+	    return 0;
+	}
+
+	/* Black height mismatch */
+	if (lh != 0 && rh != 0 && lh != rh) {
+	    G_warning("Red Black Tree debugging: Black violation");
+	    return 0;
+	}
+
+	/* Only count black links */
+	if (lh != 0 && rh != 0)
+	    return is_red(root) ? lh : lh + 1;
+	else
+	    return 0;
+    }
+}
+
+/*******************************************************
+ *                                                     *
+ *  internal functions for Red Black Tree maintenance  *
+ *                                                     *
+ *******************************************************/
+
+/* add a new node to the tree */
+struct RB_NODE *rbtree_make_node(size_t datasize, void *data)
+{
+    struct RB_NODE *new_node = G_malloc(sizeof(*new_node));
+
+    if (new_node == NULL)
+	G_fatal_error("RB Search Tree: Out of memory!");
+
+    new_node->data = G_malloc(datasize);
+    if (new_node->data == NULL)
+	G_fatal_error("RB Search Tree: Out of memory!");
+
+    memcpy(new_node->data, data, datasize);
+    new_node->red = 1;		/* 1 is red, 0 is black */
+    new_node->link[0] = NULL;
+    new_node->link[1] = NULL;
+
+    return new_node;
+}
+
+/* check for red violation */
+int is_red(struct RB_NODE *root)
+{
+    if (root)
+	return root->red == 1;
+
+    return 0;
+}
+
+/* single rotation */
+struct RB_NODE *rbtree_single(struct RB_NODE *root, int dir)
+{
+    struct RB_NODE *newroot = root->link[!dir];
+
+    root->link[!dir] = newroot->link[dir];
+    newroot->link[dir] = root;
+
+    root->red = 1;
+    newroot->red = 0;
+
+    return newroot;
+}
+
+/* double rotation */
+struct RB_NODE *rbtree_double(struct RB_NODE *root, int dir)
+{
+    root->link[!dir] = rbtree_single(root->link[!dir], !dir);
+    return rbtree_single(root, dir);
+}

Modified: grass/trunk/lib/segment/Makefile
===================================================================
--- grass/trunk/lib/segment/Makefile	2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/lib/segment/Makefile	2010-05-18 09:42:14 UTC (rev 42281)
@@ -3,6 +3,8 @@
 
 LIB = SEGMENT
 
+LIBES = $(BTREE2LIB)
+
 include $(MODULE_TOPDIR)/include/Make/Lib.make
 include $(MODULE_TOPDIR)/include/Make/Doxygen.make
 

Modified: grass/trunk/lib/segment/pagein.c
===================================================================
--- grass/trunk/lib/segment/pagein.c	2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/lib/segment/pagein.c	2010-05-18 09:42:14 UTC (rev 42281)
@@ -17,7 +17,7 @@
 #include <string.h>
 #include <errno.h>
 #include <grass/segment.h>
-#include "rbtree.h"
+#include <grass/rbtree.h>
 
 
 /**

Deleted: grass/trunk/lib/segment/rbtree.c
===================================================================
--- grass/trunk/lib/segment/rbtree.c	2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/lib/segment/rbtree.c	2010-05-18 09:42:14 UTC (rev 42281)
@@ -1,535 +0,0 @@
-/*!
- * \file rbtree.c
- *
- * \brief binary search tree 
- *
- * Generic balanced binary search tree (Red Black Tree) implementation
- *
- * (C) 2009 by the GRASS Development Team
- *
- * This program is free software under the GNU General Public License
- * (>=v2).  Read the file COPYING that comes with GRASS for details.
- *
- * \author Original author Julienne Walker 2003, 2008
- *         GRASS implementation Markus Metz, 2009
- */
-
-/* balanced binary search tree implementation
- * 
- * this one is a Red Black Tree, the bare version, no parent pointers, no threads
- * The core code comes from Julienne Walker's tutorials on binary search trees
- * original license: public domain
- * http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_rbtree.aspx
- * some ideas come from libavl (GPL >= 2)
- * I could have used some off-the-shelf solution, but that's boring
- *
- * Red Black Trees are used to maintain a data structure with
- * search, insertion and deletion in O(log N) time
- */
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <grass/gis.h>
-#include <grass/glocale.h>
-#include "rbtree.h"
-
-/* internal functions */
-void rbtree_destroy2(struct RB_NODE *);
-struct RB_NODE *rbtree_single(struct RB_NODE *, int);
-struct RB_NODE *rbtree_double(struct RB_NODE *, int);
-void *rbtree_first(struct RB_TRAV *);
-void *rbtree_next(struct RB_TRAV *);
-struct RB_NODE *rbtree_make_node(size_t, void *);
-int is_red(struct RB_NODE *);
-
-
-/* create new tree and initialize
- * returns pointer to new tree, NULL for memory allocation error
- */
-struct RB_TREE *rbtree_create(rb_compare_fn * compare, size_t rb_datasize)
-{
-    struct RB_TREE *tree = G_malloc(sizeof(*tree));
-
-    if (tree == NULL) {
-	G_warning("RB tree: Out of memory!");
-	return NULL;
-    }
-
-    assert(compare);
-
-    tree->datasize = rb_datasize;
-    tree->rb_compare = compare;
-    tree->count = 0;
-    tree->root = NULL;
-
-    return tree;
-}
-
-/* add an item to a tree
- * non-recursive top-down insertion
- * the algorithm does not allow duplicates and also does not warn about a duplicate
- * returns 1 on success, 0 on failure
- */
-int rbtree_insert(struct RB_TREE *tree, void *data)
-{
-    assert(tree && data);
-
-    if (tree->root == NULL) {
-	/* create a new root node for tree */
-	tree->root = rbtree_make_node(tree->datasize, data);
-	if (tree->root == NULL)
-	    return 0;
-    }
-    else {
-	struct RB_NODE head = { 0 };	/* False tree root */
-	struct RB_NODE *g, *t;	/* Grandparent & parent */
-	struct RB_NODE *p, *q;	/* Iterator & parent */
-	int dir = 0, last = 0;
-
-	/* Set up helpers */
-	t = &head;
-	g = p = NULL;
-	q = t->link[1] = tree->root;
-
-	/* Search down the tree */
-	for (;;) {
-	    if (q == NULL) {
-		/* Insert new node at the bottom */
-		p->link[dir] = q = rbtree_make_node(tree->datasize, data);
-		if (q == NULL)
-		    return 0;
-	    }
-	    else if (is_red(q->link[0]) && is_red(q->link[1])) {
-		/* Color flip */
-		q->red = 1;
-		q->link[0]->red = 0;
-		q->link[1]->red = 0;
-	    }
-
-	    /* Fix red violation */
-	    if (is_red(q) && is_red(p)) {
-		int dir2 = t->link[1] == g;
-
-		if (q == p->link[last])
-		    t->link[dir2] = rbtree_single(g, !last);
-		else
-		    t->link[dir2] = rbtree_double(g, !last);
-	    }
-
-	    last = dir;
-	    dir = tree->rb_compare(q->data, data);
-
-	    /* Stop if found. This check also disallows duplicates in the tree */
-	    if (dir == 0)
-		break;
-
-	    dir = dir < 0;
-
-	    /* Move the helpers down */
-	    if (g != NULL)
-		t = g;
-
-	    g = p, p = q;
-	    q = q->link[dir];
-	}
-
-	/* Update root */
-	tree->root = head.link[1];
-    }
-
-    /* Make root black */
-    tree->root->red = 0;
-
-    tree->count++;
-
-    return 1;
-}
-
-/* remove an item from a tree that matches given data
- * non-recursive top-down removal
- * returns 1 on successful removal
- * returns 0 if data item was not found
- */
-int rbtree_remove(struct RB_TREE *tree, const void *data)
-{
-    struct RB_NODE head = { 0 };	/* False tree root */
-    struct RB_NODE *q, *p, *g;	/* Helpers */
-    struct RB_NODE *f = NULL;	/* Found item */
-    int dir = 1, removed = 0;
-
-    assert(tree && data);
-
-    if (tree->root == NULL) {
-	return 0;		/* empty tree, nothing to remove */
-    }
-
-    /* Set up helpers */
-    q = &head;
-    g = p = NULL;
-    q->link[1] = tree->root;
-
-    /* Search and push a red down */
-    while (q->link[dir] != NULL) {
-	int last = dir;
-
-	/* Update helpers */
-	g = p, p = q;
-	q = q->link[dir];
-	dir = tree->rb_compare(q->data, data);
-
-	/* Save found node */
-	if (dir == 0)
-	    f = q;
-
-	dir = dir < 0;
-
-	/* Push the red node down */
-	if (!is_red(q) && !is_red(q->link[dir])) {
-	    if (is_red(q->link[!dir]))
-		p = p->link[last] = rbtree_single(q, dir);
-	    else if (!is_red(q->link[!dir])) {
-		struct RB_NODE *s = p->link[!last];
-
-		if (s != NULL) {
-		    if (!is_red(s->link[!last]) && !is_red(s->link[last])) {
-			/* Color flip */
-			p->red = 0;
-			s->red = 1;
-			q->red = 1;
-		    }
-		    else {
-			int dir2 = g->link[1] == p;
-
-			if (is_red(s->link[last]))
-			    g->link[dir2] = rbtree_double(p, last);
-			else if (is_red(s->link[!last]))
-			    g->link[dir2] = rbtree_single(p, last);
-
-			/* Ensure correct coloring */
-			q->red = g->link[dir2]->red = 1;
-			g->link[dir2]->link[0]->red = 0;
-			g->link[dir2]->link[1]->red = 0;
-		    }
-		}
-	    }
-	}
-    }
-
-    /* Replace and remove if found */
-    if (f != NULL) {
-	G_free(f->data);
-	f->data = q->data;
-	p->link[p->link[1] == q] = q->link[q->link[0] == NULL];
-	G_free(q);
-	tree->count--;
-	removed = 1;
-    }
-    else
-	G_debug(2, "RB tree: data not found in search tree");
-
-    /* Update root and make it black */
-    tree->root = head.link[1];
-    if (tree->root != NULL)
-	tree->root->red = 0;
-
-    return removed;
-}
-
-/* find data item in tree
- * returns pointer to data item if found else NULL
- */
-void *rbtree_find(struct RB_TREE *tree, const void *data)
-{
-    struct RB_NODE *curr_node = tree->root;
-    int cmp;
-
-    assert(tree && data);
-
-    while (curr_node != NULL) {
-	cmp = tree->rb_compare(curr_node->data, data);
-	if (cmp == 0)
-	    return curr_node->data;	/* found */
-
-	curr_node = curr_node->link[cmp < 0];
-    }
-    return NULL;
-}
-
-/* initialize tree traversal
- * (re-)sets trav structure
- * returns 0
- */
-int rbtree_init_trav(struct RB_TRAV *trav, struct RB_TREE *tree)
-{
-    assert(trav && tree);
-
-    trav->tree = tree;
-    trav->curr_node = tree->root;
-    trav->first = 1;
-    trav->top = 0;
-
-    return 0;
-}
-
-/* traverse the tree in ascending order
- * useful to get all items in the tree non-recursively
- * struct RB_TRAV *trav needs to be initialized first
- * returns pointer to data, NULL when finished
- */
-void *rbtree_traverse(struct RB_TRAV *trav)
-{
-    assert(trav);
-
-    if (trav->curr_node == NULL) {
-	if (trav->first)
-	    G_debug(1, "RB tree: empty tree");
-	else
-	    G_debug(1, "RB tree: finished traversing");
-
-	return NULL;
-    }
-
-    if (!trav->first)
-	return rbtree_next(trav);
-    else {
-	trav->first = 0;
-	return rbtree_first(trav);
-    }
-}
-
-/* find start point to traverse the tree in ascending order
- * useful to get a selection of items in the tree
- * magnitudes faster than traversing the whole tree
- * may return first item that's smaller or first item that's larger
- * struct RB_TRAV *trav needs to be initialized first
- * returns pointer to data, NULL when finished
- */
-void *rbtree_traverse_start(struct RB_TRAV *trav, const void *data)
-{
-    int dir = 0;
-
-    assert(trav && data);
-
-    if (trav->curr_node == NULL) {
-	if (trav->first)
-	    G_warning("RB tree: empty tree");
-	else
-	    G_warning("RB tree: finished traversing");
-
-	return NULL;
-    }
-
-    if (!trav->first)
-	return rbtree_next(trav);
-
-    /* else first time, get start node */
-
-    trav->first = 0;
-    trav->top = 0;
-
-    while (trav->curr_node != NULL) {
-	dir = trav->tree->rb_compare(trav->curr_node->data, data);
-	/* exact match, great! */
-	if (dir == 0)
-	    return trav->curr_node->data;
-	else {
-	    dir = dir < 0;
-	    /* end of branch, also reached if
-	     * smallest item is larger than search template or
-	     * largest item is smaller than search template */
-	    if (trav->curr_node->link[dir] == NULL)
-		return trav->curr_node->data;
-
-	    trav->up[trav->top++] = trav->curr_node;
-	    trav->curr_node = trav->curr_node->link[dir];
-	}
-    }
-
-    return NULL;		/* should not happen */
-}
-
-/* two functions needed to fully traverse the tree: initialize and continue
- * useful to get all items in the tree non-recursively
- * this one here uses a stack
- * parent pointers or threads would also be possible
- * but these would need to be added to RB_NODE
- * -> more memory needed for standard operations
- */
-
-/* start traversing the tree
- * returns pointer to smallest data item
- */
-void *rbtree_first(struct RB_TRAV *trav)
-{
-    /* get smallest item */
-    while (trav->curr_node->link[0] != NULL) {
-	trav->up[trav->top++] = trav->curr_node;
-	trav->curr_node = trav->curr_node->link[0];
-    }
-
-    return trav->curr_node->data;	/* return smallest item */
-}
-
-/* continue traversing the tree in ascending order
- * returns pointer to data item, NULL when finished
- */
-void *rbtree_next(struct RB_TRAV *trav)
-{
-    if (trav->curr_node->link[1] != NULL) {
-	/* something on the right side: larger item */
-	trav->up[trav->top++] = trav->curr_node;
-	trav->curr_node = trav->curr_node->link[1];
-
-	/* go down, find smallest item in this branch */
-	while (trav->curr_node->link[0] != NULL) {
-	    trav->up[trav->top++] = trav->curr_node;
-	    trav->curr_node = trav->curr_node->link[0];
-	}
-    }
-    else {
-	/* at smallest item in this branch, go back up */
-	struct RB_NODE *last;
-
-	do {
-	    if (trav->top == 0) {
-		trav->curr_node = NULL;
-		break;
-	    }
-	    last = trav->curr_node;
-	    trav->curr_node = trav->up[--trav->top];
-	} while (last == trav->curr_node->link[1]);
-    }
-
-    if (trav->curr_node != NULL) {
-	return trav->curr_node->data;
-    }
-    else
-	return NULL;		/* finished traversing */
-}
-
-/* destroy the tree */
-void rbtree_destroy(struct RB_TREE *tree)
-{
-    rbtree_destroy2(tree->root);
-    G_free(tree);
-}
-
-void rbtree_destroy2(struct RB_NODE *root)
-{
-    if (root != NULL) {
-	rbtree_destroy2(root->link[0]);
-	rbtree_destroy2(root->link[1]);
-	G_free(root->data);
-	G_free(root);
-    }
-}
-
-/* used for debugging: check for errors in tree structure */
-int rbtree_debug(struct RB_TREE *tree, struct RB_NODE *root)
-{
-    int lh, rh;
-
-    if (root == NULL)
-	return 1;
-    else {
-	struct RB_NODE *ln = root->link[0];
-	struct RB_NODE *rn = root->link[1];
-	int lcmp = 0, rcmp = 0;
-
-	/* Consecutive red links */
-	if (is_red(root)) {
-	    if (is_red(ln) || is_red(rn)) {
-		G_warning("Red Black Tree debugging: Red violation");
-		return 0;
-	    }
-	}
-
-	lh = rbtree_debug(tree, ln);
-	rh = rbtree_debug(tree, rn);
-
-	if (ln) {
-	    lcmp = tree->rb_compare(ln->data, root->data);
-	}
-
-	if (rn) {
-	    rcmp = tree->rb_compare(rn->data, root->data);
-	}
-
-	/* Invalid binary search tree:
-	 * left node >= parent or right node <= parent */
-	if ((ln != NULL && lcmp > -1)
-	    || (rn != NULL && rcmp < 1)) {
-	    G_warning("Red Black Tree debugging: Binary tree violation");
-	    return 0;
-	}
-
-	/* Black height mismatch */
-	if (lh != 0 && rh != 0 && lh != rh) {
-	    G_warning("Red Black Tree debugging: Black violation");
-	    return 0;
-	}
-
-	/* Only count black links */
-	if (lh != 0 && rh != 0)
-	    return is_red(root) ? lh : lh + 1;
-	else
-	    return 0;
-    }
-}
-
-/*******************************************************
- *                                                     *
- *  internal functions for Red Black Tree maintenance  *
- *                                                     *
- *******************************************************/
-
-/* add a new node to the tree */
-struct RB_NODE *rbtree_make_node(size_t datasize, void *data)
-{
-    struct RB_NODE *new_node = G_malloc(sizeof(*new_node));
-
-    if (new_node == NULL)
-	G_fatal_error("RB Search Tree: Out of memory!");
-
-    new_node->data = G_malloc(datasize);
-    if (new_node->data == NULL)
-	G_fatal_error("RB Search Tree: Out of memory!");
-
-    memcpy(new_node->data, data, datasize);
-    new_node->red = 1;		/* 1 is red, 0 is black */
-    new_node->link[0] = NULL;
-    new_node->link[1] = NULL;
-
-    return new_node;
-}
-
-/* check for red violation */
-int is_red(struct RB_NODE *root)
-{
-    if (root)
-	return root->red == 1;
-
-    return 0;
-}
-
-/* single rotation */
-struct RB_NODE *rbtree_single(struct RB_NODE *root, int dir)
-{
-    struct RB_NODE *newroot = root->link[!dir];
-
-    root->link[!dir] = newroot->link[dir];
-    newroot->link[dir] = root;
-
-    root->red = 1;
-    newroot->red = 0;
-
-    return newroot;
-}
-
-/* double rotation */
-struct RB_NODE *rbtree_double(struct RB_NODE *root, int dir)
-{
-    root->link[!dir] = rbtree_single(root->link[!dir], !dir);
-    return rbtree_single(root, dir);
-}

Deleted: grass/trunk/lib/segment/rbtree.h
===================================================================
--- grass/trunk/lib/segment/rbtree.h	2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/lib/segment/rbtree.h	2010-05-18 09:42:14 UTC (rev 42281)
@@ -1,112 +0,0 @@
-/*************************************************************
- *                          USAGE                            *
- *************************************************************
- *
- * NOTE: duplicates are not supported
- *
- * custom compare function
- * extern int my_compare_fn(const void *, const void *);
- * int my_compare_fn(const void *a, const void *b) {
- *   if ((mydatastruct *) a < (mydatastruct *) b)
- *     return -1;
- *   else if ((mydatastruct *) a > (mydatastruct *) b)
- *     return 1;
- *   else if ((mydatastruct *) a == (mydatastruct *) b)
- *     return 0;
- * }
- * 
- * create and initialize tree:
- * struct RB_TREE *mytree = rbtree_create(my_compare_fn, item_size);
- *
- * insert items to tree:
- * struct mydatastruct data = <some data>;
- * if (rbtree_insert(mytree, &data) == 0)
- * 	 G_warning("could not insert data");
- *
- * find item in tree:
- * struct mydatastruct data = <some data>;
- * if (rbtree_find(mytree, &data) == 0)
- * 	 G_message("data not found");
- *
- * delete item from tree:
- * struct mydatastruct data = <some data>;
- * if (rbtree_remove(mytree, &data) == 0)
- * 	  G_warning("could not find data in tree");
- *
- * traverse tree (get all items in tree in ascending order):
- * struct RB_TRAV trav;
- * rbtree_init_trav(&trav, tree);
- * while ((data = rbtree_traverse(&trav)) != NULL) {
- *   if (my_compare_fn(data, threshold_data) == 0) break;
- * 	   <do something with data>;
- *  }
- *
- * get a selection of items: all data > data1 and < data2
- * start in tree where data is last smaller or first larger compared to data1
- * struct RB_TRAV trav;
- * rbtree_init_trav(&trav, tree);
- * data = rbtree_traverse_start(&trav, &data1);
- * 	 <do something with data>;
- * while ((data = rbtree_traverse(&trav)) != NULL) {
- *	 if (data > data2) break;
- *   <do something with data>;
- * }
- *
- * destroy tree:
- * rbtree_destroy(mytree);
- *
- * debug the whole tree with
- * rbtree_debug(mytree, mytree->root);
- * 
- *************************************************************/
-
-#include <stddef.h>
-
-/* maximum RB Tree height */
-#define RBTREE_MAX_HEIGHT 64        /* should be more than enough */
-
-/* routine to compare data items
- * return -1 if rb_a < rb_b
- * return  0 if rb_a == rb_b
- * return  1 if rb_a > rb_b
- */
-typedef int rb_compare_fn(const void *rb_a, const void *rb_b);
-
-struct RB_NODE
-{
-    unsigned char red;              /* 0 = black, 1 = red */
-    void *data;                     /* any kind of data */
-    struct RB_NODE *link[2];        /* link to children: link[0] for smaller, link[1] for larger */
-};
- 
-struct RB_TREE
-{
-    struct RB_NODE *root;           /* root node */
-    size_t datasize;                /* item size */
-    size_t count;                   /* number of items in tree. */
-    rb_compare_fn *rb_compare;      /* function to compare data */
-};
-
-struct RB_TRAV
-{
-    struct RB_TREE *tree;           /* tree being traversed */
-    struct RB_NODE *curr_node;      /* current node */
-    struct RB_NODE *up[RBTREE_MAX_HEIGHT];  /* stack of parent nodes */
-    int top;                        /* index for stack */
-    int first;                      /* little helper flag */
-};
-
-/* tree functions */
-struct RB_TREE *rbtree_create(rb_compare_fn *, size_t);
-void rbtree_destroy(struct RB_TREE *);
-int rbtree_insert(struct RB_TREE *, void *);
-int rbtree_remove(struct RB_TREE *, const void *);
-void *rbtree_find(struct RB_TREE *, const void *);
-
-/* tree traversal functions */
-int rbtree_init_trav(struct RB_TRAV *, struct RB_TREE *);
-void* rbtree_traverse(struct RB_TRAV *);
-void *rbtree_traverse_start(struct RB_TRAV *, const void *);
-
-/* debug tree from given node downwards */
-int rbtree_debug(struct RB_TREE *, struct RB_NODE *);

Modified: grass/trunk/lib/segment/release.c
===================================================================
--- grass/trunk/lib/segment/release.c	2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/lib/segment/release.c	2010-05-18 09:42:14 UTC (rev 42281)
@@ -14,7 +14,7 @@
 
 #include <stdlib.h>
 #include <grass/segment.h>
-#include "rbtree.h"
+#include <grass/rbtree.h>
 
 
 /**

Modified: grass/trunk/lib/segment/setup.c
===================================================================
--- grass/trunk/lib/segment/setup.c	2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/lib/segment/setup.c	2010-05-18 09:42:14 UTC (rev 42281)
@@ -17,7 +17,7 @@
 #include <math.h>
 #include <grass/gis.h>
 #include <grass/segment.h>
-#include "rbtree.h"
+#include <grass/rbtree.h>
 
 
 /**

Modified: grass/trunk/lib/vector/Vlib/break_polygons.c
===================================================================
--- grass/trunk/lib/vector/Vlib/break_polygons.c	2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/lib/vector/Vlib/break_polygons.c	2010-05-18 09:42:14 UTC (rev 42281)
@@ -21,7 +21,6 @@
 #include <math.h>
 #include <grass/gis.h>
 #include <grass/vector.h>
-#include <grass/vect/rbtree.h>
 #include <grass/glocale.h>
 
 /* TODO: 3D support

Modified: grass/trunk/lib/vector/Vlib/snap.c
===================================================================
--- grass/trunk/lib/vector/Vlib/snap.c	2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/lib/vector/Vlib/snap.c	2010-05-18 09:42:14 UTC (rev 42281)
@@ -20,7 +20,6 @@
 #include <grass/gis.h>
 #include <grass/vector.h>
 #include <grass/glocale.h>
-#include <grass/vect/rbtree.h>
 
 /* function prototypes */
 static int sort_new(const void *pa, const void *pb);

Deleted: grass/trunk/lib/vector/diglib/rbtree.c
===================================================================
--- grass/trunk/lib/vector/diglib/rbtree.c	2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/lib/vector/diglib/rbtree.c	2010-05-18 09:42:14 UTC (rev 42281)
@@ -1,536 +0,0 @@
-/*!
- * \file rbtree.c
- *
- * \brief binary search tree 
- *
- * Generic balanced binary search tree (Red Black Tree) implementation
- *
- * (C) 2009 by the GRASS Development Team
- *
- * This program is free software under the GNU General Public License
- * (>=v2).  Read the file COPYING that comes with GRASS for details.
- *
- * \author Original author Julienne Walker 2003, 2008
- *         GRASS implementation Markus Metz, 2009
- */
-
-/* balanced binary search tree implementation
- * 
- * this one is a Red Black Tree, the bare version, no parent pointers, no threads
- * The core code comes from Julienne Walker's tutorials on binary search trees
- * original license: public domain
- * http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_rbtree.aspx
- * some ideas come from libavl (GPL >= 2)
- * I could have used some off-the-shelf solution, but that's boring
- *
- * Red Black Trees are used to maintain a data structure with
- * search, insertion and deletion in O(log N) time
- */
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <grass/gis.h>
-#include <grass/glocale.h>
-#include <grass/vect/rbtree.h>
-
-/* internal functions */
-void rbtree_destroy2(struct RB_NODE *);
-struct RB_NODE *rbtree_single(struct RB_NODE *, int);
-struct RB_NODE *rbtree_double(struct RB_NODE *, int);
-void *rbtree_first(struct RB_TRAV *);
-void *rbtree_next(struct RB_TRAV *);
-struct RB_NODE *rbtree_make_node(size_t, void *);
-int is_red(struct RB_NODE *);
-
-
-/* create new tree and initialize
- * returns pointer to new tree, NULL for memory allocation error
- */
-struct RB_TREE *rbtree_create(rb_compare_fn *compare, size_t rb_datasize)
-{
-    struct RB_TREE *tree = G_malloc(sizeof(*tree));
-
-    if (tree == NULL) {
-	G_warning("RB tree: Out of memory!");
-	return NULL;
-    }
-
-    assert(compare);
-
-    tree->datasize = rb_datasize;
-    tree->rb_compare = compare;
-    tree->count = 0;
-    tree->root = NULL;
-
-    return tree;
-} 
-
-/* add an item to a tree
- * non-recursive top-down insertion
- * the algorithm does not allow duplicates and also does not warn about a duplicate
- * returns 1 on success, 0 on failure
- */
-int rbtree_insert(struct RB_TREE *tree, void *data)
-{
-    assert(tree && data);
-    
-    if (tree->root == NULL) {
-	/* create a new root node for tree */
-	tree->root = rbtree_make_node(tree->datasize, data);
-	if (tree->root == NULL)
-	    return 0;
-    }
-    else {
-	struct RB_NODE head = {0}; /* False tree root */
-
-	struct RB_NODE *g, *t;     /* Grandparent & parent */
-	struct RB_NODE *p, *q;     /* Iterator & parent */
-	int dir = 0, last = 0;
-
-	/* Set up helpers */
-	t = &head;
-	g = p = NULL;
-	q = t->link[1] = tree->root;
-
-	/* Search down the tree */
-	for ( ; ; ) {
-	    if (q == NULL) {
-		/* Insert new node at the bottom */
-		p->link[dir] = q = rbtree_make_node(tree->datasize, data);
-		if (q == NULL)
-		    return 0;
-	    }
-	    else if (is_red(q->link[0]) && is_red(q->link[1])) {
-		/* Color flip */
-		q->red = 1;
-		q->link[0]->red = 0;
-		q->link[1]->red = 0;
-	    }
-
-	    /* Fix red violation */
-	    if (is_red(q) && is_red(p)) {
-		int dir2 = t->link[1] == g;
-
-		if (q == p->link[last])
-		    t->link[dir2] = rbtree_single(g, !last);
-		else
-		    t->link[dir2] = rbtree_double(g, !last);
-	    }
-
-	    last = dir;
-	    dir = tree->rb_compare(q->data, data);
-
-	    /* Stop if found. This check also disallows duplicates in the tree */
-	    if (dir == 0)
-		break;
-
-	    dir = dir < 0;
-
-	    /* Move the helpers down */
-	    if (g != NULL)
-		t = g;
-
-	    g = p, p = q;
-	    q = q->link[dir];
-	}
-
-	/* Update root */
-	tree->root = head.link[1];
-    }
-
-    /* Make root black */
-    tree->root->red = 0;
-
-    tree->count++;
-
-    return 1;
-}
-
-/* remove an item from a tree that matches given data
- * non-recursive top-down removal
- * returns 1 on successful removal
- * returns 0 if data item was not found
- */
-int rbtree_remove(struct RB_TREE *tree, const void *data)
-{
-    struct RB_NODE head = {0}; /* False tree root */
-    struct RB_NODE *q, *p, *g; /* Helpers */
-    struct RB_NODE *f = NULL;  /* Found item */
-    int dir = 1, removed = 0;
-
-    assert(tree && data);
-
-    if (tree->root == NULL) {
-	return 0; /* empty tree, nothing to remove */
-    }
-
-    /* Set up helpers */
-    q = &head;
-    g = p = NULL;
-    q->link[1] = tree->root;
-
-    /* Search and push a red down */
-    while (q->link[dir] != NULL) {
-	int last = dir;
-
-	/* Update helpers */
-	g = p, p = q;
-	q = q->link[dir];
-	dir = tree->rb_compare(q->data, data);
-
-	/* Save found node */
-	if (dir == 0)
-	    f = q;
-
-	dir = dir < 0;
-
-	/* Push the red node down */
-	if (!is_red(q) && !is_red(q->link[dir])) {
-	    if (is_red(q->link[!dir]))
-		p = p->link[last] = rbtree_single(q, dir);
-	    else if (!is_red(q->link[!dir])) {
-		struct RB_NODE *s = p->link[!last];
-
-		if (s != NULL) {
-		    if (!is_red(s->link[!last]) &&
-		        !is_red(s->link[last])) {
-			/* Color flip */
-			p->red = 0;
-			s->red = 1;
-			q->red = 1;
-		    }
-		    else {
-			int dir2 = g->link[1] == p;
-
-			if (is_red(s->link[last]))
-			    g->link[dir2] = rbtree_double(p, last);
-			else if (is_red(s->link[!last]))
-			    g->link[dir2] = rbtree_single(p, last);
-
-			/* Ensure correct coloring */
-			q->red = g->link[dir2]->red = 1;
-			g->link[dir2]->link[0]->red = 0;
-			g->link[dir2]->link[1]->red = 0;
-		    }
-		}
-	    }
-	}
-    }
-
-    /* Replace and remove if found */
-    if (f != NULL) {
-	G_free(f->data);
-	f->data = q->data;
-	p->link[p->link[1] == q] = q->link[q->link[0] == NULL];
-	G_free(q);
-	tree->count--;
-	removed = 1;
-    }
-    else
-	G_debug(2, "RB tree: data not found in search tree");
-
-    /* Update root and make it black */
-    tree->root = head.link[1];
-    if ( tree->root != NULL)
-	tree->root->red = 0;
-
-    return removed;
-}
-
-/* find data item in tree
- * returns pointer to data item if found else NULL
- */
-void *rbtree_find(struct RB_TREE *tree, const void *data)
-{
-    struct RB_NODE *curr_node = tree->root;
-    int cmp = 0;
-
-    assert(tree && data);
-
-    while (curr_node != NULL) {
-	cmp = tree->rb_compare(curr_node->data, data);
-	if (cmp == 0)
-	    return curr_node->data;   /* found */
-	else {
-	    curr_node = curr_node->link[cmp < 0];
-	}
-    }
-    return NULL;
-}
-
-/* initialize tree traversal
- * (re-)sets trav structure
- * returns 0
- */
-int rbtree_init_trav(struct RB_TRAV *trav, struct RB_TREE *tree)
-{
-    assert(trav && tree);
-
-    trav->tree = tree;
-    trav->curr_node = tree->root;
-    trav->first = 1;
-    trav->top = 0;
-
-    return 0;
-}
-
-/* traverse the tree in ascending order
- * useful to get all items in the tree non-recursively
- * struct RB_TRAV *trav needs to be initialized first
- * returns pointer to data, NULL when finished
- */
-void *rbtree_traverse(struct RB_TRAV *trav)
-{
-    assert(trav);
-    
-    if (trav->curr_node == NULL) {
-	if (trav->first)
-	    G_debug(1, "RB tree: empty tree");
-	else
-	    G_debug(1, "RB tree: finished traversing");
-
-	return NULL;
-    }
-	
-    if (!trav->first)
-	return rbtree_next(trav);
-    else {
-	trav->first = 0;
-	return rbtree_first(trav);
-    }
-}
-
-/* find start point to traverse the tree in ascending order
- * useful to get a selection of items in the tree
- * magnitudes faster than traversing the whole tree
- * may return first item that's smaller or first item that's larger
- * struct RB_TRAV *trav needs to be initialized first
- * returns pointer to data, NULL when finished
- */
-void *rbtree_traverse_start(struct RB_TRAV *trav, const void *data)
-{
-    int dir = 0;
-
-    assert(trav && data);
-
-    if (trav->curr_node == NULL) {
-	if (trav->first)
-	    G_warning("RB tree: empty tree");
-	else
-	    G_warning("RB tree: finished traversing");
-
-	return NULL;
-    }
-	
-    if (!trav->first)
-	return rbtree_next(trav);
-
-    /* else first time, get start node */
-
-    trav->first = 0;
-    trav->top = 0;
-
-    while (trav->curr_node != NULL) {
-	dir = trav->tree->rb_compare(trav->curr_node->data, data);
-	/* exact match, great! */
-	if (dir == 0)
-	    return trav->curr_node->data;
-	else {
-	    dir = dir < 0;
-	    /* end of branch, also reached if
-	     * smallest item is larger than search template or
-	     * largest item is smaller than search template */
-	    if (trav->curr_node->link[dir] == NULL)
-		return trav->curr_node->data;
-		
-	    trav->up[trav->top++] = trav->curr_node;
-	    trav->curr_node = trav->curr_node->link[dir];
-	}
-    }
-
-    return NULL; /* should not happen */
-}
-
-/* two functions needed to fully traverse the tree: initialize and continue
- * useful to get all items in the tree non-recursively
- * this one here uses a stack
- * parent pointers or threads would also be possible
- * but these would need to be added to RB_NODE
- * -> more memory needed for standard operations
- */
-
-/* start traversing the tree
- * returns pointer to smallest data item
- */
-void *rbtree_first(struct RB_TRAV *trav)
-{
-    /* get smallest item */
-    while (trav->curr_node->link[0] != NULL) {
-	trav->up[trav->top++] = trav->curr_node;
-	trav->curr_node = trav->curr_node->link[0];
-    }
-
-    return trav->curr_node->data; /* return smallest item */
-}
-
-/* continue traversing the tree in ascending order
- * returns pointer to data item, NULL when finished
- */
-void *rbtree_next(struct RB_TRAV *trav)
-{
-    if (trav->curr_node->link[1] != NULL) {
-	/* something on the right side: larger item */
-	trav->up[trav->top++] = trav->curr_node;
-	trav->curr_node = trav->curr_node->link[1];
-
-	/* go down, find smallest item in this branch */
-	while (trav->curr_node->link[0] != NULL) {
-	    trav->up[trav->top++] = trav->curr_node;
-	    trav->curr_node = trav->curr_node->link[0];
-	}
-    }
-    else {
-	/* at smallest item in this branch, go back up */
-	struct RB_NODE *last;
-	do {
-	    if (trav->top == 0) {
-		trav->curr_node = NULL;
-		break;
-	    }
-	    last = trav->curr_node;
-	    trav->curr_node = trav->up[--trav->top];
-	} while (last == trav->curr_node->link[1]);
-    }
-
-    if (trav->curr_node != NULL) {
-	return trav->curr_node->data;
-    }
-    else	
-	return NULL; /* finished traversing */
-}
-
-/* destroy the tree */
-void rbtree_destroy(struct RB_TREE *tree) {
-    rbtree_destroy2(tree->root);
-    G_free(tree);
-}
-
-void rbtree_destroy2(struct RB_NODE *root)
-{
-    if (root != NULL) {
-	rbtree_destroy2(root->link[0]);
-	rbtree_destroy2(root->link[1]);
-	G_free(root->data);
-	G_free(root);
-    }
-}
-
-/* used for debugging: check for errors in tree structure */
-int rbtree_debug(struct RB_TREE *tree, struct RB_NODE *root)
-{
-    int lh, rh;
- 
-    if (root == NULL)
-	return 1;
-    else {
-	struct RB_NODE *ln = root->link[0];
-	struct RB_NODE *rn = root->link[1];
-	int lcmp = 0, rcmp = 0;
-
-	/* Consecutive red links */
-	if (is_red(root)) {
-	    if (is_red(ln) || is_red(rn)) {
-		G_warning("Red Black Tree debugging: Red violation");
-		return 0;
-	    }
-	}
-
-	lh = rbtree_debug(tree, ln);
-	rh = rbtree_debug(tree, rn);
-
-	if (ln) {
-	    lcmp = tree->rb_compare(ln->data, root->data);
-	}
-	
-	if (rn) {
-	    rcmp = tree->rb_compare(rn->data, root->data);
-	}
-
-	/* Invalid binary search tree:
-	 * left node >= parent or right node <= parent */
-	if ((ln != NULL && lcmp > -1)
-	 || (rn != NULL && rcmp < 1)) {
-	    G_warning("Red Black Tree debugging: Binary tree violation" );
-	    return 0;
-	}
-
-	/* Black height mismatch */
-	if (lh != 0 && rh != 0 && lh != rh) {
-	    G_warning("Red Black Tree debugging: Black violation");
-	    return 0;
-	}
-
-	/* Only count black links */
-	if (lh != 0 && rh != 0)
-	    return is_red(root) ? lh : lh + 1;
-	else
-	    return 0;
-    }
-}
-
-/*******************************************************
- *                                                     *
- *  internal functions for Red Black Tree maintenance  *
- *                                                     *
- *******************************************************/
-
-/* add a new node to the tree */
-struct RB_NODE *rbtree_make_node(size_t datasize, void *data)
-{
-    struct RB_NODE *new_node = G_malloc(sizeof(*new_node));
-
-    if (new_node == NULL)
-	G_fatal_error("RB Search Tree: Out of memory!");
-
-    new_node->data = G_malloc(datasize);
-    if (new_node->data == NULL)
-	G_fatal_error("RB Search Tree: Out of memory!");
-	
-    memcpy(new_node->data, data, datasize);
-    new_node->red = 1;            /* 1 is red, 0 is black */
-    new_node->link[0] = NULL;
-    new_node->link[1] = NULL;
-
-    return new_node;
-}
-
-/* check for red violation */
-int is_red(struct RB_NODE *root)
-{
-    if (root)
-	return root->red == 1;
-
-    return 0;
-}
-
-/* single rotation */
-struct RB_NODE *rbtree_single(struct RB_NODE *root, int dir)
-{
-    struct RB_NODE *newroot = root->link[!dir];
-
-    root->link[!dir] = newroot->link[dir];
-    newroot->link[dir] = root;
-
-    root->red = 1;
-    newroot->red = 0;
-
-    return newroot;
-}
- 
-/* double rotation */
-struct RB_NODE *rbtree_double(struct RB_NODE *root, int dir)
-{
-    root->link[!dir] = rbtree_single(root->link[!dir], !dir);
-    return rbtree_single(root, dir);
-}

Modified: grass/trunk/raster/r.watershed/ram/Makefile
===================================================================
--- grass/trunk/raster/r.watershed/ram/Makefile	2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/raster/r.watershed/ram/Makefile	2010-05-18 09:42:14 UTC (rev 42281)
@@ -2,7 +2,7 @@
 
 PGM = r.watershed.ram
 
-LIBES = $(RASTERLIB) $(GISLIB) $(MATHLIB)
+LIBES = $(RASTERLIB) $(GISLIB) $(MATHLIB) $(BTREE2LIB)
 DEPENDENCIES = $(RASTERDEP) $(GISDEP)
 
 include $(MODULE_TOPDIR)/include/Make/Etc.make

Modified: grass/trunk/raster/r.watershed/ram/do_flatarea.c
===================================================================
--- grass/trunk/raster/r.watershed/ram/do_flatarea.c	2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/raster/r.watershed/ram/do_flatarea.c	2010-05-18 09:42:14 UTC (rev 42281)
@@ -16,9 +16,9 @@
 #include <assert.h>
 #include <grass/gis.h>
 #include <grass/glocale.h>
+#include <grass/rbtree.h>
 #include "Gwater.h"
 #include "do_astar.h"
-#include "rbtree.h"
 
 struct pq_node
 {

Deleted: grass/trunk/raster/r.watershed/ram/rbtree.c
===================================================================
--- grass/trunk/raster/r.watershed/ram/rbtree.c	2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/raster/r.watershed/ram/rbtree.c	2010-05-18 09:42:14 UTC (rev 42281)
@@ -1,535 +0,0 @@
-/*!
- * \file rbtree.c
- *
- * \brief binary search tree 
- *
- * Generic balanced binary search tree (Red Black Tree) implementation
- *
- * (C) 2009 by the GRASS Development Team
- *
- * This program is free software under the GNU General Public License
- * (>=v2).  Read the file COPYING that comes with GRASS for details.
- *
- * \author Original author Julienne Walker 2003, 2008
- *         GRASS implementation Markus Metz, 2009
- */
-
-/* balanced binary search tree implementation
- * 
- * this one is a Red Black Tree, the bare version, no parent pointers, no threads
- * The core code comes from Julienne Walker's tutorials on binary search trees
- * original license: public domain
- * http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_rbtree.aspx
- * some ideas come from libavl (GPL >= 2)
- * I could have used some off-the-shelf solution, but that's boring
- *
- * Red Black Trees are used to maintain a data structure with
- * search, insertion and deletion in O(log N) time
- */
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <grass/gis.h>
-#include <grass/glocale.h>
-#include "rbtree.h"
-
-/* internal functions */
-void rbtree_destroy2(struct RB_NODE *);
-struct RB_NODE *rbtree_single(struct RB_NODE *, int);
-struct RB_NODE *rbtree_double(struct RB_NODE *, int);
-void *rbtree_first(struct RB_TRAV *);
-void *rbtree_next(struct RB_TRAV *);
-struct RB_NODE *rbtree_make_node(size_t, void *);
-int is_red(struct RB_NODE *);
-
-
-/* create new tree and initialize
- * returns pointer to new tree, NULL for memory allocation error
- */
-struct RB_TREE *rbtree_create(rb_compare_fn * compare, size_t rb_datasize)
-{
-    struct RB_TREE *tree = G_malloc(sizeof(*tree));
-
-    if (tree == NULL) {
-	G_warning("RB tree: Out of memory!");
-	return NULL;
-    }
-
-    assert(compare);
-
-    tree->datasize = rb_datasize;
-    tree->rb_compare = compare;
-    tree->count = 0;
-    tree->root = NULL;
-
-    return tree;
-}
-
-/* add an item to a tree
- * non-recursive top-down insertion
- * the algorithm does not allow duplicates and also does not warn about a duplicate
- * returns 1 on success, 0 on failure
- */
-int rbtree_insert(struct RB_TREE *tree, void *data)
-{
-    assert(tree && data);
-
-    if (tree->root == NULL) {
-	/* create a new root node for tree */
-	tree->root = rbtree_make_node(tree->datasize, data);
-	if (tree->root == NULL)
-	    return 0;
-    }
-    else {
-	struct RB_NODE head = { 0 };	/* False tree root */
-	struct RB_NODE *g, *t;	/* Grandparent & parent */
-	struct RB_NODE *p, *q;	/* Iterator & parent */
-	int dir = 0, last = 0;
-
-	/* Set up helpers */
-	t = &head;
-	g = p = NULL;
-	q = t->link[1] = tree->root;
-
-	/* Search down the tree */
-	for (;;) {
-	    if (q == NULL) {
-		/* Insert new node at the bottom */
-		p->link[dir] = q = rbtree_make_node(tree->datasize, data);
-		if (q == NULL)
-		    return 0;
-	    }
-	    else if (is_red(q->link[0]) && is_red(q->link[1])) {
-		/* Color flip */
-		q->red = 1;
-		q->link[0]->red = 0;
-		q->link[1]->red = 0;
-	    }
-
-	    /* Fix red violation */
-	    if (is_red(q) && is_red(p)) {
-		int dir2 = t->link[1] == g;
-
-		if (q == p->link[last])
-		    t->link[dir2] = rbtree_single(g, !last);
-		else
-		    t->link[dir2] = rbtree_double(g, !last);
-	    }
-
-	    last = dir;
-	    dir = tree->rb_compare(q->data, data);
-
-	    /* Stop if found. This check also disallows duplicates in the tree */
-	    if (dir == 0)
-		break;
-
-	    dir = dir < 0;
-
-	    /* Move the helpers down */
-	    if (g != NULL)
-		t = g;
-
-	    g = p, p = q;
-	    q = q->link[dir];
-	}
-
-	/* Update root */
-	tree->root = head.link[1];
-    }
-
-    /* Make root black */
-    tree->root->red = 0;
-
-    tree->count++;
-
-    return 1;
-}
-
-/* remove an item from a tree that matches given data
- * non-recursive top-down removal
- * returns 1 on successful removal
- * returns 0 if data item was not found
- */
-int rbtree_remove(struct RB_TREE *tree, const void *data)
-{
-    struct RB_NODE head = { 0 };	/* False tree root */
-    struct RB_NODE *q, *p, *g;	/* Helpers */
-    struct RB_NODE *f = NULL;	/* Found item */
-    int dir = 1, removed = 0;
-
-    assert(tree && data);
-
-    if (tree->root == NULL) {
-	return 0;		/* empty tree, nothing to remove */
-    }
-
-    /* Set up helpers */
-    q = &head;
-    g = p = NULL;
-    q->link[1] = tree->root;
-
-    /* Search and push a red down */
-    while (q->link[dir] != NULL) {
-	int last = dir;
-
-	/* Update helpers */
-	g = p, p = q;
-	q = q->link[dir];
-	dir = tree->rb_compare(q->data, data);
-
-	/* Save found node */
-	if (dir == 0)
-	    f = q;
-
-	dir = dir < 0;
-
-	/* Push the red node down */
-	if (!is_red(q) && !is_red(q->link[dir])) {
-	    if (is_red(q->link[!dir]))
-		p = p->link[last] = rbtree_single(q, dir);
-	    else if (!is_red(q->link[!dir])) {
-		struct RB_NODE *s = p->link[!last];
-
-		if (s != NULL) {
-		    if (!is_red(s->link[!last]) && !is_red(s->link[last])) {
-			/* Color flip */
-			p->red = 0;
-			s->red = 1;
-			q->red = 1;
-		    }
-		    else {
-			int dir2 = g->link[1] == p;
-
-			if (is_red(s->link[last]))
-			    g->link[dir2] = rbtree_double(p, last);
-			else if (is_red(s->link[!last]))
-			    g->link[dir2] = rbtree_single(p, last);
-
-			/* Ensure correct coloring */
-			q->red = g->link[dir2]->red = 1;
-			g->link[dir2]->link[0]->red = 0;
-			g->link[dir2]->link[1]->red = 0;
-		    }
-		}
-	    }
-	}
-    }
-
-    /* Replace and remove if found */
-    if (f != NULL) {
-	G_free(f->data);
-	f->data = q->data;
-	p->link[p->link[1] == q] = q->link[q->link[0] == NULL];
-	G_free(q);
-	tree->count--;
-	removed = 1;
-    }
-    else
-	G_debug(2, "RB tree: data not found in search tree");
-
-    /* Update root and make it black */
-    tree->root = head.link[1];
-    if (tree->root != NULL)
-	tree->root->red = 0;
-
-    return removed;
-}
-
-/* find data item in tree
- * returns pointer to data item if found else NULL
- */
-void *rbtree_find(struct RB_TREE *tree, const void *data)
-{
-    struct RB_NODE *curr_node = tree->root;
-    int cmp;
-
-    assert(tree && data);
-
-    while (curr_node != NULL) {
-	cmp = tree->rb_compare(curr_node->data, data);
-	if (cmp == 0)
-	    return curr_node->data;	/* found */
-
-	curr_node = curr_node->link[cmp < 0];
-    }
-    return NULL;
-}
-
-/* initialize tree traversal
- * (re-)sets trav structure
- * returns 0
- */
-int rbtree_init_trav(struct RB_TRAV *trav, struct RB_TREE *tree)
-{
-    assert(trav && tree);
-
-    trav->tree = tree;
-    trav->curr_node = tree->root;
-    trav->first = 1;
-    trav->top = 0;
-
-    return 0;
-}
-
-/* traverse the tree in ascending order
- * useful to get all items in the tree non-recursively
- * struct RB_TRAV *trav needs to be initialized first
- * returns pointer to data, NULL when finished
- */
-void *rbtree_traverse(struct RB_TRAV *trav)
-{
-    assert(trav);
-
-    if (trav->curr_node == NULL) {
-	if (trav->first)
-	    G_debug(1, "RB tree: empty tree");
-	else
-	    G_debug(1, "RB tree: finished traversing");
-
-	return NULL;
-    }
-
-    if (!trav->first)
-	return rbtree_next(trav);
-    else {
-	trav->first = 0;
-	return rbtree_first(trav);
-    }
-}
-
-/* find start point to traverse the tree in ascending order
- * useful to get a selection of items in the tree
- * magnitudes faster than traversing the whole tree
- * may return first item that's smaller or first item that's larger
- * struct RB_TRAV *trav needs to be initialized first
- * returns pointer to data, NULL when finished
- */
-void *rbtree_traverse_start(struct RB_TRAV *trav, const void *data)
-{
-    int dir = 0;
-
-    assert(trav && data);
-
-    if (trav->curr_node == NULL) {
-	if (trav->first)
-	    G_warning("RB tree: empty tree");
-	else
-	    G_warning("RB tree: finished traversing");
-
-	return NULL;
-    }
-
-    if (!trav->first)
-	return rbtree_next(trav);
-
-    /* else first time, get start node */
-
-    trav->first = 0;
-    trav->top = 0;
-
-    while (trav->curr_node != NULL) {
-	dir = trav->tree->rb_compare(trav->curr_node->data, data);
-	/* exact match, great! */
-	if (dir == 0)
-	    return trav->curr_node->data;
-	else {
-	    dir = dir < 0;
-	    /* end of branch, also reached if
-	     * smallest item is larger than search template or
-	     * largest item is smaller than search template */
-	    if (trav->curr_node->link[dir] == NULL)
-		return trav->curr_node->data;
-
-	    trav->up[trav->top++] = trav->curr_node;
-	    trav->curr_node = trav->curr_node->link[dir];
-	}
-    }
-
-    return NULL;		/* should not happen */
-}
-
-/* two functions needed to fully traverse the tree: initialize and continue
- * useful to get all items in the tree non-recursively
- * this one here uses a stack
- * parent pointers or threads would also be possible
- * but these would need to be added to RB_NODE
- * -> more memory needed for standard operations
- */
-
-/* start traversing the tree
- * returns pointer to smallest data item
- */
-void *rbtree_first(struct RB_TRAV *trav)
-{
-    /* get smallest item */
-    while (trav->curr_node->link[0] != NULL) {
-	trav->up[trav->top++] = trav->curr_node;
-	trav->curr_node = trav->curr_node->link[0];
-    }
-
-    return trav->curr_node->data;	/* return smallest item */
-}
-
-/* continue traversing the tree in ascending order
- * returns pointer to data item, NULL when finished
- */
-void *rbtree_next(struct RB_TRAV *trav)
-{
-    if (trav->curr_node->link[1] != NULL) {
-	/* something on the right side: larger item */
-	trav->up[trav->top++] = trav->curr_node;
-	trav->curr_node = trav->curr_node->link[1];
-
-	/* go down, find smallest item in this branch */
-	while (trav->curr_node->link[0] != NULL) {
-	    trav->up[trav->top++] = trav->curr_node;
-	    trav->curr_node = trav->curr_node->link[0];
-	}
-    }
-    else {
-	/* at smallest item in this branch, go back up */
-	struct RB_NODE *last;
-
-	do {
-	    if (trav->top == 0) {
-		trav->curr_node = NULL;
-		break;
-	    }
-	    last = trav->curr_node;
-	    trav->curr_node = trav->up[--trav->top];
-	} while (last == trav->curr_node->link[1]);
-    }
-
-    if (trav->curr_node != NULL) {
-	return trav->curr_node->data;
-    }
-    else
-	return NULL;		/* finished traversing */
-}
-
-/* destroy the tree */
-void rbtree_destroy(struct RB_TREE *tree)
-{
-    rbtree_destroy2(tree->root);
-    G_free(tree);
-}
-
-void rbtree_destroy2(struct RB_NODE *root)
-{
-    if (root != NULL) {
-	rbtree_destroy2(root->link[0]);
-	rbtree_destroy2(root->link[1]);
-	G_free(root->data);
-	G_free(root);
-    }
-}
-
-/* used for debugging: check for errors in tree structure */
-int rbtree_debug(struct RB_TREE *tree, struct RB_NODE *root)
-{
-    int lh, rh;
-
-    if (root == NULL)
-	return 1;
-    else {
-	struct RB_NODE *ln = root->link[0];
-	struct RB_NODE *rn = root->link[1];
-	int lcmp = 0, rcmp = 0;
-
-	/* Consecutive red links */
-	if (is_red(root)) {
-	    if (is_red(ln) || is_red(rn)) {
-		G_warning("Red Black Tree debugging: Red violation");
-		return 0;
-	    }
-	}
-
-	lh = rbtree_debug(tree, ln);
-	rh = rbtree_debug(tree, rn);
-
-	if (ln) {
-	    lcmp = tree->rb_compare(ln->data, root->data);
-	}
-
-	if (rn) {
-	    rcmp = tree->rb_compare(rn->data, root->data);
-	}
-
-	/* Invalid binary search tree:
-	 * left node >= parent or right node <= parent */
-	if ((ln != NULL && lcmp > -1)
-	    || (rn != NULL && rcmp < 1)) {
-	    G_warning("Red Black Tree debugging: Binary tree violation");
-	    return 0;
-	}
-
-	/* Black height mismatch */
-	if (lh != 0 && rh != 0 && lh != rh) {
-	    G_warning("Red Black Tree debugging: Black violation");
-	    return 0;
-	}
-
-	/* Only count black links */
-	if (lh != 0 && rh != 0)
-	    return is_red(root) ? lh : lh + 1;
-	else
-	    return 0;
-    }
-}
-
-/*******************************************************
- *                                                     *
- *  internal functions for Red Black Tree maintenance  *
- *                                                     *
- *******************************************************/
-
-/* add a new node to the tree */
-struct RB_NODE *rbtree_make_node(size_t datasize, void *data)
-{
-    struct RB_NODE *new_node = G_malloc(sizeof(*new_node));
-
-    if (new_node == NULL)
-	G_fatal_error("RB Search Tree: Out of memory!");
-
-    new_node->data = G_malloc(datasize);
-    if (new_node->data == NULL)
-	G_fatal_error("RB Search Tree: Out of memory!");
-
-    memcpy(new_node->data, data, datasize);
-    new_node->red = 1;		/* 1 is red, 0 is black */
-    new_node->link[0] = NULL;
-    new_node->link[1] = NULL;
-
-    return new_node;
-}
-
-/* check for red violation */
-int is_red(struct RB_NODE *root)
-{
-    if (root)
-	return root->red == 1;
-
-    return 0;
-}
-
-/* single rotation */
-struct RB_NODE *rbtree_single(struct RB_NODE *root, int dir)
-{
-    struct RB_NODE *newroot = root->link[!dir];
-
-    root->link[!dir] = newroot->link[dir];
-    newroot->link[dir] = root;
-
-    root->red = 1;
-    newroot->red = 0;
-
-    return newroot;
-}
-
-/* double rotation */
-struct RB_NODE *rbtree_double(struct RB_NODE *root, int dir)
-{
-    root->link[!dir] = rbtree_single(root->link[!dir], !dir);
-    return rbtree_single(root, dir);
-}

Deleted: grass/trunk/raster/r.watershed/ram/rbtree.h
===================================================================
--- grass/trunk/raster/r.watershed/ram/rbtree.h	2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/raster/r.watershed/ram/rbtree.h	2010-05-18 09:42:14 UTC (rev 42281)
@@ -1,112 +0,0 @@
-/*************************************************************
- *                          USAGE                            *
- *************************************************************
- *
- * NOTE: duplicates are not supported
- *
- * custom compare function
- * extern int my_compare_fn(const void *, const void *);
- * int my_compare_fn(const void *a, const void *b) {
- *   if ((mydatastruct *) a < (mydatastruct *) b)
- *     return -1;
- *   else if ((mydatastruct *) a > (mydatastruct *) b)
- *     return 1;
- *   else if ((mydatastruct *) a == (mydatastruct *) b)
- *     return 0;
- * }
- * 
- * create and initialize tree:
- * struct RB_TREE *mytree = rbtree_create(my_compare_fn, item_size);
- *
- * insert items to tree:
- * struct mydatastruct data = <some data>;
- * if (rbtree_insert(mytree, &data) == 0)
- * 	 G_warning("could not insert data");
- *
- * find item in tree:
- * struct mydatastruct data = <some data>;
- * if (rbtree_find(mytree, &data) == 0)
- * 	 G_message("data not found");
- *
- * delete item from tree:
- * struct mydatastruct data = <some data>;
- * if (rbtree_remove(mytree, &data) == 0)
- * 	  G_warning("could not find data in tree");
- *
- * traverse tree (get all items in tree in ascending order):
- * struct RB_TRAV trav;
- * rbtree_init_trav(&trav, tree);
- * while ((data = rbtree_traverse(&trav)) != NULL) {
- *   if (my_compare_fn(data, threshold_data) == 0) break;
- * 	   <do something with data>;
- *  }
- *
- * get a selection of items: all data > data1 and < data2
- * start in tree where data is last smaller or first larger compared to data1
- * struct RB_TRAV trav;
- * rbtree_init_trav(&trav, tree);
- * data = rbtree_traverse_start(&trav, &data1);
- * 	 <do something with data>;
- * while ((data = rbtree_traverse(&trav)) != NULL) {
- *	 if (data > data2) break;
- *   <do something with data>;
- * }
- *
- * destroy tree:
- * rbtree_destroy(mytree);
- *
- * debug the whole tree with
- * rbtree_debug(mytree, mytree->root);
- * 
- *************************************************************/
-
-#include <stddef.h>
-
-/* maximum RB Tree height */
-#define RBTREE_MAX_HEIGHT 64        /* should be more than enough */
-
-/* routine to compare data items
- * return -1 if rb_a < rb_b
- * return  0 if rb_a == rb_b
- * return  1 if rb_a > rb_b
- */
-typedef int rb_compare_fn(const void *rb_a, const void *rb_b);
-
-struct RB_NODE
-{
-    unsigned char red;              /* 0 = black, 1 = red */
-    void *data;                     /* any kind of data */
-    struct RB_NODE *link[2];        /* link to children: link[0] for smaller, link[1] for larger */
-};
- 
-struct RB_TREE
-{
-    struct RB_NODE *root;           /* root node */
-    size_t datasize;                /* item size */
-    size_t count;                   /* number of items in tree. */
-    rb_compare_fn *rb_compare;      /* function to compare data */
-};
-
-struct RB_TRAV
-{
-    struct RB_TREE *tree;           /* tree being traversed */
-    struct RB_NODE *curr_node;      /* current node */
-    struct RB_NODE *up[RBTREE_MAX_HEIGHT];  /* stack of parent nodes */
-    int top;                        /* index for stack */
-    int first;                      /* little helper flag */
-};
-
-/* tree functions */
-struct RB_TREE *rbtree_create(rb_compare_fn *, size_t);
-void rbtree_destroy(struct RB_TREE *);
-int rbtree_insert(struct RB_TREE *, void *);
-int rbtree_remove(struct RB_TREE *, const void *);
-void *rbtree_find(struct RB_TREE *, const void *);
-
-/* tree traversal functions */
-int rbtree_init_trav(struct RB_TRAV *, struct RB_TREE *);
-void* rbtree_traverse(struct RB_TRAV *);
-void *rbtree_traverse_start(struct RB_TRAV *, const void *);
-
-/* debug tree from given node downwards */
-int rbtree_debug(struct RB_TREE *, struct RB_NODE *);



More information about the grass-commit mailing list