From ee3a1374eb7ac996c80e42480c5479d36ea6398f Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Sat, 25 Jan 2025 13:20:21 -0600 Subject: [PATCH] rbyd: Progress towards rbyd balance, separated y-pruning, hacky goto The main idea here is we need to unconditionally descend down red/yellow alts to check if they're post-split yellow nodes before pruning, since yellow nodes should be recolored to maintain the color balance of our tree. To make this work: - Added separate y-pruning logic before our diverged logic, this starts to look a bit like previous incarnations of this function. - Our non-y-pruning logic is all now gated behind the if-diverging check, so we shouldn't be non-y-pruning at all unless we've diverged. It may be worth rewriting this to use the trimming logic directly, instead of reachability. - Moving non-y-pruning logic behind the if-diverging check ended up causing problems for the stitching node, which is still a bit of a special case. A hacky goto solves this for now at the risk of velociraptors... https://xkcd.com/292 It's hacky, but the goal right now is to just get something working. This may seem like a lot of changes for only a couple more tests passing, but progress is progress: test_rbyd+balance before: 306/385878 failed test_rbyd+balance after: 300/385878 failed (-2.0%) Code changes: code stack ctx before: 38528 2624 640 after: 38644 (+0.3%) 2624 (+0.0%) 640 (+0.0%) --- lfs.c | 258 +++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 164 insertions(+), 94 deletions(-) diff --git a/lfs.c b/lfs.c index 35f114b4..9faa3391 100644 --- a/lfs.c +++ b/lfs.c @@ -3619,6 +3619,52 @@ trunk:; LFS_SWAP(lfs_size_t, &jump, &branch_); } + // TODO redoc? + // prune? + if (lfsr_tag_isred(p[0].alt)) { + // prune unreachable red alts + // b + // .-'| .-'| + // | >b + // | .----' | .--------|-'| + // | | %04x: yprune", + branch, lfsr_rbyd_eoff(rbyd)); + alt &= ~LFSR_TAG_R; + lfsr_rbyd_p_pop(p); + + // prune other unreachable alts + // b + // .-'| .-'| + // | | | + // | .----' | | | | + // | | %04x: rprune", + branch, lfsr_rbyd_eoff(rbyd)); + alt = p[0].alt & ~LFSR_TAG_R; + weight = p[0].weight; + jump = p[0].jump; + lfsr_rbyd_p_pop(p); + } + } + // TODO need this? does this ever get triggered? // both diverging? collapse // b @@ -3638,7 +3684,7 @@ trunk:; lower_rid, upper_rid, a_rid, a_tag, b_rid, b_tag); - if (diverging && diverging_red) { + if (!diverged && diverging && diverging_red) { LFS_DEBUG("%04x->%04x: both diverging", branch, lfsr_rbyd_eoff(rbyd)); LFS_ASSERT(a_rid < b_rid || a_tag < b_tag); @@ -3705,7 +3751,7 @@ trunk:; && (diverging || diverging_red)) { LFS_DEBUG("%04x->%04x: diverging", branch, lfsr_rbyd_eoff(rbyd)); - if (lfsr_tag_isred(p[0].alt)) { + if (lfsr_tag_isred(alt)) { LFS_DEBUG("%04x->%04x: wouldnt've diverged", branch, lfsr_rbyd_eoff(rbyd)); } @@ -3758,6 +3804,8 @@ trunk:; // TODO should we assert we're only diverging here? // not diverging_red? + // TODO can this be red? can we assert it's black? + // TODO is this uh, how much of this is already in // the diverging alt? @@ -3809,110 +3857,132 @@ trunk:; // // continue to next alt // branch = branch_; // continue; + + goto maybetrim; } // diverged? // : : // nb // .-'| .--' // 3 4 3 4 x - } else if (diverged && diverging) { - LFS_DEBUG("%04x->%04x: div pruning", - branch, lfsr_rbyd_eoff(rbyd)); - // trim so alt is pruned - lfsr_tag_trim( - alt, weight, - &lower_rid, &upper_rid, - &lower_tag, &upper_tag); - weight = 0; - } + } else if (diverged) { +// diverging = lfsr_tag_diverging2( +// alt, weight, +// p[0].alt, p[0].weight, +// lower_rid, upper_rid, +// a_rid, a_tag, +// b_rid, b_tag); +// diverging_red = lfsr_tag_isred(p[0].alt) +// && lfsr_tag_diverging( +// p[0].alt, p[0].weight, +// lower_rid, upper_rid, +// a_rid, a_tag, +// b_rid, b_tag); +// if (diverging_red) { +// LFS_DEBUG("%04x->%04x: div r pruning", +// branch, lfsr_rbyd_eoff(rbyd)); +// // trim so alt is pruned +// lfsr_tag_trim( +// p[0].alt, p[0].weight, +// &lower_rid, &upper_rid, +// &lower_tag, &upper_tag); +// p[0].weight = 0; +// +// lfsr_rbyd_p_pop(p); +// +// // TODO prune? (trim?) +// } - // prune? - // - // note if only yellow pruning this could be much simpler - - // prune unreachable red alts - // b - // .-'| .-'| - // | >b - // | .----' | .--------|-'| - // | | %04x: yprune", - branch, lfsr_rbyd_eoff(rbyd)); - alt &= ~LFSR_TAG_R; - lfsr_rbyd_p_pop(p); - } - - // prune other unreachable alts - // b - // .-'| .-'| - // | | | - // | .----' | | | | - // | | %04x: div b pruning", + branch, lfsr_rbyd_eoff(rbyd)); + // trim so alt is pruned + lfsr_tag_trim( + alt, weight, + &lower_rid, &upper_rid, + &lower_tag, &upper_tag); + weight = 0; - // TODO redoc - // prune unreachable root alts and red alts - // : : - // b + // .-'| .-'| + // | | | + // | .----' | | | | + // | | %04x: rprune", + branch, lfsr_rbyd_eoff(rbyd)); + alt = p[0].alt & ~LFSR_TAG_R; + weight = p[0].weight; + jump = p[0].jump; + lfsr_rbyd_p_pop(p); - // mark unreachable non-root black alts as unreachable, - // we can't prune these or we risk breaking the color - // balance of our tree, but if we push a red up later we - // can get rid of them - // : : - // nb - // .-'| .--' - // 3 4 3 4 x - } else { - alt = LFSR_TAG_ALT( - LFSR_TAG_B, - LFSR_TAG_LE, - (diverged && !(a_rid < b_rid || a_tag < b_tag)) - ? d_tag - : lower_tag); - // TODO hmmmmm? - LFS_ASSERT(weight == 0); - //weight = 0; - // we don't need to, but setting jump=0 asserts this - // alt is unreachable while also minimizing the the - // encoding - jump = 0; + // TODO redoc + // TODO does this ever get hit? + // prune unreachable root alts and red alts + // : : + // %04x: zprune", + branch, lfsr_rbyd_eoff(rbyd)); + branch = branch_; + continue; + + // mark unreachable non-root black alts as unreachable, + // we can't prune these or we risk breaking the color + // balance of our tree, but if we push a red up later we + // can get rid of them + // : : + // nb + // .-'| .--' + // 3 4 3 4 x + } else if (!lfsr_tag_isred(alt)) { + LFS_DEBUG("%04x->%04x: bprune", + branch, lfsr_rbyd_eoff(rbyd)); + alt = LFSR_TAG_ALT( + LFSR_TAG_B, + LFSR_TAG_LE, + (diverged && !(a_rid < b_rid || a_tag < b_tag)) + ? d_tag + : lower_tag); + // TODO hmmmmm? + LFS_ASSERT(weight == 0); + //weight = 0; + // we don't need to, but setting jump=0 asserts this + // alt is unreachable while also minimizing the the + // encoding + jump = 0; + } + } } }