reduce the number of calls to operator< made by lower_bound and upper_bound #2877

This commit is contained in:
Russell Sears 2020-03-30 16:13:37 -07:00
parent ae2d9744cb
commit 99a805517e
2 changed files with 44 additions and 15 deletions

View File

@ -114,30 +114,53 @@ 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>
void move(Version at, std::vector<const PTree<T>*>& f){ void move(Version at, std::vector<const PTree<T>*>& f){
ASSERT(f.size()); ASSERT(f.size());

View File

@ -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);