summaryrefslogtreecommitdiff
path: root/hifi/xaf/hifi-dpf/core/util/rbtree.c
diff options
context:
space:
mode:
Diffstat (limited to 'hifi/xaf/hifi-dpf/core/util/rbtree.c')
-rw-r--r--hifi/xaf/hifi-dpf/core/util/rbtree.c842
1 files changed, 842 insertions, 0 deletions
diff --git a/hifi/xaf/hifi-dpf/core/util/rbtree.c b/hifi/xaf/hifi-dpf/core/util/rbtree.c
new file mode 100644
index 00000000..740e0255
--- /dev/null
+++ b/hifi/xaf/hifi-dpf/core/util/rbtree.c
@@ -0,0 +1,842 @@
+/*******************************************************************************
+* Copyright (C) 2018 Cadence Design Systems, Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining
+* a copy of this software and associated documentation files (the
+* "Software"), to use this Software with Cadence processor cores only and
+* not with any other processors and platforms, subject to
+* the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************************/
+
+/*******************************************************************************
+ * rbtree.c
+ *
+ * Red-black tree library
+ ******************************************************************************/
+
+#include "xf.h"
+
+/*******************************************************************************
+ * Macros definitions
+ ******************************************************************************/
+
+/* ...node color */
+#define RB_RED (1)
+#define RB_BLK (0)
+
+/* ...pointer to parent node */
+#define RB_PARENT(tree, node) ((node)->parent)
+
+/* ...pointer to left child node */
+#define RB_LEFT(tree, node) ((node)->left)
+
+/* ...pointer to right child node */
+#define RB_RIGHT(tree, node) ((node)->right)
+
+/* ...pointer to right child node */
+#define RB_COLOR(tree, node) ((node)->color & 1)
+
+/* ...check if node is black */
+#define RB_IS_BLACK(tree, node) (!((node)->color & RB_RED))
+
+/* ...root node index of the tree - can be simplified? */
+#define RB_ROOT(tree) RB_LEFT((tree), &(tree)->root)
+
+/* ...empty node */
+#define RB_NULL(tree) (&(tree)->root)
+
+/*******************************************************************************
+ * Helpers
+ ******************************************************************************/
+
+#define RB_SET_P(t, n, p) \
+ ({ (n)->parent = (p); })
+
+#define RB_SET_L(t, n, l) \
+ ({ (n)->left = (l); })
+
+#define RB_SET_R(t, n, r) \
+ ({ (n)->right = (r); })
+
+#define RB_SET_C(t, n, c) \
+ RB_SET_C_##c((t), (n))
+
+#define RB_SET_C_RB_BLK(t, n) \
+ ({ (n)->color &= ~1; })
+
+#define RB_SET_C_RB_RED(t, n) \
+ ({ (n)->color |= 1; })
+
+#define RB_SET_P_C(t, n, p, c) \
+ ({ (n)->parent = (p); RB_SET_C_##c(t, n); })
+
+#define RB_SET_P_L(t, n, p, l) \
+ ({ (n)->parent = (p); (n)->left = (l); })
+
+#define RB_SET_P_L_C(t, n, p, l, c) \
+ ({ (n)->parent = (p); (n)->left = (l); RB_SET_C_##c(t, n); })
+
+#define RB_SET_P_R(t, n, p, r) \
+ ({ (n)->parent = (p); (n)->right = (r); })
+
+#define RB_SET_P_R_C(t, n, p, r, c) \
+ ({ (n)->parent = (p); (n)->right = (r); RB_SET_C_##c(t, n); })
+
+#define RB_SET_P_L_R(t, n, p, l, r) \
+ ({ (n)->parent = (p); (n)->left = (l); (n)->right = (r); })
+
+#define RB_SET_P_L_R_C(t, n, p, l, r, c)\
+ ({ (n)->parent = (p); (n)->left = (l); (n)->right = (r); RB_SET_C_##c(t, n); })
+
+#define RB_SET_ROOT(t, n) \
+ RB_SET_L((t), &(t)->root, (n))
+
+/*******************************************************************************
+ * RB-tree functions
+ ******************************************************************************/
+
+/*******************************************************************************
+ * rb_first, rb_last
+ *
+ * Return pointer to first/last item in the tree
+ ******************************************************************************/
+
+rb_idx_t rb_first(rb_tree_t *tree)
+{
+ rb_idx_t p_idx, t_idx;
+
+ if ((p_idx = RB_ROOT(tree)) != RB_NULL(tree))
+ {
+ /* ...find left-most item in non-empty tree */
+ while ((t_idx = RB_LEFT(tree, p_idx)) != RB_NULL(tree))
+ p_idx = t_idx;
+ }
+
+ return p_idx;
+}
+
+rb_idx_t rb_last(rb_tree_t *tree)
+{
+ rb_idx_t p_idx, t_idx;
+
+ if ((p_idx = RB_ROOT(tree)) != RB_NULL(tree))
+ {
+ /* ...find right-most item in non-empty tree */
+ while ((t_idx = RB_RIGHT(tree, p_idx)) != RB_NULL(tree))
+ p_idx = t_idx;
+ }
+
+ return p_idx;
+}
+
+/*******************************************************************************
+ * rb_next, rb_prev
+ *
+ * Return next / previous in-order item in the tree
+ ******************************************************************************/
+
+rb_idx_t rb_next(rb_tree_t *tree, rb_idx_t n_idx)
+{
+ rb_idx_t p_idx, c_idx, t_idx;
+
+ /* ...if we have any right children, process them */
+ if ((c_idx = RB_RIGHT(tree, n_idx)) != RB_NULL(tree))
+ {
+ /* ...descent to the left-most node starting from right child */
+ while ((t_idx = RB_LEFT(tree, c_idx)) != RB_NULL(tree))
+ c_idx = t_idx;
+ return c_idx;
+ }
+
+ /* ...no right children; ascend to our parent while we are right child */
+ while ((p_idx = RB_PARENT(tree, n_idx)) != RB_NULL(tree))
+ {
+ /* ...as soon as "n" is a left child, return "p" */
+ if (n_idx == RB_RIGHT(tree, p_idx))
+ n_idx = p_idx;
+ else
+ return p_idx;
+ }
+
+ /* ...we were right-most child */
+ return p_idx;
+}
+
+rb_idx_t rb_prev(rb_tree_t *tree, rb_idx_t n_idx)
+{
+ rb_idx_t p_idx, c_idx, t_idx;
+
+ /* ...if we have any left children, process them */
+ if ((c_idx = RB_LEFT(tree, n_idx)) != RB_NULL(tree))
+ {
+ /* ...descent to the right-most node starting from left child */
+ while ((t_idx = RB_RIGHT(tree, c_idx)) != RB_NULL(tree))
+ c_idx = t_idx;
+ return c_idx;
+ }
+
+ /* ...no left children; ascend to our parent while we are left child */
+ while ((p_idx = RB_PARENT(tree, n_idx)) != RB_NULL(tree))
+ {
+ /* ...as soon as "n" is a right child, return "p" */
+ if (n_idx == RB_LEFT(tree, p_idx))
+ n_idx = p_idx;
+ else
+ return p_idx;
+ }
+
+ /* ...we were left-most child */
+ return p_idx;
+}
+
+/*******************************************************************************
+ * rb_init
+ *
+ * Initialize rb-tree structure
+ ******************************************************************************/
+
+void rb_init(rb_tree_t *tree)
+{
+ /* ...initialize sentinel node of the empty tree */
+ RB_SET_P_L_R_C(tree, &tree->root, RB_NULL(tree), RB_NULL(tree), RB_NULL(tree), RB_BLK);
+}
+
+/*******************************************************************************
+ * rb_insert
+ *
+ * Insert new item into RB-tree. Returns non-zero node index on success
+ ******************************************************************************/
+
+/* ...internal tree balancing function */
+static void __rb_insert_balance(rb_tree_t *tree, rb_idx_t n_idx, rb_idx_t p_idx)
+{
+ rb_idx_t u_idx, g_idx, t_idx, cl_idx, cr_idx;
+
+rebalance:
+
+ /***************************************************************************
+ * Trivial case #1 - N (red) is a root
+ **************************************************************************/
+
+ if (p_idx == RB_NULL(tree))
+ {
+ RB_SET_C(tree, n_idx, RB_BLK);
+ goto root;
+ }
+
+ /***************************************************************************
+ * Trivial case #2 - P is black
+ **************************************************************************/
+
+ if (RB_IS_BLACK(tree, p_idx))
+ goto done;
+
+ /***************************************************************************
+ * Complex cases - P is red, N is red
+ **************************************************************************/
+
+ /* ...grandparent must exist and be black */
+ g_idx = RB_PARENT(tree, p_idx);
+ if (p_idx == RB_LEFT(tree, g_idx))
+ {
+ /* ...we are left grandchild; get uncle (if it exists) */
+ u_idx = RB_RIGHT(tree, g_idx);
+
+ /* ...if U is read, we have conditions of case #3 */
+ if (!RB_IS_BLACK(tree, u_idx))
+ goto case3;
+
+ /* ...we will need grand-grand-parent later */
+ t_idx = RB_PARENT(tree, g_idx);
+
+ /* ...U is black/null; if we are LL grandchild, we have case #5 */
+ if (n_idx == RB_LEFT(tree, p_idx))
+ goto case5_ll;
+
+ /* ...N is RL grandchild of G; case #4 */
+ goto case4_rl;
+ }
+ else
+ {
+ /* ...we are right grandchild; get uncle (if it exists) */
+ u_idx = RB_LEFT(tree, g_idx);
+
+ /* ...if U is read, we have conditions of case #3 */
+ if (!RB_IS_BLACK(tree, u_idx))
+ goto case3;
+
+ /* ...we will need grand-grand-parent later */
+ t_idx = RB_PARENT(tree, g_idx);
+
+ /* ...U is black/null; if we are RR grandchild, we have case #5 */
+ if (n_idx == RB_RIGHT(tree, p_idx))
+ goto case5_rr;
+
+ /* ...N is LR grandchild of G; case #4 */
+ goto case4_lr;
+ }
+
+case4_rl:
+
+ /***************************************************************************
+ * Case #4 - P is red, U is black, N is red RL grandchild of G. We will do
+ * two tree rotations - first the one described in case #4, second is the
+ * one described in case #5 (as have conditions for case #5(LL) with P and
+ * N changing roles
+ **************************************************************************/
+
+ cl_idx = RB_LEFT(tree, n_idx), cr_idx = RB_RIGHT(tree, n_idx);
+ RB_SET_P_L_R_C(tree, n_idx, t_idx, p_idx, g_idx, RB_BLK);
+ RB_SET_P_R(tree, p_idx, n_idx, cl_idx);
+ RB_SET_P(tree, cl_idx, p_idx);
+ RB_SET_P_L_C(tree, g_idx, n_idx, cr_idx, RB_RED);
+ RB_SET_P(tree, cr_idx, g_idx);
+
+ /* ...new root of subtree is N; adjust T pointer */
+ goto case5_xx;
+
+case4_lr:
+
+ /***************************************************************************
+ * Case #4 - P is red, U is black, N is red LR grandchild of G. We will do
+ * two tree rotations - first the one described in case #4, second is the
+ * one described in case #5 (as have conditions for case #5(RR) with P and
+ * N changing roles
+ **************************************************************************/
+
+ cl_idx = RB_LEFT(tree, n_idx), cr_idx = RB_RIGHT(tree, n_idx);
+ RB_SET_P_L_R_C(tree, n_idx, t_idx, g_idx, p_idx, RB_BLK);
+ RB_SET_P_L(tree, p_idx, n_idx, cr_idx);
+ RB_SET_P(tree, cr_idx, p_idx);
+ RB_SET_P_R_C(tree, g_idx, n_idx, cl_idx, RB_RED);
+ RB_SET_P(tree, cl_idx, g_idx);
+
+ /* ...new root of the subtree is N; adjust T pointer */
+ goto case5_xx;
+
+case5_ll:
+
+ /***************************************************************************
+ * Case #5: N is LL grandchild of P; N and P red, G and U black
+ **************************************************************************/
+
+ cr_idx = RB_RIGHT(tree, p_idx);
+ RB_SET_P_L_C(tree, g_idx, p_idx, cr_idx, RB_RED);
+ RB_SET_P(tree, cr_idx, g_idx);
+ RB_SET_P_R_C(tree, p_idx, t_idx, g_idx, RB_BLK);
+
+ /* ...new root of the subtree is P; relabel and adjust T pointer */
+ n_idx = p_idx;
+ goto case5_xx;
+
+case5_rr:
+
+ /***************************************************************************
+ * Case #5: N is RR grandchild of P; N and P red, G and U black
+ **************************************************************************/
+
+ cl_idx = RB_LEFT(tree, p_idx);
+ RB_SET_P_R_C(tree, g_idx, p_idx, cl_idx, RB_RED);
+ RB_SET_P(tree, cl_idx, g_idx);
+ RB_SET_P_L_C(tree, p_idx, t_idx, g_idx, RB_BLK);
+
+ /* ...new root of the subtree is P; relabel and adjust T pointer */
+ n_idx = p_idx;
+ goto case5_xx;
+
+case5_xx:
+
+ /* ...N is a (black) root of subtree; check if it is a root of tree as well */
+ if (t_idx == RB_NULL(tree))
+ goto root;
+ else if (g_idx == RB_LEFT(tree, t_idx))
+ RB_SET_L(tree, t_idx, n_idx);
+ else
+ RB_SET_R(tree, t_idx, n_idx);
+
+ goto done;
+
+case3:
+
+ /***************************************************************************
+ * Case #3 - P and U are red, G is black
+ **************************************************************************/
+
+ RB_SET_C(tree, p_idx, RB_BLK);
+ RB_SET_C(tree, u_idx, RB_BLK);
+ RB_SET_C(tree, g_idx, RB_RED);
+
+ /* ...rebalance the tree for a G */
+ n_idx = g_idx, p_idx = RB_PARENT(tree, g_idx);
+ goto rebalance;
+
+root:
+ /* ...adjust root pointer of the tree */
+ RB_SET_ROOT(tree, n_idx);
+
+done:
+ /* ...tree is balanced */
+ return;
+}
+
+/* ...high-level API function */
+void rb_insert(rb_tree_t *tree, rb_idx_t n_idx, rb_idx_t p_idx)
+{
+ if (p_idx == RB_NULL(tree))
+ {
+ /* ...set black root node */
+ RB_SET_P_L_R_C(tree, n_idx, p_idx, p_idx, p_idx, RB_BLK);
+
+ /* ...tree consists of the only root node; is balanced */
+ RB_SET_ROOT(tree, n_idx);
+ }
+ else
+ {
+ /* ...create new node - set parent pointer and paint red */
+ RB_SET_P_L_R_C(tree, n_idx, p_idx, RB_NULL(tree), RB_NULL(tree), RB_RED);
+
+ /* ...and rebalance the tree */
+ __rb_insert_balance(tree, n_idx, p_idx);
+ }
+}
+
+/*******************************************************************************
+ * rb_delete
+ *
+ * Remove item from RB-key (by key). Returns zero on success
+ ******************************************************************************/
+
+/* ...internal tree balancing function */
+static void __rb_delete_rebalance(rb_tree_t *tree, rb_idx_t p_idx)
+{
+ rb_idx_t n_idx, s_idx, sl_idx, sr_idx, g_idx, c_idx, cl_idx, cr_idx;
+
+ /* ...initialize rebalancing procedure with null-child of P */
+ n_idx = RB_NULL(tree);
+
+rebalance:
+
+ /* ...save grand-parent pointer (may be null) */
+ g_idx = RB_PARENT(tree, p_idx);
+
+ /***************************************************************************
+ * Check for complex cases
+ **************************************************************************/
+
+ if (n_idx == RB_LEFT(tree, p_idx))
+ {
+ /* ...N is left child; get sibling (must exist) and its children */
+ s_idx = RB_RIGHT(tree, p_idx);
+ sl_idx = RB_LEFT(tree, s_idx);
+ sr_idx = RB_RIGHT(tree, s_idx);
+
+ /* ...if S is black, test for conditions 3,4,5,6; otherwise - case 2 */
+ if (RB_IS_BLACK(tree, s_idx))
+ goto test3_l;
+ else
+ goto case2_l;
+ }
+ else
+ {
+ /* ...N is right child; get sibling (must exist) and its children */
+ s_idx = RB_LEFT(tree, p_idx);
+ sl_idx = RB_LEFT(tree, s_idx);
+ sr_idx = RB_RIGHT(tree, s_idx);
+
+ /* ...if S is black, test for conditions 3,4,5,6; otherwise - case 2 */
+ if (RB_IS_BLACK(tree, s_idx))
+ goto test3_r;
+ else
+ goto case2_r;
+ }
+
+case2_l:
+
+ /***************************************************************************
+ * Case #2: N is a left child of P; S is red
+ **************************************************************************/
+
+ c_idx = sl_idx;
+ RB_SET_P_L_C(tree, s_idx, g_idx, p_idx, RB_BLK);
+ RB_SET_P_R_C(tree, p_idx, s_idx, c_idx, RB_RED);
+ RB_SET_P(tree, c_idx, p_idx);
+
+ /* ...S is new root of subtree, Sl(C) is new sibling of N; update G */
+ goto case2_x;
+
+case2_r:
+
+ /***************************************************************************
+ * Case #2: N is a right child of P; S is red
+ **************************************************************************/
+
+ c_idx = sr_idx;
+ RB_SET_P_R_C(tree, s_idx, g_idx, p_idx, RB_BLK);
+ RB_SET_P_L_C(tree, p_idx, s_idx, c_idx, RB_RED);
+ RB_SET_P(tree, c_idx, p_idx);
+
+ /* ...S is new root of subtree, Sr(C) is new sibling of N; update G */
+ goto case2_x;
+
+case2_x:
+
+ /* ...check if S is becoming new (black) root of the tree */
+ if (g_idx == RB_NULL(tree))
+ RB_SET_ROOT(tree, s_idx);
+ else if (p_idx == RB_LEFT(tree, g_idx))
+ RB_SET_L(tree, g_idx, s_idx);
+ else
+ RB_SET_R(tree, g_idx, s_idx);
+
+ /* ...relabel new N's grandparent (now S) as G and new sibling (now C) as S */
+ g_idx = s_idx, s_idx = c_idx;
+ sl_idx = RB_LEFT(tree, s_idx);
+ sr_idx = RB_RIGHT(tree, s_idx);
+
+ /* ...N is still one of P's children; select proper side */
+ if (n_idx == RB_LEFT(tree, p_idx))
+ goto test3_l;
+ else
+ goto test3_r;
+
+test3_l:
+
+ /***************************************************************************
+ * Test for cases 3,4,5,6; P is any, S is black. N is left child of P
+ **************************************************************************/
+
+ if (!RB_IS_BLACK(tree, sr_idx))
+ /* ...Sr is red, Sl of any color; conditions for case #6 are met */
+ goto case6_l;
+ else if (!RB_IS_BLACK(tree, sl_idx))
+ /* ...Sr is black and Sl is red; conditions for case #5 are met */
+ goto case5_l;
+ else if (RB_IS_BLACK(tree, p_idx))
+ /* ...Sl and Sr are of the same (black) color and P is black */
+ goto case3;
+ else
+ /* ...Sl and Sr are of the same (black) color and P is red */
+ goto case4;
+
+test3_r:
+
+ /***************************************************************************
+ * Test for cases 3,4,5,6; P is any, S is black. N is right child of P
+ **************************************************************************/
+
+ if (!RB_IS_BLACK(tree, sl_idx))
+ /* ...Sl is red, Sr of any color; conditions for case #6 are met */
+ goto case6_r;
+ else if (!RB_IS_BLACK(tree, sr_idx))
+ /* ...Sl is black and Sr is red; conditions for case #5 are met */
+ goto case5_r;
+ else if (RB_IS_BLACK(tree, p_idx))
+ /* ...Sl and Sr are of the same (black) color and P is black */
+ goto case3;
+ else
+ /* ...Sl and Sr are of the same (black) color and P is red */
+ goto case4;
+
+case3:
+
+ /***************************************************************************
+ * Case #3: N, P, S, Sl and Sr are black
+ **************************************************************************/
+
+ RB_SET_C(tree, s_idx, RB_RED);
+
+ /* ...and rebalance the tree for parent */
+ n_idx = p_idx, p_idx = RB_PARENT(tree, p_idx);
+
+ if (p_idx == RB_NULL(tree))
+ goto done;
+ else
+ goto rebalance;
+
+case4:
+
+ /***************************************************************************
+ * Case #4: N and S are black, P is red, Sl and Sr are all black
+ **************************************************************************/
+
+ RB_SET_C(tree, s_idx, RB_RED);
+ RB_SET_C(tree, p_idx, RB_BLK);
+
+ goto done;
+
+case5_l:
+ /***************************************************************************
+ * Case #5: S is black, Sl is red, Sr is black; N is left child of P. We
+ * have two subsequent transformations (case #5 and case #6) combined
+ **************************************************************************/
+
+ cl_idx = RB_LEFT(tree, sl_idx);
+ cr_idx = RB_RIGHT(tree, sl_idx);
+
+ if (RB_IS_BLACK(tree, p_idx))
+ RB_SET_P_L_R_C(tree, sl_idx, g_idx, p_idx, s_idx, RB_BLK);
+ else
+ RB_SET_P_L_R_C(tree, sl_idx, g_idx, p_idx, s_idx, RB_RED);
+
+ RB_SET_P_R_C(tree, p_idx, sl_idx, cl_idx, RB_BLK);
+ RB_SET_P(tree, cl_idx, p_idx);
+ RB_SET_P_L(tree, s_idx, sl_idx, cr_idx);
+ RB_SET_P(tree, cr_idx, s_idx);
+
+ /* ...relabel new root as S (for common processing in case #6) */
+ s_idx = sl_idx;
+ goto case6_x;
+
+case5_r:
+ /***************************************************************************
+ * Case #5: S is black, Sr is red, Sl is black; N is right child of P. We
+ * have two subsequent transformations (case #5 and case #6) combined
+ **************************************************************************/
+
+ cl_idx = RB_LEFT(tree, sr_idx);
+ cr_idx = RB_RIGHT(tree, sr_idx);
+
+ if (RB_IS_BLACK(tree, p_idx))
+ RB_SET_P_L_R_C(tree, sr_idx, g_idx, s_idx, p_idx, RB_BLK);
+ else
+ RB_SET_P_L_R_C(tree, sr_idx, g_idx, s_idx, p_idx, RB_RED);
+
+ RB_SET_P_L_C(tree, p_idx, sr_idx, cr_idx, RB_BLK);
+ RB_SET_P(tree, cr_idx, p_idx);
+ RB_SET_P_R(tree, s_idx, sr_idx, cl_idx);
+ RB_SET_P(tree, cl_idx, s_idx);
+
+ /* ...relabel new root as S (for common processing in case #6) */
+ s_idx = sr_idx;
+ goto case6_x;
+
+case6_l:
+
+ /***************************************************************************
+ * Case #6: S is black, N is the left child of P, Sr is red
+ **************************************************************************/
+
+ if (RB_IS_BLACK(tree, p_idx))
+ RB_SET_P_L(tree, s_idx, g_idx, p_idx);
+ else
+ RB_SET_P_L_C(tree, s_idx, g_idx, p_idx, RB_RED);
+
+ RB_SET_P_R_C(tree, p_idx, s_idx, sl_idx, RB_BLK);
+ RB_SET_P(tree, sl_idx, p_idx);
+ RB_SET_C(tree, sr_idx, RB_BLK);
+
+ /* ...S is a new root of subtree; update G */
+ goto case6_x;
+
+case6_r:
+
+ /***************************************************************************
+ * Case #6: S is black, N is the right child of P, Sl is red
+ **************************************************************************/
+
+ if (RB_IS_BLACK(tree, p_idx))
+ RB_SET_P_R(tree, s_idx, g_idx, p_idx);
+ else
+ RB_SET_P_R_C(tree, s_idx, g_idx, p_idx, RB_RED);
+
+ RB_SET_P_L_C(tree, p_idx, s_idx, sr_idx, RB_BLK);
+ RB_SET_P(tree, sr_idx, p_idx);
+ RB_SET_C(tree, sl_idx, RB_BLK);
+
+ /* ...S is a new root of subtree; update G */
+ goto case6_x;
+
+case6_x:
+
+ /* ...S is a new root of subtree; update G's pointer */
+ if (g_idx == RB_NULL(tree))
+ RB_SET_ROOT(tree, s_idx);
+ else if (p_idx == RB_LEFT(tree, g_idx))
+ RB_SET_L(tree, g_idx, s_idx);
+ else
+ RB_SET_R(tree, g_idx, s_idx);
+
+ /* ...tree is balanced; pass through */
+
+done:
+
+ return;
+}
+
+/* ...high-level API function */
+rb_idx_t rb_delete(rb_tree_t *tree, rb_idx_t n_idx)
+{
+ rb_idx_t p_idx, t_idx, m_idx, c_idx, l_idx, r_idx, k_idx;
+ u32 color;
+
+ /* ...save parent of element N that we are going to remove */
+ p_idx = RB_PARENT(tree, n_idx);
+
+ /* ...get in-order predecessor/successor of n_idx, if possible */
+ if ((m_idx = RB_LEFT(tree, n_idx)) != RB_NULL(tree))
+ {
+ while ((t_idx = RB_RIGHT(tree, m_idx)) != RB_NULL(tree))
+ m_idx = t_idx;
+
+ /* ...set the child of in-order predecessor (may be null) */
+ c_idx = RB_LEFT(tree, m_idx);
+ }
+ else if ((m_idx = RB_RIGHT(tree, n_idx)) != RB_NULL(tree))
+ {
+ while ((t_idx = RB_LEFT(tree, m_idx)) != RB_NULL(tree))
+ m_idx = t_idx;
+
+ /* ...set the child of in-order successor (may be null) */
+ c_idx = RB_RIGHT(tree, m_idx);
+ }
+ else if (p_idx == RB_NULL(tree))
+ {
+ /* ...tree consists of the only root node N that we are removing */
+ RB_SET_ROOT(tree, m_idx);
+
+ /* ..return tree null pointer */
+ return m_idx;
+ }
+ else
+ {
+ /* ...N is a (non-root) leaf node; M and C are null */
+ c_idx = m_idx;
+
+ /* ...save the color of the node we are going to delete */
+ color = RB_COLOR(tree, n_idx);
+
+ /* ...set new parent of C */
+ t_idx = p_idx;
+
+ /* ...pointer that we return as in-order predecessor/successor */
+ k_idx = p_idx;
+
+ /* ...adjust only parent of the N */
+ goto adjust_parent;
+ }
+
+ /* ...node that replaces our component is M */
+ k_idx = m_idx;
+
+ /***************************************************************************
+ * Replace node N with M
+ **************************************************************************/
+
+ /* ...save original color of M (the node that we are deleting) */
+ color = RB_COLOR(tree, m_idx);
+
+ /* ...put M in place of N; get N's children */
+ l_idx = RB_LEFT(tree, n_idx);
+ r_idx = RB_RIGHT(tree, n_idx);
+
+ /* ...see if M is a child of N */
+ if ((t_idx = RB_PARENT(tree, m_idx)) != n_idx)
+ {
+ /* ...C becomes left or right child of M's original parent T */
+ if (c_idx == RB_LEFT(tree, m_idx))
+ RB_SET_R(tree, t_idx, c_idx);
+ else
+ RB_SET_L(tree, t_idx, c_idx);
+
+ /* ...adjust C parent pointer (okay if it's null) */
+ RB_SET_P(tree, c_idx, t_idx);
+
+ /* ...set all pointers of node M (it replaces N) */
+ RB_SET_P_L_R(tree, m_idx, p_idx, l_idx, r_idx);
+ RB_SET_P(tree, l_idx, m_idx);
+ RB_SET_P(tree, r_idx, m_idx);
+ }
+ else
+ {
+ /* ...M is a left or right child of N; it gets to N's place, and C remains intact */
+ if (m_idx == l_idx)
+ {
+ RB_SET_P_R(tree, m_idx, p_idx, r_idx);
+ RB_SET_P(tree, r_idx, m_idx);
+ }
+ else
+ {
+ RB_SET_P_L(tree, m_idx, p_idx, l_idx);
+ RB_SET_P(tree, l_idx, m_idx);
+ }
+
+ /* ...parent of C is still M (we label it as T) */
+ t_idx = m_idx;
+ }
+
+ /* ...paint M in the same color as N which it replaced */
+ if (RB_IS_BLACK(tree, n_idx))
+ RB_SET_C(tree, m_idx, RB_BLK);
+ else
+ RB_SET_C(tree, m_idx, RB_RED);
+
+adjust_parent:
+
+ /* ...adjust N's parent node to point to M */
+ if (p_idx == RB_NULL(tree))
+ RB_SET_ROOT(tree, m_idx);
+ else if (n_idx == RB_LEFT(tree, p_idx))
+ RB_SET_L(tree, p_idx, m_idx);
+ else
+ RB_SET_R(tree, p_idx, m_idx);
+
+ /* ...check for a color of deleted item (M or N in case it is a leaf) */
+ if (color == RB_BLK)
+ {
+ if (c_idx == RB_NULL(tree))
+ /* ...rebalance the tree for a T node (it is never a null)*/
+ __rb_delete_rebalance(tree, t_idx);
+ else
+ /* ...C node exists and is necessarily red; repaint it black */
+ RB_SET_C(tree, c_idx, RB_BLK);
+ }
+
+ /* ....return the node K which replaced deleted node N */
+ return k_idx;
+}
+
+/*******************************************************************************
+ * rb_replace
+ *
+ * Replace the node with the same-key node - adjust tree pointers
+ ******************************************************************************/
+
+void rb_replace(rb_tree_t *tree, rb_idx_t n_idx, rb_idx_t t_idx)
+{
+ rb_idx_t p_idx, l_idx, r_idx;
+
+ /* ...get node pointers */
+ p_idx = RB_PARENT(tree, n_idx), l_idx = RB_LEFT(tree, n_idx), r_idx = RB_RIGHT(tree, n_idx);
+
+ /* ...set new node pointers */
+ RB_SET_P_L_R(tree, t_idx, p_idx, l_idx, r_idx);
+
+ /* ...set node color */
+ if (RB_IS_BLACK(tree, n_idx))
+ RB_SET_C(tree, t_idx, RB_BLK);
+ else
+ RB_SET_C(tree, t_idx, RB_RED);
+
+ /* ...update parent node */
+ if (p_idx == RB_NULL(tree))
+ RB_SET_ROOT(tree, t_idx);
+ else if (n_idx == RB_LEFT(tree, p_idx))
+ RB_SET_L(tree, p_idx, t_idx);
+ else
+ RB_SET_R(tree, p_idx, t_idx);
+
+ /* ...update children's parent node (okay if null) */
+ RB_SET_P(tree, l_idx, t_idx), RB_SET_P(tree, r_idx, t_idx);
+}