Extra diagnostics in the hope that we can track down the problem with
[u/mdw/putty] / tree234.c
CommitLineData
febd9a0f 1/*
d2371c81 2 * tree234.c: reasonably generic counted 2-3-4 tree routines.
3 *
4 * This file is copyright 1999-2001 Simon Tatham.
5 *
6 * Permission is hereby granted, free of charge, to any person
7 * obtaining a copy of this software and associated documentation
8 * files (the "Software"), to deal in the Software without
9 * restriction, including without limitation the rights to use,
10 * copy, modify, merge, publish, distribute, sublicense, and/or
11 * sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following
13 * conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL SIMON TATHAM BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
23 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
febd9a0f 26 */
27
28#include <stdio.h>
29#include <stdlib.h>
d2371c81 30#include <assert.h>
dcbde236 31
febd9a0f 32#include "tree234.h"
33
d2371c81 34#define smalloc malloc
35#define sfree free
36
dcbde236 37#define mknew(typ) ( (typ *) smalloc (sizeof (typ)) )
febd9a0f 38
39#ifdef TEST
40#define LOG(x) (printf x)
41#else
37d868ec 42// FIXME
43#define LOG(x) (dprintf x)
febd9a0f 44#endif
45
d2371c81 46typedef struct node234_Tag node234;
47
febd9a0f 48struct tree234_Tag {
49 node234 *root;
50 cmpfn234 cmp;
51};
52
53struct node234_Tag {
54 node234 *parent;
55 node234 *kids[4];
d2371c81 56 int counts[4];
febd9a0f 57 void *elems[3];
58};
59
60/*
61 * Create a 2-3-4 tree.
62 */
63tree234 *newtree234(cmpfn234 cmp) {
64 tree234 *ret = mknew(tree234);
65 LOG(("created tree %p\n", ret));
66 ret->root = NULL;
67 ret->cmp = cmp;
68 return ret;
69}
70
71/*
72 * Free a 2-3-4 tree (not including freeing the elements).
73 */
74static void freenode234(node234 *n) {
75 if (!n)
76 return;
77 freenode234(n->kids[0]);
78 freenode234(n->kids[1]);
79 freenode234(n->kids[2]);
80 freenode234(n->kids[3]);
81 sfree(n);
82}
83void freetree234(tree234 *t) {
84 freenode234(t->root);
85 sfree(t);
86}
87
88/*
d2371c81 89 * Internal function to count a node.
90 */
91static int countnode234(node234 *n) {
92 int count = 0;
93 int i;
c404e5b3 94 if (!n)
95 return 0;
d2371c81 96 for (i = 0; i < 4; i++)
97 count += n->counts[i];
98 for (i = 0; i < 3; i++)
99 if (n->elems[i])
100 count++;
101 return count;
102}
103
104/*
105 * Count the elements in a tree.
106 */
107int count234(tree234 *t) {
108 if (t->root)
109 return countnode234(t->root);
110 else
111 return 0;
112}
113
114/*
febd9a0f 115 * Add an element e to a 2-3-4 tree t. Returns e on success, or if
116 * an existing element compares equal, returns that.
117 */
d2371c81 118static void *add234_internal(tree234 *t, void *e, int index) {
febd9a0f 119 node234 *n, **np, *left, *right;
120 void *orig_e = e;
d2371c81 121 int c, lcount, rcount;
febd9a0f 122
123 LOG(("adding node %p to tree %p\n", e, t));
124 if (t->root == NULL) {
125 t->root = mknew(node234);
126 t->root->elems[1] = t->root->elems[2] = NULL;
127 t->root->kids[0] = t->root->kids[1] = NULL;
128 t->root->kids[2] = t->root->kids[3] = NULL;
d2371c81 129 t->root->counts[0] = t->root->counts[1] = 0;
130 t->root->counts[2] = t->root->counts[3] = 0;
febd9a0f 131 t->root->parent = NULL;
132 t->root->elems[0] = e;
133 LOG((" created root %p\n", t->root));
134 return orig_e;
135 }
136
137 np = &t->root;
138 while (*np) {
d2371c81 139 int childnum;
febd9a0f 140 n = *np;
d2371c81 141 LOG((" node %p: %p/%d [%p] %p/%d [%p] %p/%d [%p] %p/%d\n",
142 n,
143 n->kids[0], n->counts[0], n->elems[0],
144 n->kids[1], n->counts[1], n->elems[1],
145 n->kids[2], n->counts[2], n->elems[2],
146 n->kids[3], n->counts[3]));
147 if (index >= 0) {
148 if (!n->kids[0]) {
149 /*
150 * Leaf node. We want to insert at kid position
151 * equal to the index:
152 *
153 * 0 A 1 B 2 C 3
154 */
155 childnum = index;
156 } else {
157 /*
158 * Internal node. We always descend through it (add
159 * always starts at the bottom, never in the
160 * middle).
161 */
162 do { /* this is a do ... while (0) to allow `break' */
163 if (index <= n->counts[0]) {
164 childnum = 0;
165 break;
166 }
167 index -= n->counts[0] + 1;
168 if (index <= n->counts[1]) {
169 childnum = 1;
170 break;
171 }
172 index -= n->counts[1] + 1;
173 if (index <= n->counts[2]) {
174 childnum = 2;
175 break;
176 }
177 index -= n->counts[2] + 1;
178 if (index <= n->counts[3]) {
179 childnum = 3;
180 break;
181 }
182 return NULL; /* error: index out of range */
183 } while (0);
184 }
185 } else {
186 if ((c = t->cmp(e, n->elems[0])) < 0)
187 childnum = 0;
188 else if (c == 0)
189 return n->elems[0]; /* already exists */
190 else if (n->elems[1] == NULL || (c = t->cmp(e, n->elems[1])) < 0)
191 childnum = 1;
192 else if (c == 0)
193 return n->elems[1]; /* already exists */
194 else if (n->elems[2] == NULL || (c = t->cmp(e, n->elems[2])) < 0)
195 childnum = 2;
196 else if (c == 0)
197 return n->elems[2]; /* already exists */
198 else
199 childnum = 3;
200 }
201 np = &n->kids[childnum];
202 LOG((" moving to child %d (%p)\n", childnum, *np));
febd9a0f 203 }
204
205 /*
206 * We need to insert the new element in n at position np.
207 */
d2371c81 208 left = NULL; lcount = 0;
209 right = NULL; rcount = 0;
febd9a0f 210 while (n) {
d2371c81 211 LOG((" at %p: %p/%d [%p] %p/%d [%p] %p/%d [%p] %p/%d\n",
212 n,
213 n->kids[0], n->counts[0], n->elems[0],
214 n->kids[1], n->counts[1], n->elems[1],
215 n->kids[2], n->counts[2], n->elems[2],
216 n->kids[3], n->counts[3]));
217 LOG((" need to insert %p/%d [%p] %p/%d at position %d\n",
218 left, lcount, e, right, rcount, np - n->kids));
febd9a0f 219 if (n->elems[1] == NULL) {
220 /*
221 * Insert in a 2-node; simple.
222 */
223 if (np == &n->kids[0]) {
224 LOG((" inserting on left of 2-node\n"));
d2371c81 225 n->kids[2] = n->kids[1]; n->counts[2] = n->counts[1];
febd9a0f 226 n->elems[1] = n->elems[0];
d2371c81 227 n->kids[1] = right; n->counts[1] = rcount;
febd9a0f 228 n->elems[0] = e;
d2371c81 229 n->kids[0] = left; n->counts[0] = lcount;
febd9a0f 230 } else { /* np == &n->kids[1] */
231 LOG((" inserting on right of 2-node\n"));
d2371c81 232 n->kids[2] = right; n->counts[2] = rcount;
febd9a0f 233 n->elems[1] = e;
d2371c81 234 n->kids[1] = left; n->counts[1] = lcount;
febd9a0f 235 }
236 if (n->kids[0]) n->kids[0]->parent = n;
237 if (n->kids[1]) n->kids[1]->parent = n;
238 if (n->kids[2]) n->kids[2]->parent = n;
239 LOG((" done\n"));
240 break;
241 } else if (n->elems[2] == NULL) {
242 /*
243 * Insert in a 3-node; simple.
244 */
245 if (np == &n->kids[0]) {
246 LOG((" inserting on left of 3-node\n"));
d2371c81 247 n->kids[3] = n->kids[2]; n->counts[3] = n->counts[2];
febd9a0f 248 n->elems[2] = n->elems[1];
d2371c81 249 n->kids[2] = n->kids[1]; n->counts[2] = n->counts[1];
febd9a0f 250 n->elems[1] = n->elems[0];
d2371c81 251 n->kids[1] = right; n->counts[1] = rcount;
febd9a0f 252 n->elems[0] = e;
d2371c81 253 n->kids[0] = left; n->counts[0] = lcount;
febd9a0f 254 } else if (np == &n->kids[1]) {
255 LOG((" inserting in middle of 3-node\n"));
d2371c81 256 n->kids[3] = n->kids[2]; n->counts[3] = n->counts[2];
febd9a0f 257 n->elems[2] = n->elems[1];
d2371c81 258 n->kids[2] = right; n->counts[2] = rcount;
febd9a0f 259 n->elems[1] = e;
d2371c81 260 n->kids[1] = left; n->counts[1] = lcount;
febd9a0f 261 } else { /* np == &n->kids[2] */
262 LOG((" inserting on right of 3-node\n"));
d2371c81 263 n->kids[3] = right; n->counts[3] = rcount;
febd9a0f 264 n->elems[2] = e;
d2371c81 265 n->kids[2] = left; n->counts[2] = lcount;
febd9a0f 266 }
267 if (n->kids[0]) n->kids[0]->parent = n;
268 if (n->kids[1]) n->kids[1]->parent = n;
269 if (n->kids[2]) n->kids[2]->parent = n;
270 if (n->kids[3]) n->kids[3]->parent = n;
271 LOG((" done\n"));
272 break;
273 } else {
274 node234 *m = mknew(node234);
275 m->parent = n->parent;
276 LOG((" splitting a 4-node; created new node %p\n", m));
277 /*
278 * Insert in a 4-node; split into a 2-node and a
279 * 3-node, and move focus up a level.
280 *
281 * I don't think it matters which way round we put the
282 * 2 and the 3. For simplicity, we'll put the 3 first
283 * always.
284 */
285 if (np == &n->kids[0]) {
d2371c81 286 m->kids[0] = left; m->counts[0] = lcount;
febd9a0f 287 m->elems[0] = e;
d2371c81 288 m->kids[1] = right; m->counts[1] = rcount;
febd9a0f 289 m->elems[1] = n->elems[0];
d2371c81 290 m->kids[2] = n->kids[1]; m->counts[2] = n->counts[1];
febd9a0f 291 e = n->elems[1];
d2371c81 292 n->kids[0] = n->kids[2]; n->counts[0] = n->counts[2];
febd9a0f 293 n->elems[0] = n->elems[2];
d2371c81 294 n->kids[1] = n->kids[3]; n->counts[1] = n->counts[3];
febd9a0f 295 } else if (np == &n->kids[1]) {
d2371c81 296 m->kids[0] = n->kids[0]; m->counts[0] = n->counts[0];
febd9a0f 297 m->elems[0] = n->elems[0];
d2371c81 298 m->kids[1] = left; m->counts[1] = lcount;
febd9a0f 299 m->elems[1] = e;
d2371c81 300 m->kids[2] = right; m->counts[2] = rcount;
febd9a0f 301 e = n->elems[1];
d2371c81 302 n->kids[0] = n->kids[2]; n->counts[0] = n->counts[2];
febd9a0f 303 n->elems[0] = n->elems[2];
d2371c81 304 n->kids[1] = n->kids[3]; n->counts[1] = n->counts[3];
febd9a0f 305 } else if (np == &n->kids[2]) {
d2371c81 306 m->kids[0] = n->kids[0]; m->counts[0] = n->counts[0];
febd9a0f 307 m->elems[0] = n->elems[0];
d2371c81 308 m->kids[1] = n->kids[1]; m->counts[1] = n->counts[1];
febd9a0f 309 m->elems[1] = n->elems[1];
d2371c81 310 m->kids[2] = left; m->counts[2] = lcount;
febd9a0f 311 /* e = e; */
d2371c81 312 n->kids[0] = right; n->counts[0] = rcount;
febd9a0f 313 n->elems[0] = n->elems[2];
d2371c81 314 n->kids[1] = n->kids[3]; n->counts[1] = n->counts[3];
febd9a0f 315 } else { /* np == &n->kids[3] */
d2371c81 316 m->kids[0] = n->kids[0]; m->counts[0] = n->counts[0];
febd9a0f 317 m->elems[0] = n->elems[0];
d2371c81 318 m->kids[1] = n->kids[1]; m->counts[1] = n->counts[1];
febd9a0f 319 m->elems[1] = n->elems[1];
d2371c81 320 m->kids[2] = n->kids[2]; m->counts[2] = n->counts[2];
321 n->kids[0] = left; n->counts[0] = lcount;
febd9a0f 322 n->elems[0] = e;
d2371c81 323 n->kids[1] = right; n->counts[1] = rcount;
febd9a0f 324 e = n->elems[2];
325 }
326 m->kids[3] = n->kids[3] = n->kids[2] = NULL;
d2371c81 327 m->counts[3] = n->counts[3] = n->counts[2] = 0;
febd9a0f 328 m->elems[2] = n->elems[2] = n->elems[1] = NULL;
329 if (m->kids[0]) m->kids[0]->parent = m;
330 if (m->kids[1]) m->kids[1]->parent = m;
331 if (m->kids[2]) m->kids[2]->parent = m;
332 if (n->kids[0]) n->kids[0]->parent = n;
333 if (n->kids[1]) n->kids[1]->parent = n;
d2371c81 334 LOG((" left (%p): %p/%d [%p] %p/%d [%p] %p/%d\n", m,
335 m->kids[0], m->counts[0], m->elems[0],
336 m->kids[1], m->counts[1], m->elems[1],
337 m->kids[2], m->counts[2]));
338 LOG((" right (%p): %p/%d [%p] %p/%d\n", n,
339 n->kids[0], n->counts[0], n->elems[0],
340 n->kids[1], n->counts[1]));
341 left = m; lcount = countnode234(left);
342 right = n; rcount = countnode234(right);
febd9a0f 343 }
344 if (n->parent)
345 np = (n->parent->kids[0] == n ? &n->parent->kids[0] :
346 n->parent->kids[1] == n ? &n->parent->kids[1] :
347 n->parent->kids[2] == n ? &n->parent->kids[2] :
348 &n->parent->kids[3]);
349 n = n->parent;
350 }
351
352 /*
353 * If we've come out of here by `break', n will still be
d2371c81 354 * non-NULL and all we need to do is go back up the tree
355 * updating counts. If we've come here because n is NULL, we
356 * need to create a new root for the tree because the old one
357 * has just split into two. */
358 if (n) {
359 while (n->parent) {
360 int count = countnode234(n);
361 int childnum;
362 childnum = (n->parent->kids[0] == n ? 0 :
363 n->parent->kids[1] == n ? 1 :
364 n->parent->kids[2] == n ? 2 : 3);
365 n->parent->counts[childnum] = count;
366 n = n->parent;
367 }
368 } else {
febd9a0f 369 LOG((" root is overloaded, split into two\n"));
370 t->root = mknew(node234);
d2371c81 371 t->root->kids[0] = left; t->root->counts[0] = lcount;
febd9a0f 372 t->root->elems[0] = e;
d2371c81 373 t->root->kids[1] = right; t->root->counts[1] = rcount;
febd9a0f 374 t->root->elems[1] = NULL;
d2371c81 375 t->root->kids[2] = NULL; t->root->counts[2] = 0;
febd9a0f 376 t->root->elems[2] = NULL;
d2371c81 377 t->root->kids[3] = NULL; t->root->counts[3] = 0;
febd9a0f 378 t->root->parent = NULL;
379 if (t->root->kids[0]) t->root->kids[0]->parent = t->root;
380 if (t->root->kids[1]) t->root->kids[1]->parent = t->root;
d2371c81 381 LOG((" new root is %p/%d [%p] %p/%d\n",
382 t->root->kids[0], t->root->counts[0],
383 t->root->elems[0],
384 t->root->kids[1], t->root->counts[1]));
febd9a0f 385 }
386
387 return orig_e;
388}
389
d2371c81 390void *add234(tree234 *t, void *e) {
391 if (!t->cmp) /* tree is unsorted */
392 return NULL;
393
394 return add234_internal(t, e, -1);
395}
396void *addpos234(tree234 *t, void *e, int index) {
397 if (index < 0 || /* index out of range */
398 t->cmp) /* tree is sorted */
399 return NULL; /* return failure */
400
401 return add234_internal(t, e, index); /* this checks the upper bound */
402}
403
febd9a0f 404/*
d2371c81 405 * Look up the element at a given numeric index in a 2-3-4 tree.
406 * Returns NULL if the index is out of range.
febd9a0f 407 */
d2371c81 408void *index234(tree234 *t, int index) {
febd9a0f 409 node234 *n;
febd9a0f 410
d2371c81 411 if (!t->root)
412 return NULL; /* tree is empty */
febd9a0f 413
d2371c81 414 if (index < 0 || index >= countnode234(t->root))
415 return NULL; /* out of range */
febd9a0f 416
417 n = t->root;
d2371c81 418
febd9a0f 419 while (n) {
d2371c81 420 if (index < n->counts[0])
febd9a0f 421 n = n->kids[0];
d2371c81 422 else if (index -= n->counts[0] + 1, index < 0)
febd9a0f 423 return n->elems[0];
d2371c81 424 else if (index < n->counts[1])
febd9a0f 425 n = n->kids[1];
d2371c81 426 else if (index -= n->counts[1] + 1, index < 0)
febd9a0f 427 return n->elems[1];
d2371c81 428 else if (index < n->counts[2])
febd9a0f 429 n = n->kids[2];
d2371c81 430 else if (index -= n->counts[2] + 1, index < 0)
febd9a0f 431 return n->elems[2];
432 else
433 n = n->kids[3];
434 }
435
d2371c81 436 /* We shouldn't ever get here. I wonder how we did. */
437 return NULL;
438}
439
440/*
441 * Find an element e in a sorted 2-3-4 tree t. Returns NULL if not
442 * found. e is always passed as the first argument to cmp, so cmp
443 * can be an asymmetric function if desired. cmp can also be passed
444 * as NULL, in which case the compare function from the tree proper
445 * will be used.
446 */
447void *findrelpos234(tree234 *t, void *e, cmpfn234 cmp,
448 int relation, int *index) {
449 node234 *n;
450 void *ret;
451 int c;
452 int idx, ecount, kcount, cmpret;
453
454 if (t->root == NULL)
455 return NULL;
456
457 if (cmp == NULL)
458 cmp = t->cmp;
459
460 n = t->root;
febd9a0f 461 /*
d2371c81 462 * Attempt to find the element itself.
febd9a0f 463 */
d2371c81 464 idx = 0;
465 ecount = -1;
466 /*
467 * Prepare a fake `cmp' result if e is NULL.
468 */
469 cmpret = 0;
470 if (e == NULL) {
471 assert(relation == REL234_LT || relation == REL234_GT);
472 if (relation == REL234_LT)
473 cmpret = +1; /* e is a max: always greater */
474 else if (relation == REL234_GT)
475 cmpret = -1; /* e is a min: always smaller */
476 }
477 while (1) {
478 for (kcount = 0; kcount < 4; kcount++) {
479 if (kcount >= 3 || n->elems[kcount] == NULL ||
480 (c = cmpret ? cmpret : cmp(e, n->elems[kcount])) < 0) {
481 break;
482 }
483 if (n->kids[kcount]) idx += n->counts[kcount];
484 if (c == 0) {
485 ecount = kcount;
486 break;
487 }
488 idx++;
489 }
490 if (ecount >= 0)
491 break;
492 if (n->kids[kcount])
493 n = n->kids[kcount];
494 else
495 break;
496 }
497
498 if (ecount >= 0) {
499 /*
500 * We have found the element we're looking for. It's
501 * n->elems[ecount], at tree index idx. If our search
502 * relation is EQ, LE or GE we can now go home.
503 */
504 if (relation != REL234_LT && relation != REL234_GT) {
505 if (index) *index = idx;
506 return n->elems[ecount];
507 }
508
509 /*
510 * Otherwise, we'll do an indexed lookup for the previous
511 * or next element. (It would be perfectly possible to
512 * implement these search types in a non-counted tree by
513 * going back up from where we are, but far more fiddly.)
514 */
515 if (relation == REL234_LT)
516 idx--;
517 else
518 idx++;
519 } else {
520 /*
521 * We've found our way to the bottom of the tree and we
522 * know where we would insert this node if we wanted to:
523 * we'd put it in in place of the (empty) subtree
524 * n->kids[kcount], and it would have index idx
525 *
526 * But the actual element isn't there. So if our search
527 * relation is EQ, we're doomed.
528 */
529 if (relation == REL234_EQ)
530 return NULL;
531
532 /*
533 * Otherwise, we must do an index lookup for index idx-1
534 * (if we're going left - LE or LT) or index idx (if we're
535 * going right - GE or GT).
536 */
537 if (relation == REL234_LT || relation == REL234_LE) {
538 idx--;
539 }
540 }
541
542 /*
543 * We know the index of the element we want; just call index234
544 * to do the rest. This will return NULL if the index is out of
545 * bounds, which is exactly what we want.
546 */
547 ret = index234(t, idx);
548 if (ret && index) *index = idx;
549 return ret;
550}
551void *find234(tree234 *t, void *e, cmpfn234 cmp) {
552 return findrelpos234(t, e, cmp, REL234_EQ, NULL);
553}
554void *findrel234(tree234 *t, void *e, cmpfn234 cmp, int relation) {
555 return findrelpos234(t, e, cmp, relation, NULL);
556}
557void *findpos234(tree234 *t, void *e, cmpfn234 cmp, int *index) {
558 return findrelpos234(t, e, cmp, REL234_EQ, index);
febd9a0f 559}
560
561/*
562 * Delete an element e in a 2-3-4 tree. Does not free the element,
563 * merely removes all links to it from the tree nodes.
564 */
d2371c81 565static void *delpos234_internal(tree234 *t, int index) {
febd9a0f 566 node234 *n;
d2371c81 567 void *retval;
febd9a0f 568 int ei = -1;
569
d2371c81 570 retval = 0;
571
febd9a0f 572 n = t->root;
d2371c81 573 LOG(("deleting item %d from tree %p\n", index, t));
febd9a0f 574 while (1) {
575 while (n) {
febd9a0f 576 int ki;
577 node234 *sub;
578
d2371c81 579 LOG((" node %p: %p/%d [%p] %p/%d [%p] %p/%d [%p] %p/%d index=%d\n",
580 n,
581 n->kids[0], n->counts[0], n->elems[0],
582 n->kids[1], n->counts[1], n->elems[1],
583 n->kids[2], n->counts[2], n->elems[2],
584 n->kids[3], n->counts[3],
585 index));
586 if (index < n->counts[0]) {
febd9a0f 587 ki = 0;
d2371c81 588 } else if (index -= n->counts[0]+1, index < 0) {
febd9a0f 589 ei = 0; break;
d2371c81 590 } else if (index < n->counts[1]) {
febd9a0f 591 ki = 1;
d2371c81 592 } else if (index -= n->counts[1]+1, index < 0) {
febd9a0f 593 ei = 1; break;
d2371c81 594 } else if (index < n->counts[2]) {
febd9a0f 595 ki = 2;
d2371c81 596 } else if (index -= n->counts[2]+1, index < 0) {
febd9a0f 597 ei = 2; break;
598 } else {
599 ki = 3;
600 }
601 /*
602 * Recurse down to subtree ki. If it has only one element,
603 * we have to do some transformation to start with.
604 */
605 LOG((" moving to subtree %d\n", ki));
606 sub = n->kids[ki];
607 if (!sub->elems[1]) {
608 LOG((" subtree has only one element!\n", ki));
609 if (ki > 0 && n->kids[ki-1]->elems[1]) {
610 /*
611 * Case 3a, left-handed variant. Child ki has
612 * only one element, but child ki-1 has two or
613 * more. So we need to move a subtree from ki-1
614 * to ki.
615 *
616 * . C . . B .
617 * / \ -> / \
618 * [more] a A b B c d D e [more] a A b c C d D e
619 */
620 node234 *sib = n->kids[ki-1];
621 int lastelem = (sib->elems[2] ? 2 :
622 sib->elems[1] ? 1 : 0);
623 sub->kids[2] = sub->kids[1];
d2371c81 624 sub->counts[2] = sub->counts[1];
febd9a0f 625 sub->elems[1] = sub->elems[0];
626 sub->kids[1] = sub->kids[0];
d2371c81 627 sub->counts[1] = sub->counts[0];
febd9a0f 628 sub->elems[0] = n->elems[ki-1];
629 sub->kids[0] = sib->kids[lastelem+1];
d2371c81 630 sub->counts[0] = sib->counts[lastelem+1];
100122a9 631 if (sub->kids[0]) sub->kids[0]->parent = sub;
febd9a0f 632 n->elems[ki-1] = sib->elems[lastelem];
633 sib->kids[lastelem+1] = NULL;
d2371c81 634 sib->counts[lastelem+1] = 0;
febd9a0f 635 sib->elems[lastelem] = NULL;
d2371c81 636 n->counts[ki] = countnode234(sub);
febd9a0f 637 LOG((" case 3a left\n"));
d2371c81 638 LOG((" index and left subtree count before adjustment: %d, %d\n",
639 index, n->counts[ki-1]));
640 index += n->counts[ki-1];
641 n->counts[ki-1] = countnode234(sib);
642 index -= n->counts[ki-1];
643 LOG((" index and left subtree count after adjustment: %d, %d\n",
644 index, n->counts[ki-1]));
febd9a0f 645 } else if (ki < 3 && n->kids[ki+1] &&
646 n->kids[ki+1]->elems[1]) {
647 /*
648 * Case 3a, right-handed variant. ki has only
649 * one element but ki+1 has two or more. Move a
650 * subtree from ki+1 to ki.
651 *
652 * . B . . C .
653 * / \ -> / \
654 * a A b c C d D e [more] a A b B c d D e [more]
655 */
656 node234 *sib = n->kids[ki+1];
657 int j;
658 sub->elems[1] = n->elems[ki];
659 sub->kids[2] = sib->kids[0];
d2371c81 660 sub->counts[2] = sib->counts[0];
100122a9 661 if (sub->kids[2]) sub->kids[2]->parent = sub;
febd9a0f 662 n->elems[ki] = sib->elems[0];
663 sib->kids[0] = sib->kids[1];
d2371c81 664 sib->counts[0] = sib->counts[1];
febd9a0f 665 for (j = 0; j < 2 && sib->elems[j+1]; j++) {
666 sib->kids[j+1] = sib->kids[j+2];
d2371c81 667 sib->counts[j+1] = sib->counts[j+2];
febd9a0f 668 sib->elems[j] = sib->elems[j+1];
669 }
670 sib->kids[j+1] = NULL;
d2371c81 671 sib->counts[j+1] = 0;
febd9a0f 672 sib->elems[j] = NULL;
d2371c81 673 n->counts[ki] = countnode234(sub);
674 n->counts[ki+1] = countnode234(sib);
febd9a0f 675 LOG((" case 3a right\n"));
676 } else {
677 /*
678 * Case 3b. ki has only one element, and has no
679 * neighbour with more than one. So pick a
680 * neighbour and merge it with ki, taking an
681 * element down from n to go in the middle.
682 *
683 * . B . .
684 * / \ -> |
685 * a A b c C d a A b B c C d
686 *
687 * (Since at all points we have avoided
688 * descending to a node with only one element,
689 * we can be sure that n is not reduced to
690 * nothingness by this move, _unless_ it was
691 * the very first node, ie the root of the
692 * tree. In that case we remove the now-empty
693 * root and replace it with its single large
694 * child as shown.)
695 */
696 node234 *sib;
697 int j;
698
d2371c81 699 if (ki > 0) {
febd9a0f 700 ki--;
d2371c81 701 index += n->counts[ki] + 1;
702 }
febd9a0f 703 sib = n->kids[ki];
704 sub = n->kids[ki+1];
705
706 sub->kids[3] = sub->kids[1];
d2371c81 707 sub->counts[3] = sub->counts[1];
febd9a0f 708 sub->elems[2] = sub->elems[0];
709 sub->kids[2] = sub->kids[0];
d2371c81 710 sub->counts[2] = sub->counts[0];
febd9a0f 711 sub->elems[1] = n->elems[ki];
712 sub->kids[1] = sib->kids[1];
d2371c81 713 sub->counts[1] = sib->counts[1];
100122a9 714 if (sub->kids[1]) sub->kids[1]->parent = sub;
febd9a0f 715 sub->elems[0] = sib->elems[0];
716 sub->kids[0] = sib->kids[0];
d2371c81 717 sub->counts[0] = sib->counts[0];
100122a9 718 if (sub->kids[0]) sub->kids[0]->parent = sub;
febd9a0f 719
d2371c81 720 n->counts[ki+1] = countnode234(sub);
721
febd9a0f 722 sfree(sib);
723
724 /*
725 * That's built the big node in sub. Now we
726 * need to remove the reference to sib in n.
727 */
728 for (j = ki; j < 3 && n->kids[j+1]; j++) {
729 n->kids[j] = n->kids[j+1];
d2371c81 730 n->counts[j] = n->counts[j+1];
febd9a0f 731 n->elems[j] = j<2 ? n->elems[j+1] : NULL;
732 }
733 n->kids[j] = NULL;
d2371c81 734 n->counts[j] = 0;
febd9a0f 735 if (j < 3) n->elems[j] = NULL;
2d56b16f 736 LOG((" case 3b ki=%d\n", ki));
febd9a0f 737
738 if (!n->elems[0]) {
739 /*
740 * The root is empty and needs to be
741 * removed.
742 */
743 LOG((" shifting root!\n"));
744 t->root = sub;
745 sub->parent = NULL;
746 sfree(n);
747 }
748 }
749 }
750 n = sub;
751 }
d2371c81 752 if (!retval)
753 retval = n->elems[ei];
754
febd9a0f 755 if (ei==-1)
d2371c81 756 return NULL; /* although this shouldn't happen */
febd9a0f 757
758 /*
759 * Treat special case: this is the one remaining item in
760 * the tree. n is the tree root (no parent), has one
761 * element (no elems[1]), and has no kids (no kids[0]).
762 */
763 if (!n->parent && !n->elems[1] && !n->kids[0]) {
764 LOG((" removed last element in tree\n"));
765 sfree(n);
766 t->root = NULL;
d2371c81 767 return retval;
febd9a0f 768 }
769
770 /*
771 * Now we have the element we want, as n->elems[ei], and we
772 * have also arranged for that element not to be the only
773 * one in its node. So...
774 */
775
776 if (!n->kids[0] && n->elems[1]) {
777 /*
778 * Case 1. n is a leaf node with more than one element,
779 * so it's _really easy_. Just delete the thing and
780 * we're done.
781 */
782 int i;
783 LOG((" case 1\n"));
a4a19e73 784 for (i = ei; i < 2 && n->elems[i+1]; i++)
febd9a0f 785 n->elems[i] = n->elems[i+1];
786 n->elems[i] = NULL;
d2371c81 787 /*
788 * Having done that to the leaf node, we now go back up
789 * the tree fixing the counts.
790 */
791 while (n->parent) {
792 int childnum;
793 childnum = (n->parent->kids[0] == n ? 0 :
794 n->parent->kids[1] == n ? 1 :
795 n->parent->kids[2] == n ? 2 : 3);
796 n->parent->counts[childnum]--;
797 n = n->parent;
798 }
799 return retval; /* finished! */
febd9a0f 800 } else if (n->kids[ei]->elems[1]) {
801 /*
802 * Case 2a. n is an internal node, and the root of the
803 * subtree to the left of e has more than one element.
804 * So find the predecessor p to e (ie the largest node
805 * in that subtree), place it where e currently is, and
806 * then start the deletion process over again on the
807 * subtree with p as target.
808 */
809 node234 *m = n->kids[ei];
810 void *target;
811 LOG((" case 2a\n"));
812 while (m->kids[0]) {
813 m = (m->kids[3] ? m->kids[3] :
814 m->kids[2] ? m->kids[2] :
815 m->kids[1] ? m->kids[1] : m->kids[0]);
816 }
817 target = (m->elems[2] ? m->elems[2] :
818 m->elems[1] ? m->elems[1] : m->elems[0]);
819 n->elems[ei] = target;
d2371c81 820 index = n->counts[ei]-1;
febd9a0f 821 n = n->kids[ei];
febd9a0f 822 } else if (n->kids[ei+1]->elems[1]) {
823 /*
824 * Case 2b, symmetric to 2a but s/left/right/ and
825 * s/predecessor/successor/. (And s/largest/smallest/).
826 */
827 node234 *m = n->kids[ei+1];
828 void *target;
829 LOG((" case 2b\n"));
830 while (m->kids[0]) {
831 m = m->kids[0];
832 }
833 target = m->elems[0];
834 n->elems[ei] = target;
835 n = n->kids[ei+1];
d2371c81 836 index = 0;
febd9a0f 837 } else {
838 /*
839 * Case 2c. n is an internal node, and the subtrees to
840 * the left and right of e both have only one element.
841 * So combine the two subnodes into a single big node
842 * with their own elements on the left and right and e
843 * in the middle, then restart the deletion process on
844 * that subtree, with e still as target.
845 */
846 node234 *a = n->kids[ei], *b = n->kids[ei+1];
847 int j;
848
849 LOG((" case 2c\n"));
850 a->elems[1] = n->elems[ei];
851 a->kids[2] = b->kids[0];
d2371c81 852 a->counts[2] = b->counts[0];
100122a9 853 if (a->kids[2]) a->kids[2]->parent = a;
febd9a0f 854 a->elems[2] = b->elems[0];
855 a->kids[3] = b->kids[1];
d2371c81 856 a->counts[3] = b->counts[1];
100122a9 857 if (a->kids[3]) a->kids[3]->parent = a;
febd9a0f 858 sfree(b);
d2371c81 859 n->counts[ei] = countnode234(a);
febd9a0f 860 /*
861 * That's built the big node in a, and destroyed b. Now
862 * remove the reference to b (and e) in n.
863 */
864 for (j = ei; j < 2 && n->elems[j+1]; j++) {
865 n->elems[j] = n->elems[j+1];
866 n->kids[j+1] = n->kids[j+2];
d2371c81 867 n->counts[j+1] = n->counts[j+2];
febd9a0f 868 }
869 n->elems[j] = NULL;
870 n->kids[j+1] = NULL;
d2371c81 871 n->counts[j+1] = 0;
e9e9556d 872 /*
873 * It's possible, in this case, that we've just removed
874 * the only element in the root of the tree. If so,
875 * shift the root.
876 */
877 if (n->elems[0] == NULL) {
878 LOG((" shifting root!\n"));
879 t->root = a;
880 a->parent = NULL;
881 sfree(n);
882 }
febd9a0f 883 /*
884 * Now go round the deletion process again, with n
885 * pointing at the new big node and e still the same.
886 */
887 n = a;
d2371c81 888 index = a->counts[0] + a->counts[1] + 1;
febd9a0f 889 }
890 }
891}
d2371c81 892void *delpos234(tree234 *t, int index) {
893 if (index < 0 || index >= countnode234(t->root))
febd9a0f 894 return NULL;
d2371c81 895 return delpos234_internal(t, index);
febd9a0f 896}
d2371c81 897void *del234(tree234 *t, void *e) {
898 int index;
899 if (!findrelpos234(t, e, NULL, REL234_EQ, &index))
900 return NULL; /* it wasn't in there anyway */
901 return delpos234_internal(t, index); /* it's there; delete it. */
febd9a0f 902}
903
904#ifdef TEST
905
2d56b16f 906/*
907 * Test code for the 2-3-4 tree. This code maintains an alternative
908 * representation of the data in the tree, in an array (using the
909 * obvious and slow insert and delete functions). After each tree
7aa7c43a 910 * operation, the verify() function is called, which ensures all
d2371c81 911 * the tree properties are preserved:
912 * - node->child->parent always equals node
913 * - tree->root->parent always equals NULL
914 * - number of kids == 0 or number of elements + 1;
915 * - tree has the same depth everywhere
916 * - every node has at least one element
917 * - subtree element counts are accurate
918 * - any NULL kid pointer is accompanied by a zero count
919 * - in a sorted tree: ordering property between elements of a
920 * node and elements of its children is preserved
921 * and also ensures the list represented by the tree is the same
922 * list it should be. (This last check also doubly verifies the
923 * ordering properties, because the `same list it should be' is by
924 * definition correctly ordered. It also ensures all nodes are
925 * distinct, because the enum functions would get caught in a loop
926 * if not.)
2d56b16f 927 */
928
929#include <stdarg.h>
930
d2371c81 931#define srealloc realloc
932
2d56b16f 933/*
934 * Error reporting function.
935 */
936void error(char *fmt, ...) {
937 va_list ap;
938 printf("ERROR: ");
939 va_start(ap, fmt);
940 vfprintf(stdout, fmt, ap);
941 va_end(ap);
942 printf("\n");
943}
944
945/* The array representation of the data. */
946void **array;
947int arraylen, arraysize;
948cmpfn234 cmp;
949
950/* The tree representation of the same data. */
951tree234 *tree;
952
953typedef struct {
954 int treedepth;
955 int elemcount;
956} chkctx;
957
d2371c81 958int chknode(chkctx *ctx, int level, node234 *node,
2d56b16f 959 void *lowbound, void *highbound) {
960 int nkids, nelems;
961 int i;
d2371c81 962 int count;
2d56b16f 963
964 /* Count the non-NULL kids. */
965 for (nkids = 0; nkids < 4 && node->kids[nkids]; nkids++);
966 /* Ensure no kids beyond the first NULL are non-NULL. */
967 for (i = nkids; i < 4; i++)
968 if (node->kids[i]) {
969 error("node %p: nkids=%d but kids[%d] non-NULL",
970 node, nkids, i);
d2371c81 971 } else if (node->counts[i]) {
972 error("node %p: kids[%d] NULL but count[%d]=%d nonzero",
973 node, i, i, node->counts[i]);
974 }
2d56b16f 975
976 /* Count the non-NULL elements. */
977 for (nelems = 0; nelems < 3 && node->elems[nelems]; nelems++);
978 /* Ensure no elements beyond the first NULL are non-NULL. */
979 for (i = nelems; i < 3; i++)
980 if (node->elems[i]) {
981 error("node %p: nelems=%d but elems[%d] non-NULL",
982 node, nelems, i);
983 }
984
985 if (nkids == 0) {
986 /*
987 * If nkids==0, this is a leaf node; verify that the tree
988 * depth is the same everywhere.
989 */
990 if (ctx->treedepth < 0)
991 ctx->treedepth = level; /* we didn't know the depth yet */
992 else if (ctx->treedepth != level)
993 error("node %p: leaf at depth %d, previously seen depth %d",
994 node, level, ctx->treedepth);
995 } else {
996 /*
997 * If nkids != 0, then it should be nelems+1, unless nelems
998 * is 0 in which case nkids should also be 0 (and so we
999 * shouldn't be in this condition at all).
1000 */
1001 int shouldkids = (nelems ? nelems+1 : 0);
1002 if (nkids != shouldkids) {
1003 error("node %p: %d elems should mean %d kids but has %d",
1004 node, nelems, shouldkids, nkids);
1005 }
1006 }
1007
1008 /*
1009 * nelems should be at least 1.
1010 */
1011 if (nelems == 0) {
1012 error("node %p: no elems", node, nkids);
1013 }
1014
1015 /*
d2371c81 1016 * Add nelems to the running element count of the whole tree.
2d56b16f 1017 */
1018 ctx->elemcount += nelems;
1019
1020 /*
1021 * Check ordering property: all elements should be strictly >
1022 * lowbound, strictly < highbound, and strictly < each other in
1023 * sequence. (lowbound and highbound are NULL at edges of tree
1024 * - both NULL at root node - and NULL is considered to be <
1025 * everything and > everything. IYSWIM.)
1026 */
d2371c81 1027 if (cmp) {
1028 for (i = -1; i < nelems; i++) {
1029 void *lower = (i == -1 ? lowbound : node->elems[i]);
1030 void *higher = (i+1 == nelems ? highbound : node->elems[i+1]);
1031 if (lower && higher && cmp(lower, higher) >= 0) {
1032 error("node %p: kid comparison [%d=%s,%d=%s] failed",
1033 node, i, lower, i+1, higher);
1034 }
1035 }
2d56b16f 1036 }
1037
1038 /*
1039 * Check parent pointers: all non-NULL kids should have a
1040 * parent pointer coming back to this node.
1041 */
1042 for (i = 0; i < nkids; i++)
1043 if (node->kids[i]->parent != node) {
1044 error("node %p kid %d: parent ptr is %p not %p",
1045 node, i, node->kids[i]->parent, node);
1046 }
1047
1048
1049 /*
1050 * Now (finally!) recurse into subtrees.
1051 */
d2371c81 1052 count = nelems;
1053
2d56b16f 1054 for (i = 0; i < nkids; i++) {
1055 void *lower = (i == 0 ? lowbound : node->elems[i-1]);
1056 void *higher = (i >= nelems ? highbound : node->elems[i]);
d2371c81 1057 int subcount = chknode(ctx, level+1, node->kids[i], lower, higher);
1058 if (node->counts[i] != subcount) {
1059 error("node %p kid %d: count says %d, subtree really has %d",
1060 node, i, node->counts[i], subcount);
1061 }
1062 count += subcount;
2d56b16f 1063 }
d2371c81 1064
1065 return count;
2d56b16f 1066}
1067
1068void verify(void) {
1069 chkctx ctx;
2d56b16f 1070 int i;
1071 void *p;
1072
1073 ctx.treedepth = -1; /* depth unknown yet */
1074 ctx.elemcount = 0; /* no elements seen yet */
1075 /*
1076 * Verify validity of tree properties.
1077 */
d2371c81 1078 if (tree->root) {
1079 if (tree->root->parent != NULL)
1080 error("root->parent is %p should be null", tree->root->parent);
2d56b16f 1081 chknode(&ctx, 0, tree->root, NULL, NULL);
d2371c81 1082 }
2d56b16f 1083 printf("tree depth: %d\n", ctx.treedepth);
1084 /*
1085 * Enumerate the tree and ensure it matches up to the array.
1086 */
d2371c81 1087 for (i = 0; NULL != (p = index234(tree, i)); i++) {
2d56b16f 1088 if (i >= arraylen)
1089 error("tree contains more than %d elements", arraylen);
1090 if (array[i] != p)
1091 error("enum at position %d: array says %s, tree says %s",
1092 i, array[i], p);
1093 }
d2371c81 1094 if (ctx.elemcount != i) {
2d56b16f 1095 error("tree really contains %d elements, enum gave %d",
d2371c81 1096 ctx.elemcount, i);
2d56b16f 1097 }
1098 if (i < arraylen) {
1099 error("enum gave only %d elements, array has %d", i, arraylen);
1100 }
d2371c81 1101 i = count234(tree);
1102 if (ctx.elemcount != i) {
1103 error("tree really contains %d elements, count234 gave %d",
1104 ctx.elemcount, i);
1105 }
2d56b16f 1106}
1107
d2371c81 1108void internal_addtest(void *elem, int index, void *realret) {
2d56b16f 1109 int i, j;
d2371c81 1110 void *retval;
2d56b16f 1111
1112 if (arraysize < arraylen+1) {
1113 arraysize = arraylen+1+256;
dcbde236 1114 array = (array == NULL ? smalloc(arraysize*sizeof(*array)) :
1115 srealloc(array, arraysize*sizeof(*array)));
2d56b16f 1116 }
1117
d2371c81 1118 i = index;
2d56b16f 1119 /* now i points to the first element >= elem */
d2371c81 1120 retval = elem; /* expect elem returned (success) */
1121 for (j = arraylen; j > i; j--)
1122 array[j] = array[j-1];
1123 array[i] = elem; /* add elem to array */
1124 arraylen++;
2d56b16f 1125
2d56b16f 1126 if (realret != retval) {
1127 error("add: retval was %p expected %p", realret, retval);
1128 }
1129
1130 verify();
1131}
1132
d2371c81 1133void addtest(void *elem) {
2d56b16f 1134 int i;
d2371c81 1135 void *realret;
1136
1137 realret = add234(tree, elem);
2d56b16f 1138
1139 i = 0;
1140 while (i < arraylen && cmp(elem, array[i]) > 0)
1141 i++;
d2371c81 1142 if (i < arraylen && !cmp(elem, array[i])) {
1143 void *retval = array[i]; /* expect that returned not elem */
1144 if (realret != retval) {
1145 error("add: retval was %p expected %p", realret, retval);
1146 }
1147 } else
1148 internal_addtest(elem, i, realret);
1149}
1150
1151void addpostest(void *elem, int i) {
1152 void *realret;
1153
1154 realret = addpos234(tree, elem, i);
1155
1156 internal_addtest(elem, i, realret);
1157}
1158
1159void delpostest(int i) {
1160 int index = i;
1161 void *elem = array[i], *ret;
1162
1163 /* i points to the right element */
1164 while (i < arraylen-1) {
1165 array[i] = array[i+1];
1166 i++;
2d56b16f 1167 }
d2371c81 1168 arraylen--; /* delete elem from array */
1169
1170 if (tree->cmp)
1171 ret = del234(tree, elem);
1172 else
1173 ret = delpos234(tree, index);
2d56b16f 1174
d2371c81 1175 if (ret != elem) {
1176 error("del returned %p, expected %p", ret, elem);
1177 }
2d56b16f 1178
1179 verify();
febd9a0f 1180}
2d56b16f 1181
d2371c81 1182void deltest(void *elem) {
1183 int i;
1184
1185 i = 0;
1186 while (i < arraylen && cmp(elem, array[i]) > 0)
1187 i++;
1188 if (i >= arraylen || cmp(elem, array[i]) != 0)
1189 return; /* don't do it! */
1190 delpostest(i);
1191}
1192
2d56b16f 1193/* A sample data set and test utility. Designed for pseudo-randomness,
1194 * and yet repeatability. */
1195
1196/*
1197 * This random number generator uses the `portable implementation'
1198 * given in ANSI C99 draft N869. It assumes `unsigned' is 32 bits;
1199 * change it if not.
1200 */
1201int randomnumber(unsigned *seed) {
1202 *seed *= 1103515245;
1203 *seed += 12345;
1204 return ((*seed) / 65536) % 32768;
febd9a0f 1205}
1206
2d56b16f 1207int mycmp(void *av, void *bv) {
1208 char const *a = (char const *)av;
1209 char const *b = (char const *)bv;
febd9a0f 1210 return strcmp(a, b);
1211}
1212
2d56b16f 1213#define lenof(x) ( sizeof((x)) / sizeof(*(x)) )
1214
1215char *strings[] = {
1216 "a", "ab", "absque", "coram", "de",
1217 "palam", "clam", "cum", "ex", "e",
1218 "sine", "tenus", "pro", "prae",
1219 "banana", "carrot", "cabbage", "broccoli", "onion", "zebra",
1220 "penguin", "blancmange", "pangolin", "whale", "hedgehog",
1221 "giraffe", "peanut", "bungee", "foo", "bar", "baz", "quux",
1222 "murfl", "spoo", "breen", "flarn", "octothorpe",
1223 "snail", "tiger", "elephant", "octopus", "warthog", "armadillo",
1224 "aardvark", "wyvern", "dragon", "elf", "dwarf", "orc", "goblin",
1225 "pixie", "basilisk", "warg", "ape", "lizard", "newt", "shopkeeper",
1226 "wand", "ring", "amulet"
1227};
1228
1229#define NSTR lenof(strings)
1230
d2371c81 1231int findtest(void) {
1232 const static int rels[] = {
1233 REL234_EQ, REL234_GE, REL234_LE, REL234_LT, REL234_GT
1234 };
1235 const static char *const relnames[] = {
1236 "EQ", "GE", "LE", "LT", "GT"
1237 };
1238 int i, j, rel, index;
1239 char *p, *ret, *realret, *realret2;
1240 int lo, hi, mid, c;
1241
1242 for (i = 0; i < NSTR; i++) {
1243 p = strings[i];
1244 for (j = 0; j < sizeof(rels)/sizeof(*rels); j++) {
1245 rel = rels[j];
1246
1247 lo = 0; hi = arraylen-1;
1248 while (lo <= hi) {
1249 mid = (lo + hi) / 2;
1250 c = strcmp(p, array[mid]);
1251 if (c < 0)
1252 hi = mid-1;
1253 else if (c > 0)
1254 lo = mid+1;
1255 else
1256 break;
1257 }
1258
1259 if (c == 0) {
1260 if (rel == REL234_LT)
1261 ret = (mid > 0 ? array[--mid] : NULL);
1262 else if (rel == REL234_GT)
1263 ret = (mid < arraylen-1 ? array[++mid] : NULL);
1264 else
1265 ret = array[mid];
1266 } else {
1267 assert(lo == hi+1);
1268 if (rel == REL234_LT || rel == REL234_LE) {
1269 mid = hi;
1270 ret = (hi >= 0 ? array[hi] : NULL);
1271 } else if (rel == REL234_GT || rel == REL234_GE) {
1272 mid = lo;
1273 ret = (lo < arraylen ? array[lo] : NULL);
1274 } else
1275 ret = NULL;
1276 }
1277
1278 realret = findrelpos234(tree, p, NULL, rel, &index);
1279 if (realret != ret) {
1280 error("find(\"%s\",%s) gave %s should be %s",
1281 p, relnames[j], realret, ret);
1282 }
1283 if (realret && index != mid) {
1284 error("find(\"%s\",%s) gave %d should be %d",
1285 p, relnames[j], index, mid);
1286 }
1287 if (realret && rel == REL234_EQ) {
1288 realret2 = index234(tree, index);
1289 if (realret2 != realret) {
1290 error("find(\"%s\",%s) gave %s(%d) but %d -> %s",
1291 p, relnames[j], realret, index, index, realret2);
1292 }
1293 }
1294#if 0
1295 printf("find(\"%s\",%s) gave %s(%d)\n", p, relnames[j],
1296 realret, index);
1297#endif
1298 }
1299 }
1300
1301 realret = findrelpos234(tree, NULL, NULL, REL234_GT, &index);
1302 if (arraylen && (realret != array[0] || index != 0)) {
1303 error("find(NULL,GT) gave %s(%d) should be %s(0)",
1304 realret, index, array[0]);
1305 } else if (!arraylen && (realret != NULL)) {
1306 error("find(NULL,GT) gave %s(%d) should be NULL",
1307 realret, index);
1308 }
1309
1310 realret = findrelpos234(tree, NULL, NULL, REL234_LT, &index);
1311 if (arraylen && (realret != array[arraylen-1] || index != arraylen-1)) {
1312 error("find(NULL,LT) gave %s(%d) should be %s(0)",
1313 realret, index, array[arraylen-1]);
1314 } else if (!arraylen && (realret != NULL)) {
1315 error("find(NULL,LT) gave %s(%d) should be NULL",
1316 realret, index);
1317 }
1318}
1319
febd9a0f 1320int main(void) {
2d56b16f 1321 int in[NSTR];
d2371c81 1322 int i, j, k;
2d56b16f 1323 unsigned seed = 0;
1324
1325 for (i = 0; i < NSTR; i++) in[i] = 0;
1326 array = NULL;
1327 arraylen = arraysize = 0;
1328 tree = newtree234(mycmp);
1329 cmp = mycmp;
1330
1331 verify();
1332 for (i = 0; i < 10000; i++) {
1333 j = randomnumber(&seed);
1334 j %= NSTR;
1335 printf("trial: %d\n", i);
1336 if (in[j]) {
1337 printf("deleting %s (%d)\n", strings[j], j);
1338 deltest(strings[j]);
1339 in[j] = 0;
1340 } else {
1341 printf("adding %s (%d)\n", strings[j], j);
1342 addtest(strings[j]);
1343 in[j] = 1;
1344 }
d2371c81 1345 findtest();
2d56b16f 1346 }
1347
1348 while (arraylen > 0) {
1349 j = randomnumber(&seed);
1350 j %= arraylen;
1351 deltest(array[j]);
1352 }
1353
d2371c81 1354 freetree234(tree);
1355
1356 /*
1357 * Now try an unsorted tree. We don't really need to test
1358 * delpos234 because we know del234 is based on it, so it's
1359 * already been tested in the above sorted-tree code; but for
1360 * completeness we'll use it to tear down our unsorted tree
1361 * once we've built it.
1362 */
1363 tree = newtree234(NULL);
1364 cmp = NULL;
1365 verify();
1366 for (i = 0; i < 1000; i++) {
1367 printf("trial: %d\n", i);
1368 j = randomnumber(&seed);
1369 j %= NSTR;
1370 k = randomnumber(&seed);
1371 k %= count234(tree)+1;
1372 printf("adding string %s at index %d\n", strings[j], k);
1373 addpostest(strings[j], k);
1374 }
1375 while (count234(tree) > 0) {
1376 printf("cleanup: tree size %d\n", count234(tree));
1377 j = randomnumber(&seed);
1378 j %= count234(tree);
1379 printf("deleting string %s from index %d\n", array[j], j);
1380 delpostest(j);
1381 }
1382
2d56b16f 1383 return 0;
febd9a0f 1384}
2d56b16f 1385
febd9a0f 1386#endif