Skip to content

Commit bcdca18

Browse files
committed
fixed findNext and a bisect terminal case bug
also added new tests
1 parent 70806e0 commit bcdca18

File tree

1 file changed

+73
-13
lines changed

1 file changed

+73
-13
lines changed

pachyderm/bisect.cpp

Lines changed: 73 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <cassert>
33
#include <cstdlib>
44
#include <algorithm>
5+
#include <cmath>
56

67
using namespace std;
78

@@ -88,19 +89,25 @@ pair<Commit*, int> findNext(Commit *c, Commit *start, int delta) {
8889
return make_pair(start, 0);
8990
}
9091

91-
auto left = findNext(c, start->left_parent_, delta / 2);
92-
auto right = findNext(c, start->right_parent_, delta / 2);
93-
if (left.first == nullptr) {
94-
return findNext(c, right.first, left.second);
95-
} else if (right.first == nullptr) {
96-
return findNext(c, left.first, right.second);
92+
if (start->right_parent_ == nullptr) {
93+
return findNext(c, start->left_parent_, delta - 1);
9794
} else {
98-
if (left.first->depth_ > right.first->depth_) {
99-
return left;
95+
auto left = findNext(c, start->left_parent_, delta / 2);
96+
auto right = findNext(c, start->right_parent_, delta / 2);
97+
if (left.first == nullptr) {
98+
// pick up the remainders
99+
return findNext(c, right.first, left.second);
100+
} else if (right.first == nullptr) {
101+
return findNext(c, left.first, right.second);
100102
} else {
101-
return right;
103+
if (left.first->depth_ > right.first->depth_) {
104+
return left;
105+
} else {
106+
return right;
107+
}
102108
}
103109
}
110+
104111
}
105112

106113
// Bisect returns a commit c such that the following holds:
@@ -111,12 +118,24 @@ pair<Commit*, int> findNext(Commit *c, Commit *start, int delta) {
111118
// About half are ancestors of c and half aren't.
112119
Commit *Bisect(set< Commit *> allCommits, set<Commit *> goodCommits, Commit *badCommit) {
113120
Commit *c = firstKnownGood(goodCommits, badCommit);
114-
int delta = (badCommit->depth_ - c->depth_) / 2;
121+
assert(c->depth_ != badCommit->depth_);
122+
int delta = (badCommit->depth_ - c->depth_);
123+
if (delta == 1) {
124+
if (badCommit->left_parent_ == c) {
125+
if (badCommit->right_parent_ != nullptr) {
126+
return badCommit->right_parent_;
127+
} else {
128+
return badCommit;
129+
}
130+
} else {
131+
return badCommit->left_parent_;
132+
}
133+
}
115134
if (delta == 0) {
116135
return badCommit;
117136
}
118137

119-
auto mid = findNext(c, badCommit, delta);
138+
auto mid = findNext(c, badCommit, delta / 2);
120139
assert(mid.first != nullptr);
121140
return mid.first;
122141
}
@@ -155,12 +174,15 @@ typedef Commit *(*Bisector)( set< Commit *> allCommits, set<Commit *> goodCommi
155174
// finds the first bad commit
156175
Commit *findBad(set< Commit *> &allCommits, set<Commit *> &goodCommits, Commit *badCommit,
157176
Bisector bisector) {
158-
while (true) {
177+
int depth = badCommit->depth_;
178+
179+
for (int i = 0; ; i++) {
159180
Commit *mid = bisector(allCommits, goodCommits, badCommit);
160181
if (mid->good_) {
161182
goodCommits.insert(mid);
162183
} else {
163184
if (mid == badCommit) {
185+
assert(i <= ((log(depth) / log(2)) + 1));
164186
return mid;
165187
} else {
166188
badCommit = mid;
@@ -213,5 +235,43 @@ main(int argc, char *argv[]) {
213235
left = left->newCommit();
214236
}
215237
final = left->merge(right);
216-
assert(findBad(root, final, Bisect) == right);
238+
auto res = findBad(root, final, Bisect);
239+
assert(res == right);
240+
241+
root = new Commit(nullptr, nullptr);
242+
left = root->newCommit()->bad();
243+
right = root;
244+
for (int i = 0; i < 10; i++) {
245+
right = right->newCommit();
246+
}
247+
final = left->merge(right);
248+
res = findBad(root, final, Bisect);
249+
assert(res == left);
250+
251+
root = new Commit(nullptr, nullptr);
252+
left = root->newCommit()->bad();
253+
right = root;
254+
for (int i = 0; i < 1000; i++) {
255+
right = right->newCommit();
256+
}
257+
final = left->merge(right);
258+
res = findBad(root, final, Bisect);
259+
assert(res == left);
260+
261+
root = new Commit(nullptr, nullptr);
262+
left = root;
263+
for (int i = 0; i < 10; i++) {
264+
left = left->newCommit();
265+
}
266+
assert(left->depth_ == 10);
267+
right = left->newCommit()->newCommit()->bad();
268+
assert(right->depth_ == 12);
269+
right = right->newCommit()->merge(right->newCommit());
270+
assert(right->depth_ == 14);
271+
left = left->newCommit()->newCommit()->newCommit();
272+
assert(left->depth_ == 13);
273+
final = left->merge(right);
274+
assert(final->depth_ == 15);
275+
res = findBad(root, final, Bisect);
276+
assert(res->depth_ == 12);
217277
}

0 commit comments

Comments
 (0)