#include <base/config.h>
#include <base/exceptions.h>
-#include <set>
+#include <vector>
+#include <algorithm>
DEAL_II_NAMESPACE_OPEN
* A type that denotes the half
* open index range
* <code>[begin,end)</code>.
+ *
+ * The nth_index_in_set denotes
+ * the how many-th index within
+ * this IndexSet the first
+ * element of the current range
+ * is. This information is only
+ * accurate if
+ * IndexSet::compress() has been
+ * called after the last
+ * insertion.
*/
struct Range
{
unsigned int begin;
unsigned int end;
+ unsigned int nth_index_in_set;
+
Range (const unsigned int i1,
const unsigned int i2);
/**
* A set of contiguous ranges of
* indices that make up (part of)
- * this index set.
+ * this index set. This variable
+ * is always kept sorted.
*
* The variable is marked
* "mutable" so that it can be
* representation of this index
* set.
*/
- mutable std::set<Range> ranges;
+ mutable std::vector<Range> ranges;
/**
* True if compress() has been
if (begin != end)
{
- ranges.insert (Range(begin,end));
+ const Range new_range(begin,end);
+ ranges.insert (std::lower_bound (ranges.begin(),
+ ranges.end(),
+ new_range),
+ new_range);
is_compressed = false;
}
}
Assert (index < index_space_size,
ExcIndexRange (index, 0, index_space_size));
- ranges.insert (Range(index, index+1));
+ const Range new_range(index, index+1);
+ ranges.insert (std::lower_bound (ranges.begin(),
+ ranges.end(),
+ new_range),
+ new_range);
is_compressed = false;
}
// of the following ranges
// because otherwise p would be
// a different iterator
- std::set<Range>::const_iterator
+ std::vector<Range>::const_iterator
p = std::upper_bound (ranges.begin(),
ranges.end(),
Range (index, size()+1));
IndexSet::n_elements () const
{
// make sure we have
- // non-overlapping ranges and
- // individual indices
+ // non-overlapping ranges
compress ();
unsigned int s = 0;
- for (std::set<Range>::iterator range = ranges.begin();
+ for (std::vector<Range>::iterator range = ranges.begin();
range != ranges.end();
++range)
s += (range->end - range->begin);
// merged. since they are sorted by
// their first index, determining
// overlap isn't all that hard
- for (std::set<Range>::iterator
+ for (std::vector<Range>::iterator
i = ranges.begin();
- i != ranges.end();
- ++i)
+ i != ranges.end(); )
{
- std::set<Range>::const_iterator
+ std::vector<Range>::iterator
next = i;
++next;
if (can_merge == true)
{
- // delete the old
- // ranges and insert the
- // new range
- ranges.erase (i, next);
- ranges.insert (Range(first_index,
- last_index));
-
- // then set iterator to
- // the same position as
- // before. in the next
- // step, the loop is then
- // going to increase 'i'
- // by one. note that we
- // don't need to
- // reconsider the same
- // iterator for merging
- // with the next range
- // because we have made
- // sure we gobble up as
- // many of the following
- // ranges as possible
- i = ranges.lower_bound (Range(first_index,
- last_index));
+ // delete the old ranges
+ // and insert the new range
+ // in place of the previous
+ // one
+ *i = Range(first_index, last_index);
+ i = ranges.erase (i+1, next);
}
+ else
+ ++i;
}
+
+ // now compute indices within set
+ unsigned int next_index = 0;
+ for (std::vector<Range>::iterator
+ i = ranges.begin();
+ i != ranges.end();
+ ++i)
+ {
+ i->nth_index_in_set = next_index;
+ next_index += (i->end - i->begin);
+ }
is_compressed = true;
+
+ // check that next_index is
+ // correct. needs to be after the
+ // previous statement because we
+ // otherwise will get into an
+ // endless loop
+ Assert (next_index == n_elements(), ExcInternalError());
}