Skip to content

Commit c4be633

Browse files
romangemkaruza
andauthored
chore(bptree): introduce ability comparing keys to non-key types (#4805)
Not yet used by sorted_map code, so no function changes. This will allow to clean up a hackish comparator code in sorted_map.cc Co-authored-by: mkaruza <[email protected]>
1 parent 555d6b5 commit c4be633

File tree

3 files changed

+34
-26
lines changed

3 files changed

+34
-26
lines changed

src/core/bptree_set.h

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ template <typename T> struct DefaultCompareTo {
2121

2222
template <typename T> struct BPTreePolicy {
2323
using KeyT = T;
24+
25+
// The three way comparator that should accept a query ( or key) on the left, and the key
26+
// on the right.
2427
using KeyCompareTo = DefaultCompareTo<T>;
2528
};
2629

@@ -89,16 +92,15 @@ template <typename T, typename Policy = BPTreePolicy<T>> class BPTree {
8992
/// Should return false to stop iteration.
9093
bool IterateReverse(uint32_t rank_start, uint32_t rank_end, std::function<bool(KeyT)> cb) const;
9194

92-
/// @brief Returns the path to the first item in the tree that is greater or equal to key.
95+
/// @brief Returns the path to the first item in the tree for which comp(q, key) >= 0.
9396
/// @param item
9497
/// @return the path if such item exists, empty path otherwise.
95-
/// @todo: to wrap the result into iterator to avoid the leakage of internal data structures.
96-
detail::BPTreePath<T> GEQ(KeyT key) const;
98+
template <typename Q> BPTreePath GEQ(Q&& query) const;
9799

98-
/// @brief Returns the path to the largest item in the tree that is less or equal to key.
100+
/// @brief Returns the path to the largest item in the tree such that comp(q, key) <= 0.
99101
/// @param key
100102
/// @return the path if such item exists, empty path otherwise.
101-
detail::BPTreePath<T> LEQ(KeyT key) const;
103+
template <typename Q> BPTreePath LEQ(Q&& query) const;
102104

103105
/// @brief Deletes the element pointed by path.
104106
/// @param path
@@ -122,10 +124,10 @@ template <typename T, typename Policy = BPTreePolicy<T>> class BPTree {
122124
void IncreaseSubtreeCounts(const BPTreePath& path, unsigned depth, int32_t delta);
123125

124126
// Charts the path towards key. Returns true if key is found.
125-
// In that case path->Last().first->Key(path->Last().second) == key.
127+
// In that case comp(q, path->Last().first->Key(path->Last().second)) == 0.
126128
// Fills the tree path not including the key itself. In case key was not found,
127129
// returns the path to the item that is greater than the key.
128-
bool Locate(KeyT key, BPTreePath* path) const;
130+
template <typename Q> bool Locate(Q&& q, BPTreePath* path) const;
129131

130132
// Sets the tree path to item at specified rank. Rank is 0-based and must be less than Size().
131133
// returns the index of the key in the last node of the path.
@@ -243,12 +245,15 @@ std::optional<uint32_t> BPTree<T, Policy>::GetRank(KeyT item, bool reverse) cons
243245
}
244246

245247
template <typename T, typename Policy>
246-
bool BPTree<T, Policy>::Locate(KeyT key, BPTreePath* path) const {
248+
template <typename Q>
249+
bool BPTree<T, Policy>::Locate(Q&& q, BPTreePath* path) const {
247250
assert(root_);
248251
BPTreeNode* node = root_;
249252
typename Policy::KeyCompareTo cmp;
253+
auto cmp_cb = [&](const KeyT& key) { return cmp(q, key); };
254+
250255
while (true) {
251-
typename BPTreeNode::SearchResult res = node->BSearch(key, cmp);
256+
typename BPTreeNode::SearchResult res = node->BSearch(cmp_cb);
252257
path->Push(node, res.index);
253258
if (res.found) {
254259
return true;
@@ -486,10 +491,11 @@ void BPTree<T, Policy>::ToRank(uint32_t rank, BPTreePath* path) const {
486491
}
487492

488493
template <typename T, typename Policy>
489-
detail::BPTreePath<T> BPTree<T, Policy>::GEQ(KeyT item) const {
494+
template <typename Q>
495+
auto BPTree<T, Policy>::GEQ(Q&& query) const -> BPTreePath {
490496
BPTreePath path;
491497

492-
bool res = Locate(item, &path);
498+
bool res = Locate(query, &path);
493499

494500
// if we did not find the item and the path does not lead to any key in the node,
495501
// adjust the path to point to the next key in the tree.
@@ -502,9 +508,10 @@ detail::BPTreePath<T> BPTree<T, Policy>::GEQ(KeyT item) const {
502508
}
503509

504510
template <typename T, typename Policy>
505-
detail::BPTreePath<T> BPTree<T, Policy>::LEQ(KeyT item) const {
511+
template <typename Q>
512+
auto BPTree<T, Policy>::LEQ(Q&& query) const -> BPTreePath {
506513
BPTreePath path;
507-
bool res = Locate(item, &path);
514+
bool res = Locate(query, &path);
508515

509516
if (!res) { // fix the result in case the path leads to key greater than item.
510517
path.Prev();

src/core/detail/bptree_internal.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,9 @@ template <typename T> class BPTreeNode {
143143
};
144144

145145
// Searches for key in the node using binary search.
146-
// Returns SearchResult with index of the key if found.
147-
template <typename Comp> SearchResult BSearch(KeyT key, Comp&& comp) const;
146+
// Returns SearchResult with index of the smallest key for which comp(key) >=0.
147+
// comp: is a three way comparator.
148+
template <typename Comp> SearchResult BSearch(Comp&& comp) const;
148149

149150
void Split(BPTreeNode* right, KeyT* median);
150151

@@ -367,13 +368,13 @@ template <typename T> class BPTreePath {
367368
// if all items are smaller than key, returns num_items_.
368369
template <typename T>
369370
template <typename Comp>
370-
auto BPTreeNode<T>::BSearch(KeyT key, Comp&& cmp_op) const -> SearchResult {
371+
auto BPTreeNode<T>::BSearch(Comp&& cmp_op) const -> SearchResult {
371372
uint16_t lo = 0;
372373
uint16_t hi = num_items_;
373374
assert(hi > 0);
374375

375376
// optimization: check the last item first.
376-
int cmp_res = cmp_op(key, Key(hi - 1));
377+
int cmp_res = cmp_op(Key(hi - 1));
377378
if (cmp_res >= 0) {
378379
return cmp_res > 0 ? SearchResult{.index = hi, .found = false}
379380
: SearchResult{.index = uint16_t(hi - 1), .found = true};
@@ -388,7 +389,7 @@ auto BPTreeNode<T>::BSearch(KeyT key, Comp&& cmp_op) const -> SearchResult {
388389

389390
KeyT item = Key(mid);
390391

391-
int cmp_res = cmp_op(key, item);
392+
int cmp_res = cmp_op(item);
392393
if (cmp_res == 0) {
393394
return SearchResult{.index = mid, .found = true};
394395
}

src/core/sorted_map.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,6 @@ class SortedMap {
4343
SortedMap(const SortedMap&) = delete;
4444
SortedMap& operator=(const SortedMap&) = delete;
4545

46-
struct ScoreSdsPolicy {
47-
using KeyT = ScoreSds;
48-
49-
struct KeyCompareTo {
50-
int operator()(KeyT a, KeyT b) const;
51-
};
52-
};
53-
5446
bool Reserve(size_t sz);
5547
int AddElem(double score, std::string_view ele, int in_flags, int* out_flags, double* newscore);
5648

@@ -97,6 +89,14 @@ class SortedMap {
9789
bool DefragIfNeeded(float ratio);
9890

9991
private:
92+
struct ScoreSdsPolicy {
93+
using KeyT = ScoreSds;
94+
95+
struct KeyCompareTo {
96+
int operator()(KeyT a, KeyT b) const;
97+
};
98+
};
99+
100100
using ScoreTree = BPTree<ScoreSds, ScoreSdsPolicy>;
101101

102102
// hash map from fields to scores.

0 commit comments

Comments
 (0)