Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/libsa/rb.h

1/******************************************************************************
2 *
3 * Copyright (C) 2008 Jason Evans <jasone@FreeBSD.org>.
4 * Copyright (c) 2008-2012 Hewlett-Packard Development Company, L.P.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice(s), this list of conditions and the following disclaimer
12 * unmodified other than the allowable addition of one or more
13 * copyright notices.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice(s), this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 ******************************************************************************
32 *
33 * cpp macro implementation of left-leaning red-black trees.
34 *
35 * Usage:
36 *
37 * (Optional, see assert(3).)
38 * #define NDEBUG
39 *
40 * (Required.)
41 * #include <assert.h>
42 * #include <rb.h>
43 * ...
44 *
45 * All operations are done non-recursively. Parent pointers are not used, and
46 * color bits are stored in the least significant bit of right-child pointers,
47 * thus making node linkage as compact as is possible for red-black trees.
48 *
49 * Some macros use a comparison function pointer, which is expected to have the
50 * following prototype:
51 *
52 * int (a_cmp *)(a_type *a_node, a_type *a_other);
53 * ^^^^^^
54 * or a_key
55 *
56 * Interpretation of comparision function return values:
57 *
58 * -1 : a_node < a_other
59 * 0 : a_node == a_other
60 * 1 : a_node > a_other
61 *
62 * In all cases, the a_node or a_key macro argument is the first argument to the
63 * comparison function, which makes it possible to write comparison functions
64 * that treat the first argument specially.
65 *
66 ******************************************************************************/
67
68#ifndef RB_H_
69#defineRB_H_
70
71//__FBSDID("$FreeBSD: head/lib/libc/stdlib/rb.h 178995 2008-05-14 18:33:13Z jasone $");
72
73/* Node structure. */
74#definerb_node(a_type)\
75struct {\
76a_type *rbn_left;\
77a_type *rbn_right_red;\
78}
79
80/* Root structure. */
81#definerb_tree(a_type)\
82struct {\
83a_type *rbt_root;\
84a_type rbt_nil;\
85}
86
87/* Left accessors. */
88#definerbp_left_get(a_type, a_field, a_node)\
89((a_node)->a_field.rbn_left)
90#definerbp_left_set(a_type, a_field, a_node, a_left) do {\
91(a_node)->a_field.rbn_left = a_left;\
92} while (0)
93
94/* Right accessors. */
95#definerbp_right_get(a_type, a_field, a_node)\
96((a_type *) (((intptr_t) (a_node)->a_field.rbn_right_red)\
97& ((ssize_t)-2)))
98#definerbp_right_set(a_type, a_field, a_node, a_right) do {\
99(a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t) a_right)\
100| (((uintptr_t) (a_node)->a_field.rbn_right_red) & ((size_t)1)));\
101} while (0)
102
103/* Color accessors. */
104#definerbp_red_get(a_type, a_field, a_node)\
105((bool) (((uintptr_t) (a_node)->a_field.rbn_right_red)\
106& ((size_t)1)))
107#definerbp_color_set(a_type, a_field, a_node, a_red) do {\
108(a_node)->a_field.rbn_right_red = (a_type *) ((((intptr_t)\
109(a_node)->a_field.rbn_right_red) & ((ssize_t)-2))\
110| ((ssize_t)a_red));\
111} while (0)
112#definerbp_red_set(a_type, a_field, a_node) do {\
113(a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t)\
114(a_node)->a_field.rbn_right_red) | ((size_t)1));\
115} while (0)
116#definerbp_black_set(a_type, a_field, a_node) do {\
117(a_node)->a_field.rbn_right_red = (a_type *) (((intptr_t)\
118(a_node)->a_field.rbn_right_red) & ((ssize_t)-2));\
119} while (0)
120
121/* Node initializer. */
122#definerbp_node_new(a_type, a_field, a_tree, a_node) do {\
123rbp_left_set(a_type, a_field, (a_node), &(a_tree)->rbt_nil);\
124rbp_right_set(a_type, a_field, (a_node), &(a_tree)->rbt_nil);\
125rbp_red_set(a_type, a_field, (a_node));\
126} while (0)
127
128/* Tree initializer. */
129#definerb_new(a_type, a_field, a_tree) do {\
130(a_tree)->rbt_root = &(a_tree)->rbt_nil;\
131rbp_node_new(a_type, a_field, a_tree, &(a_tree)->rbt_nil);\
132rbp_black_set(a_type, a_field, &(a_tree)->rbt_nil);\
133} while (0)
134
135/* Tree operations. */
136#definerbp_black_height(a_type, a_field, a_tree, r_height) do {\
137a_type *rbp_bh_t;\
138for (rbp_bh_t = (a_tree)->rbt_root, (r_height) = 0;\
139rbp_bh_t != &(a_tree)->rbt_nil;\
140rbp_bh_t = rbp_left_get(a_type, a_field, rbp_bh_t)) {\
141if (rbp_red_get(a_type, a_field, rbp_bh_t) == false) {\
142(r_height)++;\
143}\
144}\
145} while (0)
146
147#definerbp_first(a_type, a_field, a_tree, a_root, r_node) do {\
148for ((r_node) = (a_root);\
149rbp_left_get(a_type, a_field, (r_node)) != &(a_tree)->rbt_nil;\
150(r_node) = rbp_left_get(a_type, a_field, (r_node))) {\
151}\
152} while (0)
153
154#definerbp_last(a_type, a_field, a_tree, a_root, r_node) do {\
155for ((r_node) = (a_root);\
156rbp_right_get(a_type, a_field, (r_node)) != &(a_tree)->rbt_nil;\
157(r_node) = rbp_right_get(a_type, a_field, (r_node))) {\
158}\
159} while (0)
160
161#definerbp_next(a_type, a_field, a_cmp, a_tree, a_node, r_node) do {\
162if (rbp_right_get(a_type, a_field, (a_node))\
163!= &(a_tree)->rbt_nil) {\
164rbp_first(a_type, a_field, a_tree, rbp_right_get(a_type,\
165a_field, (a_node)), (r_node));\
166} else {\
167a_type *rbp_n_t = (a_tree)->rbt_root;\
168assert(rbp_n_t != &(a_tree)->rbt_nil);\
169(r_node) = &(a_tree)->rbt_nil;\
170while (true) {\
171int rbp_n_cmp = (a_cmp)((a_node), rbp_n_t);\
172if (rbp_n_cmp < 0) {\
173(r_node) = rbp_n_t;\
174rbp_n_t = rbp_left_get(a_type, a_field, rbp_n_t);\
175} else if (rbp_n_cmp > 0) {\
176rbp_n_t = rbp_right_get(a_type, a_field, rbp_n_t);\
177} else {\
178break;\
179}\
180assert(rbp_n_t != &(a_tree)->rbt_nil);\
181}\
182}\
183} while (0)
184
185#definerbp_prev(a_type, a_field, a_cmp, a_tree, a_node, r_node) do {\
186if (rbp_left_get(a_type, a_field, (a_node)) != &(a_tree)->rbt_nil) {\
187rbp_last(a_type, a_field, a_tree, rbp_left_get(a_type,\
188a_field, (a_node)), (r_node));\
189} else {\
190a_type *rbp_p_t = (a_tree)->rbt_root;\
191assert(rbp_p_t != &(a_tree)->rbt_nil);\
192(r_node) = &(a_tree)->rbt_nil;\
193while (true) {\
194int rbp_p_cmp = (a_cmp)((a_node), rbp_p_t);\
195if (rbp_p_cmp < 0) {\
196rbp_p_t = rbp_left_get(a_type, a_field, rbp_p_t);\
197} else if (rbp_p_cmp > 0) {\
198(r_node) = rbp_p_t;\
199rbp_p_t = rbp_right_get(a_type, a_field, rbp_p_t);\
200} else {\
201break;\
202}\
203assert(rbp_p_t != &(a_tree)->rbt_nil);\
204}\
205}\
206} while (0)
207
208#definerb_first(a_type, a_field, a_tree, r_node) do {\
209rbp_first(a_type, a_field, a_tree, (a_tree)->rbt_root, (r_node));\
210if ((r_node) == &(a_tree)->rbt_nil) {\
211(r_node) = NULL;\
212}\
213} while (0)
214
215#definerb_last(a_type, a_field, a_tree, r_node) do {\
216rbp_last(a_type, a_field, a_tree, (a_tree)->rbt_root, r_node);\
217if ((r_node) == &(a_tree)->rbt_nil) {\
218(r_node) = NULL;\
219}\
220} while (0)
221
222#definerb_next(a_type, a_field, a_cmp, a_tree, a_node, r_node) do {\
223rbp_next(a_type, a_field, a_cmp, a_tree, (a_node), (r_node));\
224if ((r_node) == &(a_tree)->rbt_nil) {\
225(r_node) = NULL;\
226}\
227} while (0)
228
229#definerb_prev(a_type, a_field, a_cmp, a_tree, a_node, r_node) do {\
230rbp_prev(a_type, a_field, a_cmp, a_tree, (a_node), (r_node));\
231if ((r_node) == &(a_tree)->rbt_nil) {\
232(r_node) = NULL;\
233}\
234} while (0)
235
236#definerb_search(a_type, a_field, a_cmp, a_tree, a_key, r_node) do {\
237int rbp_se_cmp;\
238(r_node) = (a_tree)->rbt_root;\
239while ((r_node) != &(a_tree)->rbt_nil\
240&& (rbp_se_cmp = (a_cmp)((a_key), (r_node))) != 0) {\
241if (rbp_se_cmp < 0) {\
242(r_node) = rbp_left_get(a_type, a_field, (r_node));\
243} else {\
244(r_node) = rbp_right_get(a_type, a_field, (r_node));\
245}\
246}\
247if ((r_node) == &(a_tree)->rbt_nil) {\
248(r_node) = NULL;\
249}\
250} while (0)
251
252/*
253 * Find a match if it exists. Otherwise, find the next greater node, if one
254 * exists.
255 */
256#definerb_nsearch(a_type, a_field, a_cmp, a_tree, a_key, r_node) do {\
257a_type *rbp_ns_t = (a_tree)->rbt_root;\
258(r_node) = NULL;\
259while (rbp_ns_t != &(a_tree)->rbt_nil) {\
260int rbp_ns_cmp = (a_cmp)((a_key), rbp_ns_t);\
261if (rbp_ns_cmp < 0) {\
262(r_node) = rbp_ns_t;\
263rbp_ns_t = rbp_left_get(a_type, a_field, rbp_ns_t);\
264} else if (rbp_ns_cmp > 0) {\
265rbp_ns_t = rbp_right_get(a_type, a_field, rbp_ns_t);\
266} else {\
267(r_node) = rbp_ns_t;\
268break;\
269}\
270}\
271} while (0)
272
273/*
274 * Find a match if it exists. Otherwise, find the previous lesser node, if one
275 * exists.
276 */
277#definerb_psearch(a_type, a_field, a_cmp, a_tree, a_key, r_node) do {\
278a_type *rbp_ps_t = (a_tree)->rbt_root;\
279(r_node) = NULL;\
280while (rbp_ps_t != &(a_tree)->rbt_nil) {\
281int rbp_ps_cmp = (a_cmp)((a_key), rbp_ps_t);\
282if (rbp_ps_cmp < 0) {\
283rbp_ps_t = rbp_left_get(a_type, a_field, rbp_ps_t);\
284} else if (rbp_ps_cmp > 0) {\
285(r_node) = rbp_ps_t;\
286rbp_ps_t = rbp_right_get(a_type, a_field, rbp_ps_t);\
287} else {\
288(r_node) = rbp_ps_t;\
289break;\
290}\
291}\
292} while (0)
293
294#definerbp_rotate_left(a_type, a_field, a_node, r_node) do {\
295(r_node) = rbp_right_get(a_type, a_field, (a_node));\
296rbp_right_set(a_type, a_field, (a_node),\
297rbp_left_get(a_type, a_field, (r_node)));\
298rbp_left_set(a_type, a_field, (r_node), (a_node));\
299} while (0)
300
301#definerbp_rotate_right(a_type, a_field, a_node, r_node) do {\
302(r_node) = rbp_left_get(a_type, a_field, (a_node));\
303rbp_left_set(a_type, a_field, (a_node),\
304rbp_right_get(a_type, a_field, (r_node)));\
305rbp_right_set(a_type, a_field, (r_node), (a_node));\
306} while (0)
307
308#definerbp_lean_left(a_type, a_field, a_node, r_node) do {\
309bool rbp_ll_red;\
310rbp_rotate_left(a_type, a_field, (a_node), (r_node));\
311rbp_ll_red = rbp_red_get(a_type, a_field, (a_node));\
312rbp_color_set(a_type, a_field, (r_node), rbp_ll_red);\
313rbp_red_set(a_type, a_field, (a_node));\
314} while (0)
315
316#definerbp_lean_right(a_type, a_field, a_node, r_node) do {\
317bool rbp_lr_red;\
318rbp_rotate_right(a_type, a_field, (a_node), (r_node));\
319rbp_lr_red = rbp_red_get(a_type, a_field, (a_node));\
320rbp_color_set(a_type, a_field, (r_node), rbp_lr_red);\
321rbp_red_set(a_type, a_field, (a_node));\
322} while (0)
323
324#definerbp_move_red_left(a_type, a_field, a_node, r_node) do {\
325a_type *rbp_mrl_t, *rbp_mrl_u;\
326rbp_mrl_t = rbp_left_get(a_type, a_field, (a_node));\
327rbp_red_set(a_type, a_field, rbp_mrl_t);\
328rbp_mrl_t = rbp_right_get(a_type, a_field, (a_node));\
329rbp_mrl_u = rbp_left_get(a_type, a_field, rbp_mrl_t);\
330if (rbp_red_get(a_type, a_field, rbp_mrl_u)) {\
331rbp_rotate_right(a_type, a_field, rbp_mrl_t, rbp_mrl_u);\
332rbp_right_set(a_type, a_field, (a_node), rbp_mrl_u);\
333rbp_rotate_left(a_type, a_field, (a_node), (r_node));\
334rbp_mrl_t = rbp_right_get(a_type, a_field, (a_node));\
335if (rbp_red_get(a_type, a_field, rbp_mrl_t)) {\
336rbp_black_set(a_type, a_field, rbp_mrl_t);\
337rbp_red_set(a_type, a_field, (a_node));\
338rbp_rotate_left(a_type, a_field, (a_node), rbp_mrl_t);\
339rbp_left_set(a_type, a_field, (r_node), rbp_mrl_t);\
340} else {\
341rbp_black_set(a_type, a_field, (a_node));\
342}\
343} else {\
344rbp_red_set(a_type, a_field, (a_node));\
345rbp_rotate_left(a_type, a_field, (a_node), (r_node));\
346}\
347} while (0)
348
349#definerbp_move_red_right(a_type, a_field, a_node, r_node) do {\
350a_type *rbp_mrr_t;\
351rbp_mrr_t = rbp_left_get(a_type, a_field, (a_node));\
352if (rbp_red_get(a_type, a_field, rbp_mrr_t)) {\
353a_type *rbp_mrr_u, *rbp_mrr_v;\
354rbp_mrr_u = rbp_right_get(a_type, a_field, rbp_mrr_t);\
355rbp_mrr_v = rbp_left_get(a_type, a_field, rbp_mrr_u);\
356if (rbp_red_get(a_type, a_field, rbp_mrr_v)) {\
357rbp_color_set(a_type, a_field, rbp_mrr_u,\
358rbp_red_get(a_type, a_field, (a_node)));\
359rbp_black_set(a_type, a_field, rbp_mrr_v);\
360rbp_rotate_left(a_type, a_field, rbp_mrr_t, rbp_mrr_u);\
361rbp_left_set(a_type, a_field, (a_node), rbp_mrr_u);\
362rbp_rotate_right(a_type, a_field, (a_node), (r_node));\
363rbp_rotate_left(a_type, a_field, (a_node), rbp_mrr_t);\
364rbp_right_set(a_type, a_field, (r_node), rbp_mrr_t);\
365} else {\
366rbp_color_set(a_type, a_field, rbp_mrr_t,\
367rbp_red_get(a_type, a_field, (a_node)));\
368rbp_red_set(a_type, a_field, rbp_mrr_u);\
369rbp_rotate_right(a_type, a_field, (a_node), (r_node));\
370rbp_rotate_left(a_type, a_field, (a_node), rbp_mrr_t);\
371rbp_right_set(a_type, a_field, (r_node), rbp_mrr_t);\
372}\
373rbp_red_set(a_type, a_field, (a_node));\
374} else {\
375rbp_red_set(a_type, a_field, rbp_mrr_t);\
376rbp_mrr_t = rbp_left_get(a_type, a_field, rbp_mrr_t);\
377if (rbp_red_get(a_type, a_field, rbp_mrr_t)) {\
378rbp_black_set(a_type, a_field, rbp_mrr_t);\
379rbp_rotate_right(a_type, a_field, (a_node), (r_node));\
380rbp_rotate_left(a_type, a_field, (a_node), rbp_mrr_t);\
381rbp_right_set(a_type, a_field, (r_node), rbp_mrr_t);\
382} else {\
383rbp_rotate_left(a_type, a_field, (a_node), (r_node));\
384}\
385}\
386} while (0)
387
388#definerb_insert(a_type, a_field, a_cmp, a_tree, a_node) do {\
389a_type rbp_i_s;\
390a_type *rbp_i_g, *rbp_i_p, *rbp_i_c, *rbp_i_t, *rbp_i_u;\
391int rbp_i_cmp = 0;\
392rbp_i_g = &(a_tree)->rbt_nil;\
393rbp_left_set(a_type, a_field, &rbp_i_s, (a_tree)->rbt_root);\
394rbp_right_set(a_type, a_field, &rbp_i_s, &(a_tree)->rbt_nil);\
395rbp_black_set(a_type, a_field, &rbp_i_s);\
396rbp_i_p = &rbp_i_s;\
397rbp_i_c = (a_tree)->rbt_root;\
398/* Iteratively search down the tree for the insertion point, */\
399/* splitting 4-nodes as they are encountered. At the end of each */\
400/* iteration, rbp_i_g->rbp_i_p->rbp_i_c is a 3-level path down */\
401/* the tree, assuming a sufficiently deep tree. */\
402while (rbp_i_c != &(a_tree)->rbt_nil) {\
403rbp_i_t = rbp_left_get(a_type, a_field, rbp_i_c);\
404rbp_i_u = rbp_left_get(a_type, a_field, rbp_i_t);\
405if (rbp_red_get(a_type, a_field, rbp_i_t)\
406&& rbp_red_get(a_type, a_field, rbp_i_u)) {\
407/* rbp_i_c is the top of a logical 4-node, so split it. */\
408/* This iteration does not move down the tree, due to the */\
409/* disruptiveness of node splitting. */\
410/* */\
411/* Rotate right. */\
412rbp_rotate_right(a_type, a_field, rbp_i_c, rbp_i_t);\
413/* Pass red links up one level. */\
414rbp_i_u = rbp_left_get(a_type, a_field, rbp_i_t);\
415rbp_black_set(a_type, a_field, rbp_i_u);\
416if (rbp_left_get(a_type, a_field, rbp_i_p) == rbp_i_c) {\
417rbp_left_set(a_type, a_field, rbp_i_p, rbp_i_t);\
418rbp_i_c = rbp_i_t;\
419} else {\
420/* rbp_i_c was the right child of rbp_i_p, so rotate */\
421/* left in order to maintain the left-leaning */\
422/* invariant. */\
423assert(rbp_right_get(a_type, a_field, rbp_i_p)\
424== rbp_i_c);\
425rbp_right_set(a_type, a_field, rbp_i_p, rbp_i_t);\
426rbp_lean_left(a_type, a_field, rbp_i_p, rbp_i_u);\
427if (rbp_left_get(a_type, a_field, rbp_i_g) == rbp_i_p) {\
428rbp_left_set(a_type, a_field, rbp_i_g, rbp_i_u);\
429} else {\
430assert(rbp_right_get(a_type, a_field, rbp_i_g)\
431== rbp_i_p);\
432rbp_right_set(a_type, a_field, rbp_i_g, rbp_i_u);\
433}\
434rbp_i_p = rbp_i_u;\
435rbp_i_cmp = (a_cmp)((a_node), rbp_i_p);\
436if (rbp_i_cmp < 0) {\
437rbp_i_c = rbp_left_get(a_type, a_field, rbp_i_p);\
438} else {\
439assert(rbp_i_cmp > 0);\
440rbp_i_c = rbp_right_get(a_type, a_field, rbp_i_p);\
441}\
442continue;\
443}\
444}\
445rbp_i_g = rbp_i_p;\
446rbp_i_p = rbp_i_c;\
447rbp_i_cmp = (a_cmp)((a_node), rbp_i_c);\
448if (rbp_i_cmp < 0) {\
449rbp_i_c = rbp_left_get(a_type, a_field, rbp_i_c);\
450} else {\
451assert(rbp_i_cmp > 0);\
452rbp_i_c = rbp_right_get(a_type, a_field, rbp_i_c);\
453}\
454}\
455/* rbp_i_p now refers to the node under which to insert. */\
456rbp_node_new(a_type, a_field, a_tree, (a_node));\
457if (rbp_i_cmp > 0) {\
458rbp_right_set(a_type, a_field, rbp_i_p, (a_node));\
459rbp_lean_left(a_type, a_field, rbp_i_p, rbp_i_t);\
460if (rbp_left_get(a_type, a_field, rbp_i_g) == rbp_i_p) {\
461rbp_left_set(a_type, a_field, rbp_i_g, rbp_i_t);\
462} else if (rbp_right_get(a_type, a_field, rbp_i_g) == rbp_i_p) {\
463rbp_right_set(a_type, a_field, rbp_i_g, rbp_i_t);\
464}\
465} else {\
466rbp_left_set(a_type, a_field, rbp_i_p, (a_node));\
467}\
468/* Update the root and make sure that it is black. */\
469(a_tree)->rbt_root = rbp_left_get(a_type, a_field, &rbp_i_s);\
470rbp_black_set(a_type, a_field, (a_tree)->rbt_root);\
471} while (0)
472
473#definerb_remove(a_type, a_field, a_cmp, a_tree, a_node) do {\
474a_type rbp_r_s;\
475a_type *rbp_r_p, *rbp_r_c, *rbp_r_xp, *rbp_r_t, *rbp_r_u;\
476int rbp_r_cmp;\
477rbp_left_set(a_type, a_field, &rbp_r_s, (a_tree)->rbt_root);\
478rbp_right_set(a_type, a_field, &rbp_r_s, &(a_tree)->rbt_nil);\
479rbp_black_set(a_type, a_field, &rbp_r_s);\
480rbp_r_p = &rbp_r_s;\
481rbp_r_c = (a_tree)->rbt_root;\
482rbp_r_xp = &(a_tree)->rbt_nil;\
483/* Iterate down the tree, but always transform 2-nodes to 3- or */\
484/* 4-nodes in order to maintain the invariant that the current */\
485/* node is not a 2-node. This allows simple deletion once a leaf */\
486/* is reached. Handle the root specially though, since there may */\
487/* be no way to convert it from a 2-node to a 3-node. */\
488rbp_r_cmp = (a_cmp)((a_node), rbp_r_c);\
489if (rbp_r_cmp < 0) {\
490rbp_r_t = rbp_left_get(a_type, a_field, rbp_r_c);\
491rbp_r_u = rbp_left_get(a_type, a_field, rbp_r_t);\
492if (rbp_red_get(a_type, a_field, rbp_r_t) == false\
493&& rbp_red_get(a_type, a_field, rbp_r_u) == false) {\
494/* Apply standard transform to prepare for left move. */\
495rbp_move_red_left(a_type, a_field, rbp_r_c, rbp_r_t);\
496rbp_black_set(a_type, a_field, rbp_r_t);\
497rbp_left_set(a_type, a_field, rbp_r_p, rbp_r_t);\
498rbp_r_c = rbp_r_t;\
499} else {\
500/* Move left. */\
501rbp_r_p = rbp_r_c;\
502rbp_r_c = rbp_left_get(a_type, a_field, rbp_r_c);\
503}\
504} else {\
505if (rbp_r_cmp == 0) {\
506assert((a_node) == rbp_r_c);\
507if (rbp_right_get(a_type, a_field, rbp_r_c)\
508== &(a_tree)->rbt_nil) {\
509/* Delete root node (which is also a leaf node). */\
510if (rbp_left_get(a_type, a_field, rbp_r_c)\
511!= &(a_tree)->rbt_nil) {\
512rbp_lean_right(a_type, a_field, rbp_r_c, rbp_r_t);\
513rbp_right_set(a_type, a_field, rbp_r_t,\
514&(a_tree)->rbt_nil);\
515} else {\
516rbp_r_t = &(a_tree)->rbt_nil;\
517}\
518rbp_left_set(a_type, a_field, rbp_r_p, rbp_r_t);\
519} else {\
520/* This is the node we want to delete, but we will */\
521/* instead swap it with its successor and delete the */\
522/* successor. Record enough information to do the */\
523/* swap later. rbp_r_xp is the a_node's parent. */\
524rbp_r_xp = rbp_r_p;\
525rbp_r_cmp = 1; /* Note that deletion is incomplete. */\
526}\
527}\
528if (rbp_r_cmp == 1) {\
529if (rbp_red_get(a_type, a_field, rbp_left_get(a_type,\
530a_field, rbp_right_get(a_type, a_field, rbp_r_c)))\
531== false) {\
532rbp_r_t = rbp_left_get(a_type, a_field, rbp_r_c);\
533if (rbp_red_get(a_type, a_field, rbp_r_t)) {\
534/* Standard transform. */\
535rbp_move_red_right(a_type, a_field, rbp_r_c,\
536rbp_r_t);\
537} else {\
538/* Root-specific transform. */\
539rbp_red_set(a_type, a_field, rbp_r_c);\
540rbp_r_u = rbp_left_get(a_type, a_field, rbp_r_t);\
541if (rbp_red_get(a_type, a_field, rbp_r_u)) {\
542rbp_black_set(a_type, a_field, rbp_r_u);\
543rbp_rotate_right(a_type, a_field, rbp_r_c,\
544rbp_r_t);\
545rbp_rotate_left(a_type, a_field, rbp_r_c,\
546rbp_r_u);\
547rbp_right_set(a_type, a_field, rbp_r_t,\
548rbp_r_u);\
549} else {\
550rbp_red_set(a_type, a_field, rbp_r_t);\
551rbp_rotate_left(a_type, a_field, rbp_r_c,\
552rbp_r_t);\
553}\
554}\
555rbp_left_set(a_type, a_field, rbp_r_p, rbp_r_t);\
556rbp_r_c = rbp_r_t;\
557} else {\
558/* Move right. */\
559rbp_r_p = rbp_r_c;\
560rbp_r_c = rbp_right_get(a_type, a_field, rbp_r_c);\
561}\
562}\
563}\
564if (rbp_r_cmp != 0) {\
565while (true) {\
566assert(rbp_r_p != &(a_tree)->rbt_nil);\
567rbp_r_cmp = (a_cmp)((a_node), rbp_r_c);\
568if (rbp_r_cmp < 0) {\
569rbp_r_t = rbp_left_get(a_type, a_field, rbp_r_c);\
570if (rbp_r_t == &(a_tree)->rbt_nil) {\
571/* rbp_r_c now refers to the successor node to */\
572/* relocate, and rbp_r_xp/a_node refer to the */\
573/* context for the relocation. */\
574if (rbp_left_get(a_type, a_field, rbp_r_xp)\
575== (a_node)) {\
576rbp_left_set(a_type, a_field, rbp_r_xp,\
577rbp_r_c);\
578} else {\
579assert(rbp_right_get(a_type, a_field,\
580rbp_r_xp) == (a_node));\
581rbp_right_set(a_type, a_field, rbp_r_xp,\
582rbp_r_c);\
583}\
584rbp_left_set(a_type, a_field, rbp_r_c,\
585rbp_left_get(a_type, a_field, (a_node)));\
586rbp_right_set(a_type, a_field, rbp_r_c,\
587rbp_right_get(a_type, a_field, (a_node)));\
588rbp_color_set(a_type, a_field, rbp_r_c,\
589rbp_red_get(a_type, a_field, (a_node)));\
590if (rbp_left_get(a_type, a_field, rbp_r_p)\
591== rbp_r_c) {\
592rbp_left_set(a_type, a_field, rbp_r_p,\
593&(a_tree)->rbt_nil);\
594} else {\
595assert(rbp_right_get(a_type, a_field, rbp_r_p)\
596== rbp_r_c);\
597rbp_right_set(a_type, a_field, rbp_r_p,\
598&(a_tree)->rbt_nil);\
599}\
600break;\
601}\
602rbp_r_u = rbp_left_get(a_type, a_field, rbp_r_t);\
603if (rbp_red_get(a_type, a_field, rbp_r_t) == false\
604&& rbp_red_get(a_type, a_field, rbp_r_u) == false) {\
605rbp_move_red_left(a_type, a_field, rbp_r_c,\
606rbp_r_t);\
607if (rbp_left_get(a_type, a_field, rbp_r_p)\
608== rbp_r_c) {\
609rbp_left_set(a_type, a_field, rbp_r_p, rbp_r_t);\
610} else {\
611rbp_right_set(a_type, a_field, rbp_r_p,\
612rbp_r_t);\
613}\
614rbp_r_c = rbp_r_t;\
615} else {\
616rbp_r_p = rbp_r_c;\
617rbp_r_c = rbp_left_get(a_type, a_field, rbp_r_c);\
618}\
619} else {\
620/* Check whether to delete this node (it has to be */\
621/* the correct node and a leaf node). */\
622if (rbp_r_cmp == 0) {\
623assert((a_node) == rbp_r_c);\
624if (rbp_right_get(a_type, a_field, rbp_r_c)\
625== &(a_tree)->rbt_nil) {\
626/* Delete leaf node. */\
627if (rbp_left_get(a_type, a_field, rbp_r_c)\
628!= &(a_tree)->rbt_nil) {\
629rbp_lean_right(a_type, a_field, rbp_r_c,\
630rbp_r_t);\
631rbp_right_set(a_type, a_field, rbp_r_t,\
632&(a_tree)->rbt_nil);\
633} else {\
634rbp_r_t = &(a_tree)->rbt_nil;\
635}\
636if (rbp_left_get(a_type, a_field, rbp_r_p)\
637== rbp_r_c) {\
638rbp_left_set(a_type, a_field, rbp_r_p,\
639rbp_r_t);\
640} else {\
641rbp_right_set(a_type, a_field, rbp_r_p,\
642rbp_r_t);\
643}\
644break;\
645} else {\
646/* This is the node we want to delete, but we */\
647/* will instead swap it with its successor */\
648/* and delete the successor. Record enough */\
649/* information to do the swap later. */\
650/* rbp_r_xp is a_node's parent. */\
651rbp_r_xp = rbp_r_p;\
652}\
653}\
654rbp_r_t = rbp_right_get(a_type, a_field, rbp_r_c);\
655rbp_r_u = rbp_left_get(a_type, a_field, rbp_r_t);\
656if (rbp_red_get(a_type, a_field, rbp_r_u) == false) {\
657rbp_move_red_right(a_type, a_field, rbp_r_c,\
658rbp_r_t);\
659if (rbp_left_get(a_type, a_field, rbp_r_p)\
660== rbp_r_c) {\
661rbp_left_set(a_type, a_field, rbp_r_p, rbp_r_t);\
662} else {\
663rbp_right_set(a_type, a_field, rbp_r_p,\
664rbp_r_t);\
665}\
666rbp_r_c = rbp_r_t;\
667} else {\
668rbp_r_p = rbp_r_c;\
669rbp_r_c = rbp_right_get(a_type, a_field, rbp_r_c);\
670}\
671}\
672}\
673}\
674/* Update root. */\
675(a_tree)->rbt_root = rbp_left_get(a_type, a_field, &rbp_r_s);\
676} while (0)
677
678/*
679 * The rb_wrap() macro provides a convenient way to wrap functions around the
680 * cpp macros. The main benefits of wrapping are that 1) repeated macro
681 * expansion can cause code bloat, especially for rb_{insert,remove)(), and
682 * 2) type, linkage, comparison functions, etc. need not be specified at every
683 * call point.
684 */
685
686#definerb_wrap(a_attr, a_prefix, a_tree_type, a_type, a_field, a_cmp)\
687a_attr void\
688a_prefix##new(a_tree_type *tree) {\
689rb_new(a_type, a_field, tree);\
690}\
691a_attr a_type *\
692a_prefix##first(a_tree_type *tree) {\
693a_type *ret;\
694rb_first(a_type, a_field, tree, ret);\
695return (ret);\
696}\
697a_attr a_type *\
698a_prefix##last(a_tree_type *tree) {\
699a_type *ret;\
700rb_last(a_type, a_field, tree, ret);\
701return (ret);\
702}\
703a_attr a_type *\
704a_prefix##next(a_tree_type *tree, a_type *node) {\
705a_type *ret;\
706rb_next(a_type, a_field, a_cmp, tree, node, ret);\
707return (ret);\
708}\
709a_attr a_type *\
710a_prefix##prev(a_tree_type *tree, a_type *node) {\
711a_type *ret;\
712rb_prev(a_type, a_field, a_cmp, tree, node, ret);\
713return (ret);\
714}\
715a_attr a_type *\
716a_prefix##search(a_tree_type *tree, a_type *key) {\
717a_type *ret;\
718rb_search(a_type, a_field, a_cmp, tree, key, ret);\
719return (ret);\
720}\
721a_attr a_type *\
722a_prefix##nsearch(a_tree_type *tree, a_type *key) {\
723a_type *ret;\
724rb_nsearch(a_type, a_field, a_cmp, tree, key, ret);\
725return (ret);\
726}\
727a_attr a_type *\
728a_prefix##psearch(a_tree_type *tree, a_type *key) {\
729a_type *ret;\
730rb_psearch(a_type, a_field, a_cmp, tree, key, ret);\
731return (ret);\
732}\
733a_attr void\
734a_prefix##insert(a_tree_type *tree, a_type *node) {\
735rb_insert(a_type, a_field, a_cmp, tree, node);\
736}\
737a_attr void\
738a_prefix##remove(a_tree_type *tree, a_type *node) {\
739rb_remove(a_type, a_field, a_cmp, tree, node);\
740}
741
742/*
743 * The iterators simulate recursion via an array of pointers that store the
744 * current path. This is critical to performance, since a series of calls to
745 * rb_{next,prev}() would require time proportional to (n lg n), whereas this
746 * implementation only requires time proportional to (n).
747 *
748 * Since the iterators cache a path down the tree, any tree modification may
749 * cause the cached path to become invalid. In order to continue iteration,
750 * use something like the following sequence:
751 *
752 * {
753 * a_type *node, *tnode;
754 *
755 * rb_foreach_begin(a_type, a_field, a_tree, node) {
756 * ...
757 * rb_next(a_type, a_field, a_cmp, a_tree, node, tnode);
758 * rb_remove(a_type, a_field, a_cmp, a_tree, node);
759 * rb_foreach_next(a_type, a_field, a_cmp, a_tree, tnode);
760 * ...
761 * } rb_foreach_end(a_type, a_field, a_tree, node)
762 * }
763 *
764 * Note that this idiom is not advised if every iteration modifies the tree,
765 * since in that case there is no algorithmic complexity improvement over a
766 * series of rb_{next,prev}() calls, thus making the setup overhead wasted
767 * effort.
768 */
769
770#definerb_foreach_begin(a_type, a_field, a_tree, a_var) {\
771/* Compute the maximum possible tree depth (3X the black height). */\
772unsigned rbp_f_height;\
773rbp_black_height(a_type, a_field, a_tree, rbp_f_height);\
774rbp_f_height *= 3;\
775{\
776/* Initialize the path to contain the left spine. */\
777a_type *rbp_f_path[rbp_f_height];\
778a_type *rbp_f_node;\
779bool rbp_f_synced = false;\
780unsigned rbp_f_depth = 0;\
781if ((a_tree)->rbt_root != &(a_tree)->rbt_nil) {\
782rbp_f_path[rbp_f_depth] = (a_tree)->rbt_root;\
783rbp_f_depth++;\
784while ((rbp_f_node = rbp_left_get(a_type, a_field,\
785rbp_f_path[rbp_f_depth-1])) != &(a_tree)->rbt_nil) {\
786rbp_f_path[rbp_f_depth] = rbp_f_node;\
787rbp_f_depth++;\
788}\
789}\
790/* While the path is non-empty, iterate. */\
791while (rbp_f_depth > 0) {\
792(a_var) = rbp_f_path[rbp_f_depth-1];
793
794/* Only use if modifying the tree during iteration. */
795#definerb_foreach_next(a_type, a_field, a_cmp, a_tree, a_node)\
796/* Re-initialize the path to contain the path to a_node. */\
797rbp_f_depth = 0;\
798if (a_node != NULL) {\
799if ((a_tree)->rbt_root != &(a_tree)->rbt_nil) {\
800rbp_f_path[rbp_f_depth] = (a_tree)->rbt_root;\
801rbp_f_depth++;\
802rbp_f_node = rbp_f_path[0];\
803while (true) {\
804int rbp_f_cmp = (a_cmp)((a_node),\
805rbp_f_path[rbp_f_depth-1]);\
806if (rbp_f_cmp < 0) {\
807rbp_f_node = rbp_left_get(a_type, a_field,\
808rbp_f_path[rbp_f_depth-1]);\
809} else if (rbp_f_cmp > 0) {\
810rbp_f_node = rbp_right_get(a_type, a_field,\
811rbp_f_path[rbp_f_depth-1]);\
812} else {\
813break;\
814}\
815assert(rbp_f_node != &(a_tree)->rbt_nil);\
816rbp_f_path[rbp_f_depth] = rbp_f_node;\
817rbp_f_depth++;\
818}\
819}\
820}\
821rbp_f_synced = true;
822
823#definerb_foreach_end(a_type, a_field, a_tree, a_var)\
824if (rbp_f_synced) {\
825rbp_f_synced = false;\
826continue;\
827}\
828/* Find the successor. */\
829if ((rbp_f_node = rbp_right_get(a_type, a_field,\
830rbp_f_path[rbp_f_depth-1])) != &(a_tree)->rbt_nil) {\
831/* The successor is the left-most node in the right */\
832/* subtree. */\
833rbp_f_path[rbp_f_depth] = rbp_f_node;\
834rbp_f_depth++;\
835while ((rbp_f_node = rbp_left_get(a_type, a_field,\
836rbp_f_path[rbp_f_depth-1])) != &(a_tree)->rbt_nil) {\
837rbp_f_path[rbp_f_depth] = rbp_f_node;\
838rbp_f_depth++;\
839}\
840} else {\
841/* The successor is above the current node. Unwind */\
842/* until a left-leaning edge is removed from the */\
843/* path, or the path is empty. */\
844for (rbp_f_depth--; rbp_f_depth > 0; rbp_f_depth--) {\
845if (rbp_left_get(a_type, a_field,\
846rbp_f_path[rbp_f_depth-1])\
847== rbp_f_path[rbp_f_depth]) {\
848break;\
849}\
850}\
851}\
852}\
853}\
854}
855
856#definerb_foreach_reverse_begin(a_type, a_field, a_tree, a_var) {\
857/* Compute the maximum possible tree depth (3X the black height). */\
858unsigned rbp_fr_height;\
859rbp_black_height(a_type, a_field, a_tree, rbp_fr_height);\
860rbp_fr_height *= 3;\
861{\
862/* Initialize the path to contain the right spine. */\
863a_type *rbp_fr_path[rbp_fr_height];\
864a_type *rbp_fr_node;\
865bool rbp_fr_synced = false;\
866unsigned rbp_fr_depth = 0;\
867if ((a_tree)->rbt_root != &(a_tree)->rbt_nil) {\
868rbp_fr_path[rbp_fr_depth] = (a_tree)->rbt_root;\
869rbp_fr_depth++;\
870while ((rbp_fr_node = rbp_right_get(a_type, a_field,\
871rbp_fr_path[rbp_fr_depth-1])) != &(a_tree)->rbt_nil) {\
872rbp_fr_path[rbp_fr_depth] = rbp_fr_node;\
873rbp_fr_depth++;\
874}\
875}\
876/* While the path is non-empty, iterate. */\
877while (rbp_fr_depth > 0) {\
878(a_var) = rbp_fr_path[rbp_fr_depth-1];
879
880/* Only use if modifying the tree during iteration. */
881#definerb_foreach_reverse_prev(a_type, a_field, a_cmp, a_tree, a_node)\
882/* Re-initialize the path to contain the path to a_node. */\
883rbp_fr_depth = 0;\
884if (a_node != NULL) {\
885if ((a_tree)->rbt_root != &(a_tree)->rbt_nil) {\
886rbp_fr_path[rbp_fr_depth] = (a_tree)->rbt_root;\
887rbp_fr_depth++;\
888rbp_fr_node = rbp_fr_path[0];\
889while (true) {\
890int rbp_fr_cmp = (a_cmp)((a_node),\
891rbp_fr_path[rbp_fr_depth-1]);\
892if (rbp_fr_cmp < 0) {\
893rbp_fr_node = rbp_left_get(a_type, a_field,\
894rbp_fr_path[rbp_fr_depth-1]);\
895} else if (rbp_fr_cmp > 0) {\
896rbp_fr_node = rbp_right_get(a_type, a_field,\
897rbp_fr_path[rbp_fr_depth-1]);\
898} else {\
899break;\
900}\
901assert(rbp_fr_node != &(a_tree)->rbt_nil);\
902rbp_fr_path[rbp_fr_depth] = rbp_fr_node;\
903rbp_fr_depth++;\
904}\
905}\
906}\
907rbp_fr_synced = true;
908
909#definerb_foreach_reverse_end(a_type, a_field, a_tree, a_var)\
910if (rbp_fr_synced) {\
911rbp_fr_synced = false;\
912continue;\
913}\
914if (rbp_fr_depth == 0) {\
915/* rb_foreach_reverse_sync() was called with a NULL */\
916/* a_node. */\
917break;\
918}\
919/* Find the predecessor. */\
920if ((rbp_fr_node = rbp_left_get(a_type, a_field,\
921rbp_fr_path[rbp_fr_depth-1])) != &(a_tree)->rbt_nil) {\
922/* The predecessor is the right-most node in the left */\
923/* subtree. */\
924rbp_fr_path[rbp_fr_depth] = rbp_fr_node;\
925rbp_fr_depth++;\
926while ((rbp_fr_node = rbp_right_get(a_type, a_field,\
927rbp_fr_path[rbp_fr_depth-1])) != &(a_tree)->rbt_nil) {\
928rbp_fr_path[rbp_fr_depth] = rbp_fr_node;\
929rbp_fr_depth++;\
930}\
931} else {\
932/* The predecessor is above the current node. Unwind */\
933/* until a right-leaning edge is removed from the */\
934/* path, or the path is empty. */\
935for (rbp_fr_depth--; rbp_fr_depth > 0; rbp_fr_depth--) {\
936if (rbp_right_get(a_type, a_field,\
937rbp_fr_path[rbp_fr_depth-1])\
938== rbp_fr_path[rbp_fr_depth]) {\
939break;\
940}\
941}\
942}\
943}\
944}\
945}
946
947#endif /* RB_H_ */

Archive Download this file

Revision: 2182