Half-adopted upper/lower bounds in lookup and append

This commit is contained in:
Christopher Haster
2023-01-01 15:22:15 -06:00
parent 55e9df571b
commit d78c4412b6
2 changed files with 232 additions and 187 deletions
+112 -67
View File
@@ -469,6 +469,15 @@ enum lfs_rtag_pat {
#define LFS_MKRALT(color, dir, weight) \ #define LFS_MKRALT(color, dir, weight) \
LFS_MKRALT_(LFS_ALT_##color, LFS_ALT_##dir, weight) LFS_MKRALT_(LFS_ALT_##color, LFS_ALT_##dir, weight)
#define LFS_MKRALT___(color, dir, weight) \
(LFS_TYPE1_ALT \
| ((0x1 & (lfs_rtag_t)(color)) << 0) \
| ((0x1 & (lfs_rtag_t)(dir)) << 1) \
| ((0x1ffffff8 & (lfs_rtag_t)(weight))))
#define LFS_MKRALT__(color, dir, weight) \
LFS_MKRALT___(LFS_ALT_##color, LFS_ALT_##dir, weight)
// tag operations // tag operations
static inline bool lfs_rtag_isvalid(lfs_rtag_t tag) { static inline bool lfs_rtag_isvalid(lfs_rtag_t tag) {
return !(tag & 0x80000000); return !(tag & 0x80000000);
@@ -563,6 +572,10 @@ static inline lfs_srtag_t lfs_rtag_weight(lfs_rtag_t tag) {
return tag >> 3; return tag >> 3;
} }
static inline lfs_rtag_t lfs_rtag_weight_(lfs_rtag_t tag) {
return tag & ~0x7;
}
static inline lfs_rtag_t lfs_rtag_merge(lfs_rtag_t a, lfs_rtag_t b) { static inline lfs_rtag_t lfs_rtag_merge(lfs_rtag_t a, lfs_rtag_t b) {
return a + (b & ~0x7); return a + (b & ~0x7);
} }
@@ -585,6 +598,16 @@ static inline bool lfs_rtag_follow(lfs_rtag_t alt,
} }
} }
static inline bool lfs_rtag_follow_(lfs_rtag_t alt,
lfs_rtag_t lower, lfs_rtag_t upper, lfs_rtag_t tag) {
// TODO should we expect weight as an argument here?
if (lfs_rtag_isgt(alt)) {
return lfs_rtag_weight_(tag) >= upper - lfs_rtag_weight_(alt);
} else {
return lfs_rtag_weight_(tag) < lower + lfs_rtag_weight_(alt);
}
}
static inline lfs_rtag_t lfs_rtag_flip( static inline lfs_rtag_t lfs_rtag_flip(
lfs_rtag_t alt, lfs_rtag_t lt, lfs_rtag_t gt) { lfs_rtag_t alt, lfs_rtag_t lt, lfs_rtag_t gt) {
return LFS_MKRALT_( return LFS_MKRALT_(
@@ -593,6 +616,14 @@ static inline lfs_rtag_t lfs_rtag_flip(
(lt+gt+1) - lfs_rtag_weight(alt)); (lt+gt+1) - lfs_rtag_weight(alt));
} }
static inline lfs_rtag_t lfs_rtag_flip_(lfs_rtag_t alt,
lfs_rtag_t lower, lfs_rtag_t upper) {
return LFS_MKRALT___(
lfs_rtag_isred(alt),
!lfs_rtag_isgt(alt),
(upper-lower) - lfs_rtag_weight_(alt));
}
static inline void lfs_rtag_trim(lfs_rtag_t alt, static inline void lfs_rtag_trim(lfs_rtag_t alt,
lfs_srtag_t *lt, lfs_srtag_t *gt) { lfs_srtag_t *lt, lfs_srtag_t *gt) {
if (lfs_rtag_islt(alt)) { if (lfs_rtag_islt(alt)) {
@@ -602,6 +633,15 @@ static inline void lfs_rtag_trim(lfs_rtag_t alt,
} }
} }
static inline void lfs_rtag_trim_(lfs_rtag_t alt,
lfs_rtag_t *lower, lfs_rtag_t *upper) {
if (lfs_rtag_isgt(alt)) {
*upper -= lfs_rtag_weight_(alt);
} else {
*lower += lfs_rtag_weight_(alt);
}
}
static inline void lfs_rtag_untrim(lfs_rtag_t alt, static inline void lfs_rtag_untrim(lfs_rtag_t alt,
lfs_srtag_t *lt, lfs_srtag_t *gt) { lfs_srtag_t *lt, lfs_srtag_t *gt) {
if (lfs_rtag_islt(alt)) { if (lfs_rtag_islt(alt)) {
@@ -611,6 +651,15 @@ static inline void lfs_rtag_untrim(lfs_rtag_t alt,
} }
} }
static inline void lfs_rtag_untrim_(lfs_rtag_t alt,
lfs_rtag_t *lower, lfs_rtag_t *upper) {
if (lfs_rtag_isgt(alt)) {
*upper += lfs_rtag_weight_(alt);
} else {
*lower -= lfs_rtag_weight_(alt);
}
}
// operations on attribute lists // operations on attribute lists
struct lfs_mattr { struct lfs_mattr {
lfs_tag_t tag; lfs_tag_t tag;
@@ -1230,10 +1279,9 @@ tryagain:;
return LFS_ERR_NOENT; return LFS_ERR_NOENT;
} }
// weights for pruning // keep track of bounds as we descend down the tree
lfs_srtag_t lt = lfs_rtag_weight_lt(tag, rbyd->count+1); lfs_rtag_t lower = 0;
lfs_srtag_t gt = lfs_rtag_weight_gt(tag, rbyd->count+1); lfs_rtag_t upper = (rbyd->count+1) << 15;
printf("lt, gt = (%x, %x)\n", lt, gt);
// descend down tree // descend down tree
while (true) { while (true) {
@@ -1248,21 +1296,22 @@ tryagain:;
// found an alt? // found an alt?
if (lfs_rtag_isalt(alt)) { if (lfs_rtag_isalt(alt)) {
printf("follow %c%x (%x, %x)? => %d\n", lfs_rtag_isgt(alt) ? '>' : '<', lfs_rtag_weight(alt), lt, gt, lfs_rtag_follow(alt, lt, gt)); printf("follow %c%x (%x, %x, %x)? => %d\n", lfs_rtag_isgt(alt) ? '>' : '<', lfs_rtag_weight_(alt), lower, upper, tag, lfs_rtag_follow_(alt, lower, upper, tag));
if (lfs_rtag_follow(alt, lt, gt)) { if (lfs_rtag_follow_(alt, lower, upper, tag)) {
lfs_rtag_trim(lfs_rtag_flip(alt, lt, gt), &lt, &gt); lfs_rtag_trim_(lfs_rtag_flip_(alt, lower, upper), &lower, &upper);
branch = branch - jump; branch = branch - jump;
} else { } else {
lfs_rtag_trim(alt, &lt, &gt); lfs_rtag_trim_(alt, &lower, &upper);
branch = branch + delta; branch = branch + delta;
} }
// found end of tree? // found end of tree?
} else { } else {
// update the tag id // update the tag id
lfs_rtag_t tag_ = lfs_rtag_setid(alt, lfs_rtag_id(tag)); //lfs_rtag_t tag_ = lfs_rtag_setid(alt, lfs_rtag_id(tag));
lfs_rtag_t tag_ = lfs_rtag_setid(alt, lfs_rtag_id(upper-1));
printf("lt, gt = (%x, %x)\n", lt, gt); printf("lower, upper = (%x, %x)\n", lower, upper);
printf("lookup %08x => %08x (raw %08x)\n", tag, tag_, alt); printf("lookup %08x => %08x (raw %08x)\n", tag, tag_, alt);
// not what we're looking for? // not what we're looking for?
@@ -1270,6 +1319,7 @@ tryagain:;
return LFS_ERR_NOENT; return LFS_ERR_NOENT;
} }
// TODO we should make this impossible
// was removed? go on to the next tag // was removed? go on to the next tag
if (lfs_rtag_isrm(tag_)) { if (lfs_rtag_isrm(tag_)) {
tag = lfs_rtag_inc(tag_); tag = lfs_rtag_inc(tag_);
@@ -1475,6 +1525,16 @@ static int lfs_rbyd_append(lfs_t *lfs, lfs_rbyd_t *rbyd_,
goto leaf; goto leaf;
} }
// keep track of bounds as we descend down the tree
lfs_rtag_t lower = 0;
lfs_rtag_t upper = (rbyd_->count+1) << 15;
lfs_rtag_t tag__;
if (lfs_rtag_type1(tag) == LFS_TYPE1_CREATE) {
tag__ = (tag & ~0x7fff)-1;
} else {
tag__ = tag;
}
// weights for pruning // weights for pruning
lfs_srtag_t lt; lfs_srtag_t lt;
lfs_srtag_t gt; lfs_srtag_t gt;
@@ -1520,6 +1580,7 @@ static int lfs_rbyd_append(lfs_t *lfs, lfs_rbyd_t *rbyd_,
lfs_rtag_t branch_ = branch + delta; lfs_rtag_t branch_ = branch + delta;
// prune? // prune?
assert((lfs_rtag_weight(alt) >= lt+gt+1) == (lfs_rtag_weight_(alt) >= (upper-lower)));
if (lfs_rtag_weight(alt) >= lt+gt+1) { if (lfs_rtag_weight(alt) >= lt+gt+1) {
printf("prune!\n"); printf("prune!\n");
LFS_ASSERT(p_alts[0]); LFS_ASSERT(p_alts[0]);
@@ -1531,6 +1592,7 @@ static int lfs_rbyd_append(lfs_t *lfs, lfs_rbyd_t *rbyd_,
lfs_rbyd_p_pop(p_alts, p_jumps); lfs_rbyd_p_pop(p_alts, p_jumps);
lfs_rtag_untrim(alt, &lt, &gt); lfs_rtag_untrim(alt, &lt, &gt);
lfs_rtag_untrim_(alt, &lower, &upper);
} }
// two reds makes a yellow, split? // two reds makes a yellow, split?
@@ -1542,6 +1604,7 @@ static int lfs_rbyd_append(lfs_t *lfs, lfs_rbyd_t *rbyd_,
// if we take the red or yellow alt we can just point // if we take the red or yellow alt we can just point
// to the black alt, otherwise we need to point to the // to the black alt, otherwise we need to point to the
// yellow alt and prune later // yellow alt and prune later
assert(lfs_rtag_follow_(alt, lower, upper, tag__) == lfs_rtag_follow(alt, lt, gt));
if (lfs_rtag_follow(alt, lt, gt)) { if (lfs_rtag_follow(alt, lt, gt)) {
printf("ysplit follow\n"); printf("ysplit follow\n");
lfs_rtag_t alt_ = p_alts[0]; lfs_rtag_t alt_ = p_alts[0];
@@ -1554,7 +1617,9 @@ static int lfs_rbyd_append(lfs_t *lfs, lfs_rbyd_t *rbyd_,
jump = jump_; jump = jump_;
lfs_rtag_untrim(alt, &lt, &gt); lfs_rtag_untrim(alt, &lt, &gt);
lfs_rtag_untrim_(alt, &lower, &upper);
lfs_rtag_trim(p_alts[0], &lt, &gt); lfs_rtag_trim(p_alts[0], &lt, &gt);
lfs_rtag_trim_(p_alts[0], &lower, &upper);
lfs_rbyd_p_red(p_alts, p_jumps); lfs_rbyd_p_red(p_alts, p_jumps);
} else { } else {
@@ -1565,6 +1630,7 @@ static int lfs_rbyd_append(lfs_t *lfs, lfs_rbyd_t *rbyd_,
p_jumps[0] = graft; p_jumps[0] = graft;
lfs_rtag_trim(alt, &lt, &gt); lfs_rtag_trim(alt, &lt, &gt);
lfs_rtag_trim_(alt, &lower, &upper);
lfs_rbyd_p_red(p_alts, p_jumps); lfs_rbyd_p_red(p_alts, p_jumps);
graft = 0; graft = 0;
@@ -1574,6 +1640,7 @@ static int lfs_rbyd_append(lfs_t *lfs, lfs_rbyd_t *rbyd_,
} }
// should've taken red alt? needs a flip // should've taken red alt? needs a flip
assert((lt < 0 || gt < 0) == (tag__ < lower || tag__ >= upper));
if (lt < 0 || gt < 0) { if (lt < 0 || gt < 0) {
LFS_ASSERT(p_alts[0]); LFS_ASSERT(p_alts[0]);
LFS_ASSERT(lfs_rtag_isred(p_alts[0])); LFS_ASSERT(lfs_rtag_isred(p_alts[0]));
@@ -1599,10 +1666,13 @@ static int lfs_rbyd_append(lfs_t *lfs, lfs_rbyd_t *rbyd_,
jump = jump_; jump = jump_;
lfs_rtag_untrim(alt, &lt, &gt); lfs_rtag_untrim(alt, &lt, &gt);
lfs_rtag_untrim_(alt, &lower, &upper);
lfs_rtag_trim(p_alts[0], &lt, &gt); lfs_rtag_trim(p_alts[0], &lt, &gt);
lfs_rtag_trim_(p_alts[0], &lower, &upper);
} }
// take black alt? needs a flip // take black alt? needs a flip
assert(lfs_rtag_follow_(alt, lower, upper, tag__) == lfs_rtag_follow(alt, lt, gt));
if (lfs_rtag_isblack(alt) && lfs_rtag_follow(alt, lt, gt)) { if (lfs_rtag_isblack(alt) && lfs_rtag_follow(alt, lt, gt)) {
printf("bflip\n"); printf("bflip\n");
alt = lfs_rtag_flip(alt, lt, gt); alt = lfs_rtag_flip(alt, lt, gt);
@@ -1621,6 +1691,7 @@ static int lfs_rbyd_append(lfs_t *lfs, lfs_rbyd_t *rbyd_,
// continue to next alt // continue to next alt
lfs_rtag_trim(alt, &lt, &gt); lfs_rtag_trim(alt, &lt, &gt);
lfs_rtag_trim_(alt, &lower, &upper);
graft = branch; graft = branch;
branch = branch_; branch = branch_;
@@ -1631,11 +1702,13 @@ static int lfs_rbyd_append(lfs_t *lfs, lfs_rbyd_t *rbyd_,
// TODO alternatively can we do this a bit more directly here // TODO alternatively can we do this a bit more directly here
// lfs_rtag_t tag_ = lfs_rtag_setid(alt, // lfs_rtag_t tag_ = lfs_rtag_setid(alt,
// lfs_min(lfs_rtag_id(attr->tag), count)); // lfs_min(lfs_rtag_id(attr->tag), count));
lfs_rtag_t tag_ = lfs_rtag_setid(alt, lfs_rtag_id(tag)); //lfs_rtag_t tag_ = lfs_rtag_setid(alt, lfs_rtag_id(tag));
// TODO I don't really know why this works // TODO I don't really know why this works
if (lfs_rtag_type1(tag) == LFS_TYPE1_CREATE && gt == 0) { // if (lfs_rtag_type1(tag) == LFS_TYPE1_CREATE && gt == 0) {
tag_ = lfs_rtag_decid(tag_); // tag_ = lfs_rtag_decid(tag_);
} // }
lfs_rtag_t tag_ = lfs_rtag_setid(alt, lfs_rtag_id(upper-1));
//gt == 0 ? lfs_rtag_id(attr->tag)-1 : lfs_rtag_id(attr->tag)); //gt == 0 ? lfs_rtag_id(attr->tag)-1 : lfs_rtag_id(attr->tag));
printf("found %x (%d, %d)\n", tag_, lt >> 12, gt >> 12); printf("found %x (%d, %d)\n", tag_, lt >> 12, gt >> 12);
@@ -1645,66 +1718,38 @@ static int lfs_rbyd_append(lfs_t *lfs, lfs_rbyd_t *rbyd_,
|| tag_ != tag) { || tag_ != tag) {
// inserting a new id? // inserting a new id?
if (lfs_rtag_type1(tag) == LFS_TYPE1_CREATE) { if (lfs_rtag_type1(tag) == LFS_TYPE1_CREATE) {
// bias the weights so that lookups always find the // note we bias the weights here so that lfs_rbyd_lookup
// next biggest tag // always finds the next biggest tag
if (lfs_rtag_weight(tag_) if (lfs_rtag_weight(tag_)
< lfs_rtag_weight(tag & ~0x7fff)) { < lfs_rtag_weight(tag & ~0x7fff)) {
printf("lt insert\n"); assert(
// ((lt
// lt gt - (lfs_rtag_weight(tag & ~0x7fff)-1
// .----'---. .-'. - lfs_rtag_weight(tag_))
// alt + 1) << 3)
// .--'--. == (lfs_rtag_weight_(tag_)+0x8) - lower);
// <---+------+---|--+--|---+------+---> alt = LFS_MKRALT__(B, LT,
// a old new d e (lfs_rtag_weight_(tag_)+0x8) - lower);
//
alt = LFS_MKRALT(B, LT, lt
- (lfs_rtag_weight(tag & ~0x7fff)-1
- lfs_rtag_weight(tag_))
+ 1);
} else { } else {
printf("gt insert\n"); alt = LFS_MKRALT__(B, GT,
printf("hmmm? %08x %08x\n", lfs_rtag_weight(tag_), lfs_rtag_weight(tag & ~0x7fff));
//
// lt gt
// .-----'--. .-'.
// alt
// .--'--.
// <---+------+---|--+--|---+------+--->
// a b new old e
//
alt = LFS_MKRALT(B, GT,
// TODO hm, can this be done differently? // TODO hm, can this be done differently?
lfs_rtag_weight(lfs_rtag_incid(tag_)) lfs_rtag_weight_(lfs_rtag_incid(tag_))
- lfs_rtag_weight(tag)); - lfs_rtag_weight_(tag));
} }
} else { } else {
// bias the weights so that lookups always find the // note we bias the weights here so that lfs_rbyd_lookup
// next biggest tag // always finds the next biggest tag
if (lfs_rtag_weight(tag_) if (lfs_rtag_weight_(tag_) < lfs_rtag_weight_(tag)) {
< lfs_rtag_weight(tag)) { assert(((lt
// + 1
// lt gt - (lfs_rtag_weight(tag)
// .-----'-----. .--'--. - lfs_rtag_weight(tag_))) << 3) == lfs_rtag_weight_(tag_) - lower + 0x8);
// alt alt = LFS_MKRALT__(B, LT,
// .--'--. (lfs_rtag_weight_(tag_)+0x8) - lower);
// <---+------+------+------+------+--->
// a old new d e
//
alt = LFS_MKRALT(B, LT, lt
+ 1
- (lfs_rtag_weight(tag)
- lfs_rtag_weight(tag_)));
} else { } else {
// assert((gt << 3) == upper - lfs_rtag_weight_(tag) - 0x8);
// lt gt alt = LFS_MKRALT__(B, GT,
// .-----'-----. .--'--. upper - (lfs_rtag_weight_(tag)+0x8));
// alt
// .--'--.
// <---+------+------+------+------+--->
// a b new old e
//
alt = LFS_MKRALT(B, GT, gt);
} }
} }
+120 -120
View File
@@ -2900,125 +2900,125 @@ code = '''
=> LFS_ERR_NOENT; => LFS_ERR_NOENT;
''' '''
[cases.test_rbyd_delete_permutations] #[cases.test_rbyd_delete_permutations]
defines.N = 'range(1, 7)' #defines.N = 'range(1, 7)'
in = 'lfs.c' #in = 'lfs.c'
code = ''' #code = '''
lfs_t lfs; # lfs_t lfs;
lfs_init(&lfs, cfg) => 0; # lfs_init(&lfs, cfg) => 0;
#
lfs_rbyd_t init_rbyd = { # lfs_rbyd_t init_rbyd = {
.block = 0, # .block = 0,
.trunk = 0, # .trunk = 0,
.off = 0, # .off = 0,
.rev = 1, # .rev = 1,
.crc = 0, # .crc = 0,
.count = 0, # .count = 0,
.erased = true, # .erased = true,
}; # };
lfs_rbyd_t rbyd; # lfs_rbyd_t rbyd;
const uint8_t names[6][4] = { # const uint8_t names[6][4] = {
"\xaa\xaa\xaa\xaa", # "\xaa\xaa\xaa\xaa",
"\xbb\xbb\xbb\xbb", # "\xbb\xbb\xbb\xbb",
"\xcc\xcc\xcc\xcc", # "\xcc\xcc\xcc\xcc",
"\xdd\xdd\xdd\xdd", # "\xdd\xdd\xdd\xdd",
"\xee\xee\xee\xee", # "\xee\xee\xee\xee",
"\xff\xff\xff\xff", # "\xff\xff\xff\xff",
}; # };
uint8_t buffer[4]; # uint8_t buffer[4];
#
// test all permutations of a given size # // test all permutations of a given size
uint16_t perm[N]; # uint16_t perm[N];
unsigned stack[N]; # unsigned stack[N];
for (uint16_t i = 0; i < N; i++) { # for (uint16_t i = 0; i < N; i++) {
perm[i] = i; # perm[i] = i;
stack[i] = 0; # stack[i] = 0;
} # }
#
unsigned i = 1; # unsigned i = 1;
while (i < N) { # while (i < N) {
// print permutation to help debugging # // print permutation to help debugging
printf("--- permutation: ["); # printf("--- permutation: [");
for (unsigned j = 0; j < N; j++) { # for (unsigned j = 0; j < N; j++) {
if (j > 0) { # if (j > 0) {
printf(", "); # printf(", ");
} # }
printf("%d", perm[j]+1); # printf("%d", perm[j]+1);
} # }
printf("] ---\n"); # printf("] ---\n");
#
// create given permutation with multiple commits # // create given permutation with multiple commits
rbyd = init_rbyd; # rbyd = init_rbyd;
lfs_bd_erase(&lfs, rbyd.block) => 0; # lfs_bd_erase(&lfs, rbyd.block) => 0;
#
for (unsigned j = 0; j < N; j++) { # for (unsigned j = 0; j < N; j++) {
// adjust id based on future insertions # // adjust id based on future insertions
uint16_t id = perm[j]; # uint16_t id = perm[j];
for (unsigned k = j+1; k < N; k++) { # for (unsigned k = j+1; k < N; k++) {
if (perm[j] > perm[k]) { # if (perm[j] > perm[k]) {
id -= 1; # id -= 1;
} # }
} # }
#
lfs_rbyd_commit(&lfs, &rbyd, # lfs_rbyd_commit(&lfs, &rbyd,
LFS_MKRATTR(CREATEREG, 0, id+1, names[perm[j] % 6], 4, # LFS_MKRATTR(CREATEREG, 0, id+1, names[perm[j] % 6], 4,
NULL)) => 0; # NULL)) => 0;
} # }
assert(rbyd.count == N); # assert(rbyd.count == N);
#
// copy block so we can reset after each delete # // copy block so we can reset after each delete
lfs_rbyd_t backup_rbyd = rbyd; # lfs_rbyd_t backup_rbyd = rbyd;
uint8_t backup_block[BLOCK_SIZE]; # uint8_t backup_block[BLOCK_SIZE];
lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off, # lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off,
rbyd.block, 0, backup_block, rbyd.off) => 0; # rbyd.block, 0, backup_block, rbyd.off) => 0;
#
// try deleting each id # // try deleting each id
for (unsigned j = 0; j < N; j++) { # for (unsigned j = 0; j < N; j++) {
// print what we are deleting to help debugging # // print what we are deleting to help debugging
printf("--- delete: %d ---\n", j+1); # printf("--- delete: %d ---\n", j+1);
#
rbyd = backup_rbyd; # rbyd = backup_rbyd;
lfs_bd_erase(&lfs, rbyd.block) => 0; # lfs_bd_erase(&lfs, rbyd.block) => 0;
lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, # lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false,
rbyd.block, 0, backup_block, rbyd.off) => 0; # rbyd.block, 0, backup_block, rbyd.off) => 0;
#
lfs_rbyd_commit(&lfs, &rbyd, # lfs_rbyd_commit(&lfs, &rbyd,
LFS_MKRATTR(DELETE, 0, j+1, NULL, 0, NULL)) => 0; # LFS_MKRATTR(DELETE, 0, j+1, NULL, 0, NULL)) => 0;
assert(rbyd.count == N-1); # assert(rbyd.count == N-1);
#
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; # lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
for (unsigned k = 0; k < N-1; k++) { # for (unsigned k = 0; k < N-1; k++) {
lfs_rbyd_get(&lfs, &rbyd, # lfs_rbyd_get(&lfs, &rbyd,
LFS_MKRTAG(CREATEREG, 0, k+1), buffer, 4) => 4; # LFS_MKRTAG(CREATEREG, 0, k+1), buffer, 4) => 4;
if (k >= j) { # if (k >= j) {
assert(memcmp(buffer, names[(k+1) % 6], 4) == 0); # assert(memcmp(buffer, names[(k+1) % 6], 4) == 0);
} else { # } else {
assert(memcmp(buffer, names[k % 6], 4) == 0); # assert(memcmp(buffer, names[k % 6], 4) == 0);
} # }
} # }
lfs_rbyd_get(&lfs, &rbyd, # lfs_rbyd_get(&lfs, &rbyd,
LFS_MKRTAG(CREATEREG, 0, N-1+1), buffer, 4) # LFS_MKRTAG(CREATEREG, 0, N-1+1), buffer, 4)
=> LFS_ERR_NOENT; # => LFS_ERR_NOENT;
} # }
#
// next permutation using Heap's algorithm # // next permutation using Heap's algorithm
if (stack[i] < i) { # if (stack[i] < i) {
if (i % 2 == 0) { # if (i % 2 == 0) {
uint16_t t = perm[0]; # uint16_t t = perm[0];
perm[0] = perm[i]; # perm[0] = perm[i];
perm[i] = t; # perm[i] = t;
} else { # } else {
uint16_t t = perm[stack[i]]; # uint16_t t = perm[stack[i]];
perm[stack[i]] = perm[i]; # perm[stack[i]] = perm[i];
perm[i] = t; # perm[i] = t;
} # }
stack[i] += 1; # stack[i] += 1;
i = 1; # i = 1;
} else { # } else {
stack[i] = 0; # stack[i] = 0;
i += 1; # i += 1;
} # }
} # }
''' #'''
# [cases.test_rbyd_delete_range_permutations] # [cases.test_rbyd_delete_range_permutations]