Module Name:    src
Committed By:   yamt
Date:           Mon May 25 14:54:06 UTC 2009

Modified Files:
        src/common/lib/libc/gen: rpst.c
        src/sys/sys: rpst.h

Log Message:
maintain parent node pointers to speed up search and node removal.


To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/common/lib/libc/gen/rpst.c
cvs rdiff -u -r1.1 -r1.2 src/sys/sys/rpst.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/common/lib/libc/gen/rpst.c
diff -u src/common/lib/libc/gen/rpst.c:1.4 src/common/lib/libc/gen/rpst.c:1.5
--- src/common/lib/libc/gen/rpst.c:1.4	Mon May 25 14:16:54 2009
+++ src/common/lib/libc/gen/rpst.c	Mon May 25 14:54:06 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: rpst.c,v 1.4 2009/05/25 14:16:54 yamt Exp $	*/
+/*	$NetBSD: rpst.c,v 1.5 2009/05/25 14:54:06 yamt Exp $	*/
 
 /*-
  * Copyright (c)2009 YAMAMOTO Takashi,
@@ -43,10 +43,10 @@
 #include <sys/cdefs.h>
 
 #if defined(_KERNEL)
-__KERNEL_RCSID(0, "$NetBSD: rpst.c,v 1.4 2009/05/25 14:16:54 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rpst.c,v 1.5 2009/05/25 14:54:06 yamt Exp $");
 #include <sys/param.h>
 #else /* defined(_KERNEL) */
-__RCSID("$NetBSD: rpst.c,v 1.4 2009/05/25 14:16:54 yamt Exp $");
+__RCSID("$NetBSD: rpst.c,v 1.5 2009/05/25 14:54:06 yamt Exp $");
 #include <assert.h>
 #include <stdbool.h>
 #include <string.h>
@@ -130,6 +130,22 @@
 }
 
 /*
+ * rpst_update_parents: update n_parent of children
+ */
+
+static inline void
+rpst_update_parents(struct rpst_node *n)
+{
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		if (n->n_children[i] != NULL) {
+			n->n_children[i]->n_parent = n;
+		}
+	}
+}
+
+/*
  * rpst_enlarge_tree: enlarge tree so that 'index' can be stored
  */
 
@@ -144,7 +160,9 @@
 			rpst_remove_node(t, n);
 			memset(&n->n_children, 0, sizeof(n->n_children));
 			n->n_children[0] = t->t_root;
+			t->t_root->n_parent = n;
 			t->t_root = n;
+			n->n_parent = NULL;
 		}
 		t->t_height++;
 	}
@@ -157,23 +175,32 @@
 static struct rpst_node *
 rpst_insert_node1(struct rpst_node **where, struct rpst_node *n, uint64_t mask)
 {
+	struct rpst_node *parent;
 	struct rpst_node *cur;
 	unsigned int idx;
 
 	KASSERT((n->n_x & ((-mask) << 1)) == 0);
+	parent = NULL;
 next:
 	cur = *where;
 	if (cur == NULL) {
+		n->n_parent = parent;
 		memset(&n->n_children, 0, sizeof(n->n_children));
 		*where = n;
 		return NULL;
 	}
+	KASSERT(cur->n_parent == parent);
 	if (n->n_y == cur->n_y && n->n_x == cur->n_x) {
 		return cur;
 	}
 	if (n->n_y < cur->n_y) {
-		/* swap cur and n */
+		/*
+		 * swap cur and n.
+		 * note that n is not in tree.
+		 */
 		memcpy(n->n_children, cur->n_children, sizeof(n->n_children));
+		n->n_parent = cur->n_parent;
+		rpst_update_parents(n);
 		*where = n;
 		n = cur;
 		cur = *where;
@@ -181,6 +208,7 @@
 	KASSERT(*where == cur);
 	idx = (n->n_x & mask) != 0;
 	where = &cur->n_children[idx];
+	parent = cur;
 	KASSERT((*where) == NULL || ((((*where)->n_x & mask) != 0) == idx));
 	KASSERT((*where) == NULL || (*where)->n_y >= cur->n_y);
 	mask >>= 1;
@@ -207,33 +235,26 @@
  * rpst_find_pptr: find a pointer to the given node.
  *
  * also, return the parent node via parentp.  (NULL for the root node.)
- *
- * XXX is it better to simply make each nodes have a pointer to parent?
  */
 
-static struct rpst_node **
-rpst_find_pptr(struct rpst_node **where, struct rpst_node *n, uint64_t mask,
+static inline struct rpst_node **
+rpst_find_pptr(struct rpst_tree *t, struct rpst_node *n,
     struct rpst_node **parentp)
 {
-	struct rpst_node *pn = NULL;
-	struct rpst_node *cur;
-	unsigned int idx;
+	struct rpst_node * const parent = n->n_parent;
+	unsigned int i;
 
-next:
-	cur = *where;
-	KASSERT(cur != NULL);
-	if (cur == n) {
-		KASSERT(pn == NULL || pn->n_y <= n->n_y);
-		*parentp = pn;
-		return where;
+	*parentp = parent;
+	if (parent == NULL) {
+		return &t->t_root;
 	}
-	idx = (n->n_x & mask) != 0;
-	pn = cur;
-	where = &cur->n_children[idx];
-	KASSERT((*where) == NULL || ((((*where)->n_x & mask) != 0) == idx));
-	KASSERT((*where) == NULL || (*where)->n_y >= cur->n_y);
-	mask >>= 1;
-	goto next;
+	for (i = 0; i < 2 - 1; i++) {
+		if (parent->n_children[i] == n) {
+			break;
+		}
+	}
+	KASSERT(parent->n_children[i] == n);
+	return &parent->n_children[i];
 }
 
 /*
@@ -241,22 +262,23 @@
  */
 
 static void
-rpst_remove_node_at(struct rpst_node **where)
+rpst_remove_node_at(struct rpst_node *parent, struct rpst_node **where,
+    struct rpst_node *cur)
 {
 	struct rpst_node *tmp[2];
-	struct rpst_node *cur;
 	struct rpst_node *selected;
-	unsigned int selected_idx;
+	unsigned int selected_idx = 0; /* XXX gcc */
 	unsigned int i;
 
-	cur = *where;
 	KASSERT(cur != NULL);
+	KASSERT(parent == cur->n_parent);
 next:
 	selected = NULL;
 	for (i = 0; i < 2; i++) {
 		struct rpst_node *c;
 
 		c = cur->n_children[i];
+		KASSERT(c == NULL || c->n_parent == cur);
 		if (selected == NULL || (c != NULL && c->n_y < selected->n_y)) {
 			selected = c;
 			selected_idx = i;
@@ -265,6 +287,7 @@
 	/*
 	 * now we have:
 	 *
+	 *      parent
 	 *          \ <- where
 	 *           cur
 	 *           / \
@@ -282,7 +305,11 @@
 	memcpy(tmp, selected->n_children, sizeof(tmp));
 	memcpy(selected->n_children, cur->n_children, sizeof(tmp));
 	memcpy(cur->n_children, tmp, sizeof(tmp));
+	rpst_update_parents(cur);
+	rpst_update_parents(selected);
+	selected->n_parent = parent;
 	/*
+	 *      parent
 	 *          \ <- where
 	 *          selected
 	 *           / \
@@ -294,15 +321,20 @@
 	 */
 	where = &selected->n_children[selected_idx];
 	/*
+	 *      parent
 	 *          \
 	 *          selected
 	 *           / \ <- where
-	 *          A  selected
+	 *          A  selected (*)
 	 *
-	 *              cur
+	 *              cur (**)
 	 *              / \
 	 *             B   C
+	 *
+	 * (*) this 'selected' will be overwritten in the next iteration.
+	 * (**) cur->n_parent is bogus.
 	 */
+	parent = selected;
 	goto next;
 }
 
@@ -316,9 +348,8 @@
 	struct rpst_node *parent;
 	struct rpst_node **where;
 
-	where = rpst_find_pptr(&t->t_root, n, rpst_startmask(t), &parent);
-	KASSERT(*where == n);
-	rpst_remove_node_at(where);
+	where = rpst_find_pptr(t, n, &parent);
+	rpst_remove_node_at(parent, where, n);
 }
 
 static bool __unused
@@ -432,7 +463,7 @@
 	} else if (idx == maxidx + 2) { /* back to the parent */
 		struct rpst_node **where;
 
-		where = rpst_find_pptr(&t->t_root, n, rpst_startmask(t), &next);
+		where = rpst_find_pptr(t, n, &next);
 		if (next == NULL) {
 			KASSERT(level == 0);
 			KASSERT(t->t_root == n);
@@ -455,6 +486,7 @@
 		idx++;
 		goto next;
 	}
+	KASSERT(next->n_parent == n);
 	KASSERT(next->n_y >= n->n_y);
 	level++;
 	mask >>= 1;

Index: src/sys/sys/rpst.h
diff -u src/sys/sys/rpst.h:1.1 src/sys/sys/rpst.h:1.2
--- src/sys/sys/rpst.h:1.1	Tue May 19 12:39:56 2009
+++ src/sys/sys/rpst.h	Mon May 25 14:54:06 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: rpst.h,v 1.1 2009/05/19 12:39:56 yamt Exp $	*/
+/*	$NetBSD: rpst.h,v 1.2 2009/05/25 14:54:06 yamt Exp $	*/
 
 /*-
  * Copyright (c)2009 YAMAMOTO Takashi,
@@ -41,6 +41,7 @@
 };
 
 struct rpst_node {
+	struct rpst_node *n_parent;
 	struct rpst_node *n_children[2];
 	uint64_t n_y;
 	uint64_t n_x;

Reply via email to