diff --git a/lfs.c b/lfs.c index bfc17865..5c85d6fb 100644 --- a/lfs.c +++ b/lfs.c @@ -2655,8 +2655,6 @@ static void lfsr_rbyd_p_red( lfsr_rid_t p_weights[static 3], lfs_size_t p_jumps[static 3]) { // propagate a red edge upwards - p_alts[0] &= ~LFSR_TAG_R; - if (p_alts[1]) { p_alts[1] |= LFSR_TAG_R; @@ -2696,20 +2694,46 @@ 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, + LFSR_D_NOTDIVERGING = 0x0, + LFSR_D_DIVERGINGLOWER = 0x2, + LFSR_D_DIVERGINGUPPER = 0x3, + LFSR_D_DIVERGEDLOWER = 0x4, + LFSR_D_DIVERGEDUPPER = 0x5, + LFSR_D_PRUNEDLOWER = 0x6, + LFSR_D_PRUNEDUPPER = 0x7, }; static inline bool lfsr_d_isdiverged(uint8_t d_state) { return d_state >= LFSR_D_DIVERGEDLOWER; } +static inline bool lfsr_d_isupper(uint8_t d_state) { + return d_state & 0x1; +} + +static inline bool lfsr_d_islower(uint8_t d_state) { + return !(d_state & 0x1); +} + +static inline bool lfsr_d_ispruned(uint8_t d_state) { + return d_state >= LFSR_D_PRUNEDLOWER; +} + 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); + return (!lfsr_d_isdiverged(d_state)) + ? d_state + (LFSR_D_DIVERGEDLOWER - LFSR_D_DIVERGINGLOWER) + : d_state; +} + +static inline uint8_t lfsr_d_prune(uint8_t d_state) { + LFS_ASSERT(lfsr_d_isdiverged(d_state)); + return d_state | 0x2; +} + +static inline uint8_t lfsr_d_unprune(uint8_t d_state) { + LFS_ASSERT(lfsr_d_isdiverged(d_state)); + return d_state & ~0x2; } // core rbyd algorithm @@ -2881,7 +2905,7 @@ again:; d_state = lfsr_d_diverge(d_state); // stitch together diverged branches - if (d_state == LFSR_D_DIVERGEDUPPER && d_tag) { + if (lfsr_d_isupper(d_state) && d_tag) { err = lfsr_rbyd_p_push(lfs, rbyd, p_alts, p_weights, p_jumps, LFSR_TAG_ALT(LFSR_TAG_LE, LFSR_TAG_B, d_tag), @@ -2904,16 +2928,15 @@ again:; // | |