Add and use LowerBound methods in IdList. NFC.
Clearer and less error-prone to use standard-supplied algorithms.
This commit is contained in:
parent
0c941aedb1
commit
3340392bf0
89
src/dsc.h
89
src/dsc.h
@ -315,6 +315,17 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Comparison functor used by IdList and related classes
|
||||||
|
template <class T, class H>
|
||||||
|
struct CompareId {
|
||||||
|
bool operator()(T const& lhs, T const& rhs) const {
|
||||||
|
return lhs.h.v < rhs.h.v;
|
||||||
|
}
|
||||||
|
bool operator()(T const& lhs, H rhs) const {
|
||||||
|
return lhs.h.v < rhs.v;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// A list, where each element has an integer identifier. The list is kept
|
// A list, where each element has an integer identifier. The list is kept
|
||||||
// sorted by that identifier, and items can be looked up in log n time by
|
// sorted by that identifier, and items can be looked up in log n time by
|
||||||
// id.
|
// id.
|
||||||
@ -325,6 +336,8 @@ public:
|
|||||||
int n;
|
int n;
|
||||||
int elemsAllocated;
|
int elemsAllocated;
|
||||||
|
|
||||||
|
using Compare = CompareId<T, H>;
|
||||||
|
|
||||||
bool IsEmpty() const {
|
bool IsEmpty() const {
|
||||||
return n == 0;
|
return n == 0;
|
||||||
}
|
}
|
||||||
@ -344,6 +357,31 @@ public:
|
|||||||
return t->h;
|
return t->h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T * LowerBound(T const& t) {
|
||||||
|
if(IsEmpty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto it = std::lower_bound(begin(), end(), t, Compare());
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
T * LowerBound(H const& h) {
|
||||||
|
if(IsEmpty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto it = std::lower_bound(begin(), end(), h, Compare());
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LowerBoundIndex(T const& t) {
|
||||||
|
if(IsEmpty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
auto it = LowerBound(t);
|
||||||
|
auto idx = std::distance(begin(), it);
|
||||||
|
auto i = static_cast<int>(idx);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
void ReserveMore(int howMuch) {
|
void ReserveMore(int howMuch) {
|
||||||
if(n + howMuch > elemsAllocated) {
|
if(n + howMuch > elemsAllocated) {
|
||||||
elemsAllocated = n + howMuch;
|
elemsAllocated = n + howMuch;
|
||||||
@ -361,21 +399,12 @@ public:
|
|||||||
if(n >= elemsAllocated) {
|
if(n >= elemsAllocated) {
|
||||||
ReserveMore((elemsAllocated + 32)*2 - n);
|
ReserveMore((elemsAllocated + 32)*2 - n);
|
||||||
}
|
}
|
||||||
|
auto newIndex = LowerBoundIndex(*t);
|
||||||
int first = 0, last = n;
|
if (newIndex < n) {
|
||||||
// We know that we must insert within the closed interval [first,last]
|
H hm = elem[newIndex].h;
|
||||||
while(first != last) {
|
|
||||||
int mid = (first + last)/2;
|
|
||||||
H hm = elem[mid].h;
|
|
||||||
ssassert(hm.v != t->h.v, "Handle isn't unique");
|
ssassert(hm.v != t->h.v, "Handle isn't unique");
|
||||||
if(hm.v > t->h.v) {
|
|
||||||
last = mid;
|
|
||||||
} else if(hm.v < t->h.v) {
|
|
||||||
first = mid + 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
int i = static_cast<int>(newIndex);
|
||||||
int i = first;
|
|
||||||
new(&elem[n]) T();
|
new(&elem[n]) T();
|
||||||
std::move_backward(elem + i, elem + n, elem + n + 1);
|
std::move_backward(elem + i, elem + n, elem + n + 1);
|
||||||
elem[i] = *t;
|
elem[i] = *t;
|
||||||
@ -392,17 +421,10 @@ public:
|
|||||||
if(IsEmpty()) {
|
if(IsEmpty()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int first = 0, last = n-1;
|
auto it = LowerBound(h);
|
||||||
while(first <= last) {
|
auto idx = std::distance(begin(), it);
|
||||||
int mid = (first + last)/2;
|
if (idx < n) {
|
||||||
H hm = elem[mid].h;
|
return idx;
|
||||||
if(hm.v > h.v) {
|
|
||||||
last = mid-1; // and first stays the same
|
|
||||||
} else if(hm.v < h.v) {
|
|
||||||
first = mid+1; // and last stays the same
|
|
||||||
} else {
|
|
||||||
return mid;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -411,19 +433,14 @@ public:
|
|||||||
if(IsEmpty()) {
|
if(IsEmpty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
int first = 0, last = n-1;
|
auto it = LowerBound(h);
|
||||||
while(first <= last) {
|
if (it == nullptr || it == end()) {
|
||||||
int mid = (first + last)/2;
|
return nullptr;
|
||||||
H hm = elem[mid].h;
|
|
||||||
if(hm.v > h.v) {
|
|
||||||
last = mid-1; // and first stays the same
|
|
||||||
} else if(hm.v < h.v) {
|
|
||||||
first = mid+1; // and last stays the same
|
|
||||||
} else {
|
|
||||||
return &(elem[mid]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return NULL;
|
if (it->h.v == h.v) {
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
T *First() {
|
T *First() {
|
||||||
|
Loading…
Reference in New Issue
Block a user