Home | History | Annotate | Download | only in util
      1 /*******************************************************************************
      2 * Copyright (C) 2018 Cadence Design Systems, Inc.
      3 *
      4 * Permission is hereby granted, free of charge, to any person obtaining
      5 * a copy of this software and associated documentation files (the
      6 * "Software"), to use this Software with Cadence processor cores only and
      7 * not with any other processors and platforms, subject to
      8 * the following conditions:
      9 *
     10 * The above copyright notice and this permission notice shall be included
     11 * in all copies or substantial portions of the Software.
     12 *
     13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     14 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     15 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     16 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
     17 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     18 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     19 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     20 
     21 ******************************************************************************/
     22 
     23 /*******************************************************************************
     24  * rbtree.c
     25  *
     26  * Red-black tree library
     27  ******************************************************************************/
     28 
     29 #include "xf.h"
     30 
     31 /*******************************************************************************
     32  * Macros definitions
     33  ******************************************************************************/
     34 
     35 /* ...node color */
     36 #define RB_RED                          (1)
     37 #define RB_BLK                          (0)
     38 
     39 /* ...pointer to parent node */
     40 #define RB_PARENT(tree, node)           ((node)->parent)
     41 
     42 /* ...pointer to left child node */
     43 #define RB_LEFT(tree, node)             ((node)->left)
     44 
     45 /* ...pointer to right child node */
     46 #define RB_RIGHT(tree, node)            ((node)->right)
     47 
     48 /* ...pointer to right child node */
     49 #define RB_COLOR(tree, node)            ((node)->color & 1)
     50 
     51 /* ...check if node is black */
     52 #define RB_IS_BLACK(tree, node)         (!((node)->color & RB_RED))
     53 
     54 /* ...root node index of the tree - can be simplified? */
     55 #define RB_ROOT(tree)                   RB_LEFT((tree), &(tree)->root)
     56 
     57 /* ...empty node */
     58 #define RB_NULL(tree)                   (&(tree)->root)
     59 
     60 /*******************************************************************************
     61  * Helpers
     62  ******************************************************************************/
     63 
     64 #define RB_SET_P(t, n, p)               \
     65     ({ (n)->parent = (p); })
     66 
     67 #define RB_SET_L(t, n, l)               \
     68     ({ (n)->left = (l); })
     69 
     70 #define RB_SET_R(t, n, r)               \
     71     ({ (n)->right = (r); })
     72 
     73 #define RB_SET_C(t, n, c)               \
     74     RB_SET_C_##c((t), (n))
     75 
     76 #define RB_SET_C_RB_BLK(t, n)           \
     77     ({ (n)->color &= ~1; })
     78 
     79 #define RB_SET_C_RB_RED(t, n)           \
     80     ({ (n)->color |= 1; })
     81 
     82 #define RB_SET_P_C(t, n, p, c)          \
     83     ({ (n)->parent = (p); RB_SET_C_##c(t, n); })
     84 
     85 #define RB_SET_P_L(t, n, p, l)          \
     86     ({ (n)->parent = (p); (n)->left = (l); })
     87 
     88 #define RB_SET_P_L_C(t, n, p, l, c)     \
     89     ({ (n)->parent = (p); (n)->left = (l); RB_SET_C_##c(t, n); })
     90 
     91 #define RB_SET_P_R(t, n, p, r)          \
     92     ({ (n)->parent = (p); (n)->right = (r); })
     93 
     94 #define RB_SET_P_R_C(t, n, p, r, c)     \
     95     ({ (n)->parent = (p); (n)->right = (r); RB_SET_C_##c(t, n); })
     96 
     97 #define RB_SET_P_L_R(t, n, p, l, r)     \
     98     ({ (n)->parent = (p); (n)->left = (l); (n)->right = (r); })
     99 
    100 #define RB_SET_P_L_R_C(t, n, p, l, r, c)\
    101     ({ (n)->parent = (p); (n)->left = (l); (n)->right = (r); RB_SET_C_##c(t, n); })
    102 
    103 #define RB_SET_ROOT(t, n)               \
    104     RB_SET_L((t), &(t)->root, (n))
    105 
    106 /*******************************************************************************
    107  * RB-tree functions
    108  ******************************************************************************/
    109 
    110 /*******************************************************************************
    111  * rb_first, rb_last
    112  *
    113  * Return pointer to first/last item in the tree
    114  ******************************************************************************/
    115 
    116 rb_idx_t rb_first(rb_tree_t *tree)
    117 {
    118     rb_idx_t    p_idx, t_idx;
    119 
    120     if ((p_idx = RB_ROOT(tree)) != RB_NULL(tree))
    121     {
    122         /* ...find left-most item in non-empty tree */
    123         while ((t_idx = RB_LEFT(tree, p_idx)) != RB_NULL(tree))
    124             p_idx = t_idx;
    125     }
    126 
    127     return p_idx;
    128 }
    129 
    130 rb_idx_t rb_last(rb_tree_t *tree)
    131 {
    132     rb_idx_t    p_idx, t_idx;
    133 
    134     if ((p_idx = RB_ROOT(tree)) != RB_NULL(tree))
    135     {
    136         /* ...find right-most item in non-empty tree */
    137         while ((t_idx = RB_RIGHT(tree, p_idx)) != RB_NULL(tree))
    138             p_idx = t_idx;
    139     }
    140 
    141     return p_idx;
    142 }
    143 
    144 /*******************************************************************************
    145  * rb_next, rb_prev
    146  *
    147  * Return next / previous in-order item in the tree
    148  ******************************************************************************/
    149 
    150 rb_idx_t rb_next(rb_tree_t *tree, rb_idx_t n_idx)
    151 {
    152     rb_idx_t    p_idx, c_idx, t_idx;
    153 
    154     /* ...if we have any right children, process them */
    155     if ((c_idx = RB_RIGHT(tree, n_idx)) != RB_NULL(tree))
    156     {
    157         /* ...descent to the left-most node starting from right child */
    158         while ((t_idx = RB_LEFT(tree, c_idx)) != RB_NULL(tree))
    159             c_idx = t_idx;
    160         return c_idx;
    161     }
    162 
    163     /* ...no right children; ascend to our parent while we are right child */
    164     while ((p_idx = RB_PARENT(tree, n_idx)) != RB_NULL(tree))
    165     {
    166         /* ...as soon as "n" is a left child, return "p" */
    167         if (n_idx == RB_RIGHT(tree, p_idx))
    168             n_idx = p_idx;
    169         else
    170             return p_idx;
    171     }
    172 
    173     /* ...we were right-most child */
    174     return p_idx;
    175 }
    176 
    177 rb_idx_t rb_prev(rb_tree_t *tree, rb_idx_t n_idx)
    178 {
    179     rb_idx_t    p_idx, c_idx, t_idx;
    180 
    181     /* ...if we have any left children, process them */
    182     if ((c_idx = RB_LEFT(tree, n_idx)) != RB_NULL(tree))
    183     {
    184         /* ...descent to the right-most node starting from left child */
    185         while ((t_idx = RB_RIGHT(tree, c_idx)) != RB_NULL(tree))
    186             c_idx = t_idx;
    187         return c_idx;
    188     }
    189 
    190     /* ...no left children; ascend to our parent while we are left child */
    191     while ((p_idx = RB_PARENT(tree, n_idx)) != RB_NULL(tree))
    192     {
    193         /* ...as soon as "n" is a right child, return "p" */
    194         if (n_idx == RB_LEFT(tree, p_idx))
    195             n_idx = p_idx;
    196         else
    197             return p_idx;
    198     }
    199 
    200     /* ...we were left-most child */
    201     return p_idx;
    202 }
    203 
    204 /*******************************************************************************
    205  * rb_init
    206  *
    207  * Initialize rb-tree structure
    208  ******************************************************************************/
    209 
    210 void rb_init(rb_tree_t *tree)
    211 {
    212     /* ...initialize sentinel node of the empty tree */
    213     RB_SET_P_L_R_C(tree, &tree->root, RB_NULL(tree), RB_NULL(tree), RB_NULL(tree), RB_BLK);
    214 }
    215 
    216 /*******************************************************************************
    217  * rb_insert
    218  *
    219  * Insert new item into RB-tree. Returns non-zero node index on success
    220  ******************************************************************************/
    221 
    222 /* ...internal tree balancing function */
    223 static void __rb_insert_balance(rb_tree_t *tree, rb_idx_t n_idx, rb_idx_t p_idx)
    224 {
    225 	rb_idx_t    u_idx, g_idx, t_idx, cl_idx, cr_idx;
    226 
    227 rebalance:
    228 
    229 	/***************************************************************************
    230 	 * Trivial case #1 - N (red) is a root
    231 	 **************************************************************************/
    232 
    233 	if (p_idx == RB_NULL(tree))
    234     {
    235 		RB_SET_C(tree, n_idx, RB_BLK);
    236 		goto root;
    237 	}
    238 
    239 	/***************************************************************************
    240 	 * Trivial case #2 - P is black
    241 	 **************************************************************************/
    242 
    243 	if (RB_IS_BLACK(tree, p_idx))
    244 		goto done;
    245 
    246 	/***************************************************************************
    247 	 * Complex cases - P is red, N is red
    248 	 **************************************************************************/
    249 
    250 	/* ...grandparent must exist and be black */
    251 	g_idx = RB_PARENT(tree, p_idx);
    252 	if (p_idx == RB_LEFT(tree, g_idx))
    253     {
    254 		/* ...we are left grandchild; get uncle (if it exists) */
    255 		u_idx = RB_RIGHT(tree, g_idx);
    256 
    257 		/* ...if U is read, we have conditions of case #3 */
    258 		if (!RB_IS_BLACK(tree, u_idx))
    259 			goto case3;
    260 
    261 		/* ...we will need grand-grand-parent later */
    262 		t_idx = RB_PARENT(tree, g_idx);
    263 
    264 		/* ...U is black/null; if we are LL grandchild, we have case #5 */
    265 		if (n_idx == RB_LEFT(tree, p_idx))
    266 			goto case5_ll;
    267 
    268 		/* ...N is RL grandchild of G; case #4 */
    269 		goto case4_rl;
    270 	}
    271     else
    272     {
    273 		/* ...we are right grandchild; get uncle (if it exists) */
    274 		u_idx = RB_LEFT(tree, g_idx);
    275 
    276 		/* ...if U is read, we have conditions of case #3 */
    277 		if (!RB_IS_BLACK(tree, u_idx))
    278 			goto case3;
    279 
    280 		/* ...we will need grand-grand-parent later */
    281 		t_idx = RB_PARENT(tree, g_idx);
    282 
    283 		/* ...U is black/null; if we are RR grandchild, we have case #5 */
    284 		if (n_idx == RB_RIGHT(tree, p_idx))
    285 			goto case5_rr;
    286 
    287 		/* ...N is LR grandchild of G; case #4 */
    288 		goto case4_lr;
    289 	}
    290 
    291 case4_rl:
    292 
    293 	/***************************************************************************
    294 	 * Case #4 - P is red, U is black, N is red RL grandchild of G. We will do
    295 	 * two tree rotations - first the one described in case #4, second is the
    296 	 * one described in case #5 (as have conditions for case #5(LL) with P and
    297 	 * N changing roles
    298 	 **************************************************************************/
    299 
    300 	cl_idx = RB_LEFT(tree, n_idx), cr_idx = RB_RIGHT(tree, n_idx);
    301 	RB_SET_P_L_R_C(tree, n_idx, t_idx, p_idx, g_idx, RB_BLK);
    302 	RB_SET_P_R(tree, p_idx, n_idx, cl_idx);
    303 	RB_SET_P(tree, cl_idx, p_idx);
    304 	RB_SET_P_L_C(tree, g_idx, n_idx, cr_idx, RB_RED);
    305 	RB_SET_P(tree, cr_idx, g_idx);
    306 
    307 	/* ...new root of subtree is N; adjust T pointer */
    308 	goto case5_xx;
    309 
    310 case4_lr:
    311 
    312 	/***************************************************************************
    313 	 * Case #4 - P is red, U is black, N is red LR grandchild of G. We will do
    314 	 * two tree rotations - first the one described in case #4, second is the
    315 	 * one described in case #5 (as have conditions for case #5(RR) with P and
    316 	 * N changing roles
    317 	 **************************************************************************/
    318 
    319 	cl_idx = RB_LEFT(tree, n_idx), cr_idx = RB_RIGHT(tree, n_idx);
    320 	RB_SET_P_L_R_C(tree, n_idx, t_idx, g_idx, p_idx, RB_BLK);
    321 	RB_SET_P_L(tree, p_idx, n_idx, cr_idx);
    322 	RB_SET_P(tree, cr_idx, p_idx);
    323 	RB_SET_P_R_C(tree, g_idx, n_idx, cl_idx, RB_RED);
    324 	RB_SET_P(tree, cl_idx, g_idx);
    325 
    326 	/* ...new root of the subtree is N; adjust T pointer */
    327 	goto case5_xx;
    328 
    329 case5_ll:
    330 
    331 	/***************************************************************************
    332 	 * Case #5: N is LL grandchild of P; N and P red, G and U black
    333 	 **************************************************************************/
    334 
    335 	cr_idx = RB_RIGHT(tree, p_idx);
    336 	RB_SET_P_L_C(tree, g_idx, p_idx, cr_idx, RB_RED);
    337 	RB_SET_P(tree, cr_idx, g_idx);
    338 	RB_SET_P_R_C(tree, p_idx, t_idx, g_idx, RB_BLK);
    339 
    340 	/* ...new root of the subtree is P; relabel and adjust T pointer */
    341 	n_idx = p_idx;
    342 	goto case5_xx;
    343 
    344 case5_rr:
    345 
    346 	/***************************************************************************
    347 	 * Case #5: N is RR grandchild of P; N and P red, G and U black
    348 	 **************************************************************************/
    349 
    350 	cl_idx = RB_LEFT(tree, p_idx);
    351 	RB_SET_P_R_C(tree, g_idx, p_idx, cl_idx, RB_RED);
    352 	RB_SET_P(tree, cl_idx, g_idx);
    353 	RB_SET_P_L_C(tree, p_idx, t_idx, g_idx, RB_BLK);
    354 
    355 	/* ...new root of the subtree is P; relabel and adjust T pointer */
    356 	n_idx = p_idx;
    357 	goto case5_xx;
    358 
    359 case5_xx:
    360 
    361 	/* ...N is a (black) root of subtree; check if it is a root of tree as well */
    362     if (t_idx == RB_NULL(tree))
    363         goto root;
    364     else if (g_idx == RB_LEFT(tree, t_idx))
    365         RB_SET_L(tree, t_idx, n_idx);
    366     else
    367         RB_SET_R(tree, t_idx, n_idx);
    368 
    369     goto done;
    370 
    371 case3:
    372 
    373 	/***************************************************************************
    374 	 * Case #3 - P and U are red, G is black
    375 	 **************************************************************************/
    376 
    377 	RB_SET_C(tree, p_idx, RB_BLK);
    378 	RB_SET_C(tree, u_idx, RB_BLK);
    379 	RB_SET_C(tree, g_idx, RB_RED);
    380 
    381 	/* ...rebalance the tree for a G */
    382 	n_idx = g_idx, p_idx = RB_PARENT(tree, g_idx);
    383 	goto rebalance;
    384 
    385 root:
    386 	/* ...adjust root pointer of the tree */
    387 	RB_SET_ROOT(tree, n_idx);
    388 
    389 done:
    390 	/* ...tree is balanced */
    391 	return;
    392 }
    393 
    394 /* ...high-level API function */
    395 void rb_insert(rb_tree_t *tree, rb_idx_t n_idx, rb_idx_t p_idx)
    396 {
    397     if (p_idx == RB_NULL(tree))
    398     {
    399         /* ...set black root node */
    400 		RB_SET_P_L_R_C(tree, n_idx, p_idx, p_idx, p_idx, RB_BLK);
    401 
    402         /* ...tree consists of the only root node; is balanced */
    403 		RB_SET_ROOT(tree, n_idx);
    404     }
    405     else
    406     {
    407         /* ...create new node - set parent pointer and paint red */
    408         RB_SET_P_L_R_C(tree, n_idx, p_idx, RB_NULL(tree), RB_NULL(tree), RB_RED);
    409 
    410         /* ...and rebalance the tree */
    411         __rb_insert_balance(tree, n_idx, p_idx);
    412     }
    413 }
    414 
    415 /*******************************************************************************
    416  * rb_delete
    417  *
    418  * Remove item from RB-key (by key). Returns zero on success
    419  ******************************************************************************/
    420 
    421 /* ...internal tree balancing function */
    422 static void __rb_delete_rebalance(rb_tree_t *tree, rb_idx_t p_idx)
    423 {
    424 	rb_idx_t    n_idx, s_idx, sl_idx, sr_idx, g_idx, c_idx, cl_idx, cr_idx;
    425 
    426     /* ...initialize rebalancing procedure with null-child of P */
    427     n_idx = RB_NULL(tree);
    428 
    429 rebalance:
    430 
    431 	/* ...save grand-parent pointer (may be null) */
    432 	g_idx = RB_PARENT(tree, p_idx);
    433 
    434 	/***************************************************************************
    435 	 * Check for complex cases
    436 	 **************************************************************************/
    437 
    438 	if (n_idx == RB_LEFT(tree, p_idx))
    439     {
    440 		/* ...N is left child; get sibling (must exist) and its children  */
    441 		s_idx = RB_RIGHT(tree, p_idx);
    442 		sl_idx = RB_LEFT(tree, s_idx);
    443 		sr_idx = RB_RIGHT(tree, s_idx);
    444 
    445 		/* ...if S is black, test for conditions 3,4,5,6; otherwise - case 2 */
    446 		if (RB_IS_BLACK(tree, s_idx))
    447 			goto test3_l;
    448 		else
    449 			goto case2_l;
    450 	}
    451     else
    452     {
    453 		/* ...N is right child; get sibling (must exist) and its children */
    454 		s_idx = RB_LEFT(tree, p_idx);
    455 		sl_idx = RB_LEFT(tree, s_idx);
    456 		sr_idx = RB_RIGHT(tree, s_idx);
    457 
    458 		/* ...if S is black, test for conditions 3,4,5,6; otherwise - case 2 */
    459 		if (RB_IS_BLACK(tree, s_idx))
    460 			goto test3_r;
    461 		else
    462 			goto case2_r;
    463 	}
    464 
    465 case2_l:
    466 
    467 	/***************************************************************************
    468 	 * Case #2: N is a left child of P; S is red
    469 	 **************************************************************************/
    470 
    471 	c_idx = sl_idx;
    472 	RB_SET_P_L_C(tree, s_idx, g_idx, p_idx, RB_BLK);
    473 	RB_SET_P_R_C(tree, p_idx, s_idx, c_idx, RB_RED);
    474 	RB_SET_P(tree, c_idx, p_idx);
    475 
    476 	/* ...S is new root of subtree, Sl(C) is new sibling of N; update G */
    477 	goto case2_x;
    478 
    479 case2_r:
    480 
    481 	/***************************************************************************
    482 	 * Case #2: N is a right child of P; S is red
    483 	 **************************************************************************/
    484 
    485 	c_idx = sr_idx;
    486 	RB_SET_P_R_C(tree, s_idx, g_idx, p_idx, RB_BLK);
    487 	RB_SET_P_L_C(tree, p_idx, s_idx, c_idx, RB_RED);
    488 	RB_SET_P(tree, c_idx, p_idx);
    489 
    490 	/* ...S is new root of subtree, Sr(C) is new sibling of N; update G */
    491 	goto case2_x;
    492 
    493 case2_x:
    494 
    495 	/* ...check if S is becoming new (black) root of the tree */
    496     if (g_idx == RB_NULL(tree))
    497         RB_SET_ROOT(tree, s_idx);
    498     else if (p_idx == RB_LEFT(tree, g_idx))
    499         RB_SET_L(tree, g_idx, s_idx);
    500     else
    501         RB_SET_R(tree, g_idx, s_idx);
    502 
    503 	/* ...relabel new N's grandparent (now S) as G and new sibling (now C) as S	 */
    504 	g_idx = s_idx, s_idx = c_idx;
    505 	sl_idx = RB_LEFT(tree, s_idx);
    506 	sr_idx = RB_RIGHT(tree, s_idx);
    507 
    508 	/* ...N is still one of P's children; select proper side */
    509 	if (n_idx == RB_LEFT(tree, p_idx))
    510 		goto test3_l;
    511 	else
    512 		goto test3_r;
    513 
    514 test3_l:
    515 
    516 	/***************************************************************************
    517 	 * Test for cases 3,4,5,6; P is any, S is black. N is left child of P
    518 	 **************************************************************************/
    519 
    520     if (!RB_IS_BLACK(tree, sr_idx))
    521 		/* ...Sr is red, Sl of any color; conditions for case #6 are met */
    522 		goto case6_l;
    523     else if (!RB_IS_BLACK(tree, sl_idx))
    524         /* ...Sr is black and Sl is red; conditions for case #5 are met */
    525         goto case5_l;
    526     else if (RB_IS_BLACK(tree, p_idx))
    527         /* ...Sl and Sr are of the same (black) color and P is black */
    528         goto case3;
    529     else
    530         /* ...Sl and Sr are of the same (black) color and P is red */
    531         goto case4;
    532 
    533 test3_r:
    534 
    535 	/***************************************************************************
    536 	 * Test for cases 3,4,5,6; P is any, S is black. N is right child of P
    537 	 **************************************************************************/
    538 
    539     if (!RB_IS_BLACK(tree, sl_idx))
    540 		/* ...Sl is red, Sr of any color; conditions for case #6 are met */
    541 		goto case6_r;
    542     else if (!RB_IS_BLACK(tree, sr_idx))
    543         /* ...Sl is black and Sr is red; conditions for case #5 are met */
    544         goto case5_r;
    545     else if (RB_IS_BLACK(tree, p_idx))
    546         /* ...Sl and Sr are of the same (black) color and P is black */
    547         goto case3;
    548     else
    549         /* ...Sl and Sr are of the same (black) color and P is red */
    550         goto case4;
    551 
    552 case3:
    553 
    554 	/***************************************************************************
    555 	 * Case #3: N, P, S, Sl and Sr are black
    556 	 **************************************************************************/
    557 
    558 	RB_SET_C(tree, s_idx, RB_RED);
    559 
    560 	/* ...and rebalance the tree for parent */
    561 	n_idx = p_idx, p_idx = RB_PARENT(tree, p_idx);
    562 
    563 	if (p_idx == RB_NULL(tree))
    564 		goto done;
    565 	else
    566 		goto rebalance;
    567 
    568 case4:
    569 
    570 	/***************************************************************************
    571 	 * Case #4: N and S are black, P is red, Sl and Sr are all black
    572 	 **************************************************************************/
    573 
    574 	RB_SET_C(tree, s_idx, RB_RED);
    575 	RB_SET_C(tree, p_idx, RB_BLK);
    576 
    577 	goto done;
    578 
    579 case5_l:
    580 	/***************************************************************************
    581 	 * Case #5: S is black, Sl is red, Sr is black; N is left child of P. We
    582 	 * have two subsequent transformations (case #5 and case #6) combined
    583 	 **************************************************************************/
    584 
    585 	cl_idx = RB_LEFT(tree, sl_idx);
    586 	cr_idx = RB_RIGHT(tree, sl_idx);
    587 
    588 	if (RB_IS_BLACK(tree, p_idx))
    589 		RB_SET_P_L_R_C(tree, sl_idx, g_idx, p_idx, s_idx, RB_BLK);
    590 	else
    591 		RB_SET_P_L_R_C(tree, sl_idx, g_idx, p_idx, s_idx, RB_RED);
    592 
    593 	RB_SET_P_R_C(tree, p_idx, sl_idx, cl_idx, RB_BLK);
    594 	RB_SET_P(tree, cl_idx, p_idx);
    595 	RB_SET_P_L(tree, s_idx, sl_idx, cr_idx);
    596 	RB_SET_P(tree, cr_idx, s_idx);
    597 
    598 	/* ...relabel new root as S (for common processing in case #6) */
    599 	s_idx = sl_idx;
    600 	goto case6_x;
    601 
    602 case5_r:
    603 	/***************************************************************************
    604 	 * Case #5: S is black, Sr is red, Sl is black; N is right child of P. We
    605 	 * have two subsequent transformations (case #5 and case #6) combined
    606 	 **************************************************************************/
    607 
    608 	cl_idx = RB_LEFT(tree, sr_idx);
    609 	cr_idx = RB_RIGHT(tree, sr_idx);
    610 
    611 	if (RB_IS_BLACK(tree, p_idx))
    612 		RB_SET_P_L_R_C(tree, sr_idx, g_idx, s_idx, p_idx, RB_BLK);
    613 	else
    614 		RB_SET_P_L_R_C(tree, sr_idx, g_idx, s_idx, p_idx, RB_RED);
    615 
    616 	RB_SET_P_L_C(tree, p_idx, sr_idx, cr_idx, RB_BLK);
    617 	RB_SET_P(tree, cr_idx, p_idx);
    618 	RB_SET_P_R(tree, s_idx, sr_idx, cl_idx);
    619 	RB_SET_P(tree, cl_idx, s_idx);
    620 
    621 	/* ...relabel new root as S (for common processing in case #6) */
    622 	s_idx = sr_idx;
    623 	goto case6_x;
    624 
    625 case6_l:
    626 
    627 	/***************************************************************************
    628 	 * Case #6: S is black, N is the left child of P, Sr is red
    629 	 **************************************************************************/
    630 
    631 	if (RB_IS_BLACK(tree, p_idx))
    632 		RB_SET_P_L(tree, s_idx, g_idx, p_idx);
    633 	else
    634 		RB_SET_P_L_C(tree, s_idx, g_idx, p_idx, RB_RED);
    635 
    636 	RB_SET_P_R_C(tree, p_idx, s_idx, sl_idx, RB_BLK);
    637 	RB_SET_P(tree, sl_idx, p_idx);
    638 	RB_SET_C(tree, sr_idx, RB_BLK);
    639 
    640 	/* ...S is a new root of subtree; update G */
    641 	goto case6_x;
    642 
    643 case6_r:
    644 
    645 	/***************************************************************************
    646 	 * Case #6: S is black, N is the right child of P, Sl is red
    647 	 **************************************************************************/
    648 
    649 	if (RB_IS_BLACK(tree, p_idx))
    650 		RB_SET_P_R(tree, s_idx, g_idx, p_idx);
    651 	else
    652 		RB_SET_P_R_C(tree, s_idx, g_idx, p_idx, RB_RED);
    653 
    654 	RB_SET_P_L_C(tree, p_idx, s_idx, sr_idx, RB_BLK);
    655 	RB_SET_P(tree, sr_idx, p_idx);
    656 	RB_SET_C(tree, sl_idx, RB_BLK);
    657 
    658 	/* ...S is a new root of subtree; update G */
    659 	goto case6_x;
    660 
    661 case6_x:
    662 
    663 	/* ...S is a new root of subtree; update G's pointer */
    664     if (g_idx == RB_NULL(tree))
    665 		RB_SET_ROOT(tree, s_idx);
    666     else if (p_idx == RB_LEFT(tree, g_idx))
    667         RB_SET_L(tree, g_idx, s_idx);
    668     else
    669         RB_SET_R(tree, g_idx, s_idx);
    670 
    671 	/* ...tree is balanced; pass through */
    672 
    673 done:
    674 
    675 	return;
    676 }
    677 
    678 /* ...high-level API function */
    679 rb_idx_t rb_delete(rb_tree_t *tree, rb_idx_t n_idx)
    680 {
    681 	rb_idx_t    p_idx, t_idx, m_idx, c_idx, l_idx, r_idx, k_idx;
    682     u32         color;
    683 
    684     /* ...save parent of element N that we are going to remove */
    685     p_idx = RB_PARENT(tree, n_idx);
    686 
    687 	/* ...get in-order predecessor/successor of n_idx, if possible */
    688 	if ((m_idx = RB_LEFT(tree, n_idx)) != RB_NULL(tree))
    689     {
    690 		while ((t_idx = RB_RIGHT(tree, m_idx)) != RB_NULL(tree))
    691 			m_idx = t_idx;
    692 
    693         /* ...set the child of in-order predecessor (may be null) */
    694 		c_idx = RB_LEFT(tree, m_idx);
    695 	}
    696     else if ((m_idx = RB_RIGHT(tree, n_idx)) != RB_NULL(tree))
    697     {
    698 		while ((t_idx = RB_LEFT(tree, m_idx)) != RB_NULL(tree))
    699 			m_idx = t_idx;
    700 
    701         /* ...set the child of in-order successor (may be null) */
    702 		c_idx = RB_RIGHT(tree, m_idx);
    703 	}
    704     else if (p_idx == RB_NULL(tree))
    705     {
    706         /* ...tree consists of the only root node N that we are removing */
    707         RB_SET_ROOT(tree, m_idx);
    708 
    709         /* ..return tree null pointer */
    710         return m_idx;
    711     }
    712     else
    713     {
    714         /* ...N is a (non-root) leaf node; M and C are null */
    715 		c_idx = m_idx;
    716 
    717         /* ...save the color of the node we are going to delete */
    718         color = RB_COLOR(tree, n_idx);
    719 
    720         /* ...set new parent of C */
    721         t_idx = p_idx;
    722 
    723         /* ...pointer that we return as in-order predecessor/successor */
    724         k_idx = p_idx;
    725 
    726         /* ...adjust only parent of the N */
    727         goto adjust_parent;
    728     }
    729 
    730     /* ...node that replaces our component is M */
    731     k_idx = m_idx;
    732 
    733 	/***************************************************************************
    734 	 * Replace node N with M
    735 	 **************************************************************************/
    736 
    737     /* ...save original color of M (the node that we are deleting) */
    738     color = RB_COLOR(tree, m_idx);
    739 
    740     /* ...put M in place of N; get N's children */
    741     l_idx = RB_LEFT(tree, n_idx);
    742     r_idx = RB_RIGHT(tree, n_idx);
    743 
    744     /* ...see if M is a child of N */
    745     if ((t_idx = RB_PARENT(tree, m_idx)) != n_idx)
    746     {
    747         /* ...C becomes left or right child of M's original parent T */
    748         if (c_idx == RB_LEFT(tree, m_idx))
    749             RB_SET_R(tree, t_idx, c_idx);
    750         else
    751             RB_SET_L(tree, t_idx, c_idx);
    752 
    753         /* ...adjust C parent pointer (okay if it's null)  */
    754         RB_SET_P(tree, c_idx, t_idx);
    755 
    756         /* ...set all pointers of node M (it replaces N) */
    757         RB_SET_P_L_R(tree, m_idx, p_idx, l_idx, r_idx);
    758         RB_SET_P(tree, l_idx, m_idx);
    759         RB_SET_P(tree, r_idx, m_idx);
    760     }
    761     else
    762     {
    763         /* ...M is a left or right child of N; it gets to N's place, and C remains intact */
    764         if (m_idx == l_idx)
    765         {
    766             RB_SET_P_R(tree, m_idx, p_idx, r_idx);
    767             RB_SET_P(tree, r_idx, m_idx);
    768         }
    769         else
    770         {
    771             RB_SET_P_L(tree, m_idx, p_idx, l_idx);
    772             RB_SET_P(tree, l_idx, m_idx);
    773         }
    774 
    775         /* ...parent of C is still M (we label it as T) */
    776         t_idx = m_idx;
    777     }
    778 
    779     /* ...paint M in the same color as N which it replaced */
    780     if (RB_IS_BLACK(tree, n_idx))
    781         RB_SET_C(tree, m_idx, RB_BLK);
    782     else
    783         RB_SET_C(tree, m_idx, RB_RED);
    784 
    785 adjust_parent:
    786 
    787     /* ...adjust N's parent node to point to M */
    788     if (p_idx == RB_NULL(tree))
    789         RB_SET_ROOT(tree, m_idx);
    790     else if (n_idx == RB_LEFT(tree, p_idx))
    791         RB_SET_L(tree, p_idx, m_idx);
    792     else
    793         RB_SET_R(tree, p_idx, m_idx);
    794 
    795 	/* ...check for a color of deleted item (M or N in case it is a leaf) */
    796 	if (color == RB_BLK)
    797     {
    798 		if (c_idx == RB_NULL(tree))
    799             /* ...rebalance the tree for a T node (it is never a null)*/
    800             __rb_delete_rebalance(tree, t_idx);
    801 		else
    802             /* ...C node exists and is necessarily red; repaint it black */
    803             RB_SET_C(tree, c_idx, RB_BLK);
    804 	}
    805 
    806     /* ....return the node K which replaced deleted node N */
    807     return k_idx;
    808 }
    809 
    810 /*******************************************************************************
    811  * rb_replace
    812  *
    813  * Replace the node with the same-key node - adjust tree pointers
    814  ******************************************************************************/
    815 
    816 void rb_replace(rb_tree_t *tree, rb_idx_t n_idx, rb_idx_t t_idx)
    817 {
    818     rb_idx_t    p_idx, l_idx, r_idx;
    819 
    820     /* ...get node pointers */
    821     p_idx = RB_PARENT(tree, n_idx), l_idx = RB_LEFT(tree, n_idx), r_idx = RB_RIGHT(tree, n_idx);
    822 
    823     /* ...set new node pointers */
    824     RB_SET_P_L_R(tree, t_idx, p_idx, l_idx, r_idx);
    825 
    826     /* ...set node color */
    827     if (RB_IS_BLACK(tree, n_idx))
    828         RB_SET_C(tree, t_idx, RB_BLK);
    829     else
    830         RB_SET_C(tree, t_idx, RB_RED);
    831 
    832     /* ...update parent node */
    833     if (p_idx == RB_NULL(tree))
    834         RB_SET_ROOT(tree, t_idx);
    835     else if (n_idx == RB_LEFT(tree, p_idx))
    836         RB_SET_L(tree, p_idx, t_idx);
    837     else
    838         RB_SET_R(tree, p_idx, t_idx);
    839 
    840     /* ...update children's parent node (okay if null) */
    841     RB_SET_P(tree, l_idx, t_idx), RB_SET_P(tree, r_idx, t_idx);
    842 }
    843