Cleaned up reworked range removal/diverging trunk algorithm
Note this is still blanket recoloring alts to black in diverged trunks.
So we don't get the main benefit of this rework yet: preserving the rbyd
color invariants.
But this is a nice checkpoint that shows that our two-pass diverging
trunk algorithm works without breaking right-leaning invariants.
Before, we made a single pass, and stitched together alternating
alts in any diverged trunks in order to remove ranges of tags (ignore
coloring for now, coloring _does_ help here):
.-----------o
.-------o-------. | o-----------.
.---o---. .---o---. | .-----o |
.-o-. .-o-. .-o-. .-o-. .-o-. | o-----. .-o-.
.o. .o. .o. .o. .o. .o. .o. .o. .o. .o. .o. .--o--. .o. .o. .o.
a b c d e f g h i j k l m n o p => a b c d e f g j k l m n o p
'-+-'
remove
Now, we do two passes: One to write any alts on the lower-diverged
trunk. And one to write the non-diverging part of the trunk, stitch in the
lower-diverged trunk with an alt, and then write any alts on the
upper-diverged trunk.
This results in a somewhat complex diverging state machine:
diverge possible? diverge not possible?
| |
v |
DIVERGINGLOWER-----------. |
| | |
v v v
DIVERGEDLOWER NOTDIVERGING
| |
v |
DIVERGINGUPPER |
| |
v |
DIVERGEDUPPER |
'--------. .--------'
v v
leaf stuff
But the end result is a much more balanced tree, at least on first
inspection:
.-------o-------. .--o--.
.---o---. .---o---. .--------o o--------.
.-o-. .-o-. .-o-. .-o-. .-o-. .--o o--. .-o-.
.o. .o. .o. .o. .o. .o. .o. .o. .o. .o. .o. | | .o. .o. .o.
a b c d e f g h i j k l m n o p => a b c d e f g j k l m n o p
'-+-'
remove
Unfortunately, this does mean we need, well, two passes, even if the
resulting tree doesn't actually end up with a diverging trunk. We can
avoid two passes if we know a diverged trunk is impossible, but we only
know this in the single attr append case (no negative deltas, no
submask, no supmask, etc).
At the very least we don't end up _progging_ any more alts than is
necessary. Even though we write two trunks, the number of alts after
pruning end up the same as in our single-pass algorithm. The only
additional cost is a single null tag (4 bytes) to terminate the diverged
trunk.
This two pass algorithm may sound more complicated, and therefore more
costly, but keep in mind this replaces the previous diverged-swapping
state, which I would argue resulted in more mess and a harder to
understand lfsr_rbyd_appendattr.
Now that the dust has settled, we can actually start comparing the
relative code costs, though again note we are still blanket recoloring.
The result is a surprising basically net-zero code code:
code stack
one-pass: 33852 2880
two-pass: 33860 (+0.0%) 2880 (+0.0%)
This commit is contained in:
@@ -781,12 +781,6 @@ enum lfsr_tag {
|
|||||||
LFSR_TAG_GROW = 0x4000,
|
LFSR_TAG_GROW = 0x4000,
|
||||||
LFSR_TAG_SUP = 0x2000,
|
LFSR_TAG_SUP = 0x2000,
|
||||||
LFSR_TAG_SUB = 0x1000,
|
LFSR_TAG_SUB = 0x1000,
|
||||||
|
|
||||||
// lfsr_rbyd_appendattr specific flags, also in-device only
|
|
||||||
LFSR_TAG_DIVERGED = 0x4000,
|
|
||||||
LFSR_TAG_DIVERGEDUPPER = 0x2000,
|
|
||||||
LFSR_TAG_DIVERGEDLOWER = 0x0000,
|
|
||||||
LFSR_TAG_DIVERGEDDONE = 0x1000,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// some other tag encodings with their own subfields
|
// some other tag encodings with their own subfields
|
||||||
@@ -863,23 +857,6 @@ static inline bool lfsr_tag_issub(lfsr_tag_t tag) {
|
|||||||
return tag & LFSR_TAG_SUB;
|
return tag & LFSR_TAG_SUB;
|
||||||
}
|
}
|
||||||
|
|
||||||
// lfsr_rbyd_appendattr diverged specific flags
|
|
||||||
static inline bool lfsr_tag_hasdiverged(lfsr_tag_t tag) {
|
|
||||||
return tag & LFSR_TAG_DIVERGED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool lfsr_tag_isdivergedupper(lfsr_tag_t tag) {
|
|
||||||
return tag & LFSR_TAG_DIVERGEDUPPER;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool lfsr_tag_isdivergedlower(lfsr_tag_t tag) {
|
|
||||||
return !(tag & LFSR_TAG_DIVERGEDUPPER);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool lfsr_tag_isdivergeddone(lfsr_tag_t tag) {
|
|
||||||
return tag & LFSR_TAG_DIVERGEDDONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// alt operations
|
// alt operations
|
||||||
static inline bool lfsr_tag_isblack(lfsr_tag_t tag) {
|
static inline bool lfsr_tag_isblack(lfsr_tag_t tag) {
|
||||||
return !(tag & LFSR_TAG_R);
|
return !(tag & LFSR_TAG_R);
|
||||||
@@ -2717,6 +2694,24 @@ static void lfsr_rbyd_p_red(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// diverged state machine for range appends
|
||||||
|
enum {
|
||||||
|
LFSR_D_NOTDIVERGING = 0,
|
||||||
|
LFSR_D_DIVERGINGLOWER = 1,
|
||||||
|
LFSR_D_DIVERGINGUPPER = 2,
|
||||||
|
LFSR_D_DIVERGEDLOWER = 3,
|
||||||
|
LFSR_D_DIVERGEDUPPER = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline bool lfsr_d_isdiverged(uint8_t d_state) {
|
||||||
|
return d_state >= LFSR_D_DIVERGEDLOWER;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8_t lfsr_d_diverge(uint8_t d_state) {
|
||||||
|
LFS_ASSERT(d_state != LFSR_D_NOTDIVERGING);
|
||||||
|
return d_state + (LFSR_D_DIVERGEDLOWER - LFSR_D_DIVERGINGLOWER);
|
||||||
|
}
|
||||||
|
|
||||||
// core rbyd algorithm
|
// core rbyd algorithm
|
||||||
static int lfsr_rbyd_appendattr(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
static int lfsr_rbyd_appendattr(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
||||||
lfsr_srid_t rid, lfsr_tag_t tag, lfsr_srid_t delta, lfsr_data_t data) {
|
lfsr_srid_t rid, lfsr_tag_t tag, lfsr_srid_t delta, lfsr_data_t data) {
|
||||||
@@ -2741,10 +2736,7 @@ static int lfsr_rbyd_appendattr(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// figure out the range of tags we're operating on
|
// figure out what range of tags we're operating on
|
||||||
//
|
|
||||||
// several lower bits are reserved, so we repurpose these
|
|
||||||
// to keep track of some append state
|
|
||||||
lfsr_srid_t a_rid;
|
lfsr_srid_t a_rid;
|
||||||
lfsr_srid_t b_rid;
|
lfsr_srid_t b_rid;
|
||||||
lfsr_tag_t a_tag;
|
lfsr_tag_t a_tag;
|
||||||
@@ -2769,7 +2761,7 @@ static int lfsr_rbyd_appendattr(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
a_tag = 0;
|
a_tag = 0;
|
||||||
b_tag = a_tag;
|
b_tag = 0;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
LFS_ASSERT(rid < (lfsr_srid_t)rbyd->weight);
|
LFS_ASSERT(rid < (lfsr_srid_t)rbyd->weight);
|
||||||
@@ -2786,7 +2778,6 @@ static int lfsr_rbyd_appendattr(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
a_tag = lfsr_tag_supkey(tag);
|
a_tag = lfsr_tag_supkey(tag);
|
||||||
b_tag = lfsr_tag_supkey(tag) + 0x100;
|
b_tag = lfsr_tag_supkey(tag) + 0x100;
|
||||||
} else if (lfsr_tag_isrm(tag) || !lfsr_tag_key(tag)) {
|
} else if (lfsr_tag_isrm(tag) || !lfsr_tag_key(tag)) {
|
||||||
//LFS_ASSERT(lfsr_tag_key(tag)); // when does this happen?
|
|
||||||
a_tag = lfsr_tag_key(tag);
|
a_tag = lfsr_tag_key(tag);
|
||||||
b_tag = lfsr_tag_key(tag) + 0x1;
|
b_tag = lfsr_tag_key(tag) + 0x1;
|
||||||
} else {
|
} else {
|
||||||
@@ -2794,60 +2785,57 @@ static int lfsr_rbyd_appendattr(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
b_tag = lfsr_tag_key(tag);
|
b_tag = lfsr_tag_key(tag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// a_tag = lfs_max16(a_tag, 0x1);
|
|
||||||
// b_tag = lfs_max16(b_tag, 0x1);
|
|
||||||
|
|
||||||
// keep track of the diverged branch if we're removing a range
|
// keep track of diverged state
|
||||||
bool diverging = (a_rid != b_rid || a_tag != b_tag);
|
//
|
||||||
bool d_upper = false;
|
// this is only used if we operate on a range of tags, in which case
|
||||||
lfs_size_t d_branch = 0;
|
// we may need to write two trunks
|
||||||
lfsr_tag_t d_tag;
|
//
|
||||||
lfs_size_t d_branch_;
|
// to pull this off, we make two passes:
|
||||||
lfsr_srid_t d_lower_rid;
|
// 1. to write the diverged-lower trunk
|
||||||
lfsr_srid_t d_upper_rid;
|
// 2. to write the non-diverging trunk and diverged-upper trunk,
|
||||||
|
// stitching in the diverged-lower trunk where the trunks diverged
|
||||||
|
//
|
||||||
|
// we may also end up not diverging, in which case we fallback to a
|
||||||
|
// normal append
|
||||||
|
//
|
||||||
|
uint8_t d_state = (a_rid != b_rid || a_tag != b_tag)
|
||||||
|
? LFSR_D_DIVERGINGLOWER
|
||||||
|
: LFSR_D_NOTDIVERGING;
|
||||||
|
lfs_size_t d_branch = rbyd->eoff;
|
||||||
|
lfsr_tag_t d_tag = 0;
|
||||||
|
lfsr_srid_t d_rid = 0;
|
||||||
|
|
||||||
again:;
|
again:;
|
||||||
// TODO move me?
|
// the new trunk starts here
|
||||||
lfsr_tag_t tag__ = 0;
|
lfs_size_t trunk = (rbyd->trunk & LFSR_RBYD_ISSHRUB) | rbyd->eoff;
|
||||||
bool diverged = false;
|
|
||||||
|
|
||||||
// keep track of bounds as we descend down the tree
|
// keep track of bounds as we descend down the tree
|
||||||
//
|
//
|
||||||
// this gets a bit confusing as we also may need to keep
|
// this gets a bit confusing as we also may need to keep
|
||||||
// track of both the lower and upper bounds of diverging paths
|
// track of both the lower and upper bounds of diverging paths
|
||||||
// in the case of range deletions
|
// in the case of range deletions
|
||||||
lfs_size_t a_branch = lfsr_rbyd_trunk(rbyd);
|
lfs_size_t branch = lfsr_rbyd_trunk(rbyd);
|
||||||
lfsr_srid_t a_lower_rid = 0;
|
lfsr_srid_t lower_rid = 0;
|
||||||
lfsr_srid_t a_upper_rid = rbyd->weight;
|
lfsr_srid_t upper_rid = rbyd->weight;
|
||||||
lfsr_tag_t a_lower_tag = 0x0000;
|
lfsr_tag_t lower_tag = 0x0000;
|
||||||
lfsr_tag_t a_upper_tag = 0xffff;
|
lfsr_tag_t upper_tag = 0xffff;
|
||||||
|
|
||||||
// diverged state in case we are removing a range from the tree
|
|
||||||
//
|
|
||||||
// this is a second copy of the search path state, used to keep track
|
|
||||||
// of two search paths simulaneously when our range diverges.
|
|
||||||
//
|
|
||||||
// note we can't just perform two searches sequentially, or else our tree
|
|
||||||
// will end up very unbalanced.
|
|
||||||
lfs_size_t b_branch = 0;
|
|
||||||
lfsr_srid_t b_lower_rid = 0;
|
|
||||||
lfsr_srid_t b_upper_rid = 0;
|
|
||||||
lfsr_tag_t b_lower_tag = 0;
|
|
||||||
lfsr_tag_t b_upper_tag = 0;
|
|
||||||
|
|
||||||
// the new trunk starts here
|
|
||||||
lfs_size_t trunk = (rbyd->trunk & LFSR_RBYD_ISSHRUB) | rbyd->eoff;
|
|
||||||
|
|
||||||
// no trunk yet?
|
// no trunk yet?
|
||||||
if (!a_branch) {
|
if (!branch) {
|
||||||
goto leaf;
|
goto leaf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// keep track of the tag we find at the end of the trunk
|
||||||
|
lfsr_tag_t tag_ = 0;
|
||||||
|
|
||||||
// queue of pending alts we can emulate rotations with
|
// queue of pending alts we can emulate rotations with
|
||||||
lfsr_tag_t p_alts[3] = {0, 0, 0};
|
lfsr_tag_t p_alts[3] = {0, 0, 0};
|
||||||
lfsr_rid_t p_weights[3] = {0, 0, 0};
|
lfsr_rid_t p_weights[3] = {0, 0, 0};
|
||||||
lfs_size_t p_jumps[3] = {0, 0, 0};
|
lfs_size_t p_jumps[3] = {0, 0, 0};
|
||||||
lfs_size_t graft = 0;
|
|
||||||
|
// keep track of the last incoming branch for yellow splits
|
||||||
|
lfs_size_t y_branch = 0;
|
||||||
|
|
||||||
// descend down tree, building alt pointers
|
// descend down tree, building alt pointers
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -2856,7 +2844,7 @@ again:;
|
|||||||
lfsr_rid_t weight;
|
lfsr_rid_t weight;
|
||||||
lfs_size_t jump;
|
lfs_size_t jump;
|
||||||
lfs_ssize_t d = lfsr_bd_readtag(lfs,
|
lfs_ssize_t d = lfsr_bd_readtag(lfs,
|
||||||
rbyd->blocks[0], a_branch, 0,
|
rbyd->blocks[0], branch, 0,
|
||||||
&alt, &weight, &jump, NULL);
|
&alt, &weight, &jump, NULL);
|
||||||
if (d < 0) {
|
if (d < 0) {
|
||||||
return d;
|
return d;
|
||||||
@@ -2865,201 +2853,86 @@ again:;
|
|||||||
// found an alt?
|
// found an alt?
|
||||||
if (lfsr_tag_isalt(alt)) {
|
if (lfsr_tag_isalt(alt)) {
|
||||||
// make jump absolute
|
// make jump absolute
|
||||||
jump = a_branch - jump;
|
jump = branch - jump;
|
||||||
lfs_size_t branch_ = a_branch + d;
|
lfs_size_t branch_ = branch + d;
|
||||||
|
|
||||||
// do bounds want to take different paths? begin diverging
|
// do bounds want to take different paths? begin diverging
|
||||||
if (!diverged
|
if (!lfsr_d_isdiverged(d_state)
|
||||||
&& lfsr_tag_follow2(alt, weight,
|
&& lfsr_tag_follow2(alt, weight,
|
||||||
p_alts[0], p_weights[0],
|
p_alts[0], p_weights[0],
|
||||||
a_lower_rid, a_upper_rid,
|
lower_rid, upper_rid,
|
||||||
a_rid, a_tag)
|
a_rid, a_tag)
|
||||||
^ lfsr_tag_follow2(alt, weight,
|
^ lfsr_tag_follow2(alt, weight,
|
||||||
p_alts[0], p_weights[0],
|
p_alts[0], p_weights[0],
|
||||||
a_lower_rid, a_upper_rid,
|
lower_rid, upper_rid,
|
||||||
b_rid, b_tag)) {
|
b_rid, b_tag)) {
|
||||||
LFS_ASSERT(diverging);
|
LFS_ASSERT(d_state != LFSR_D_NOTDIVERGING);
|
||||||
|
|
||||||
// take care of any lingering red alts before diverging
|
// take care of any lingering red alts before diverging
|
||||||
if (lfsr_tag_isred(p_alts[0])) {
|
if (lfsr_tag_isred(p_alts[0])) {
|
||||||
alt = p_alts[0] & ~LFSR_TAG_R;
|
alt = p_alts[0] & ~LFSR_TAG_R;
|
||||||
weight = p_weights[0];
|
weight = p_weights[0];
|
||||||
jump = p_jumps[0];
|
jump = p_jumps[0];
|
||||||
branch_ = a_branch;
|
branch_ = branch;
|
||||||
lfsr_rbyd_p_pop(p_alts, p_weights, p_jumps);
|
lfsr_rbyd_p_pop(p_alts, p_weights, p_jumps);
|
||||||
|
|
||||||
// begin diverging
|
// begin diverging
|
||||||
} else if (!d_upper) {
|
|
||||||
printf("diverged lower: %#x\n", a_branch);
|
|
||||||
// TODO need this?
|
|
||||||
alt &= ~LFSR_TAG_R;
|
|
||||||
|
|
||||||
d_branch = rbyd->eoff; // TODO need this?
|
|
||||||
diverged = true;
|
|
||||||
|
|
||||||
// // TODO too many swaps?
|
|
||||||
// lfs_swap16(&a_tag, &b_tag);
|
|
||||||
// lfs_sswap32(&a_rid, &b_rid);
|
|
||||||
|
|
||||||
// connect diverged branch
|
|
||||||
} else {
|
} else {
|
||||||
printf("diverged upper: %#x\n", a_branch);
|
d_state = lfsr_d_diverge(d_state);
|
||||||
// TODO need this?
|
|
||||||
alt &= ~LFSR_TAG_R;
|
|
||||||
// if (lfsr_tag_follow2(alt, weight,
|
|
||||||
// p_alts[0], p_weights[0],
|
|
||||||
// a_lower_rid, a_upper_rid,
|
|
||||||
// a_rid, a_tag)) {
|
|
||||||
// branch_ = d_branch;
|
|
||||||
// } else {
|
|
||||||
// jump = d_branch;
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
if (lfsr_tag_follow2(
|
|
||||||
alt, weight,
|
|
||||||
p_alts[0], p_weights[0],
|
|
||||||
a_lower_rid, a_upper_rid,
|
|
||||||
a_rid, a_tag)) {
|
|
||||||
lfsr_tag_flip2(
|
|
||||||
&alt, &weight,
|
|
||||||
p_alts[0], p_weights[0],
|
|
||||||
a_lower_rid, a_upper_rid);
|
|
||||||
lfs_swap32(&jump, &branch_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO ??? special handling for null?
|
|
||||||
if (lfsr_tag_key(d_tag)) {
|
|
||||||
printf("stitching: %#x %d-%d %#x\n",
|
|
||||||
LFSR_TAG_ALT(
|
|
||||||
LFSR_TAG_LE,
|
|
||||||
LFSR_TAG_B,
|
|
||||||
d_tag),
|
|
||||||
//alt,
|
|
||||||
//LFSR_TAG_ALT(LFSR_TAG_GT, LFSR_TAG_B, b_tag),
|
|
||||||
a_lower_rid, d_lower_rid,
|
|
||||||
d_branch);
|
|
||||||
|
|
||||||
|
// stitch together diverged branches
|
||||||
|
if (d_state == LFSR_D_DIVERGEDUPPER && d_tag) {
|
||||||
err = lfsr_rbyd_p_push(lfs, rbyd,
|
err = lfsr_rbyd_p_push(lfs, rbyd,
|
||||||
p_alts, p_weights, p_jumps,
|
p_alts, p_weights, p_jumps,
|
||||||
LFSR_TAG_ALT(
|
LFSR_TAG_ALT(
|
||||||
LFSR_TAG_LE,
|
LFSR_TAG_LE,
|
||||||
LFSR_TAG_B,
|
LFSR_TAG_B,
|
||||||
d_tag),
|
d_tag),
|
||||||
//lfs_smax32(weight + delta, 0),
|
d_rid - lower_rid,
|
||||||
d_lower_rid - a_lower_rid,
|
|
||||||
// LFSR_TAG_ALT(
|
|
||||||
// LFSR_TAG_LE,
|
|
||||||
// LFSR_TAG_B,
|
|
||||||
// // TODO this better?
|
|
||||||
// (lfsr_tag_key(a_tag))
|
|
||||||
// ? a_tag-1
|
|
||||||
// : 0),
|
|
||||||
// a_lower_rid,
|
|
||||||
d_branch);
|
d_branch);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
diverged = true;
|
|
||||||
|
|
||||||
lfsr_tag_trim(
|
|
||||||
alt, weight,
|
|
||||||
&a_lower_rid, &a_upper_rid,
|
|
||||||
&a_lower_tag, &a_upper_tag);
|
|
||||||
|
|
||||||
graft = a_branch;
|
|
||||||
a_branch = branch_;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// // follow the upper path first
|
|
||||||
// // TODO too many swaps?
|
|
||||||
// lfs_swap16(&a_tag, &b_tag);
|
|
||||||
// lfs_sswap32(&a_rid, &b_rid);
|
|
||||||
|
|
||||||
// a_tag |= LFSR_TAG_DIVERGED | LFSR_TAG_DIVERGEDLOWER;
|
|
||||||
// b_tag |= LFSR_TAG_DIVERGED | LFSR_TAG_DIVERGEDUPPER;
|
|
||||||
// b_branch = a_branch;
|
|
||||||
// b_lower_rid = a_lower_rid;
|
|
||||||
// b_upper_rid = a_upper_rid;
|
|
||||||
// b_lower_tag = a_lower_tag;
|
|
||||||
// b_upper_tag = a_upper_tag;
|
|
||||||
|
|
||||||
// TODO rm me
|
// TODO rm me
|
||||||
if (diverged) {
|
if (lfsr_d_isdiverged(d_state)) {
|
||||||
alt &= ~LFSR_TAG_R;
|
alt &= ~LFSR_TAG_R;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prune diverged?
|
// prune diverged?
|
||||||
// TODO can we merge with yellow prune?
|
if (d_state == LFSR_D_DIVERGINGLOWER
|
||||||
if ((diverging && !d_upper && !diverged)
|
|| (lfsr_d_isdiverged(d_state)
|
||||||
|| (diverged
|
&& (d_state == LFSR_D_DIVERGEDUPPER)
|
||||||
&& d_upper
|
|
||||||
^ lfsr_tag_isgt(alt)
|
^ lfsr_tag_isgt(alt)
|
||||||
^ lfsr_tag_follow2(
|
^ lfsr_tag_follow2(
|
||||||
alt, weight,
|
alt, weight,
|
||||||
p_alts[0], p_weights[0],
|
p_alts[0], p_weights[0],
|
||||||
a_lower_rid, a_upper_rid,
|
lower_rid, upper_rid,
|
||||||
a_rid, a_tag))) {
|
a_rid, a_tag))) {
|
||||||
if (lfsr_tag_follow2(
|
if (lfsr_tag_follow2(
|
||||||
alt, weight,
|
alt, weight,
|
||||||
p_alts[0], p_weights[0],
|
p_alts[0], p_weights[0],
|
||||||
a_lower_rid, a_upper_rid,
|
lower_rid, upper_rid,
|
||||||
a_rid, a_tag)) {
|
a_rid, a_tag)) {
|
||||||
lfsr_tag_flip2(
|
lfsr_tag_flip2(
|
||||||
&alt, &weight,
|
&alt, &weight,
|
||||||
p_alts[0], p_weights[0],
|
p_alts[0], p_weights[0],
|
||||||
a_lower_rid, a_upper_rid);
|
lower_rid, upper_rid);
|
||||||
lfs_swap32(&jump, &branch_);
|
lfs_swap32(&jump, &branch_);
|
||||||
}
|
}
|
||||||
lfsr_tag_trim(
|
lfsr_tag_trim(
|
||||||
alt, weight,
|
alt, weight,
|
||||||
&a_lower_rid, &a_upper_rid,
|
&lower_rid, &upper_rid,
|
||||||
&a_lower_tag, &a_upper_tag);
|
&lower_tag, &upper_tag);
|
||||||
|
|
||||||
graft = a_branch;
|
y_branch = branch;
|
||||||
a_branch = branch_;
|
branch = branch_;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// // if we diverged, paint alts black, this isn't perfect but
|
|
||||||
// // otherwise we run into recoloring issues
|
|
||||||
// if (lfsr_tag_hasdiverged(a_tag)) {
|
|
||||||
// alt &= ~LFSR_TAG_R;
|
|
||||||
//
|
|
||||||
// // prune diverged?
|
|
||||||
// if (lfsr_tag_isdivergedupper(a_tag)
|
|
||||||
// ^ lfsr_tag_isgt(alt)
|
|
||||||
// ^ lfsr_tag_follow2(
|
|
||||||
// alt, weight,
|
|
||||||
// p_alts[0], p_weights[0],
|
|
||||||
// a_lower_rid, a_upper_rid,
|
|
||||||
// a_rid, a_tag)) {
|
|
||||||
// if (lfsr_tag_follow2(
|
|
||||||
// alt, weight,
|
|
||||||
// p_alts[0], p_weights[0],
|
|
||||||
// a_lower_rid, a_upper_rid,
|
|
||||||
// a_rid, a_tag)) {
|
|
||||||
// lfsr_tag_flip2(
|
|
||||||
// &alt, &weight,
|
|
||||||
// p_alts[0], p_weights[0],
|
|
||||||
// a_lower_rid, a_upper_rid);
|
|
||||||
// lfs_swap32(&jump, &branch_);
|
|
||||||
// }
|
|
||||||
// lfsr_tag_trim(
|
|
||||||
// alt, weight,
|
|
||||||
// &a_lower_rid, &a_upper_rid,
|
|
||||||
// &a_lower_tag, &a_upper_tag);
|
|
||||||
//
|
|
||||||
// graft = a_branch;
|
|
||||||
// a_branch = branch_;
|
|
||||||
// goto next;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// prune?
|
// prune?
|
||||||
// <b >b
|
// <b >b
|
||||||
// .-'| .-'|
|
// .-'| .-'|
|
||||||
@@ -3073,8 +2946,8 @@ again:;
|
|||||||
if (lfsr_tag_prune2(
|
if (lfsr_tag_prune2(
|
||||||
alt, weight,
|
alt, weight,
|
||||||
p_alts[0], p_weights[0],
|
p_alts[0], p_weights[0],
|
||||||
a_lower_rid, a_upper_rid,
|
lower_rid, upper_rid,
|
||||||
a_lower_tag, a_upper_tag)) {
|
lower_tag, upper_tag)) {
|
||||||
if (lfsr_tag_isred(p_alts[0])) {
|
if (lfsr_tag_isred(p_alts[0])) {
|
||||||
alt = p_alts[0] & ~LFSR_TAG_R;
|
alt = p_alts[0] & ~LFSR_TAG_R;
|
||||||
weight = p_weights[0];
|
weight = p_weights[0];
|
||||||
@@ -3082,8 +2955,8 @@ again:;
|
|||||||
jump = p_jumps[0];
|
jump = p_jumps[0];
|
||||||
lfsr_rbyd_p_pop(p_alts, p_weights, p_jumps);
|
lfsr_rbyd_p_pop(p_alts, p_weights, p_jumps);
|
||||||
} else {
|
} else {
|
||||||
graft = a_branch;
|
y_branch = branch;
|
||||||
a_branch = jump;
|
branch = jump;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3104,11 +2977,11 @@ again:;
|
|||||||
if (lfsr_tag_follow2(
|
if (lfsr_tag_follow2(
|
||||||
alt, weight,
|
alt, weight,
|
||||||
p_alts[0], p_weights[0],
|
p_alts[0], p_weights[0],
|
||||||
a_lower_rid, a_upper_rid,
|
lower_rid, upper_rid,
|
||||||
a_rid, a_tag)) {
|
a_rid, a_tag)) {
|
||||||
lfsr_tag_flip2(&alt, &weight,
|
lfsr_tag_flip2(&alt, &weight,
|
||||||
p_alts[0], p_weights[0],
|
p_alts[0], p_weights[0],
|
||||||
a_lower_rid, a_upper_rid);
|
lower_rid, upper_rid);
|
||||||
lfs_swap32(&jump, &branch_);
|
lfs_swap32(&jump, &branch_);
|
||||||
|
|
||||||
lfs_swap16(&p_alts[0], &alt);
|
lfs_swap16(&p_alts[0], &alt);
|
||||||
@@ -3118,8 +2991,8 @@ again:;
|
|||||||
|
|
||||||
lfsr_tag_trim(
|
lfsr_tag_trim(
|
||||||
p_alts[0], p_weights[0],
|
p_alts[0], p_weights[0],
|
||||||
&a_lower_rid, &a_upper_rid,
|
&lower_rid, &upper_rid,
|
||||||
&a_lower_tag, &a_upper_tag);
|
&lower_tag, &upper_tag);
|
||||||
lfsr_rbyd_p_red(p_alts, p_weights, p_jumps);
|
lfsr_rbyd_p_red(p_alts, p_weights, p_jumps);
|
||||||
|
|
||||||
// otherwise we need to point to the yellow alt and
|
// otherwise we need to point to the yellow alt and
|
||||||
@@ -3134,18 +3007,18 @@ again:;
|
|||||||
// | | .-'| | | .----'|
|
// | | .-'| | | .----'|
|
||||||
// 1 2 3 4 1 2 3 4 4
|
// 1 2 3 4 1 2 3 4 4
|
||||||
} else {
|
} else {
|
||||||
LFS_ASSERT(graft != 0);
|
LFS_ASSERT(y_branch != 0);
|
||||||
p_alts[0] = alt;
|
p_alts[0] = alt;
|
||||||
p_weights[0] += weight;
|
p_weights[0] += weight;
|
||||||
p_jumps[0] = graft;
|
p_jumps[0] = y_branch;
|
||||||
|
|
||||||
lfsr_tag_trim(
|
lfsr_tag_trim(
|
||||||
p_alts[0], p_weights[0],
|
p_alts[0], p_weights[0],
|
||||||
&a_lower_rid, &a_upper_rid,
|
&lower_rid, &upper_rid,
|
||||||
&a_lower_tag, &a_upper_tag);
|
&lower_tag, &upper_tag);
|
||||||
lfsr_rbyd_p_red(p_alts, p_weights, p_jumps);
|
lfsr_rbyd_p_red(p_alts, p_weights, p_jumps);
|
||||||
|
|
||||||
a_branch = branch_;
|
branch = branch_;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3158,11 +3031,11 @@ again:;
|
|||||||
&& lfsr_tag_follow2(
|
&& lfsr_tag_follow2(
|
||||||
alt, weight,
|
alt, weight,
|
||||||
p_alts[0], p_weights[0],
|
p_alts[0], p_weights[0],
|
||||||
a_lower_rid, a_upper_rid,
|
lower_rid, upper_rid,
|
||||||
a_rid, a_tag)) {
|
a_rid, a_tag)) {
|
||||||
lfsr_tag_flip2(&alt, &weight,
|
lfsr_tag_flip2(&alt, &weight,
|
||||||
p_alts[0], p_weights[0],
|
p_alts[0], p_weights[0],
|
||||||
a_lower_rid, a_upper_rid);
|
lower_rid, upper_rid);
|
||||||
lfs_swap32(&jump, &branch_);
|
lfs_swap32(&jump, &branch_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3174,7 +3047,7 @@ again:;
|
|||||||
// 1 2 3 1 2 3 1
|
// 1 2 3 1 2 3 1
|
||||||
if (lfsr_tag_isred(p_alts[0])
|
if (lfsr_tag_isred(p_alts[0])
|
||||||
&& lfsr_tag_follow(p_alts[0], p_weights[0],
|
&& lfsr_tag_follow(p_alts[0], p_weights[0],
|
||||||
a_lower_rid, a_upper_rid,
|
lower_rid, upper_rid,
|
||||||
a_rid, a_tag)) {
|
a_rid, a_tag)) {
|
||||||
lfs_swap16(&p_alts[0], &alt);
|
lfs_swap16(&p_alts[0], &alt);
|
||||||
lfs_swap32(&p_weights[0], &weight);
|
lfs_swap32(&p_weights[0], &weight);
|
||||||
@@ -3184,7 +3057,7 @@ again:;
|
|||||||
|
|
||||||
lfsr_tag_flip2(&alt, &weight,
|
lfsr_tag_flip2(&alt, &weight,
|
||||||
p_alts[0], p_weights[0],
|
p_alts[0], p_weights[0],
|
||||||
a_lower_rid, a_upper_rid);
|
lower_rid, upper_rid);
|
||||||
lfs_swap32(&jump, &branch_);
|
lfs_swap32(&jump, &branch_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3193,8 +3066,8 @@ again:;
|
|||||||
lfsr_tag_trim2(
|
lfsr_tag_trim2(
|
||||||
alt, weight,
|
alt, weight,
|
||||||
p_alts[0], p_weights[0],
|
p_alts[0], p_weights[0],
|
||||||
&a_lower_rid, &a_upper_rid,
|
&lower_rid, &upper_rid,
|
||||||
&a_lower_tag, &a_upper_tag);
|
&lower_tag, &upper_tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
// push alt onto our queue
|
// push alt onto our queue
|
||||||
@@ -3205,79 +3078,34 @@ again:;
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// // if we diverged, stitch our paths together with alternating
|
|
||||||
// // red alts, this gives us an optimal ternary tree if we
|
|
||||||
// // started with a binary tree, but the above recoloring makes
|
|
||||||
// // this not optimal
|
|
||||||
// if (lfsr_tag_hasdiverged(a_tag) && lfsr_tag_isblack(p_alts[2])) {
|
|
||||||
// lfsr_rbyd_p_red(p_alts, p_weights, p_jumps);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// continue to next alt
|
// continue to next alt
|
||||||
graft = a_branch;
|
y_branch = branch;
|
||||||
a_branch = branch_;
|
branch = branch_;
|
||||||
|
|
||||||
// found end of tree?
|
// found end of tree?
|
||||||
} else {
|
} else {
|
||||||
// update the found tag/rid, marking as done while preserving
|
// update the found tag
|
||||||
// any diverged state
|
tag_ = lfsr_tag_key(alt);
|
||||||
tag__ = lfsr_tag_mode(a_tag) | alt;
|
|
||||||
|
|
||||||
// // done?
|
|
||||||
// if (!lfsr_tag_hasdiverged(a_tag)
|
|
||||||
// || lfsr_tag_isdivergeddone(b_tag)) {
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// next:;
|
|
||||||
// // switch to the other path if we have diverged
|
|
||||||
// if (lfsr_tag_hasdiverged(a_tag)) {
|
|
||||||
// lfs_swap16(&a_tag, &b_tag);
|
|
||||||
// lfs_sswap32(&a_rid, &b_rid);
|
|
||||||
// lfs_swap32(&a_branch, &b_branch);
|
|
||||||
// lfs_sswap32(&a_lower_rid, &b_lower_rid);
|
|
||||||
// lfs_sswap32(&a_upper_rid, &b_upper_rid);
|
|
||||||
// lfs_swap16(&a_lower_tag, &b_lower_tag);
|
|
||||||
// lfs_swap16(&a_upper_tag, &b_upper_tag);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// the last alt should always end up black
|
// the last alt should always end up black
|
||||||
LFS_ASSERT(lfsr_tag_isblack(p_alts[0]));
|
LFS_ASSERT(lfsr_tag_isblack(p_alts[0]));
|
||||||
|
|
||||||
// // if we diverged, merge the bounds
|
// no divergence? guess we only need one trunk then, actually write
|
||||||
// LFS_ASSERT(lfsr_tag_isdivergeddone(a_tag));
|
// it out this time
|
||||||
// LFS_ASSERT(!lfsr_tag_hasdiverged(a_tag)
|
if (d_state == LFSR_D_DIVERGINGLOWER) {
|
||||||
// || lfsr_tag_isdivergeddone(b_tag));
|
d_state = LFSR_D_NOTDIVERGING;
|
||||||
// if (lfsr_tag_hasdiverged(a_tag)) {
|
goto again;
|
||||||
// if (lfsr_tag_isdivergedlower(a_tag)) {
|
|
||||||
// // finished on lower path
|
|
||||||
// a_tag = b_tag;
|
|
||||||
// a_branch = b_branch;
|
|
||||||
// a_upper_rid = b_upper_rid;
|
|
||||||
// } else {
|
|
||||||
// // finished on upper path
|
|
||||||
// a_lower_rid = b_lower_rid;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// need a second diverging trunk?
|
// diverged lower trunk? we need an upper trunk too
|
||||||
if (diverging && !d_upper) {
|
} else if (d_state == LFSR_D_DIVERGEDLOWER) {
|
||||||
// no diverging branch? guess we only need one trunk then
|
// keep track of last alt on diverged trunk to stitch the trunks
|
||||||
if (!diverged) {
|
// together with
|
||||||
printf("false diverge\n");
|
d_state = LFSR_D_DIVERGINGUPPER;
|
||||||
diverging = false;
|
|
||||||
// // TODO too many swaps
|
|
||||||
// lfs_swap16(&a_tag, &b_tag);
|
|
||||||
// lfs_sswap32(&a_rid, &b_rid);
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO is this not a_lower_tag?
|
|
||||||
d_tag = p_alts[0];
|
d_tag = p_alts[0];
|
||||||
|
d_rid = lower_rid;
|
||||||
|
|
||||||
// flush any pending alts
|
// flush any pending alts
|
||||||
err = lfsr_rbyd_p_flush(lfs, rbyd,
|
err = lfsr_rbyd_p_flush(lfs, rbyd,
|
||||||
@@ -3286,10 +3114,7 @@ again:;
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO can we avoid lingering unreachable tags when when d_tag=0?
|
// terminate diverged trunk with an unreachable tag
|
||||||
// why does hiding this behind if d_tag=0 not work?
|
|
||||||
//
|
|
||||||
// terminate diverged branch with an unreachable tag
|
|
||||||
if (d_tag) {
|
if (d_tag) {
|
||||||
err = lfsr_rbyd_appendattr_(lfs, rbyd,
|
err = lfsr_rbyd_appendattr_(lfs, rbyd,
|
||||||
(lfsr_rbyd_isshrub(rbyd) ? LFSR_TAG_SHRUB : 0)
|
(lfsr_rbyd_isshrub(rbyd) ? LFSR_TAG_SHRUB : 0)
|
||||||
@@ -3301,36 +3126,24 @@ again:;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// save the found lower rid/tag
|
// swap tag/rid and write out the upper trunk
|
||||||
// d_tag = a_lower_tag; //tag__;
|
|
||||||
d_branch_ = a_branch;
|
|
||||||
d_lower_rid = a_lower_rid;
|
|
||||||
d_upper_rid = a_upper_rid;
|
|
||||||
|
|
||||||
lfs_swap16(&a_tag, &b_tag);
|
lfs_swap16(&a_tag, &b_tag);
|
||||||
lfs_sswap32(&a_rid, &b_rid);
|
lfs_sswap32(&a_rid, &b_rid);
|
||||||
d_upper = true;
|
|
||||||
printf("found dtag: %#x: %#x\n", d_branch_, d_tag);
|
|
||||||
goto again;
|
goto again;
|
||||||
}
|
|
||||||
|
|
||||||
// use the diverged lower rid for leaf weight calculation
|
// diverged upper trunk? done diverging
|
||||||
a_tag = tag__;
|
} else if (d_state == LFSR_D_DIVERGEDUPPER) {
|
||||||
if (diverged) {
|
// use the diverged rid bound for leaf weight calculation
|
||||||
// a_tag = d_tag;
|
lower_rid = d_rid;
|
||||||
// a_branch = d_branch_;
|
|
||||||
// a_upper_rid = d_upper_rid;
|
|
||||||
a_lower_rid = d_lower_rid;
|
|
||||||
}
|
}
|
||||||
printf("done: %#x %d %d\n", a_tag, a_lower_rid, a_upper_rid);
|
|
||||||
|
|
||||||
// split leaf nodes?
|
// split leaf nodes?
|
||||||
//
|
//
|
||||||
// note we bias the weights here so that lfsr_rbyd_lookupnext
|
// note we bias the weights here so that lfsr_rbyd_lookupnext
|
||||||
// always finds the next biggest tag
|
// always finds the next biggest tag
|
||||||
//
|
//
|
||||||
// note also if lfsr_tag_key(a_tag) is null, we found a removed tag that
|
// note also if tag_ is null, we found a removed tag that we should just
|
||||||
// we should just prune
|
// prune
|
||||||
//
|
//
|
||||||
// this gets real messy because we have a lot of special behavior built in:
|
// this gets real messy because we have a lot of special behavior built in:
|
||||||
// - default => split if tags mismatch
|
// - default => split if tags mismatch
|
||||||
@@ -3339,67 +3152,67 @@ again:;
|
|||||||
// - rm-bit set => never split, but emit alt-always tags, making our
|
// - rm-bit set => never split, but emit alt-always tags, making our
|
||||||
// tag effectively unreachable
|
// tag effectively unreachable
|
||||||
//
|
//
|
||||||
lfsr_tag_t a_alt = 0;
|
lfsr_tag_t alt = 0;
|
||||||
lfsr_rid_t a_weight = 0;
|
lfsr_rid_t weight = 0;
|
||||||
if (lfsr_tag_key(a_tag)
|
if (tag_
|
||||||
&& (a_upper_rid-1 < rid-lfs_smax32(-delta, 0)
|
&& (upper_rid-1 < rid-lfs_smax32(-delta, 0)
|
||||||
|| (a_upper_rid-1 == rid-lfs_smax32(-delta, 0)
|
|| (upper_rid-1 == rid-lfs_smax32(-delta, 0)
|
||||||
&& ((!lfsr_tag_isgrow(tag) && delta > 0)
|
&& ((!lfsr_tag_isgrow(tag) && delta > 0)
|
||||||
|| (!lfsr_tag_issup(tag)
|
|| (!lfsr_tag_issup(tag)
|
||||||
&& lfsr_tag_supkey(a_tag) < lfsr_tag_supkey(tag))
|
&& lfsr_tag_supkey(tag_) < lfsr_tag_supkey(tag))
|
||||||
|| (!lfsr_tag_issup(tag)
|
|| (!lfsr_tag_issup(tag)
|
||||||
&& !lfsr_tag_issub(tag)
|
&& !lfsr_tag_issub(tag)
|
||||||
&& lfsr_tag_key(a_tag) < lfsr_tag_key(tag)))))) {
|
&& lfsr_tag_key(tag_) < lfsr_tag_key(tag)))))) {
|
||||||
if (lfsr_tag_isrm(tag) || !lfsr_tag_key(tag)) {
|
if (lfsr_tag_isrm(tag) || !lfsr_tag_key(tag)) {
|
||||||
// if removed, make our tag unreachable
|
// if removed, make our tag unreachable
|
||||||
a_alt = LFSR_TAG_ALT(LFSR_TAG_GT, LFSR_TAG_B, 0);
|
alt = LFSR_TAG_ALT(LFSR_TAG_GT, LFSR_TAG_B, 0);
|
||||||
a_weight = a_upper_rid - a_lower_rid + delta;
|
weight = upper_rid - lower_rid + delta;
|
||||||
a_upper_rid -= a_weight;
|
upper_rid -= weight;
|
||||||
} else {
|
} else {
|
||||||
// split less than
|
// split less than
|
||||||
a_alt = LFSR_TAG_ALT(
|
alt = LFSR_TAG_ALT(
|
||||||
LFSR_TAG_LE,
|
LFSR_TAG_LE,
|
||||||
//(!lfsr_tag_hasdiverged(a_tag)) TODO
|
// TODO should this always be red?
|
||||||
(!diverged)
|
(!lfsr_d_isdiverged(d_state))
|
||||||
? LFSR_TAG_R
|
? LFSR_TAG_R
|
||||||
: LFSR_TAG_B,
|
: LFSR_TAG_B,
|
||||||
a_tag);
|
tag_);
|
||||||
a_weight = a_upper_rid - a_lower_rid;
|
weight = upper_rid - lower_rid;
|
||||||
a_lower_rid += a_weight;
|
lower_rid += weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (lfsr_tag_key(a_tag)
|
} else if (tag_
|
||||||
&& (a_upper_rid-1 > rid
|
&& (upper_rid-1 > rid
|
||||||
|| (a_upper_rid-1 == rid
|
|| (upper_rid-1 == rid
|
||||||
&& ((!lfsr_tag_isgrow(tag) && delta > 0)
|
&& ((!lfsr_tag_isgrow(tag) && delta > 0)
|
||||||
|| (!lfsr_tag_issup(tag)
|
|| (!lfsr_tag_issup(tag)
|
||||||
&& lfsr_tag_supkey(a_tag) > lfsr_tag_supkey(tag))
|
&& lfsr_tag_supkey(tag_) > lfsr_tag_supkey(tag))
|
||||||
|| (!lfsr_tag_issup(tag)
|
|| (!lfsr_tag_issup(tag)
|
||||||
&& !lfsr_tag_issub(tag)
|
&& !lfsr_tag_issub(tag)
|
||||||
&& lfsr_tag_key(a_tag) > lfsr_tag_key(tag)))))) {
|
&& lfsr_tag_key(tag_) > lfsr_tag_key(tag)))))) {
|
||||||
if (lfsr_tag_isrm(tag) || !lfsr_tag_key(tag)) {
|
if (lfsr_tag_isrm(tag) || !lfsr_tag_key(tag)) {
|
||||||
// if removed, make our tag unreachable
|
// if removed, make our tag unreachable
|
||||||
a_alt = LFSR_TAG_ALT(LFSR_TAG_GT, LFSR_TAG_B, 0);
|
alt = LFSR_TAG_ALT(LFSR_TAG_GT, LFSR_TAG_B, 0);
|
||||||
a_weight = a_upper_rid - a_lower_rid + delta;
|
weight = upper_rid - lower_rid + delta;
|
||||||
a_upper_rid -= a_weight;
|
upper_rid -= weight;
|
||||||
} else {
|
} else {
|
||||||
// split greater than
|
// split greater than
|
||||||
a_alt = LFSR_TAG_ALT(
|
alt = LFSR_TAG_ALT(
|
||||||
LFSR_TAG_GT,
|
LFSR_TAG_GT,
|
||||||
// (!lfsr_tag_hasdiverged(a_tag)) TODO
|
// TODO should this always be red?
|
||||||
(!diverged)
|
(!lfsr_d_isdiverged(d_state))
|
||||||
? LFSR_TAG_R
|
? LFSR_TAG_R
|
||||||
: LFSR_TAG_B,
|
: LFSR_TAG_B,
|
||||||
tag);
|
tag);
|
||||||
a_weight = a_upper_rid - (rid+1);
|
weight = upper_rid - (rid+1);
|
||||||
a_upper_rid -= a_weight;
|
upper_rid -= weight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a_alt) {
|
if (alt) {
|
||||||
err = lfsr_rbyd_p_push(lfs, rbyd,
|
err = lfsr_rbyd_p_push(lfs, rbyd,
|
||||||
p_alts, p_weights, p_jumps,
|
p_alts, p_weights, p_jumps,
|
||||||
a_alt, a_weight, a_branch);
|
alt, weight, branch);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -3429,7 +3242,7 @@ leaf:;
|
|||||||
| ((lfsr_tag_isrm(tag))
|
| ((lfsr_tag_isrm(tag))
|
||||||
? LFSR_TAG_NULL
|
? LFSR_TAG_NULL
|
||||||
: lfsr_tag_key(tag)),
|
: lfsr_tag_key(tag)),
|
||||||
a_upper_rid - a_lower_rid + delta,
|
upper_rid - lower_rid + delta,
|
||||||
data);
|
data);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
|
|||||||
Reference in New Issue
Block a user