Home | History | Annotate | Line # | Download | only in gen
rpst.c revision 1.11.46.2
      1  1.11.46.1  martin /*	$NetBSD: rpst.c,v 1.11.46.2 2020/04/21 19:37:49 martin 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.46.1  martin __KERNEL_RCSID(0, "$NetBSD: rpst.c,v 1.11.46.2 2020/04/21 19:37:49 martin 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.46.1  martin __RCSID("$NetBSD: rpst.c,v 1.11.46.2 2020/04/21 19:37:49 martin 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