2 * Copyright (C) 2024 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
23 #define NEG(idx) ((idx) ^ 1)
25 static struct tree_entry
*rb_parent(struct tree_entry
*n
)
28 if (n
->idx
!= RB_IDX_LEFT
&& n
->idx
!= RB_IDX_RIGHT
)
29 internal(file_line
, "rb_parent: invalid index %d", n
->idx
);
31 return get_struct(n
->parent
- n
->idx
, struct tree_entry
, children
[0]);
35 static void rb_verify_node_no_color(struct tree_entry
*n
)
37 if (unlikely(n
->color
!= RB_BLACK
&& n
->color
!= RB_RED
))
38 internal(file_line
, "rb_verify_node_no_color(%p): invalid color %d", n
, n
->color
);
39 if (unlikely(!n
->parent
))
40 internal(file_line
, "rb_verify_node_no_color(%p): no parent link", n
);
41 if (unlikely(*n
->parent
!= n
))
42 internal(file_line
, "rb_verify_node_no_color(%p): bad parent link: %p, %p", n
, *n
->parent
, n
);
43 if (unlikely(n
->idx
!= RB_IDX_ROOT
)) {
44 struct tree_entry
*p
= rb_parent(n
);
45 if (unlikely(p
->idx
!= RB_IDX_LEFT
&& p
->idx
!= RB_IDX_RIGHT
&& p
->idx
!= RB_IDX_ROOT
))
46 internal(file_line
, "rb_verify_node_no_color(%p): invalid parent: %p, %d", n
, p
, p
->idx
);
48 if (n
->children
[0] && (n
->children
[0]->parent
!= &n
->children
[0] || n
->children
[0]->idx
!= RB_IDX_LEFT
))
49 internal(file_line
, "rb_verify_node_no_color(%p): bad left child: %p, %p, %d", n
, n
->children
[0]->parent
, &n
->children
[0], n
->children
[0]->idx
);
50 if (n
->children
[1] && (n
->children
[1]->parent
!= &n
->children
[1] || n
->children
[1]->idx
!= RB_IDX_RIGHT
))
51 internal(file_line
, "rb_verify_node_no_color(%p): bad right child: %p, %p, %d", n
, n
->children
[1]->parent
, &n
->children
[1], n
->children
[1]->idx
);
53 void tree_verify_node(struct tree_entry
*n
)
55 rb_verify_node_no_color(n
);
56 if (n
->idx
== RB_IDX_ROOT
&& n
->color
== RB_RED
)
57 internal(file_line
, "tree_verify_node(%p): root is red", n
);
58 if (n
->color
== RB_RED
) {
59 if ((n
->children
[0] && n
->children
[0]->color
!= RB_BLACK
) ||
60 (n
->children
[1] && n
->children
[1]->color
!= RB_BLACK
))
61 internal(file_line
, "tree_verify_node(%p): red node has a red child", n
);
62 if (n
->idx
!= RB_IDX_ROOT
) {
63 struct tree_entry
*p
= rb_parent(n
);
64 if (p
->color
!= RB_BLACK
)
65 internal(file_line
, "tree_verify_node(%p): red parent %p has a red child", n
, p
);
70 #define rb_verify_node_no_color(n) ((void)0)
73 static attr_noinline
void rb_rotate(struct tree_entry
*p
, struct tree_entry
*n
)
75 uchar_efficient_t neg_n_idx
;
76 struct tree_entry
*ch
;
78 rb_verify_node_no_color(p
);
79 rb_verify_node_no_color(n
);
82 n
->parent
= p
->parent
;
83 neg_n_idx
= NEG(n
->idx
);
84 ch
= p
->children
[n
->idx
] = n
->children
[neg_n_idx
];
86 ch
->parent
= &p
->children
[n
->idx
];
89 p
->parent
= &n
->children
[neg_n_idx
];
90 n
->children
[neg_n_idx
] = p
;
94 rb_verify_node_no_color(p
);
95 rb_verify_node_no_color(n
);
98 void attr_fastcall
tree_insert_after_find_impl(struct tree_entry
*n
, uchar_efficient_t idx
, struct tree_entry
**link
)
104 n
->children
[0] = n
->children
[1] = NULL
;
106 rb_verify_node_no_color(n
);
109 struct tree_entry
*p
, *gp
, *un
;
110 if (n
->idx
== RB_IDX_ROOT
) {
115 rb_verify_node_no_color(p
);
116 if (p
->color
== RB_BLACK
)
119 rb_verify_node_no_color(gp
);
120 un
= gp
->children
[NEG(p
->idx
)];
121 if (un
&& un
->color
== RB_RED
) {
122 rb_verify_node_no_color(un
);
125 un
->color
= RB_BLACK
;
128 if (n
->idx
!= p
->idx
) {
129 struct tree_entry
*tmp
;
143 static void rb_fix_ptrs(struct tree_entry
*n
)
146 if (n
->children
[0]) n
->children
[0]->parent
= &n
->children
[0];
147 if (n
->children
[1]) n
->children
[1]->parent
= &n
->children
[1];
150 void attr_fastcall
tree_delete(struct tree_entry
*n
)
152 uchar_efficient_t idx
;
153 struct tree_entry
*ch
, *p
;
157 if (!n
->children
[0]) {
159 } else if (!n
->children
[1]) {
162 struct tree_entry
*c
, tmp
;
165 while (c
->children
[0]) {
170 if (tmp
.parent
== &n
->children
[1]) tmp
.parent
= &c
->children
[1];
172 if (c
->children
[1] == c
) c
->children
[1] = n
;
180 ch
= n
->children
[idx
];
183 ch
->parent
= n
->parent
;
186 if (n
->color
== RB_RED
)
190 if (idx
== RB_IDX_ROOT
)
193 rb_verify_node_no_color(p
);
194 if (!ch
|| ch
->color
== RB_BLACK
) {
195 struct tree_entry
*s
, *z
;
197 s
= p
->children
[NEG(idx
)];
198 rb_verify_node_no_color(s
);
199 if (s
->color
== RB_BLACK
) {
200 z
= s
->children
[NEG(idx
)];
201 if (z
&& z
->color
== RB_RED
) {
202 rb_verify_node_no_color(z
);
210 z
= s
->children
[idx
];
211 if (z
&& z
->color
== RB_RED
) {
212 rb_verify_node_no_color(z
);
216 goto rotate_p_s_return
;
231 ch
->color
= RB_BLACK
;
234 struct tree_entry
* attr_fastcall
tree_first(struct tree
*root
)
236 struct tree_entry
*n
= root
->root
;
240 while (n
->children
[0]) {
247 struct tree_entry
* attr_fastcall
tree_next(struct tree_entry
*e
)
250 if (e
->children
[1]) {
253 while (e
->children
[0]) {
259 while (e
->idx
== RB_IDX_RIGHT
) {
263 if (e
->idx
== RB_IDX_LEFT
) {
271 struct tree_entry
* attr_fastcall
tree_last(struct tree
*root
)
273 struct tree_entry
*n
= root
->root
;
277 while (n
->children
[1]) {