Half-adopted upper/lower bounds in lookup and append
This commit is contained in:
@@ -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), <, >);
|
lfs_rtag_trim_(lfs_rtag_flip_(alt, lower, upper), &lower, &upper);
|
||||||
branch = branch - jump;
|
branch = branch - jump;
|
||||||
} else {
|
} else {
|
||||||
lfs_rtag_trim(alt, <, >);
|
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, <, >);
|
lfs_rtag_untrim(alt, <, >);
|
||||||
|
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, <, >);
|
lfs_rtag_untrim(alt, <, >);
|
||||||
|
lfs_rtag_untrim_(alt, &lower, &upper);
|
||||||
lfs_rtag_trim(p_alts[0], <, >);
|
lfs_rtag_trim(p_alts[0], <, >);
|
||||||
|
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, <, >);
|
lfs_rtag_trim(alt, <, >);
|
||||||
|
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, <, >);
|
lfs_rtag_untrim(alt, <, >);
|
||||||
|
lfs_rtag_untrim_(alt, &lower, &upper);
|
||||||
lfs_rtag_trim(p_alts[0], <, >);
|
lfs_rtag_trim(p_alts[0], <, >);
|
||||||
|
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, <, >);
|
lfs_rtag_trim(alt, <, >);
|
||||||
|
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
@@ -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]
|
||||||
|
|||||||
Reference in New Issue
Block a user