Home | History | Annotate | Line # | Download | only in gen
rpst.c revision 1.11
      1  1.11  yamt /*	$NetBSD: rpst.c,v 1.11 2011/04/26 20:53:34 yamt Exp $	*/
      2   1.1  yamt 
      3   1.1  yamt /*-
      4   1.1  yamt  * Copyright (c)2009 YAMAMOTO Takashi,
      5   1.1  yamt  * All rights reserved.
      6   1.1  yamt  *
      7   1.1  yamt  * Redistribution and use in source and binary forms, with or without
      8   1.1  yamt  * modification, are permitted provided that the following conditions
      9   1.1  yamt  * are met:
     10   1.1  yamt  * 1. Redistributions of source code must retain the above copyright
     11   1.1  yamt  *    notice, this list of conditions and the following disclaimer.
     12   1.1  yamt  * 2. Redistributions in binary form must reproduce the above copyright
     13   1.1  yamt  *    notice, this list of conditions and the following disclaimer in the
     14   1.1  yamt  *    documentation and/or other materials provided with the distribution.
     15   1.1  yamt  *
     16   1.1  yamt  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17   1.1  yamt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18   1.1  yamt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19   1.1  yamt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20   1.1  yamt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21   1.1  yamt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22   1.1  yamt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23   1.1  yamt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24   1.1  yamt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25   1.1  yamt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26   1.1  yamt  * SUCH DAMAGE.
     27   1.1  yamt  */
     28   1.1  yamt 
     29   1.1  yamt /*
     30   1.1  yamt  * radix priority search tree
     31   1.1  yamt  *
     32   1.1  yamt  * described in:
     33   1.1  yamt  *	SIAM J. COMPUT.
     34   1.1  yamt  *	Vol. 14, No. 2, May 1985
     35   1.1  yamt  *	PRIORITY SEARCH TREES
     36   1.1  yamt  *	EDWARD M. McCREIGHT
     37   1.1  yamt  *
     38   1.1  yamt  * ideas from linux:
     39   1.1  yamt  *	- grow tree height on-demand.
     40   1.1  yamt  *	- allow duplicated X values.  in that case, we act as a heap.
     41   1.1  yamt  */
     42   1.1  yamt 
     43   1.1  yamt #include <sys/cdefs.h>
     44   1.1  yamt 
     45  1.10  yamt #if defined(_KERNEL) || defined(_STANDALONE)
     46  1.11  yamt __KERNEL_RCSID(0, "$NetBSD: rpst.c,v 1.11 2011/04/26 20:53:34 yamt Exp $");
     47   1.1  yamt #include <sys/param.h>
     48  1.11  yamt #include <lib/libkern/libkern.h>
     49  1.11  yamt #if defined(_STANDALONE)
     50  1.11  yamt #include <lib/libsa/stand.h>
     51  1.11  yamt #endif /* defined(_STANDALONE) */
     52  1.10  yamt #else /* defined(_KERNEL) || defined(_STANDALONE) */
     53  1.11  yamt __RCSID("$NetBSD: rpst.c,v 1.11 2011/04/26 20:53:34 yamt Exp $");
     54   1.1  yamt #include <assert.h>
     55   1.1  yamt #include <stdbool.h>
     56   1.1  yamt #include <string.h>
     57   1.2  yamt #if 1
     58   1.1  yamt #define	KASSERT	assert
     59   1.2  yamt #else
     60   1.2  yamt #define	KASSERT(a)
     61   1.2  yamt #endif
     62  1.10  yamt #endif /* defined(_KERNEL) || defined(_STANDALONE) */
     63   1.1  yamt 
     64   1.1  yamt #include <sys/rpst.h>
     65   1.1  yamt 
     66   1.1  yamt /*
     67   1.1  yamt  * rpst_init_tree: initialize a tree.
     68   1.1  yamt  */
     69   1.1  yamt 
     70   1.1  yamt void
     71   1.1  yamt rpst_init_tree(struct rpst_tree *t)
     72   1.1  yamt {
     73   1.1  yamt 
     74   1.1  yamt 	t->t_root = NULL;
     75   1.1  yamt 	t->t_height = 0;
     76   1.1  yamt }
     77   1.1  yamt 
     78   1.1  yamt /*
     79   1.1  yamt  * rpst_height2max: calculate the maximum index which can be handled by
     80   1.1  yamt  * a tree with the given height.
     81   1.1  yamt  *
     82   1.1  yamt  * 0  ... 0x0000000000000001
     83   1.1  yamt  * 1  ... 0x0000000000000003
     84   1.1  yamt  * 2  ... 0x0000000000000007
     85   1.1  yamt  * 3  ... 0x000000000000000f
     86   1.1  yamt  *
     87   1.1  yamt  * 31 ... 0x00000000ffffffff
     88   1.1  yamt  *
     89   1.1  yamt  * 63 ... 0xffffffffffffffff
     90   1.1  yamt  */
     91   1.1  yamt 
     92   1.1  yamt static uint64_t
     93   1.1  yamt rpst_height2max(unsigned int height)
     94   1.1  yamt {
     95   1.1  yamt 
     96   1.1  yamt 	KASSERT(height < 64);
     97   1.1  yamt 	if (height == 63) {
     98   1.1  yamt 		return UINT64_MAX;
     99   1.1  yamt 	}
    100   1.1  yamt 	return (UINT64_C(1) << (height + 1)) - 1;
    101   1.1  yamt }
    102   1.1  yamt 
    103   1.1  yamt /*
    104   1.2  yamt  * rpst_level2mask: calculate the mask for the given level in the tree.
    105   1.2  yamt  *
    106   1.2  yamt  * the mask used to index root's children is level 0.
    107   1.2  yamt  */
    108   1.2  yamt 
    109   1.2  yamt static uint64_t
    110   1.2  yamt rpst_level2mask(const struct rpst_tree *t, unsigned int level)
    111   1.2  yamt {
    112   1.2  yamt 	uint64_t mask;
    113   1.2  yamt 
    114   1.2  yamt 	if (t->t_height < level) {
    115   1.2  yamt 		mask = 0;
    116   1.2  yamt 	} else {
    117   1.2  yamt 		mask = UINT64_C(1) << (t->t_height - level);
    118   1.2  yamt 	}
    119   1.2  yamt 	return mask;
    120   1.2  yamt }
    121   1.2  yamt 
    122   1.2  yamt /*
    123   1.1  yamt  * rpst_startmask: calculate the mask for the start of a search.
    124   1.1  yamt  * (ie. the mask for the top-most bit)
    125   1.1  yamt  */
    126   1.1  yamt 
    127   1.1  yamt static uint64_t
    128   1.1  yamt rpst_startmask(const struct rpst_tree *t)
    129   1.1  yamt {
    130   1.2  yamt 	const uint64_t mask = rpst_level2mask(t, 0);
    131   1.1  yamt 
    132   1.2  yamt 	KASSERT((mask | (mask - 1)) == rpst_height2max(t->t_height));
    133   1.2  yamt 	return mask;
    134   1.1  yamt }
    135   1.1  yamt 
    136   1.1  yamt /*
    137   1.5  yamt  * rpst_update_parents: update n_parent of children
    138   1.5  yamt  */
    139   1.5  yamt 
    140   1.5  yamt static inline void
    141   1.5  yamt rpst_update_parents(struct rpst_node *n)
    142   1.5  yamt {
    143   1.5  yamt 	int i;
    144   1.5  yamt 
    145   1.5  yamt 	for (i = 0; i < 2; i++) {
    146   1.5  yamt 		if (n->n_children[i] != NULL) {
    147   1.5  yamt 			n->n_children[i]->n_parent = n;
    148   1.5  yamt 		}
    149   1.5  yamt 	}
    150   1.5  yamt }
    151   1.5  yamt 
    152   1.5  yamt /*
    153   1.9  yamt  * rpst_enlarge_tree: enlarge tree so that 'idx' can be stored
    154   1.1  yamt  */
    155   1.1  yamt 
    156   1.1  yamt static void
    157   1.1  yamt rpst_enlarge_tree(struct rpst_tree *t, uint64_t idx)
    158   1.1  yamt {
    159   1.1  yamt 
    160   1.1  yamt 	while (idx > rpst_height2max(t->t_height)) {
    161   1.1  yamt 		struct rpst_node *n = t->t_root;
    162   1.1  yamt 
    163   1.1  yamt 		if (n != NULL) {
    164   1.1  yamt 			rpst_remove_node(t, n);
    165   1.1  yamt 			memset(&n->n_children, 0, sizeof(n->n_children));
    166   1.1  yamt 			n->n_children[0] = t->t_root;
    167   1.5  yamt 			t->t_root->n_parent = n;
    168   1.1  yamt 			t->t_root = n;
    169   1.5  yamt 			n->n_parent = NULL;
    170   1.1  yamt 		}
    171   1.1  yamt 		t->t_height++;
    172   1.1  yamt 	}
    173   1.1  yamt }
    174   1.1  yamt 
    175   1.1  yamt /*
    176   1.1  yamt  * rpst_insert_node1: a helper for rpst_insert_node.
    177   1.1  yamt  */
    178   1.1  yamt 
    179   1.1  yamt static struct rpst_node *
    180   1.1  yamt rpst_insert_node1(struct rpst_node **where, struct rpst_node *n, uint64_t mask)
    181   1.1  yamt {
    182   1.5  yamt 	struct rpst_node *parent;
    183   1.1  yamt 	struct rpst_node *cur;
    184   1.1  yamt 	unsigned int idx;
    185   1.1  yamt 
    186   1.1  yamt 	KASSERT((n->n_x & ((-mask) << 1)) == 0);
    187   1.5  yamt 	parent = NULL;
    188   1.1  yamt next:
    189   1.1  yamt 	cur = *where;
    190   1.1  yamt 	if (cur == NULL) {
    191   1.5  yamt 		n->n_parent = parent;
    192   1.1  yamt 		memset(&n->n_children, 0, sizeof(n->n_children));
    193   1.1  yamt 		*where = n;
    194   1.1  yamt 		return NULL;
    195   1.1  yamt 	}
    196   1.5  yamt 	KASSERT(cur->n_parent == parent);
    197   1.3  yamt 	if (n->n_y == cur->n_y && n->n_x == cur->n_x) {
    198   1.1  yamt 		return cur;
    199   1.1  yamt 	}
    200   1.1  yamt 	if (n->n_y < cur->n_y) {
    201   1.5  yamt 		/*
    202   1.5  yamt 		 * swap cur and n.
    203   1.5  yamt 		 * note that n is not in tree.
    204   1.5  yamt 		 */
    205   1.1  yamt 		memcpy(n->n_children, cur->n_children, sizeof(n->n_children));
    206   1.5  yamt 		n->n_parent = cur->n_parent;
    207   1.5  yamt 		rpst_update_parents(n);
    208   1.1  yamt 		*where = n;
    209   1.1  yamt 		n = cur;
    210   1.1  yamt 		cur = *where;
    211   1.1  yamt 	}
    212   1.1  yamt 	KASSERT(*where == cur);
    213   1.1  yamt 	idx = (n->n_x & mask) != 0;
    214   1.1  yamt 	where = &cur->n_children[idx];
    215   1.5  yamt 	parent = cur;
    216   1.2  yamt 	KASSERT((*where) == NULL || ((((*where)->n_x & mask) != 0) == idx));
    217   1.2  yamt 	KASSERT((*where) == NULL || (*where)->n_y >= cur->n_y);
    218   1.1  yamt 	mask >>= 1;
    219   1.1  yamt 	goto next;
    220   1.1  yamt }
    221   1.1  yamt 
    222   1.1  yamt /*
    223   1.1  yamt  * rpst_insert_node: insert a node into the tree.
    224   1.1  yamt  *
    225   1.1  yamt  * => return NULL on success.
    226   1.1  yamt  * => if a duplicated node (a node with the same X,Y pair as ours) is found,
    227   1.1  yamt  *    return the node.  in that case, the tree is intact.
    228   1.1  yamt  */
    229   1.1  yamt 
    230   1.1  yamt struct rpst_node *
    231   1.1  yamt rpst_insert_node(struct rpst_tree *t, struct rpst_node *n)
    232   1.1  yamt {
    233   1.1  yamt 
    234   1.1  yamt 	rpst_enlarge_tree(t, n->n_x);
    235   1.1  yamt 	return rpst_insert_node1(&t->t_root, n, rpst_startmask(t));
    236   1.1  yamt }
    237   1.1  yamt 
    238   1.1  yamt /*
    239   1.1  yamt  * rpst_find_pptr: find a pointer to the given node.
    240   1.1  yamt  *
    241   1.1  yamt  * also, return the parent node via parentp.  (NULL for the root node.)
    242   1.1  yamt  */
    243   1.1  yamt 
    244   1.5  yamt static inline struct rpst_node **
    245   1.5  yamt rpst_find_pptr(struct rpst_tree *t, struct rpst_node *n,
    246   1.1  yamt     struct rpst_node **parentp)
    247   1.1  yamt {
    248   1.5  yamt 	struct rpst_node * const parent = n->n_parent;
    249   1.5  yamt 	unsigned int i;
    250   1.1  yamt 
    251   1.5  yamt 	*parentp = parent;
    252   1.5  yamt 	if (parent == NULL) {
    253   1.5  yamt 		return &t->t_root;
    254   1.5  yamt 	}
    255   1.5  yamt 	for (i = 0; i < 2 - 1; i++) {
    256   1.5  yamt 		if (parent->n_children[i] == n) {
    257   1.5  yamt 			break;
    258   1.5  yamt 		}
    259   1.1  yamt 	}
    260   1.5  yamt 	KASSERT(parent->n_children[i] == n);
    261   1.5  yamt 	return &parent->n_children[i];
    262   1.1  yamt }
    263   1.1  yamt 
    264   1.1  yamt /*
    265   1.1  yamt  * rpst_remove_node_at: remove a node at *where.
    266   1.1  yamt  */
    267   1.1  yamt 
    268   1.1  yamt static void
    269   1.5  yamt rpst_remove_node_at(struct rpst_node *parent, struct rpst_node **where,
    270   1.5  yamt     struct rpst_node *cur)
    271   1.1  yamt {
    272   1.1  yamt 	struct rpst_node *tmp[2];
    273   1.1  yamt 	struct rpst_node *selected;
    274   1.5  yamt 	unsigned int selected_idx = 0; /* XXX gcc */
    275   1.1  yamt 	unsigned int i;
    276   1.1  yamt 
    277   1.1  yamt 	KASSERT(cur != NULL);
    278   1.5  yamt 	KASSERT(parent == cur->n_parent);
    279   1.1  yamt next:
    280   1.1  yamt 	selected = NULL;
    281   1.1  yamt 	for (i = 0; i < 2; i++) {
    282   1.1  yamt 		struct rpst_node *c;
    283   1.1  yamt 
    284   1.1  yamt 		c = cur->n_children[i];
    285   1.5  yamt 		KASSERT(c == NULL || c->n_parent == cur);
    286   1.1  yamt 		if (selected == NULL || (c != NULL && c->n_y < selected->n_y)) {
    287   1.1  yamt 			selected = c;
    288   1.1  yamt 			selected_idx = i;
    289   1.1  yamt 		}
    290   1.1  yamt 	}
    291   1.4  yamt 	/*
    292   1.4  yamt 	 * now we have:
    293   1.4  yamt 	 *
    294   1.5  yamt 	 *      parent
    295   1.4  yamt 	 *          \ <- where
    296   1.4  yamt 	 *           cur
    297   1.4  yamt 	 *           / \
    298   1.4  yamt 	 *          A  selected
    299   1.4  yamt 	 *              / \
    300   1.4  yamt 	 *             B   C
    301   1.4  yamt 	 */
    302   1.1  yamt 	*where = selected;
    303   1.1  yamt 	if (selected == NULL) {
    304   1.1  yamt 		return;
    305   1.1  yamt 	}
    306   1.1  yamt 	/*
    307   1.1  yamt 	 * swap selected->n_children and cur->n_children.
    308   1.1  yamt 	 */
    309   1.1  yamt 	memcpy(tmp, selected->n_children, sizeof(tmp));
    310   1.1  yamt 	memcpy(selected->n_children, cur->n_children, sizeof(tmp));
    311   1.1  yamt 	memcpy(cur->n_children, tmp, sizeof(tmp));
    312   1.5  yamt 	rpst_update_parents(cur);
    313   1.5  yamt 	rpst_update_parents(selected);
    314   1.5  yamt 	selected->n_parent = parent;
    315   1.4  yamt 	/*
    316   1.5  yamt 	 *      parent
    317   1.4  yamt 	 *          \ <- where
    318   1.4  yamt 	 *          selected
    319   1.4  yamt 	 *           / \
    320   1.4  yamt 	 *          A  selected
    321   1.4  yamt 	 *
    322   1.4  yamt 	 *              cur
    323   1.4  yamt 	 *              / \
    324   1.4  yamt 	 *             B   C
    325   1.4  yamt 	 */
    326   1.1  yamt 	where = &selected->n_children[selected_idx];
    327   1.4  yamt 	/*
    328   1.5  yamt 	 *      parent
    329   1.4  yamt 	 *          \
    330   1.4  yamt 	 *          selected
    331   1.4  yamt 	 *           / \ <- where
    332   1.5  yamt 	 *          A  selected (*)
    333   1.4  yamt 	 *
    334   1.5  yamt 	 *              cur (**)
    335   1.4  yamt 	 *              / \
    336   1.4  yamt 	 *             B   C
    337   1.5  yamt 	 *
    338   1.5  yamt 	 * (*) this 'selected' will be overwritten in the next iteration.
    339   1.5  yamt 	 * (**) cur->n_parent is bogus.
    340   1.4  yamt 	 */
    341   1.5  yamt 	parent = selected;
    342   1.1  yamt 	goto next;
    343   1.1  yamt }
    344   1.1  yamt 
    345   1.1  yamt /*
    346   1.1  yamt  * rpst_remove_node: remove a node from the tree.
    347   1.1  yamt  */
    348   1.1  yamt 
    349   1.1  yamt void
    350   1.1  yamt rpst_remove_node(struct rpst_tree *t, struct rpst_node *n)
    351   1.1  yamt {
    352   1.1  yamt 	struct rpst_node *parent;
    353   1.1  yamt 	struct rpst_node **where;
    354   1.1  yamt 
    355   1.5  yamt 	where = rpst_find_pptr(t, n, &parent);
    356   1.5  yamt 	rpst_remove_node_at(parent, where, n);
    357   1.1  yamt }
    358   1.1  yamt 
    359   1.1  yamt static bool __unused
    360   1.1  yamt rpst_iterator_match_p(const struct rpst_node *n, const struct rpst_iterator *it)
    361   1.1  yamt {
    362   1.1  yamt 
    363   1.1  yamt 	if (n->n_y > it->it_max_y) {
    364   1.1  yamt 		return false;
    365   1.1  yamt 	}
    366   1.1  yamt 	if (n->n_x < it->it_min_x) {
    367   1.1  yamt 		return false;
    368   1.1  yamt 	}
    369   1.1  yamt 	if (n->n_x > it->it_max_x) {
    370   1.1  yamt 		return false;
    371   1.1  yamt 	}
    372   1.1  yamt 	return true;
    373   1.1  yamt }
    374   1.1  yamt 
    375   1.1  yamt struct rpst_node *
    376   1.1  yamt rpst_iterate_first(struct rpst_tree *t, uint64_t max_y, uint64_t min_x,
    377   1.1  yamt     uint64_t max_x, struct rpst_iterator *it)
    378   1.1  yamt {
    379   1.1  yamt 	struct rpst_node *n;
    380   1.1  yamt 
    381   1.1  yamt 	KASSERT(min_x <= max_x);
    382   1.1  yamt 	n = t->t_root;
    383   1.2  yamt 	if (n == NULL || n->n_y > max_y) {
    384   1.1  yamt 		return NULL;
    385   1.1  yamt 	}
    386   1.7  yamt 	if (rpst_height2max(t->t_height) < min_x) {
    387   1.7  yamt 		return NULL;
    388   1.7  yamt 	}
    389   1.1  yamt 	it->it_tree = t;
    390   1.1  yamt 	it->it_cur = n;
    391   1.2  yamt 	it->it_idx = (min_x & rpst_startmask(t)) != 0;
    392   1.1  yamt 	it->it_level = 0;
    393   1.1  yamt 	it->it_max_y = max_y;
    394   1.1  yamt 	it->it_min_x = min_x;
    395   1.1  yamt 	it->it_max_x = max_x;
    396   1.1  yamt 	return rpst_iterate_next(it);
    397   1.1  yamt }
    398   1.1  yamt 
    399   1.6  yamt static inline unsigned int
    400   1.2  yamt rpst_node_on_edge_p(const struct rpst_node *n, uint64_t val, uint64_t mask)
    401   1.2  yamt {
    402   1.2  yamt 
    403   1.2  yamt 	return ((n->n_x ^ val) & ((-mask) << 1)) == 0;
    404   1.2  yamt }
    405   1.2  yamt 
    406   1.6  yamt static inline uint64_t
    407   1.2  yamt rpst_maxidx(const struct rpst_node *n, uint64_t max_x, uint64_t mask)
    408   1.2  yamt {
    409   1.2  yamt 
    410   1.2  yamt 	if (rpst_node_on_edge_p(n, max_x, mask)) {
    411   1.2  yamt 		return (max_x & mask) != 0;
    412   1.2  yamt 	} else {
    413   1.2  yamt 		return 1;
    414   1.2  yamt 	}
    415   1.2  yamt }
    416   1.2  yamt 
    417   1.6  yamt static inline uint64_t
    418   1.2  yamt rpst_minidx(const struct rpst_node *n, uint64_t min_x, uint64_t mask)
    419   1.2  yamt {
    420   1.2  yamt 
    421   1.2  yamt 	if (rpst_node_on_edge_p(n, min_x, mask)) {
    422   1.2  yamt 		return (min_x & mask) != 0;
    423   1.2  yamt 	} else {
    424   1.2  yamt 		return 0;
    425   1.2  yamt 	}
    426   1.2  yamt }
    427   1.2  yamt 
    428   1.1  yamt struct rpst_node *
    429   1.1  yamt rpst_iterate_next(struct rpst_iterator *it)
    430   1.1  yamt {
    431   1.1  yamt 	struct rpst_tree *t;
    432   1.1  yamt 	struct rpst_node *n;
    433   1.1  yamt 	struct rpst_node *next;
    434   1.1  yamt 	const uint64_t max_y = it->it_max_y;
    435   1.1  yamt 	const uint64_t min_x = it->it_min_x;
    436   1.1  yamt 	const uint64_t max_x = it->it_max_x;
    437   1.1  yamt 	unsigned int idx;
    438   1.1  yamt 	unsigned int maxidx;
    439   1.1  yamt 	unsigned int level;
    440   1.1  yamt 	uint64_t mask;
    441   1.1  yamt 
    442   1.1  yamt 	t = it->it_tree;
    443   1.1  yamt 	n = it->it_cur;
    444   1.1  yamt 	idx = it->it_idx;
    445   1.1  yamt 	level = it->it_level;
    446   1.1  yamt 	mask = rpst_level2mask(t, level);
    447   1.2  yamt 	maxidx = rpst_maxidx(n, max_x, mask);
    448   1.1  yamt 	KASSERT(n == t->t_root || rpst_iterator_match_p(n, it));
    449   1.1  yamt next:
    450   1.1  yamt 	KASSERT(mask == rpst_level2mask(t, level));
    451   1.2  yamt 	KASSERT(idx >= rpst_minidx(n, min_x, mask));
    452   1.2  yamt 	KASSERT(maxidx == rpst_maxidx(n, max_x, mask));
    453   1.1  yamt 	KASSERT(idx <= maxidx + 2);
    454   1.1  yamt 	KASSERT(n != NULL);
    455   1.1  yamt #if 0
    456   1.1  yamt 	printf("%s: cur=%p, idx=%u maxidx=%u level=%u mask=%" PRIx64 "\n",
    457   1.1  yamt 	    __func__, (void *)n, idx, maxidx, level, mask);
    458   1.1  yamt #endif
    459   1.1  yamt 	if (idx == maxidx + 1) { /* visit the current node */
    460   1.1  yamt 		idx++;
    461   1.1  yamt 		if (min_x <= n->n_x && n->n_x <= max_x) {
    462   1.1  yamt 			it->it_cur = n;
    463   1.1  yamt 			it->it_idx = idx;
    464   1.1  yamt 			it->it_level = level;
    465   1.1  yamt 			KASSERT(rpst_iterator_match_p(n, it));
    466   1.1  yamt 			return n; /* report */
    467   1.1  yamt 		}
    468   1.1  yamt 		goto next;
    469   1.1  yamt 	} else if (idx == maxidx + 2) { /* back to the parent */
    470   1.1  yamt 		struct rpst_node **where;
    471   1.1  yamt 
    472   1.5  yamt 		where = rpst_find_pptr(t, n, &next);
    473   1.1  yamt 		if (next == NULL) {
    474   1.1  yamt 			KASSERT(level == 0);
    475   1.1  yamt 			KASSERT(t->t_root == n);
    476   1.1  yamt 			KASSERT(&t->t_root == where);
    477   1.1  yamt 			return NULL; /* done */
    478   1.1  yamt 		}
    479   1.1  yamt 		KASSERT(level > 0);
    480   1.1  yamt 		level--;
    481   1.2  yamt 		n = next;
    482   1.1  yamt 		mask = rpst_level2mask(t, level);
    483   1.2  yamt 		maxidx = rpst_maxidx(n, max_x, mask);
    484   1.1  yamt 		idx = where - n->n_children + 1;
    485   1.1  yamt 		KASSERT(idx < 2 + 1);
    486   1.1  yamt 		goto next;
    487   1.1  yamt 	}
    488   1.1  yamt 	/* go to a child */
    489   1.1  yamt 	KASSERT(idx < 2);
    490   1.1  yamt 	next = n->n_children[idx];
    491   1.1  yamt 	if (next == NULL || next->n_y > max_y) {
    492   1.1  yamt 		idx++;
    493   1.1  yamt 		goto next;
    494   1.1  yamt 	}
    495   1.5  yamt 	KASSERT(next->n_parent == n);
    496   1.2  yamt 	KASSERT(next->n_y >= n->n_y);
    497   1.1  yamt 	level++;
    498   1.1  yamt 	mask >>= 1;
    499   1.1  yamt 	n = next;
    500   1.2  yamt 	idx = rpst_minidx(n, min_x, mask);
    501   1.2  yamt 	maxidx = rpst_maxidx(n, max_x, mask);
    502   1.2  yamt #if 0
    503   1.2  yamt 	printf("%s: visit %p idx=%u level=%u mask=%llx\n",
    504   1.2  yamt 	    __func__, n, idx, level, mask);
    505   1.2  yamt #endif
    506   1.1  yamt 	goto next;
    507   1.1  yamt }
    508   1.1  yamt 
    509   1.1  yamt #if defined(UNITTEST)
    510   1.1  yamt #include <sys/time.h>
    511   1.1  yamt 
    512   1.1  yamt #include <inttypes.h>
    513   1.1  yamt #include <stdio.h>
    514   1.1  yamt #include <stdlib.h>
    515   1.1  yamt 
    516   1.1  yamt static void
    517   1.1  yamt rpst_dump_node(const struct rpst_node *n, unsigned int depth)
    518   1.1  yamt {
    519   1.1  yamt 	unsigned int i;
    520   1.1  yamt 
    521   1.1  yamt 	for (i = 0; i < depth; i++) {
    522   1.1  yamt 		printf("  ");
    523   1.1  yamt 	}
    524   1.1  yamt 	printf("[%u]", depth);
    525   1.1  yamt 	if (n == NULL) {
    526   1.1  yamt 		printf("NULL\n");
    527   1.1  yamt 		return;
    528   1.1  yamt 	}
    529   1.1  yamt 	printf("%p x=%" PRIx64 "(%" PRIu64 ") y=%" PRIx64 "(%" PRIu64 ")\n",
    530   1.1  yamt 	    (const void *)n, n->n_x, n->n_x, n->n_y, n->n_y);
    531   1.1  yamt 	for (i = 0; i < 2; i++) {
    532   1.1  yamt 		rpst_dump_node(n->n_children[i], depth + 1);
    533   1.1  yamt 	}
    534   1.1  yamt }
    535   1.1  yamt 
    536   1.1  yamt static void
    537   1.1  yamt rpst_dump_tree(const struct rpst_tree *t)
    538   1.1  yamt {
    539   1.1  yamt 
    540   1.2  yamt 	printf("pst %p height=%u\n", (const void *)t, t->t_height);
    541   1.1  yamt 	rpst_dump_node(t->t_root, 0);
    542   1.1  yamt }
    543   1.1  yamt 
    544   1.1  yamt struct testnode {
    545   1.1  yamt 	struct rpst_node n;
    546   1.1  yamt 	struct testnode *next;
    547   1.2  yamt 	bool failed;
    548   1.2  yamt 	bool found;
    549   1.1  yamt };
    550   1.1  yamt 
    551   1.2  yamt struct rpst_tree t;
    552   1.2  yamt struct testnode *h = NULL;
    553   1.2  yamt 
    554   1.2  yamt static uintmax_t
    555   1.2  yamt tvdiff(const struct timeval *tv1, const struct timeval *tv2)
    556   1.2  yamt {
    557   1.2  yamt 
    558   1.2  yamt 	return (uintmax_t)tv1->tv_sec * 1000000 + tv1->tv_usec -
    559   1.2  yamt 	    tv2->tv_sec * 1000000 - tv2->tv_usec;
    560   1.2  yamt }
    561   1.2  yamt 
    562   1.2  yamt static unsigned int
    563   1.2  yamt query(uint64_t max_y, uint64_t min_x, uint64_t max_x)
    564   1.2  yamt {
    565   1.2  yamt 	struct testnode *n;
    566   1.2  yamt 	struct rpst_node *rn;
    567   1.2  yamt 	struct rpst_iterator it;
    568   1.2  yamt 	struct timeval start;
    569   1.2  yamt 	struct timeval end;
    570   1.2  yamt 	unsigned int done;
    571   1.2  yamt 
    572   1.2  yamt 	printf("quering max_y=%" PRIu64 " min_x=%" PRIu64 " max_x=%" PRIu64
    573   1.2  yamt 	    "\n",
    574   1.2  yamt 	    max_y, min_x, max_x);
    575   1.2  yamt 	done = 0;
    576   1.2  yamt 	gettimeofday(&start, NULL);
    577   1.2  yamt 	for (rn = rpst_iterate_first(&t, max_y, min_x, max_x, &it);
    578   1.2  yamt 	    rn != NULL;
    579   1.2  yamt 	    rn = rpst_iterate_next(&it)) {
    580   1.2  yamt 		done++;
    581   1.2  yamt #if 0
    582   1.2  yamt 		printf("found %p x=%" PRIu64 " y=%" PRIu64 "\n",
    583   1.2  yamt 		    (void *)rn, rn->n_x, rn->n_y);
    584   1.2  yamt #endif
    585   1.2  yamt 		n = (void *)rn;
    586   1.2  yamt 		assert(!n->found);
    587   1.2  yamt 		n->found = true;
    588   1.2  yamt 	}
    589   1.2  yamt 	gettimeofday(&end, NULL);
    590   1.2  yamt 	printf("%u nodes found in %ju usecs\n", done,
    591   1.2  yamt 	    tvdiff(&end, &start));
    592   1.2  yamt 
    593   1.2  yamt 	gettimeofday(&start, NULL);
    594   1.2  yamt 	for (n = h; n != NULL; n = n->next) {
    595   1.2  yamt 		assert(n->failed ||
    596   1.2  yamt 		    n->found == rpst_iterator_match_p(&n->n, &it));
    597   1.2  yamt 		n->found = false;
    598   1.2  yamt 	}
    599   1.2  yamt 	gettimeofday(&end, NULL);
    600   1.2  yamt 	printf("(linear search took %ju usecs)\n", tvdiff(&end, &start));
    601   1.2  yamt 	return done;
    602   1.2  yamt }
    603   1.2  yamt 
    604   1.1  yamt int
    605   1.1  yamt main(int argc, char *argv[])
    606   1.1  yamt {
    607   1.1  yamt 	struct testnode *n;
    608   1.2  yamt 	unsigned int i;
    609   1.1  yamt 	struct rpst_iterator it;
    610   1.1  yamt 	struct timeval start;
    611   1.1  yamt 	struct timeval end;
    612   1.2  yamt 	uint64_t min_y = UINT64_MAX;
    613   1.2  yamt 	uint64_t max_y = 0;
    614   1.2  yamt 	uint64_t min_x = UINT64_MAX;
    615   1.2  yamt 	uint64_t max_x = 0;
    616   1.2  yamt 	uint64_t w;
    617   1.1  yamt 	unsigned int done;
    618   1.2  yamt 	unsigned int fail;
    619   1.2  yamt 	unsigned int num = 500000;
    620   1.1  yamt 
    621   1.1  yamt 	rpst_init_tree(&t);
    622   1.1  yamt 	rpst_dump_tree(&t);
    623   1.1  yamt 	assert(NULL == rpst_iterate_first(&t, UINT64_MAX, 0, UINT64_MAX, &it));
    624   1.1  yamt 
    625   1.2  yamt 	for (i = 0; i < num; i++) {
    626   1.1  yamt 		n = malloc(sizeof(*n));
    627   1.1  yamt 		if (i > 499000) {
    628   1.1  yamt 			n->n.n_x = 10;
    629   1.1  yamt 			n->n.n_y = random();
    630   1.1  yamt 		} else if (i > 400000) {
    631   1.1  yamt 			n->n.n_x = i;
    632   1.1  yamt 			n->n.n_y = random();
    633   1.1  yamt 		} else {
    634   1.1  yamt 			n->n.n_x = random();
    635   1.1  yamt 			n->n.n_y = random();
    636   1.1  yamt 		}
    637   1.2  yamt 		if (n->n.n_y < min_y) {
    638   1.2  yamt 			min_y = n->n.n_y;
    639   1.2  yamt 		}
    640   1.2  yamt 		if (n->n.n_y > max_y) {
    641   1.2  yamt 			max_y = n->n.n_y;
    642   1.2  yamt 		}
    643   1.2  yamt 		if (n->n.n_x < min_x) {
    644   1.2  yamt 			min_x = n->n.n_x;
    645   1.2  yamt 		}
    646   1.2  yamt 		if (n->n.n_x > max_x) {
    647   1.2  yamt 			max_x = n->n.n_x;
    648   1.2  yamt 		}
    649   1.2  yamt 		n->found = false;
    650   1.2  yamt 		n->failed = false;
    651   1.1  yamt 		n->next = h;
    652   1.1  yamt 		h = n;
    653   1.1  yamt 	}
    654   1.1  yamt 
    655   1.1  yamt 	done = 0;
    656   1.2  yamt 	fail = 0;
    657   1.1  yamt 	gettimeofday(&start, NULL);
    658   1.2  yamt 	for (n = h; n != NULL; n = n->next) {
    659   1.2  yamt 		struct rpst_node *o;
    660   1.1  yamt #if 0
    661   1.2  yamt 		printf("insert %p x=%" PRIu64 " y=%" PRIu64 "\n",
    662   1.2  yamt 		    n, n->n.n_x, n->n.n_y);
    663   1.1  yamt #endif
    664   1.2  yamt 		o = rpst_insert_node(&t, &n->n);
    665   1.2  yamt 		if (o == NULL) {
    666   1.2  yamt 			done++;
    667   1.2  yamt 		} else {
    668   1.2  yamt 			n->failed = true;
    669   1.2  yamt 			fail++;
    670   1.2  yamt 		}
    671   1.1  yamt 	}
    672   1.1  yamt 	gettimeofday(&end, NULL);
    673   1.2  yamt 	printf("%u nodes inserted and %u insertion failed in %ju usecs\n",
    674   1.2  yamt 	    done, fail,
    675   1.2  yamt 	    tvdiff(&end, &start));
    676   1.2  yamt 
    677   1.2  yamt 	assert(min_y == 0 || 0 == query(min_y - 1, 0, UINT64_MAX));
    678   1.2  yamt 	assert(max_x == UINT64_MAX ||
    679   1.2  yamt 	    0 == query(UINT64_MAX, max_x + 1, UINT64_MAX));
    680   1.2  yamt 	assert(min_x == 0 || 0 == query(UINT64_MAX, 0, min_x - 1));
    681   1.2  yamt 
    682   1.2  yamt 	done = query(max_y, min_x, max_x);
    683   1.2  yamt 	assert(done == num - fail);
    684   1.2  yamt 
    685   1.2  yamt 	done = query(UINT64_MAX, 0, UINT64_MAX);
    686   1.2  yamt 	assert(done == num - fail);
    687   1.2  yamt 
    688   1.2  yamt 	w = max_x - min_x;
    689   1.2  yamt 	query(max_y / 2, min_x, max_x);
    690   1.2  yamt 	query(max_y, min_x + w / 2, max_x);
    691   1.2  yamt 	query(max_y / 2, min_x + w / 2, max_x);
    692   1.2  yamt 	query(max_y / 2, min_x, max_x - w / 2);
    693   1.2  yamt 	query(max_y / 2, min_x + w / 3, max_x - w / 3);
    694   1.2  yamt 	query(max_y - 1, min_x + 1, max_x - 1);
    695   1.2  yamt 	query(UINT64_MAX, 10, 10);
    696   1.1  yamt 
    697   1.1  yamt 	done = 0;
    698   1.1  yamt 	gettimeofday(&start, NULL);
    699   1.2  yamt 	for (n = h; n != NULL; n = n->next) {
    700   1.2  yamt 		if (n->failed) {
    701   1.2  yamt 			continue;
    702   1.2  yamt 		}
    703   1.1  yamt #if 0
    704   1.2  yamt 		printf("remove %p x=%" PRIu64 " y=%" PRIu64 "\n",
    705   1.1  yamt 		    n, n->n.n_x, n->n.n_y);
    706   1.1  yamt #endif
    707   1.1  yamt 		rpst_remove_node(&t, &n->n);
    708   1.1  yamt 		done++;
    709   1.1  yamt 	}
    710   1.1  yamt 	gettimeofday(&end, NULL);
    711   1.1  yamt 	printf("%u nodes removed in %ju usecs\n", done,
    712   1.2  yamt 	    tvdiff(&end, &start));
    713   1.1  yamt 
    714   1.1  yamt 	rpst_dump_tree(&t);
    715   1.1  yamt }
    716   1.1  yamt #endif /* defined(UNITTEST) */
    717