New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve IndexSet::add_indices() for sorted ranges with duplicates #15400
Milestone
Comments
Specifically, this is how the function looks like: template <typename ForwardIterator>
inline void
IndexSet::add_indices(const ForwardIterator &begin, const ForwardIterator &end)
{
if (begin == end)
return;
// identify ranges in the given iterator range by checking whether some
// indices happen to be consecutive. to avoid quadratic complexity when
// calling add_range many times (as add_range() going into the middle of an
// already existing range must shift entries around), we first collect a
// vector of ranges.
boost::container::small_vector<std::pair<size_type, size_type>, 200>
tmp_ranges;
bool ranges_are_sorted = true;
for (ForwardIterator p = begin; p != end;)
{
// Starting with the current iterator 'p', find an iterator
// 'q' so that the indices pointed to by the iterators in
// the range [p,q) are consecutive. These indices then form
// a range that is contiguous, and that can be added all
// at once.
const size_type begin_index = *p;
size_type end_index = begin_index + 1;
ForwardIterator q = p;
++q;
while ((q != end) && (static_cast<size_type>(*q) == end_index)) // This will fail for duplicate elements
{
++end_index;
++q;
}
// Add this range:
tmp_ranges.emplace_back(begin_index, end_index);
// Then move on to the next element in the input range.
// If the starting index of the next go-around of the for loop is less
// than the end index of the one just identified, then we will have at
// least one pair of ranges that are not sorted, and consequently the
// whole collection of ranges is not sorted.
p = q;
if (p != end && static_cast<size_type>(*p) < end_index)
ranges_are_sorted = false;
}
add_ranges_internal(tmp_ranges, ranges_are_sorted);
} |
No. I thought that merging sets of ranges in |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
#15366 illustrates how expensive it can be to insert indices one by one, but I think we can make the process even cheaper. The current best paradigm is to use the following idiom:
It seems unnecessary to call the
unique()/erase()
function combination in the middle:IndexSet::add_indices()
should simply be able to deal with duplicates, but I believe that currently it doesn't.The text was updated successfully, but these errors were encountered: