reduce the number of calls to operator< made by lower_bound and upper_bound #2877
This commit is contained in:
parent
ae2d9744cb
commit
99a805517e
|
@ -114,28 +114,51 @@ namespace PTreeImpl {
|
||||||
return contains(p->child(!less, at), at, x);
|
return contains(p->child(!less, at), at, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Remove the number of invocations of operator<, and replace with something closer to memcmp.
|
||||||
|
// and same for upper_bound.
|
||||||
template<class T, class X>
|
template<class T, class X>
|
||||||
void lower_bound(const Reference<PTree<T>>& p, Version at, const X& x, std::vector<const PTree<T>*>& f){
|
void lower_bound(const Reference<PTree<T>>& p, Version at, const X& x, std::vector<const PTree<T>*>& f, std::vector<bool>& lessThan){
|
||||||
if (!p) {
|
if (!p) {
|
||||||
while (f.size() && !(x < f.back()->data))
|
while (f.size() && !(lessThan.back())) {
|
||||||
f.pop_back();
|
f.pop_back();
|
||||||
|
lessThan.pop_back();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
f.push_back(p.getPtr());
|
f.push_back(p.getPtr());
|
||||||
bool less = x < p->data;
|
bool less = x < p->data;
|
||||||
|
lessThan.push_back(less);
|
||||||
if (!less && !(p->data<x)) return; // x == p->data
|
if (!less && !(p->data<x)) return; // x == p->data
|
||||||
lower_bound(p->child(!less, at), at, x, f);
|
lower_bound(p->child(!less, at), at, x, f, lessThan);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class X>
|
||||||
|
void lower_bound(const Reference<PTree<T>>& p, Version at, const X& x, std::vector<const PTree<T>*>& f) {
|
||||||
|
assert(!f.size());
|
||||||
|
std::vector<bool> lessThan;
|
||||||
|
lower_bound(p, at, x, f, lessThan);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class X>
|
||||||
|
void upper_bound(const Reference<PTree<T>>& p, Version at, const X& x, std::vector<const PTree<T>*>& f, std::vector<bool>& lessThan){
|
||||||
|
if (!p) {
|
||||||
|
while (f.size() && !(lessThan.back())) {
|
||||||
|
f.pop_back();
|
||||||
|
lessThan.pop_back();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
f.push_back(p.getPtr());
|
||||||
|
bool less = x < p->data;
|
||||||
|
lessThan.push_back(less);
|
||||||
|
upper_bound(p->child(!less, at), at, x, f, lessThan);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T, class X>
|
template<class T, class X>
|
||||||
void upper_bound(const Reference<PTree<T>>& p, Version at, const X& x, std::vector<const PTree<T>*>& f){
|
void upper_bound(const Reference<PTree<T>>& p, Version at, const X& x, std::vector<const PTree<T>*>& f){
|
||||||
if (!p) {
|
assert(!f.size());
|
||||||
while (f.size() && !(x < f.back()->data))
|
std::vector<bool> lessThan;
|
||||||
f.pop_back();
|
upper_bound(p, at, x, f, lessThan);
|
||||||
return;
|
|
||||||
}
|
|
||||||
f.push_back(p.getPtr());
|
|
||||||
upper_bound(p->child(!(x < p->data), at), at, x, f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T, bool forward>
|
template<class T, bool forward>
|
||||||
|
|
|
@ -700,6 +700,7 @@ int IndexedSet<T,Metric>::insert(const std::vector<std::pair<T,Metric>>& dataVec
|
||||||
// traverse to find insert point
|
// traverse to find insert point
|
||||||
bool foundNode = false;
|
bool foundNode = false;
|
||||||
while (true){
|
while (true){
|
||||||
|
// TODO: remove implicit double invocation of memcmp
|
||||||
d = t->data < data;
|
d = t->data < data;
|
||||||
if (!d)
|
if (!d)
|
||||||
blockEnd = t;
|
blockEnd = t;
|
||||||
|
@ -995,6 +996,7 @@ template <class Key>
|
||||||
typename IndexedSet<T,Metric>::iterator IndexedSet<T,Metric>::find(const Key &key) const {
|
typename IndexedSet<T,Metric>::iterator IndexedSet<T,Metric>::find(const Key &key) const {
|
||||||
Node* t = root;
|
Node* t = root;
|
||||||
while (t){
|
while (t){
|
||||||
|
// TODO: avoid indirect double invocation of memcmp
|
||||||
int d = t->data < key;
|
int d = t->data < key;
|
||||||
if (!d && !(key < t->data)) // t->data == key
|
if (!d && !(key < t->data)) // t->data == key
|
||||||
return iterator(t);
|
return iterator(t);
|
||||||
|
@ -1009,13 +1011,15 @@ template <class Key>
|
||||||
typename IndexedSet<T,Metric>::iterator IndexedSet<T,Metric>::lower_bound(const Key &key) const {
|
typename IndexedSet<T,Metric>::iterator IndexedSet<T,Metric>::lower_bound(const Key &key) const {
|
||||||
Node* t = root;
|
Node* t = root;
|
||||||
if (!t) return iterator();
|
if (!t) return iterator();
|
||||||
|
bool less;
|
||||||
while (true) {
|
while (true) {
|
||||||
Node *n = t->child[ t->data < key ];
|
less = t->data < key;
|
||||||
|
Node *n = t->child[less];
|
||||||
if (!n) break;
|
if (!n) break;
|
||||||
t = n;
|
t = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t->data < key)
|
if (less)
|
||||||
moveIterator<1>(t);
|
moveIterator<1>(t);
|
||||||
|
|
||||||
return iterator(t);
|
return iterator(t);
|
||||||
|
@ -1027,13 +1031,15 @@ template <class Key>
|
||||||
typename IndexedSet<T,Metric>::iterator IndexedSet<T,Metric>::upper_bound(const Key &key) const {
|
typename IndexedSet<T,Metric>::iterator IndexedSet<T,Metric>::upper_bound(const Key &key) const {
|
||||||
Node* t = root;
|
Node* t = root;
|
||||||
if (!t) return iterator();
|
if (!t) return iterator();
|
||||||
|
bool not_less;
|
||||||
while (true) {
|
while (true) {
|
||||||
Node *n = t->child[ !(key < t->data) ];
|
not_less = !(key < t->data);
|
||||||
|
Node *n = t->child[not_less];
|
||||||
if (!n) break;
|
if (!n) break;
|
||||||
t = n;
|
t = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(key < t->data))
|
if (not_less)
|
||||||
moveIterator<1>(t);
|
moveIterator<1>(t);
|
||||||
|
|
||||||
return iterator(t);
|
return iterator(t);
|
||||||
|
|
Loading…
Reference in New Issue