Add NumericTrie::search_lesser.

This commit is contained in:
Harpreet Sangar 2023-05-29 17:32:48 +05:30
parent 06b46ab961
commit 64ec856097
2 changed files with 202 additions and 10 deletions

View File

@ -25,7 +25,7 @@ void NumericTrie::search_range(const int32_t& low, const bool& low_inclusive,
uint32_t* negative_ids = nullptr;
uint32_t negative_ids_length = 0;
if (!(low == -1 && !low_inclusive)) { // No need to search for (-1, ...
if (negative_trie != nullptr && !(low == -1 && !low_inclusive)) { // No need to search for (-1, ...
auto abs_low = std::abs(low);
// Since we store absolute values, search_lesser would yield result for >low from negative_trie.
negative_trie->search_lesser(low_inclusive ? abs_low : abs_low - 1, negative_ids, negative_ids_length);
@ -33,7 +33,7 @@ void NumericTrie::search_range(const int32_t& low, const bool& low_inclusive,
uint32_t* positive_ids = nullptr;
uint32_t positive_ids_length = 0;
if (!(high == 0 && !high_inclusive)) { // No need to search for ..., 0)
if (positive_trie != nullptr && !(high == 0 && !high_inclusive)) { // No need to search for ..., 0)
positive_trie->search_lesser(high_inclusive ? high : high - 1, positive_ids, positive_ids_length);
}
@ -51,14 +51,18 @@ void NumericTrie::search_range(const int32_t& low, const bool& low_inclusive,
void NumericTrie::search_greater(const int32_t& value, const bool& inclusive, uint32_t*& ids, uint32_t& ids_length) {
if ((value == 0 && inclusive) || (value == -1 && !inclusive)) { // [0, ∞), (-1, ∞)
positive_trie->get_all_ids(ids, ids_length);
if (positive_trie != nullptr) {
positive_trie->get_all_ids(ids, ids_length);
}
return;
}
if (value >= 0) {
uint32_t* positive_ids = nullptr;
uint32_t positive_ids_length = 0;
positive_trie->search_greater(inclusive ? value : value + 1, positive_ids, positive_ids_length);
if (positive_trie != nullptr) {
positive_trie->search_greater(inclusive ? value : value + 1, positive_ids, positive_ids_length);
}
ids_length = positive_ids_length;
ids = positive_ids;
@ -67,13 +71,17 @@ void NumericTrie::search_greater(const int32_t& value, const bool& inclusive, ui
uint32_t* negative_ids = nullptr;
uint32_t negative_ids_length = 0;
auto abs_low = std::abs(value);
// Since we store absolute values, search_lesser would yield result for >low from negative_trie.
negative_trie->search_lesser(inclusive ? abs_low : abs_low - 1, negative_ids, negative_ids_length);
// Since we store absolute values, search_lesser would yield result for >value from negative_trie.
if (negative_trie != nullptr) {
auto abs_low = std::abs(value);
negative_trie->search_lesser(inclusive ? abs_low : abs_low - 1, negative_ids, negative_ids_length);
}
uint32_t* positive_ids = nullptr;
uint32_t positive_ids_length = 0;
positive_trie->get_all_ids(positive_ids, positive_ids_length);
if (positive_trie != nullptr) {
positive_trie->get_all_ids(positive_ids, positive_ids_length);
}
ids_length = ArrayUtils::or_scalar(negative_ids, negative_ids_length, positive_ids, positive_ids_length, &ids);
@ -83,6 +91,48 @@ void NumericTrie::search_greater(const int32_t& value, const bool& inclusive, ui
}
}
void NumericTrie::search_lesser(const int32_t& value, const bool& inclusive, uint32_t*& ids, uint32_t& ids_length) {
if ((value == 0 && !inclusive) || (value == -1 && inclusive)) { // (-∞, 0), (-∞, -1]
if (negative_trie != nullptr) {
negative_trie->get_all_ids(ids, ids_length);
}
return;
}
if (value < 0) {
uint32_t* negative_ids = nullptr;
uint32_t negative_ids_length = 0;
// Since we store absolute values, search_greater would yield result for <value from negative_trie.
if (negative_trie != nullptr) {
auto abs_low = std::abs(value);
negative_trie->search_greater(inclusive ? abs_low : abs_low + 1, negative_ids, negative_ids_length);
}
ids_length = negative_ids_length;
ids = negative_ids;
} else {
// Have to combine the results of <value from positive_trie and all the ids in negative_trie
uint32_t* positive_ids = nullptr;
uint32_t positive_ids_length = 0;
if (positive_trie != nullptr) {
positive_trie->search_lesser(inclusive ? value : value - 1, positive_ids, positive_ids_length);
}
uint32_t* negative_ids = nullptr;
uint32_t negative_ids_length = 0;
if (negative_trie != nullptr) {
negative_trie->get_all_ids(negative_ids, negative_ids_length);
}
ids_length = ArrayUtils::or_scalar(positive_ids, positive_ids_length, negative_ids, negative_ids_length, &ids);
delete [] negative_ids;
delete [] positive_ids;
return;
}
}
void NumericTrieNode::insert(const int32_t& value, const uint32_t& seq_id) {
char level = 0;
return insert(value, seq_id, level);

View File

@ -23,7 +23,7 @@ TEST_F(NumericRangeTrieTest, SearchRange) {
{32768, 91}
};
for (auto const pair: pairs) {
for (auto const& pair: pairs) {
trie->insert(pair.first, pair.second);
}
@ -124,7 +124,7 @@ TEST_F(NumericRangeTrieTest, SearchGreater) {
{32768, 91}
};
for (auto const pair: pairs) {
for (auto const& pair: pairs) {
trie->insert(pair.first, pair.second);
}
@ -193,4 +193,146 @@ TEST_F(NumericRangeTrieTest, SearchGreater) {
ids_guard.reset(ids);
ASSERT_EQ(0, ids_length);
trie->search_greater(-100000, false, ids, ids_length);
ids_guard.reset(ids);
ASSERT_EQ(8, ids_length);
for (uint32_t i = 0; i < pairs.size(); i++) {
ASSERT_EQ(pairs[i].second, ids[i]);
}
}
TEST_F(NumericRangeTrieTest, SearchLesser) {
auto trie = new NumericTrie();
std::unique_ptr<NumericTrie> trie_guard(trie);
std::vector<std::pair<int32_t, uint32_t>> pairs = {
{-32768, 8},
{-24576, 32},
{-16384, 35},
{-8192, 43},
{8192, 49},
{16384, 56},
{24576, 58},
{32768, 91}
};
for (auto const& pair: pairs) {
trie->insert(pair.first, pair.second);
}
uint32_t* ids = nullptr;
uint32_t ids_length = 0;
trie->search_lesser(0, true, ids, ids_length);
std::unique_ptr<uint32_t[]> ids_guard(ids);
ASSERT_EQ(4, ids_length);
for (uint32_t i = 4, j = 0; i < ids_length; i++, j++) {
ASSERT_EQ(pairs[i].second, ids[j]);
}
trie->search_lesser(0, false, ids, ids_length);
ids_guard.reset(ids);
ASSERT_EQ(4, ids_length);
for (uint32_t i = 0; i < ids_length; i++) {
ASSERT_EQ(pairs[i].second, ids[i]);
}
trie->search_lesser(-1, true, ids, ids_length);
ids_guard.reset(ids);
ASSERT_EQ(4, ids_length);
for (uint32_t i = 0; i < ids_length; i++) {
ASSERT_EQ(pairs[i].second, ids[i]);
}
trie->search_lesser(-16384, true, ids, ids_length);
ids_guard.reset(ids);
ASSERT_EQ(3, ids_length);
for (uint32_t i = 0; i < ids_length; i++) {
ASSERT_EQ(pairs[i].second, ids[i]);
}
trie->search_lesser(-16384, false, ids, ids_length);
ids_guard.reset(ids);
ASSERT_EQ(2, ids_length);
for (uint32_t i = 0; i < ids_length; i++) {
ASSERT_EQ(pairs[i].second, ids[i]);
}
trie->search_lesser(8192, true, ids, ids_length);
ids_guard.reset(ids);
ASSERT_EQ(5, ids_length);
for (uint32_t i = 0; i < ids_length; i++) {
ASSERT_EQ(pairs[i].second, ids[i]);
}
trie->search_lesser(8192, false, ids, ids_length);
ids_guard.reset(ids);
ASSERT_EQ(4, ids_length);
for (uint32_t i = 0; i < ids_length; i++) {
ASSERT_EQ(pairs[i].second, ids[i]);
}
trie->search_lesser(-100000, false, ids, ids_length);
ids_guard.reset(ids);
ASSERT_EQ(0, ids_length);
trie->search_lesser(100000, true, ids, ids_length);
ids_guard.reset(ids);
ASSERT_EQ(8, ids_length);
for (uint32_t i = 0; i < ids_length; i++) {
ASSERT_EQ(pairs[i].second, ids[i]);
}
}
TEST_F(NumericRangeTrieTest, Validation) {
auto trie = new NumericTrie();
std::unique_ptr<NumericTrie> trie_guard(trie);
uint32_t* ids = nullptr;
uint32_t ids_length = 0;
trie->search_range(-32768, true, 32768, true, ids, ids_length);
std::unique_ptr<uint32_t[]> ids_guard(ids);
ASSERT_EQ(0, ids_length);
trie->search_greater(0, true, ids, ids_length);
ids_guard.reset(ids);
ASSERT_EQ(0, ids_length);
trie->search_greater(15, true, ids, ids_length);
ids_guard.reset(ids);
ASSERT_EQ(0, ids_length);
trie->search_greater(-15, true, ids, ids_length);
ids_guard.reset(ids);
ASSERT_EQ(0, ids_length);
trie->search_lesser(0, false, ids, ids_length);
ids_guard.reset(ids);
ASSERT_EQ(0, ids_length);
trie->search_lesser(-15, true, ids, ids_length);
ids_guard.reset(ids);
ASSERT_EQ(0, ids_length);
trie->search_lesser(15, true, ids, ids_length);
ids_guard.reset(ids);
ASSERT_EQ(0, ids_length);
}