1 1.12 andvar /* $NetBSD: rpst.c,v 1.12 2021/11/14 20:51:57 andvar 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.12 andvar __KERNEL_RCSID(0, "$NetBSD: rpst.c,v 1.12 2021/11/14 20:51:57 andvar 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.12 andvar __RCSID("$NetBSD: rpst.c,v 1.12 2021/11/14 20:51:57 andvar 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.12 andvar printf("querying 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