diff --git a/.gitignore b/.gitignore index c04f2fa..fa9c71a 100644 --- a/.gitignore +++ b/.gitignore @@ -12,5 +12,5 @@ vgcore.* *_NORMAL.png *_TEMPLATE.png /out -GRAPH*.dot +GRAPH*.gv GRAPH*.png \ No newline at end of file diff --git a/src/l1/core/int_primitives.h b/src/l1/core/int_primitives.h index d576eca..03f48cf 100644 --- a/src/l1/core/int_primitives.h +++ b/src/l1/core/int_primitives.h @@ -22,6 +22,7 @@ int_minmax_function_Definition(U8) int_minmax_function_Definition(U32) int_minmax_function_Definition(S32) int_minmax_function_Definition(U64) +int_minmax_function_Definition(S64) int_minmax_function_Definition(float) int_minmax_function_Definition(double) diff --git a/src/l1_5/codegen/rb_tree_set_map_template_inst.h b/src/l1_5/codegen/rb_tree_set_map_template_inst.h index 0da914d..cd26652 100644 --- a/src/l1_5/codegen/rb_tree_set_map_template_inst.h +++ b/src/l1_5/codegen/rb_tree_set_map_template_inst.h @@ -178,29 +178,35 @@ void codegen_append_rb_tree_set_erase_kind_method( SPACE "U64 y = (self->tree.buf[z].left == 0 || self->tree.buf[z].right == 0) ? z : RBTree_minimum_in_subtree(self->tree.buf, self->tree.buf[z].right);\n" SPACE "U64 x = self->tree.buf[y].left != 0 ? self->tree.buf[y].left : self->tree.buf[y].right;\n" SPACE "assert(x != y && x != z);\n" - SPACE "U64 py = self->tree.buf[y].parent;\n" // May be null - SPACE "self->tree.buf[x].parent = self->tree.buf[y].parent;\n" - SPACE "if (py == 0)\n" + SPACE "U64 x_adopter = self->tree.buf[y].parent;\n" + SPACE "self->tree.buf[x].parent = x_adopter;\n" + SPACE "if (x_adopter == 0)\n" SPACE SPACE "self->root = x;\n" - SPACE "else if (self->tree.buf[py].left == y)\n" - SPACE SPACE "self->tree.buf[py].left = x;\n" + SPACE "else if (self->tree.buf[x_adopter].left == y)\n" + SPACE SPACE "self->tree.buf[x_adopter].left = x;\n" SPACE "else\n" - SPACE SPACE "self->tree.buf[py].right = x;\n" + SPACE SPACE "self->tree.buf[x_adopter].right = x;\n" SPACE "RBTreeColor y_org_clr = self->tree.buf[y].color;\n" - SPACE "if (z != y)\n" + SPACE "if (z != y) {\n" SPACE SPACE "RBTree_steal_neighbours(self->tree.buf, &self->root, z, y);\n" - SPACE "U64 L = self->el.len;\n" /* self->tree.len - 1 */ - SPACE "if (L != z){\n" + SPACE SPACE "if (x_adopter == z)\n" + SPACE SPACE SPACE "x_adopter = y;\n" + SPACE "}\n" + SPACE "U64 L = self->el.len;\n" + SPACE "if (L != z) {\n" SPACE SPACE "RBTree_steal_neighbours(self->tree.buf, &self->root, L, z);\n" SPACE SPACE "self->el.buf[z-1] = self->el.buf[L-1];\n" SPACE SPACE "if (L == x)\n" SPACE SPACE SPACE "x = z;\n" + SPACE SPACE "else if (L == x_adopter) \n" + SPACE SPACE SPACE "x_adopter = z;\n" SPACE "}\n" + SPACE "self->tree.buf[x].parent = x_adopter;\n" SPACE "self->tree.len--;\n" SPACE "self->el.len--;\n" SPACE "if (y_org_clr == RBTree_black)\n" SPACE SPACE "RBTree_fix_after_delete(self->tree.buf, &self->root, x);\n" - "%v" /* ret_found_case */ + "%v" /* ret_found_case */ "}\n\n", RT, set, method_name, set, codegen_rb_tree_set_taking_ref_t_argument(op), not_found_case, diff --git a/src/l1_5/core/rb_tree_node.h b/src/l1_5/core/rb_tree_node.h index a7d46d6..44771f0 100644 --- a/src/l1_5/core/rb_tree_node.h +++ b/src/l1_5/core/rb_tree_node.h @@ -162,7 +162,7 @@ void RBTree_fix_after_delete(RBTreeNode* tree, U64* root, U64 me){ continue; } /* Cases 3,4 */ - if (tree[nephew_benjamin].right) { + if (tree[nephew_benjamin].color == RBTree_black) { /* Case 3 */ tree[nephew_firstborn].color = RBTree_black; tree[sister].color = RBTree_red; @@ -175,7 +175,8 @@ void RBTree_fix_after_delete(RBTreeNode* tree, U64* root, U64 me){ /* Case 4 */ tree[sister].color = tree[mom].color; tree[mom].color = RBTree_black; - tree[nephew_benjamin].color = RBTree_red; + tree[nephew_benjamin].color = RBTree_black; + RBTree_left_rotate(tree, root, mom); me = *root; } else if (me == tree[mom].right) { /* We are on the right */ U64 sister = tree[mom].left; @@ -197,7 +198,7 @@ void RBTree_fix_after_delete(RBTreeNode* tree, U64* root, U64 me){ continue; } /* Cases 3,4 */ - if (tree[nephew_firstborn].left) { + if (tree[nephew_firstborn].color == RBTree_black) { /* Case 3 */ tree[nephew_benjamin].color = RBTree_black; tree[sister].color = RBTree_red; @@ -210,7 +211,8 @@ void RBTree_fix_after_delete(RBTreeNode* tree, U64* root, U64 me){ /* Case 4 */ tree[sister].color = tree[mom].color; tree[mom].color = RBTree_black; - tree[nephew_firstborn].color = RBTree_red; + tree[nephew_firstborn].color = RBTree_black; + RBTree_right_rotate(tree, root, mom); me = *root; } } diff --git a/src/l2/tests/data_structures/t0.c b/src/l2/tests/data_structures/t0.c index 1c06a03..e2629b2 100644 --- a/src/l2/tests/data_structures/t0.c +++ b/src/l2/tests/data_structures/t0.c @@ -1,6 +1,9 @@ #include "../../../../gen/l1_5/BuffRBTree_SetS64.h" +#include "../../../../gen/l1/VecAndSpan_int_primitives.h" #include "../../../l1/core/VecU8_as_str.h" #include "../../../l1/system/fileio.h" +#include "../../../l1/system/fsmanip.h" +#include "../../../l1/system/creating_child_proc.h" void check_structure_h_dfs(const VecRBTreeNode* tree, U64 x, VecU8* f){ if (x == 0) @@ -22,7 +25,31 @@ U32 check_structure_h_dfs_2(RBTreeNode* tree, U64 x){ return a + (tree[x].color == RBTree_black ? 1 : 0); } -void check_structure(const BuffRBTree_SetS64* self){ +S64 min_key_in_subtree(const BuffRBTree_SetS64* self, U64 x){ + assert(x != 0 && x < self->tree.len); + S64 ans = self->el.buf[x - 1]; + if (self->tree.buf[x].left != 0) { + ans = MIN_S64(ans, min_key_in_subtree(self, self->tree.buf[x].left)); + } + if (self->tree.buf[x].right != 0) { + ans = MIN_S64(ans, min_key_in_subtree(self, self->tree.buf[x].right)); + } + return ans; +} + +S64 max_key_in_subtree(const BuffRBTree_SetS64* self, U64 x){ + assert(x != 0 && x < self->tree.len); + S64 ans = self->el.buf[x - 1]; + if (self->tree.buf[x].left != 0) { + ans = MAX_S64(ans, max_key_in_subtree(self, self->tree.buf[x].left)); + } + if (self->tree.buf[x].right != 0) { + ans = MAX_S64(ans, max_key_in_subtree(self, self->tree.buf[x].right)); + } + return ans; +} + +void check_only_structure(const BuffRBTree_SetS64* self){ check(self->tree.len == self->el.len + 1); check(self->root < self->tree.len); if (self->tree.len > 1) { @@ -45,13 +72,15 @@ void check_structure(const BuffRBTree_SetS64* self){ check(self->tree.buf[v].right < self->tree.len); if (self->tree.buf[v].left != 0) { check(self->tree.buf[self->tree.buf[v].left].parent == v); - check(self->el.buf[self->tree.buf[v].left - 1] < self->el.buf[v - 1]); } if (self->tree.buf[v].right != 0) { check(self->tree.buf[self->tree.buf[v].right].parent == v); - check(self->el.buf[v - 1] < self->el.buf[self->tree.buf[v].right - 1]); } } +} + +void check_correctness(const BuffRBTree_SetS64* self){ + check_only_structure(self); /* Checking coloring */ check(self->tree.buf[0].color == RBTree_black); @@ -64,39 +93,118 @@ void check_structure(const BuffRBTree_SetS64* self){ } } check_structure_h_dfs_2(self->tree.buf, self->root); + + /* checking keys, but better */ + for (size_t v = 1; v < self->tree.len; v++) { + if (self->tree.buf[v].left != 0) { + check(self->el.buf[self->tree.buf[v].left - 1] < self->el.buf[v - 1]); + } + if (self->tree.buf[v].right != 0) { + check(self->el.buf[v - 1] < self->el.buf[self->tree.buf[v].right - 1]); + } + } + for (size_t v = 1; v < self->tree.len; v++) { + if (self->tree.buf[v].left != 0) { + check(max_key_in_subtree(self, self->tree.buf[v].left) < self->el.buf[v - 1]); + } + if (self->tree.buf[v].right != 0) { + check(self->el.buf[v - 1] < min_key_in_subtree(self, self->tree.buf[v].right)); + } + } } void save_tree_to_file(const BuffRBTree_SetS64* set, SpanU8 name){ - check_structure(set); + check_only_structure(set); + + VecS64 ranked_node_to_rb_node = VecS64_new_reserved(set->el.len); + { + VecS64 bfs_nxt = VecS64_new(); + VecS64 bfs = VecS64_new(); + if (set->root != 0) + VecS64_append(&bfs_nxt, (S64)set->root); + while (bfs_nxt.len > 0) { + VecS64 t = bfs_nxt; + bfs_nxt = bfs; + bfs = t; + for (size_t j = 0; j < bfs.len; j++) { + S64 cur = *VecS64_at(&bfs, j); + assert(cur != 0); + VecS64_append(&ranked_node_to_rb_node, cur); + if (cur < 0) + continue; + if (set->tree.buf[cur].left != 0) + VecS64_append(&bfs_nxt, (S64)set->tree.buf[cur].left); + else if (set->tree.buf[cur].right != 0) + VecS64_append(&bfs_nxt, -cur); + if (set->tree.buf[cur].right != 0) + VecS64_append(&bfs_nxt, (S64)set->tree.buf[cur].right); + else if (set->tree.buf[cur].left != 0) + VecS64_append(&bfs_nxt, -cur); + } + bfs.len = 0; + } + } VecU8 graph = VecU8_new(); VecU8_append_span(&graph, cstr( "digraph rbtree {\n" " fontsize = 20\n" " rankdir = TB\n" " bgcolor = \"lightgray\"\n" - " node [fontname = \"Arial\"];\n")); - for (size_t i = 1; i < set->tree.len; i++) { - VecU8_append_vec(&graph, VecU8_fmt(" v%s")); + " node [fontname = \"Arial\", style=\"rounded,filled\", shape=circle];\n")); + for (U64 j = 0; j < ranked_node_to_rb_node.len; j++) { + S64 cur = ranked_node_to_rb_node.buf[j]; + assert(cur != 0); + if (cur < 0) { + VecU8_append_vec(&graph, VecU8_fmt(" n_%i [style=invis, label=\"\"]\n", -cur)); + continue; + } + U64 i = (U64)cur; + VecU8_append_vec(&graph, VecU8_fmt( + " v%u [label=%i, xlabel=<%u>, color=%s, fontcolor=%s]\n", + i, set->el.buf[i - 1], + set->tree.buf[i].color == RBTree_black ? cstr("black") : cstr("red"), i, + set->tree.buf[i].color == RBTree_black ? cstr("black") : cstr("red"), + set->tree.buf[i].color == RBTree_black ? cstr("white") : cstr("black"))); + } + VecU8_append_span(&graph, cstr("\n")); + for (U64 j = 0; j < ranked_node_to_rb_node.len; j++) { + S64 cur = ranked_node_to_rb_node.buf[j]; + if (cur < 0) + continue; + U64 i = (U64)cur; + if (set->tree.buf[i].left != 0) { + VecU8_append_vec(&graph, VecU8_fmt(" v%u -> v%u [weight=2]\n", i, set->tree.buf[i].left)); + } else if (set->tree.buf[i].right != 0) { + VecU8_append_vec(&graph, VecU8_fmt(" v%u -> n_%u [style=invis, weight=3]\n", i, i)); + } + if (set->tree.buf[i].right != 0) { + VecU8_append_vec(&graph, VecU8_fmt(" v%u -> v%u [weight=2]\n", i, set->tree.buf[i].right)); + } else if (set->tree.buf[i].left != 0) { + VecU8_append_vec(&graph, VecU8_fmt(" v%u -> n_%u [style=invis, weight=3]\n", i, i)); + } } VecU8_append_span(&graph, cstr("}\n")); - - VecU8 dot_filename_nt = VecU8_fmt("GRAPHS/GRAPH_%s.dot%c", name, 0); + mkdir_nofail("GRAPHS"); + VecU8 dot_filename_nt = VecU8_fmt("GRAPHS/GRAPH_%s.gv%c", name, 0); write_whole_file_or_abort((CSTR)dot_filename_nt.buf, VecU8_to_span(&graph)); VecU8_drop(graph); VecU8_drop(dot_filename_nt); + VecU8 command_nt = VecU8_fmt("dot -Tpng GRAPHS/GRAPH_%s.gv -o GRAPHS/GRAPH_%s.png%c", name, name, 0); + calling_system_func_nofail((CSTR)command_nt.buf); + VecU8_drop(command_nt); } void insert_only(){ { BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); - check_structure(&set); + check_correctness(&set); BuffRBTree_SetS64_drop(set); } { BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); bool ret = BuffRBTree_SetS64_insert(&set, 42); check(ret); - check_structure(&set); + check_correctness(&set); check(set.el.len == 1); check(set.root == 1); BuffRBTree_SetS64_drop(set); @@ -106,10 +214,10 @@ void insert_only(){ BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); ret = BuffRBTree_SetS64_insert(&set, 42); check(ret); - check_structure(&set); + check_correctness(&set); ret = BuffRBTree_SetS64_insert(&set, 69); check(ret); - check_structure(&set); + check_correctness(&set); check(set.el.len == 2); BuffRBTree_SetS64_drop(set); } @@ -118,10 +226,10 @@ void insert_only(){ BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); ret = BuffRBTree_SetS64_insert(&set, 70); check(ret); - check_structure(&set); + check_correctness(&set); ret = BuffRBTree_SetS64_insert(&set, 50); check(ret); - check_structure(&set); + check_correctness(&set); check(set.el.len == 2); BuffRBTree_SetS64_drop(set); } @@ -130,13 +238,13 @@ void insert_only(){ BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); ret = BuffRBTree_SetS64_insert(&set, 1); check(ret); - check_structure(&set); + check_correctness(&set); ret = BuffRBTree_SetS64_insert(&set, 2); check(ret); - check_structure(&set); + check_correctness(&set); ret = BuffRBTree_SetS64_insert(&set, 3); check(ret); - check_structure(&set); + check_correctness(&set); BuffRBTree_SetS64_drop(set); } { @@ -144,7 +252,7 @@ void insert_only(){ for (S64 i = 10; i < 100; i++) { bool ret = BuffRBTree_SetS64_insert(&set, i); check(ret); - check_structure(&set); + check_correctness(&set); } BuffRBTree_SetS64_drop(set); } @@ -153,7 +261,7 @@ void insert_only(){ for (S64 i = 99; i >= 10; i--) { bool ret = BuffRBTree_SetS64_insert(&set, i); check(ret); - check_structure(&set); + check_correctness(&set); } BuffRBTree_SetS64_drop(set); } @@ -162,10 +270,10 @@ void insert_only(){ for (S64 i = 10; i < 100; i++) { bool ret = BuffRBTree_SetS64_insert(&set, i); check(ret); - check_structure(&set); + check_correctness(&set); bool ret2 = BuffRBTree_SetS64_insert(&set, 1000 - i); check(ret2); - check_structure(&set); + check_correctness(&set); } BuffRBTree_SetS64_drop(set); } @@ -181,7 +289,7 @@ void insert_and_then_find(){ for (S64 p = 0; p < 100; p++) { bool ret = BuffRBTree_SetS64_insert(&set, 2 * p); check(ret); - check_structure(&set); + check_correctness(&set); for (S64 i = 0; i <= p; i++) { U64 ret1 = BuffRBTree_SetS64_find(&set, 2 * i); check(ret1); @@ -196,25 +304,25 @@ void insert_and_delete(){ { BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); check(BuffRBTree_SetS64_insert(&set, 1)) - check_structure(&set); + check_correctness(&set); check(BuffRBTree_SetS64_find(&set, 1)); check(BuffRBTree_SetS64_erase(&set, 1)); - check_structure(&set); + check_correctness(&set); check(!BuffRBTree_SetS64_find(&set, 1)); BuffRBTree_SetS64_drop(set); } { BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); check(BuffRBTree_SetS64_insert(&set, 1)) - check_structure(&set); + check_correctness(&set); check(BuffRBTree_SetS64_insert(&set, 2)) - check_structure(&set); + check_correctness(&set); check(BuffRBTree_SetS64_erase(&set, 2)); - check_structure(&set); + check_correctness(&set); check(BuffRBTree_SetS64_find(&set, 1)); check(!BuffRBTree_SetS64_find(&set, 2)); check(BuffRBTree_SetS64_erase(&set, 1)); - check_structure(&set); + check_correctness(&set); check(!BuffRBTree_SetS64_find(&set, 1)); check(!BuffRBTree_SetS64_find(&set, 2)); BuffRBTree_SetS64_drop(set); @@ -222,11 +330,11 @@ void insert_and_delete(){ { BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); check(BuffRBTree_SetS64_insert(&set, 1)) - check_structure(&set); + check_correctness(&set); check(BuffRBTree_SetS64_insert(&set, 2)) - check_structure(&set); + check_correctness(&set); check(BuffRBTree_SetS64_erase(&set, 1)); - check_structure(&set); + check_correctness(&set); check(!BuffRBTree_SetS64_find(&set, 1)); check(BuffRBTree_SetS64_find(&set, 2)); @@ -234,17 +342,180 @@ void insert_and_delete(){ check(!BuffRBTree_SetS64_find(&set, 1)); check(BuffRBTree_SetS64_find(&set, 2)); check(BuffRBTree_SetS64_erase(&set, 2)); - check_structure(&set); + check_correctness(&set); check(!BuffRBTree_SetS64_find(&set, 1)); check(!BuffRBTree_SetS64_find(&set, 2)); BuffRBTree_SetS64_drop(set); } + { + BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); + for (S64 i = -120; i < 1000; i += 10) { + check(BuffRBTree_SetS64_insert(&set, i)) + check_correctness(&set); + } + // save_tree_to_file(&set, cstr("tree")); + BuffRBTree_SetS64_drop(set); + } + { + BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); + check(BuffRBTree_SetS64_insert(&set, 1)) + check_correctness(&set); + check(BuffRBTree_SetS64_insert(&set, 2)) + check_correctness(&set); + check(BuffRBTree_SetS64_insert(&set, 3)) + check_correctness(&set); + // save_tree_to_file(&set, cstr("trio")); + check(BuffRBTree_SetS64_erase(&set, 2)); + check_correctness(&set); + // save_tree_to_file(&set, cstr("duo")); + BuffRBTree_SetS64_drop(set); + } +} + +void MutSpanS64_shuffle(MutSpanS64 span){ + if (span.len <= 1) + return; + for (size_t i = span.len-1; i > 0; i--) { + size_t j = rand() % (i + 1); + S64 temp = span.data[i]; + span.data[i] = span.data[j]; + span.data[j] = temp; + } +} + +VecS64 gen_cool_sequence(S64 i){ + VecS64 res = VecS64_new_reserved(i); + for (S64 j = 0; j < i; j++) { + VecS64_append(&res, (j + 1) * 10); + } + MutSpanS64_shuffle(VecS64_to_mspan(&res)); + return res; +} + +void chaos(){ + for (int i = 1; i < 100; i++) { + srand(i); + BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); + VecS64 seq_to_insert = gen_cool_sequence(i); + for (int j = 0; j < i; j++) { + S64 to_insert = seq_to_insert.buf[j]; + BuffRBTree_SetS64_insert(&set, to_insert); + check_correctness(&set); + } + assert(set.el.len == (size_t)i); + // save_tree_to_file(&set, cstr("last_good")); + S64 to_delete = (rand() % i + 1) * 10; + printf("Started deleting from i=%d\n", i); + check(BuffRBTree_SetS64_erase(&set, to_delete)); + printf("Deleted from i=%d\n", i); + check_only_structure(&set); + // save_tree_to_file(&set, cstr("fucked_tree")); + check_correctness(&set); + VecS64_drop(seq_to_insert); + BuffRBTree_SetS64_drop(set); + } +} + +void triple_black(){ + BuffRBTree_SetS64 set; + { + VecRBTreeNode tree = VecRBTreeNode_new_zeroinit(4); + tree.buf[1] = (RBTreeNode){.parent = 3}; + tree.buf[2] = (RBTreeNode){.parent = 3}; + tree.buf[3] = (RBTreeNode){.left = 2, .right = 1}; + VecS64 el = VecS64_new_reserved(3); + VecS64_append(&el, 300); + VecS64_append(&el, 100); + VecS64_append(&el, 200); + set = (BuffRBTree_SetS64){.tree = tree, .root = 3, .el = el}; + } + check_correctness(&set); + check(BuffRBTree_SetS64_erase(&set, 300)); + check_correctness(&set); + BuffRBTree_SetS64_drop(set); +} + +void absolute_chaos(){ + for (int i = 1; i < 100; i++) { + srand(i); + BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); + VecS64 seq_to_insert = gen_cool_sequence(i); + for (int j = 0; j < i; j++) { + S64 to_insert = seq_to_insert.buf[j]; + check(BuffRBTree_SetS64_insert(&set, to_insert)); + check_correctness(&set); + } + printf("Filled chaos with i = %d\n", i); + // save_tree_to_file(&set, cstr("i_3")); + assert(set.el.len == (size_t)i); + VecS64 seq_to_erase = gen_cool_sequence(i); + for (int j = 0; j < i; j++) { + S64 to_erase = seq_to_erase.buf[j]; + check(BuffRBTree_SetS64_erase(&set, to_erase)); + check_correctness(&set); + } + printf("Emptied chaos with i = %d\n", i); + assert(set.el.len == 0); + VecS64_drop(seq_to_insert); + VecS64_drop(seq_to_erase); + BuffRBTree_SetS64_drop(set); + } +} + +void stress(){ + printf("Prepare for some real stress\n"); + for (int s = 2; s < 1000; s++) { + srand(s); + BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); + VecS64 real_set = VecS64_new(); + U32 n = (U32)s; + VecS64 complementary_set = VecS64_new_reserved(n); + for (size_t i = 0; i < n; i++) { + VecS64_append(&complementary_set, (S64)i * 10); + } + for (int t = 0; t < 1000; t++) { + /* Do something */ + int do_insertion = rand() % 2; + if (real_set.len == 0) + do_insertion = 1; + if (complementary_set.len == 0) + do_insertion = 0; + if (do_insertion) { + assert(complementary_set.len > 0); + size_t j = rand() % complementary_set.len; + S64 v = VecS64_unordered_pop(&complementary_set, j); + VecS64_append(&real_set, v); + check(BuffRBTree_SetS64_insert(&set, v)); + } else { + assert(real_set.len > 0); + size_t j = rand() % real_set.len; + S64 v = VecS64_unordered_pop(&real_set, j); + VecS64_append(&complementary_set, v); + check(BuffRBTree_SetS64_erase(&set, v)); + } + /* We did something */ + check(real_set.len == set.el.len); + for (size_t j = 0; j < real_set.len; j++) { + check(BuffRBTree_SetS64_find(&set, real_set.buf[j]) != 0); + } + for (size_t j = 0; j < complementary_set.len; j++) { + check(BuffRBTree_SetS64_find(&set, complementary_set.buf[j]) == 0); + } + } + VecS64_drop(real_set); + BuffRBTree_SetS64_drop(set); + printf("Seed s=%d passed test\n", s); + } } int main() { insert_only(); insert_and_then_find(); insert_and_delete(); + chaos(); + triple_black(); + absolute_chaos(); + stress(); return 0; }