rbyd: Cleaned up rbyd balance rework
Aside from cleaning up the mess of debug statements/commented code, this
also includes a bit of fiddling with the append logic to try to make
things a bit more readable and minimize code cost:
code stack ctx
before: 38784 2624 640
after: 38548 (-0.6%) 2624 (+0.0%) 640 (+0.0%)
Now we can better compare before and after the balance rework:
code stack ctx
before rbyd-balance-rework: 38440 2624 640
after rbyd-balance-rework: 38548 (+0.3%) 2624 (+0.0%) 640 (+0.0%)
Though it's worth emphasizing that maintaining strictly balanced rbyds
is well worth the extra code cost, since it's sort of what the rest of
the filesystem is built on.
This commit is contained in:
@@ -1397,7 +1397,7 @@ static inline bool lfsr_tag_diverging(
|
|||||||
alt, weight,
|
alt, weight,
|
||||||
lower_rid, upper_rid,
|
lower_rid, upper_rid,
|
||||||
a_rid, a_tag)
|
a_rid, a_tag)
|
||||||
^ lfsr_tag_follow(
|
!= lfsr_tag_follow(
|
||||||
alt, weight,
|
alt, weight,
|
||||||
lower_rid, upper_rid,
|
lower_rid, upper_rid,
|
||||||
b_rid, b_tag);
|
b_rid, b_tag);
|
||||||
@@ -1414,7 +1414,7 @@ static inline bool lfsr_tag_diverging2(
|
|||||||
alt2, weight2,
|
alt2, weight2,
|
||||||
lower_rid, upper_rid,
|
lower_rid, upper_rid,
|
||||||
a_rid, a_tag)
|
a_rid, a_tag)
|
||||||
^ lfsr_tag_follow2(
|
!= lfsr_tag_follow2(
|
||||||
alt, weight,
|
alt, weight,
|
||||||
alt2, weight2,
|
alt2, weight2,
|
||||||
lower_rid, upper_rid,
|
lower_rid, upper_rid,
|
||||||
@@ -3087,9 +3087,6 @@ static int lfsr_rbyd_lookupnext_(lfs_t *lfs, const lfsr_rbyd_t *rbyd,
|
|||||||
if (!tag__
|
if (!tag__
|
||||||
|| rid__ < rid
|
|| rid__ < rid
|
||||||
|| (rid__ == rid && tag__ < tag)) {
|
|| (rid__ == rid && tag__ < tag)) {
|
||||||
if (height_) {
|
|
||||||
LFS_DEBUG("not found height: %d\n", *height_);
|
|
||||||
}
|
|
||||||
return LFS_ERR_NOENT;
|
return LFS_ERR_NOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3504,11 +3501,6 @@ static int lfsr_rbyd_appendrat(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
a_tag = lfs_max(a_tag, 0x1);
|
a_tag = lfs_max(a_tag, 0x1);
|
||||||
b_tag = lfs_max(b_tag, 0x1);
|
b_tag = lfs_max(b_tag, 0x1);
|
||||||
|
|
||||||
LFS_DEBUG("%04x: rbyd append %d %04x %d %04x",
|
|
||||||
lfsr_rbyd_eoff(rbyd),
|
|
||||||
a_rid, a_tag,
|
|
||||||
b_rid, b_tag);
|
|
||||||
|
|
||||||
// keep track of diverged state
|
// keep track of diverged state
|
||||||
//
|
//
|
||||||
// this is only used if we operate on a range of tags, in which case
|
// this is only used if we operate on a range of tags, in which case
|
||||||
@@ -3520,11 +3512,8 @@ static int lfsr_rbyd_appendrat(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
// two diverged trunks together where they diverged
|
// two diverged trunks together where they diverged
|
||||||
//
|
//
|
||||||
bool diverged = false;
|
bool diverged = false;
|
||||||
lfsr_srid_t d_rid = 0;
|
|
||||||
lfsr_srid_t d_upper_rid = rbyd->weight;
|
|
||||||
lfsr_srid_t d_weight = 0;
|
|
||||||
lfsr_tag_t d_tag = 0;
|
lfsr_tag_t d_tag = 0;
|
||||||
lfs_size_t d_branch = 0;
|
lfsr_srid_t d_weight = 0;
|
||||||
|
|
||||||
// follow the current trunk
|
// follow the current trunk
|
||||||
lfs_size_t branch = lfsr_rbyd_trunk(rbyd);
|
lfs_size_t branch = lfsr_rbyd_trunk(rbyd);
|
||||||
@@ -3624,62 +3613,6 @@ trunk:;
|
|||||||
LFS_SWAP(lfs_size_t, &jump, &branch_);
|
LFS_SWAP(lfs_size_t, &jump, &branch_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO need this? does this ever get triggered?
|
|
||||||
// both diverging? collapse
|
|
||||||
// <r >b
|
|
||||||
// .----'| .-'|
|
|
||||||
// | <b => | |
|
|
||||||
// | .-'| .-----|--'
|
|
||||||
// 1 2 3 1 2 3 x
|
|
||||||
bool diverging = lfsr_tag_diverging2(
|
|
||||||
alt, weight,
|
|
||||||
p[0].alt, p[0].weight,
|
|
||||||
lower_rid, upper_rid,
|
|
||||||
a_rid, a_tag,
|
|
||||||
b_rid, b_tag);
|
|
||||||
bool 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 (!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);
|
|
||||||
LFS_ASSERT(lfsr_tag_isparallel(alt, p[0].alt));
|
|
||||||
|
|
||||||
weight += p[0].weight;
|
|
||||||
jump = p[0].jump;
|
|
||||||
lfsr_rbyd_p_pop(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
// // TODO need this?
|
|
||||||
// // only diverging red? swap
|
|
||||||
// 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: diverging red",
|
|
||||||
// branch, lfsr_rbyd_eoff(rbyd));
|
|
||||||
// LFS_ASSERT(!lfsr_tag_isparallel(alt, p[0].alt));
|
|
||||||
//
|
|
||||||
// LFS_SWAP(lfsr_tag_t, &p[0].alt, &alt);
|
|
||||||
// LFS_SWAP(lfsr_rid_t, &p[0].weight, &weight);
|
|
||||||
// LFS_SWAP(lfs_size_t, &p[0].jump, &jump);
|
|
||||||
// alt = (alt & ~LFSR_TAG_R) | (p[0].alt & LFSR_TAG_R);
|
|
||||||
// p[0].alt |= LFSR_TAG_R;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// do bounds want to take different paths? begin diverging
|
// do bounds want to take different paths? begin diverging
|
||||||
// >b <b
|
// >b <b
|
||||||
// .-'| .-'|
|
// .-'| .-'|
|
||||||
@@ -3688,60 +3621,50 @@ trunk:;
|
|||||||
// <b <b | <b | nb
|
// <b <b | <b | nb
|
||||||
// .-'| .-'| | .-'| | .-----'
|
// .-'| .-'| | .-'| | .-----'
|
||||||
// 1 2 3 4 1 2 3 4 x 1 2 3 4 x x
|
// 1 2 3 4 1 2 3 4 x 1 2 3 4 x x
|
||||||
diverging = lfsr_tag_diverging2(
|
bool diverging_b = lfsr_tag_diverging2(
|
||||||
alt, weight,
|
alt, weight,
|
||||||
p[0].alt, p[0].weight,
|
p[0].alt, p[0].weight,
|
||||||
lower_rid, upper_rid,
|
lower_rid, upper_rid,
|
||||||
a_rid, a_tag,
|
a_rid, a_tag,
|
||||||
b_rid, b_tag);
|
b_rid, b_tag);
|
||||||
diverging_red = lfsr_tag_isred(p[0].alt)
|
bool diverging_r = lfsr_tag_isred(p[0].alt)
|
||||||
&& lfsr_tag_diverging(
|
&& lfsr_tag_diverging(
|
||||||
p[0].alt, p[0].weight,
|
p[0].alt, p[0].weight,
|
||||||
lower_rid, upper_rid,
|
lower_rid, upper_rid,
|
||||||
a_rid, a_tag,
|
a_rid, a_tag,
|
||||||
b_rid, b_tag);
|
b_rid, b_tag);
|
||||||
bool just_diverged = false;
|
if (!diverged) {
|
||||||
if (!diverged
|
// both diverging? collapse
|
||||||
|
// <r >b
|
||||||
|
// .----'| .-'|
|
||||||
|
// | <b => | |
|
||||||
|
// | .-'| .-----|--'
|
||||||
|
// 1 2 3 1 2 3 x
|
||||||
|
if (diverging_b && diverging_r) {
|
||||||
|
LFS_ASSERT(a_rid < b_rid || a_tag < b_tag);
|
||||||
|
LFS_ASSERT(lfsr_tag_isparallel(alt, p[0].alt));
|
||||||
|
|
||||||
|
weight += p[0].weight;
|
||||||
|
jump = p[0].jump;
|
||||||
|
lfsr_rbyd_p_pop(p);
|
||||||
|
|
||||||
|
diverging_r = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// diverging? start trimming inner alts
|
||||||
|
// >b
|
||||||
|
// .-'|
|
||||||
|
// <b => | nb
|
||||||
|
// .----'| .--------|--'
|
||||||
|
// <b <b | <b
|
||||||
|
// .-'| .-'| | .-'|
|
||||||
|
// 1 2 3 4 1 2 3 4 x
|
||||||
|
if ((diverging_b || diverging_r)
|
||||||
// diverging black?
|
// diverging black?
|
||||||
// && lfsr_tag_isblack(alt)
|
|
||||||
&& (lfsr_tag_isblack(alt)
|
&& (lfsr_tag_isblack(alt)
|
||||||
// give up if we find a yellow alt
|
// give up if we find a yellow alt
|
||||||
|| (lfsr_tag_isred(p[0].alt)))
|
|| (lfsr_tag_isred(p[0].alt)))) {
|
||||||
&& (diverging || diverging_red)) {
|
|
||||||
LFS_DEBUG("%04x->%04x: diverging",
|
|
||||||
branch, lfsr_rbyd_eoff(rbyd));
|
|
||||||
if (lfsr_tag_isred(alt)) {
|
|
||||||
LFS_DEBUG("%04x->%04x: wouldnt've diverged",
|
|
||||||
branch, lfsr_rbyd_eoff(rbyd));
|
|
||||||
}
|
|
||||||
diverged = true;
|
diverged = true;
|
||||||
just_diverged = true;
|
|
||||||
|
|
||||||
// // TODO need this? does this ever get triggered?
|
|
||||||
// // both diverging? collapse
|
|
||||||
// // <r >b
|
|
||||||
// // .----'| .-'|
|
|
||||||
// // | <b => | |
|
|
||||||
// // | .-'| .-----|--'
|
|
||||||
// // 1 2 3 1 2 3 x
|
|
||||||
// if (diverging && diverging_red) {
|
|
||||||
// LFS_DEBUG("%04x->%04x: both diverging",
|
|
||||||
// branch, lfsr_rbyd_eoff(rbyd));
|
|
||||||
// LFS_ASSERT(a_rid < b_rid || a_tag < b_tag);
|
|
||||||
// LFS_ASSERT(lfsr_tag_isparallel(alt, p[0].alt));
|
|
||||||
//
|
|
||||||
// p[0].alt = alt | LFSR_TAG_R;
|
|
||||||
// p[0].weight += weight;
|
|
||||||
// weight = 0;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // propagate a red edge?
|
|
||||||
// if (lfsr_tag_isred(alt) && lfsr_tag_isred(p[0].alt)) {
|
|
||||||
// LFS_DEBUG("%04x->%04x: recolor",
|
|
||||||
// branch, lfsr_rbyd_eoff(rbyd));
|
|
||||||
// lfsr_rbyd_p_recolor(p);
|
|
||||||
// alt &= ~LFSR_TAG_R;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// diverging upper? stitch together both trunks
|
// diverging upper? stitch together both trunks
|
||||||
// >b <b
|
// >b <b
|
||||||
@@ -3752,118 +3675,23 @@ trunk:;
|
|||||||
// | .-'| | .-----'
|
// | .-'| | .-----'
|
||||||
// 1 2 3 4 x 1 2 3 4 x x
|
// 1 2 3 4 x 1 2 3 4 x x
|
||||||
if (a_rid > b_rid || a_tag > b_tag) {
|
if (a_rid > b_rid || a_tag > b_tag) {
|
||||||
LFS_DEBUG("%04x->%04x: stitching %d ((%d, %d), (%d, %d)) "
|
LFS_ASSERT(!diverging_r);
|
||||||
"%04x %04x",
|
|
||||||
branch, lfsr_rbyd_eoff(rbyd),
|
|
||||||
d_rid - lower_rid,
|
|
||||||
d_rid, d_upper_rid,
|
|
||||||
lower_rid, upper_rid,
|
|
||||||
alt, d_tag);
|
|
||||||
|
|
||||||
// TODO should we assert we're only diverging here?
|
alt = LFSR_TAG_ALT(
|
||||||
// not diverging_red?
|
alt & LFSR_TAG_R,
|
||||||
|
LFSR_TAG_LE,
|
||||||
|
d_tag);
|
||||||
|
weight -= d_weight;
|
||||||
|
lower_rid += d_weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 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?
|
|
||||||
|
|
||||||
// stitch together both trunks
|
|
||||||
lfsr_srid_t weight_ = weight;
|
|
||||||
if (lfsr_tag_isred(alt)) {
|
|
||||||
alt = LFSR_TAG_ALT(LFSR_TAG_R, LFSR_TAG_LE, d_tag);
|
|
||||||
} else {
|
} else {
|
||||||
alt = LFSR_TAG_ALT(LFSR_TAG_B, LFSR_TAG_LE, d_tag);
|
// diverged? trim so alt will be pruned
|
||||||
}
|
|
||||||
//weight = (d_rid - lower_rid) - lfs_smax(-rat.weight, 0);
|
|
||||||
//weight = d_rid - lower_rid;
|
|
||||||
|
|
||||||
lfsr_srid_t delta =
|
|
||||||
lfs_smax(-rat.weight, d_upper_rid - d_rid);
|
|
||||||
// lfs_smax(-rat.weight, 0)
|
|
||||||
// + (d_upper_rid - d_rid);
|
|
||||||
// (lfs_smax(-rat.weight, 0) > 0)
|
|
||||||
// ? lfs_smax(-rat.weight, 0)
|
|
||||||
// : (d_upper_rid - d_rid);
|
|
||||||
|
|
||||||
// + lfs_smax(-rat.weight, 0);
|
|
||||||
// + (weight - (d_rid - lower_rid));
|
|
||||||
|
|
||||||
// weight = weight
|
|
||||||
// - lfs_smax(-rat.weight, 0)
|
|
||||||
// - (weight - (d_rid - lower_rid));
|
|
||||||
weight -= delta;
|
|
||||||
// branch_ = jump;
|
|
||||||
|
|
||||||
// lower_rid += lfs_smax(-rat.weight, 0);
|
|
||||||
lower_rid += delta;
|
|
||||||
|
|
||||||
// lfsr_tag_trim2(
|
|
||||||
// alt, weight,
|
|
||||||
// p[0].alt, p[0].weight,
|
|
||||||
// &lower_rid, &upper_rid,
|
|
||||||
// &lower_tag, &upper_tag);
|
|
||||||
//
|
|
||||||
// // stitch together both trunks
|
|
||||||
// err = lfsr_rbyd_p_push(lfs, rbyd, p,
|
|
||||||
// LFSR_TAG_ALT(LFSR_TAG_B, LFSR_TAG_LE, d_tag),
|
|
||||||
// d_rid - (lower_rid - weight),
|
|
||||||
// jump);
|
|
||||||
// if (err) {
|
|
||||||
// return err;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // continue to next alt
|
|
||||||
// branch = branch_;
|
|
||||||
// continue;
|
|
||||||
|
|
||||||
// goto maybetrim;
|
|
||||||
}
|
|
||||||
// diverged?
|
|
||||||
// <b => nb
|
// <b => nb
|
||||||
// .-'| .--'
|
// .-'| .--'
|
||||||
// 3 4 3 4 x
|
// 3 4 3 4 x
|
||||||
} else if (diverged) {
|
if (diverging_b) {
|
||||||
// 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);
|
|
||||||
// // TODO I think this logic is wrong, what's correct here?
|
|
||||||
// if (diverging_red) {
|
|
||||||
// LFS_DEBUG("%04x->%04x: div r trimming",
|
|
||||||
// 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?)
|
|
||||||
// }
|
|
||||||
|
|
||||||
diverging = lfsr_tag_diverging2(
|
|
||||||
alt, weight,
|
|
||||||
p[0].alt, p[0].weight,
|
|
||||||
lower_rid, upper_rid,
|
|
||||||
a_rid, a_tag,
|
|
||||||
b_rid, b_tag);
|
|
||||||
if (diverging) {
|
|
||||||
// && (!lfsr_tag_isred(alt)
|
|
||||||
// || lfsr_tag_isred(p[0].alt))) {
|
|
||||||
LFS_DEBUG("%04x->%04x: div b trimming",
|
|
||||||
branch, lfsr_rbyd_eoff(rbyd));
|
|
||||||
// trim so alt is pruned
|
|
||||||
lfsr_tag_trim(
|
lfsr_tag_trim(
|
||||||
alt, weight,
|
alt, weight,
|
||||||
&lower_rid, &upper_rid,
|
&lower_rid, &upper_rid,
|
||||||
@@ -3872,20 +3700,10 @@ trunk:;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO hmmmm
|
// note we need to prioritize yellow-split pruning here,
|
||||||
if (lfsr_tag_isred(p[0].alt)
|
// which unfortunately makes this logic a bit of a mess
|
||||||
&& lfsr_tag_unreachable(
|
|
||||||
p[0].alt, p[0].weight,
|
// prune unreachable yellow-split yellow alts
|
||||||
lower_rid, upper_rid,
|
|
||||||
lower_tag, upper_tag)
|
|
||||||
&& p[0].jump > branch) {
|
|
||||||
// prune unreachable recolorable alts
|
|
||||||
// <r => <b
|
|
||||||
// .----'| .----'|
|
|
||||||
// | <b | |
|
|
||||||
// | .-'| | .--'
|
|
||||||
// 1 2 3 1 2 3 x
|
|
||||||
// this includes unreachable yellow alts in yellow splits
|
|
||||||
// <b >b
|
// <b >b
|
||||||
// .-'| .-'|
|
// .-'| .-'|
|
||||||
// <y | | |
|
// <y | | |
|
||||||
@@ -3895,25 +3713,16 @@ trunk:;
|
|||||||
// | | <b | <b |
|
// | | <b | <b |
|
||||||
// | | .----'| | .----'| |
|
// | | .----'| | .----'| |
|
||||||
// 1 2 3 4 4 1 2 3 4 4 1
|
// 1 2 3 4 4 1 2 3 4 4 1
|
||||||
LFS_DEBUG("%04x->%04x: yprune",
|
if (lfsr_tag_isred(p[0].alt)
|
||||||
branch, lfsr_rbyd_eoff(rbyd));
|
&& lfsr_tag_unreachable(
|
||||||
alt &= ~LFSR_TAG_R;
|
|
||||||
lfsr_rbyd_p_pop(p);
|
|
||||||
}
|
|
||||||
if (lfsr_tag_unreachable2(
|
|
||||||
alt, weight,
|
|
||||||
p[0].alt, p[0].weight,
|
p[0].alt, p[0].weight,
|
||||||
lower_rid, upper_rid,
|
lower_rid, upper_rid,
|
||||||
lower_tag, upper_tag)
|
lower_tag, upper_tag)
|
||||||
&& lfsr_tag_isred(p[0].alt)
|
&& p[0].jump > branch) {
|
||||||
&& jump > branch) {
|
alt &= ~LFSR_TAG_R;
|
||||||
// prune unreachable recolorable alts
|
lfsr_rbyd_p_pop(p);
|
||||||
// <r => <b
|
|
||||||
// .----'| .-------'|
|
// prune unreachable yellow-split red alts
|
||||||
// | <b | |
|
|
||||||
// | .-'| | .-----'
|
|
||||||
// 1 2 3 1 2 3 x
|
|
||||||
// this includes unreachable red alts in yellow splits
|
|
||||||
// <b >b
|
// <b >b
|
||||||
// .-'| .-'|
|
// .-'| .-'|
|
||||||
// <y | | <b
|
// <y | | <b
|
||||||
@@ -3923,10 +3732,14 @@ trunk:;
|
|||||||
// | | <b | <b |
|
// | | <b | <b |
|
||||||
// | | .----'| | .----'| |
|
// | | .----'| | .----'| |
|
||||||
// 1 2 3 4 4 1 2 3 4 4 2
|
// 1 2 3 4 4 1 2 3 4 4 2
|
||||||
LFS_DEBUG("%04x->%04x: rprune",
|
} else if (lfsr_tag_isred(p[0].alt)
|
||||||
branch, lfsr_rbyd_eoff(rbyd));
|
&& lfsr_tag_unreachable2(
|
||||||
alt = (p[0].alt & ~LFSR_TAG_R) | (alt & LFSR_TAG_R);
|
alt, weight,
|
||||||
alt &= ~LFSR_TAG_R;
|
p[0].alt, p[0].weight,
|
||||||
|
lower_rid, upper_rid,
|
||||||
|
lower_tag, upper_tag)
|
||||||
|
&& jump > branch) {
|
||||||
|
alt = p[0].alt & ~LFSR_TAG_R;
|
||||||
weight = p[0].weight;
|
weight = p[0].weight;
|
||||||
jump = p[0].jump;
|
jump = p[0].jump;
|
||||||
lfsr_rbyd_p_pop(p);
|
lfsr_rbyd_p_pop(p);
|
||||||
@@ -3944,21 +3757,7 @@ trunk:;
|
|||||||
// | <b | |
|
// | <b | |
|
||||||
// | .-'| | .--'
|
// | .-'| | .--'
|
||||||
// 1 2 3 1 2 3 x
|
// 1 2 3 1 2 3 x
|
||||||
// this includes unreachable yellow alts in yellow splits
|
LFS_ASSERT(p[0].jump < branch);
|
||||||
// <b >b
|
|
||||||
// .-'| .-'|
|
|
||||||
// <y | | |
|
|
||||||
// .-------'| | | |
|
|
||||||
// | <r | => | >b
|
|
||||||
// | .----' | .--------|-'|
|
|
||||||
// | | <b | <b |
|
|
||||||
// | | .----'| | .----'| |
|
|
||||||
// 1 2 3 4 4 1 2 3 4 4 1
|
|
||||||
LFS_DEBUG("%04x->%04x: yprune",
|
|
||||||
branch, lfsr_rbyd_eoff(rbyd));
|
|
||||||
if (p[0].jump > branch) {
|
|
||||||
alt &= ~LFSR_TAG_R;
|
|
||||||
}
|
|
||||||
lfsr_rbyd_p_pop(p);
|
lfsr_rbyd_p_pop(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3968,11 +3767,16 @@ trunk:;
|
|||||||
p[0].alt, p[0].weight,
|
p[0].alt, p[0].weight,
|
||||||
lower_rid, upper_rid,
|
lower_rid, upper_rid,
|
||||||
lower_tag, upper_tag)) {
|
lower_tag, upper_tag)) {
|
||||||
if (!lfsr_tag_isred(p[0].alt)
|
// root alts are a special case that we can prune
|
||||||
&& lfsr_tag_isred(alt)) {
|
// immediately
|
||||||
LFS_DEBUG("%04x->%04x: would've zpruned",
|
// <b => <b
|
||||||
branch, lfsr_rbyd_eoff(rbyd));
|
// .----'| .----'|
|
||||||
}
|
// <b <b | |
|
||||||
|
// .-'| .-'| | .--'
|
||||||
|
// 1 3 4 5 1 3 4 5 x
|
||||||
|
if (!p[0].alt) {
|
||||||
|
branch = branch_;
|
||||||
|
continue;
|
||||||
|
|
||||||
// prune unreachable recolorable alts
|
// prune unreachable recolorable alts
|
||||||
// <r => <b
|
// <r => <b
|
||||||
@@ -3980,63 +3784,31 @@ trunk:;
|
|||||||
// | <b | |
|
// | <b | |
|
||||||
// | .-'| | .-----'
|
// | .-'| | .-----'
|
||||||
// 1 2 3 1 2 3 x
|
// 1 2 3 1 2 3 x
|
||||||
// this includes unreachable red alts in yellow splits
|
} else if (lfsr_tag_isred(p[0].alt)) {
|
||||||
// <b >b
|
LFS_ASSERT(jump < branch);
|
||||||
// .-'| .-'|
|
|
||||||
// <y | | <b
|
|
||||||
// .-------'| | .-----------|-'|
|
|
||||||
// | <r | => | | |
|
|
||||||
// | .----' | | | |
|
|
||||||
// | | <b | <b |
|
|
||||||
// | | .----'| | .----'| |
|
|
||||||
// 1 2 3 4 4 1 2 3 4 4 2
|
|
||||||
if (lfsr_tag_isred(p[0].alt)) {
|
|
||||||
LFS_DEBUG("%04x->%04x: rprune",
|
|
||||||
branch, lfsr_rbyd_eoff(rbyd));
|
|
||||||
alt = (p[0].alt & ~LFSR_TAG_R) | (alt & LFSR_TAG_R);
|
alt = (p[0].alt & ~LFSR_TAG_R) | (alt & LFSR_TAG_R);
|
||||||
if (jump > branch) {
|
|
||||||
alt &= ~LFSR_TAG_R;
|
|
||||||
}
|
|
||||||
weight = p[0].weight;
|
weight = p[0].weight;
|
||||||
jump = p[0].jump;
|
jump = p[0].jump;
|
||||||
lfsr_rbyd_p_pop(p);
|
lfsr_rbyd_p_pop(p);
|
||||||
|
|
||||||
// TODO redoc
|
// we can't prune non-root black alts or we risk
|
||||||
// TODO does this ever get hit?
|
// breaking the color balance of our tree, so instead
|
||||||
// prune unreachable root alts and red alts
|
// we just mark these alts as unreachable (jump=0), and
|
||||||
// <r => <b
|
// collapse them if we propagate a red edge later
|
||||||
// .----'| .----'|
|
|
||||||
// | <b | |
|
|
||||||
// | .-'| | .--'
|
|
||||||
// 3 4 5 3 4 5 x
|
|
||||||
} else if (!p[0].alt) {
|
|
||||||
LFS_DEBUG("%04x->%04x: zprune",
|
|
||||||
branch, lfsr_rbyd_eoff(rbyd));
|
|
||||||
branch = branch_;
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// mark unreachable non-root black alts as unreachable (
|
|
||||||
// jump=0), we can't prune these right now or we risk
|
|
||||||
// breaking the color balance of our tree, but if we
|
|
||||||
// push up a red edge later we can get rid of these
|
|
||||||
// <b => nb
|
// <b => nb
|
||||||
// .-'| .--'
|
// .-'| .--'
|
||||||
// 3 4 3 4 x
|
// 3 4 3 4 x
|
||||||
} else if (!lfsr_tag_isred(alt)) {
|
} else if (lfsr_tag_isblack(alt)) {
|
||||||
LFS_DEBUG("%04x->%04x: bprune",
|
|
||||||
branch, lfsr_rbyd_eoff(rbyd));
|
|
||||||
alt = LFSR_TAG_ALT(
|
alt = LFSR_TAG_ALT(
|
||||||
LFSR_TAG_B,
|
LFSR_TAG_B,
|
||||||
LFSR_TAG_LE,
|
LFSR_TAG_LE,
|
||||||
(diverged && !(a_rid < b_rid || a_tag < b_tag))
|
(diverged && (a_rid > b_rid || a_tag > b_tag))
|
||||||
? d_tag
|
? d_tag
|
||||||
: lower_tag);
|
: lower_tag);
|
||||||
// TODO hmmmmm?
|
|
||||||
LFS_ASSERT(weight == 0);
|
LFS_ASSERT(weight == 0);
|
||||||
//weight = 0;
|
// jump=0 also asserts the alt is unreachable (or
|
||||||
// we don't need to, but setting jump=0 asserts this
|
// else we loop indefinitely), and uses the minimum
|
||||||
// alt is unreachable while also minimizing the the
|
// alt encoding
|
||||||
// encoding
|
|
||||||
jump = 0;
|
jump = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4056,8 +3828,6 @@ trunk:;
|
|||||||
// | | .-'| | .-'| |
|
// | | .-'| | .-'| |
|
||||||
// 1 2 3 4 1 2 3 4 1
|
// 1 2 3 4 1 2 3 4 1
|
||||||
if (branch_ < branch) {
|
if (branch_ < branch) {
|
||||||
LFS_DEBUG("%04x->%04x: ysplit b",
|
|
||||||
branch, lfsr_rbyd_eoff(rbyd));
|
|
||||||
if (jump > branch) {
|
if (jump > branch) {
|
||||||
LFS_SWAP(lfsr_tag_t, &p[0].alt, &alt);
|
LFS_SWAP(lfsr_tag_t, &p[0].alt, &alt);
|
||||||
LFS_SWAP(lfsr_rid_t, &p[0].weight, &weight);
|
LFS_SWAP(lfsr_rid_t, &p[0].weight, &weight);
|
||||||
@@ -4083,8 +3853,6 @@ trunk:;
|
|||||||
// | | .-'| | | .----'|
|
// | | .-'| | | .----'|
|
||||||
// 1 2 3 4 1 2 3 4 4
|
// 1 2 3 4 1 2 3 4 4
|
||||||
} else {
|
} else {
|
||||||
LFS_DEBUG("%04x->%04x: ysplit y",
|
|
||||||
branch, lfsr_rbyd_eoff(rbyd));
|
|
||||||
LFS_ASSERT(y_branch != 0);
|
LFS_ASSERT(y_branch != 0);
|
||||||
p[0].alt = alt;
|
p[0].alt = alt;
|
||||||
p[0].weight += weight;
|
p[0].weight += weight;
|
||||||
@@ -4146,10 +3914,7 @@ trunk:;
|
|||||||
// diverged lower trunk? move on to upper trunk
|
// diverged lower trunk? move on to upper trunk
|
||||||
if (a_rid < b_rid || a_tag < b_tag) {
|
if (a_rid < b_rid || a_tag < b_tag) {
|
||||||
// keep track of the lower diverged bound
|
// keep track of the lower diverged bound
|
||||||
d_rid = lower_rid;
|
|
||||||
d_tag = lower_tag;
|
d_tag = lower_tag;
|
||||||
// TODO need this?
|
|
||||||
d_upper_rid = upper_rid;
|
|
||||||
d_weight = upper_rid - lower_rid;
|
d_weight = upper_rid - lower_rid;
|
||||||
|
|
||||||
// flush any pending alts
|
// flush any pending alts
|
||||||
@@ -4158,10 +3923,6 @@ trunk:;
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO need this? can we instead make the trunk
|
|
||||||
// unreachable?
|
|
||||||
d_branch = lfsr_rbyd_eoff(rbyd);
|
|
||||||
|
|
||||||
// terminate diverged trunk with an unreachable tag
|
// terminate diverged trunk with an unreachable tag
|
||||||
err = lfsr_rbyd_appendrat_(lfs, rbyd, LFSR_RAT(
|
err = lfsr_rbyd_appendrat_(lfs, rbyd, LFSR_RAT(
|
||||||
(lfsr_rbyd_isshrub(rbyd) ? LFSR_TAG_SHRUB : 0)
|
(lfsr_rbyd_isshrub(rbyd) ? LFSR_TAG_SHRUB : 0)
|
||||||
@@ -4182,18 +3943,8 @@ trunk:;
|
|||||||
} else {
|
} else {
|
||||||
// use the lower diverged bound for leaf weight
|
// use the lower diverged bound for leaf weight
|
||||||
// calculation
|
// calculation
|
||||||
lower_rid = d_rid;
|
lower_rid -= d_weight;
|
||||||
lower_tag = d_tag;
|
lower_tag = d_tag;
|
||||||
|
|
||||||
// // TODO ???
|
|
||||||
// // needed for balance reasons if we end up reachable
|
|
||||||
// err = lfsr_rbyd_p_push(lfs, rbyd, p,
|
|
||||||
// LFSR_TAG_ALT(LFSR_TAG_B, LFSR_TAG_LE, lower_tag),
|
|
||||||
// 0,
|
|
||||||
// 0);
|
|
||||||
// if (err) {
|
|
||||||
// return err;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4231,15 +3982,11 @@ stem:;
|
|||||||
&& lfsr_tag_key(tag_)
|
&& lfsr_tag_key(tag_)
|
||||||
< lfsr_tag_key(rat.tag)))))) {
|
< lfsr_tag_key(rat.tag)))))) {
|
||||||
if (lfsr_tag_isrm(rat.tag) || !lfsr_tag_key(rat.tag)) {
|
if (lfsr_tag_isrm(rat.tag) || !lfsr_tag_key(rat.tag)) {
|
||||||
LFS_DEBUG("%04x->%04x: leaf unr lt",
|
|
||||||
branch, lfsr_rbyd_eoff(rbyd));
|
|
||||||
// if removed, make our tag unreachable
|
// if removed, make our tag unreachable
|
||||||
alt = LFSR_TAG_ALT(LFSR_TAG_B, LFSR_TAG_GT, lower_tag);
|
alt = LFSR_TAG_ALT(LFSR_TAG_B, LFSR_TAG_GT, lower_tag);
|
||||||
weight = upper_rid - lower_rid + rat.weight;
|
weight = upper_rid - lower_rid + rat.weight;
|
||||||
upper_rid -= weight;
|
upper_rid -= weight;
|
||||||
} else {
|
} else {
|
||||||
LFS_DEBUG("%04x->%04x: leaf split lt",
|
|
||||||
branch, lfsr_rbyd_eoff(rbyd));
|
|
||||||
// split less than
|
// split less than
|
||||||
alt = LFSR_TAG_ALT(LFSR_TAG_B, LFSR_TAG_LE, tag_);
|
alt = LFSR_TAG_ALT(LFSR_TAG_B, LFSR_TAG_LE, tag_);
|
||||||
weight = upper_rid - lower_rid;
|
weight = upper_rid - lower_rid;
|
||||||
@@ -4258,15 +4005,11 @@ stem:;
|
|||||||
&& lfsr_tag_key(tag_)
|
&& lfsr_tag_key(tag_)
|
||||||
> lfsr_tag_key(rat.tag)))))) {
|
> lfsr_tag_key(rat.tag)))))) {
|
||||||
if (lfsr_tag_isrm(rat.tag) || !lfsr_tag_key(rat.tag)) {
|
if (lfsr_tag_isrm(rat.tag) || !lfsr_tag_key(rat.tag)) {
|
||||||
LFS_DEBUG("%04x->%04x: leaf unr gt",
|
|
||||||
branch, lfsr_rbyd_eoff(rbyd));
|
|
||||||
// if removed, make our tag unreachable
|
// if removed, make our tag unreachable
|
||||||
alt = LFSR_TAG_ALT(LFSR_TAG_B, LFSR_TAG_GT, lower_tag);
|
alt = LFSR_TAG_ALT(LFSR_TAG_B, LFSR_TAG_GT, lower_tag);
|
||||||
weight = upper_rid - lower_rid + rat.weight;
|
weight = upper_rid - lower_rid + rat.weight;
|
||||||
upper_rid -= weight;
|
upper_rid -= weight;
|
||||||
} else {
|
} else {
|
||||||
LFS_DEBUG("%04x->%04x: leaf split gt",
|
|
||||||
branch, lfsr_rbyd_eoff(rbyd));
|
|
||||||
// split greater than
|
// split greater than
|
||||||
alt = LFSR_TAG_ALT(LFSR_TAG_B, LFSR_TAG_GT, rat.tag);
|
alt = LFSR_TAG_ALT(LFSR_TAG_B, LFSR_TAG_GT, rat.tag);
|
||||||
weight = upper_rid - (rid+1);
|
weight = upper_rid - (rid+1);
|
||||||
|
|||||||
Reference in New Issue
Block a user