*/
mutable std::set<ContiguousRange, RangeComparison> contiguous_ranges;
- /**
- * A set of individual indices
- * that make up (part of) this
- * index set, together with the
- * contiguous ranges.
- *
- * The variable is marked
- * "mutable" so that it can be
- * changed by compress(), though
- * this of course doesn't change
- * anything about the external
- * representation of this index
- * set.
- */
- mutable std::set<unsigned int> individual_indices;
-
/**
* The overall size of the index
* range. Elements of this index
void
IndexSet::set_size (const unsigned int sz)
{
- Assert (contiguous_ranges.size() == 0
- &&
- individual_indices.size() == 0,
+ Assert (contiguous_ranges.size() == 0,
ExcMessage ("This function can only be called if the current "
"object does not yet contain any elements."));
index_space_size = sz;
Assert (index < index_space_size,
ExcIndexRange (index, 0, index_space_size));
- individual_indices.insert (index);
+ contiguous_ranges.insert (ContiguousRange(index, index+1));
}
bool
IndexSet::is_element (const unsigned int index) const
{
- // see if it's in the list of
- // individual indices
- if ((individual_indices.size() > 0) &&
- (individual_indices.find (index) != individual_indices.end()))
- return true;
-
+//TODO: since the list of ranges is sorted, we be faster here by doing a binary search
// if not, we need to walk the list
// of contiguous ranges:
if (contiguous_ranges.size() > 0)
IndexSet::is_contiguous () const
{
compress ();
- return ((individual_indices.size() == 0)
- &&
- (contiguous_ranges.size() <= 1));
+ return (contiguous_ranges.size() <= 1);
}
// individual indices
compress ();
- unsigned int s = individual_indices.size();
+ unsigned int s = 0;
for (std::set<ContiguousRange, RangeComparison>::iterator
range = contiguous_ranges.begin();
range != contiguous_ranges.end();
void
IndexSet::compress () const
{
- // first see if any of the
- // individual entries can be merged
- // to form contiguous ranges
- {
- std::set<unsigned int>::iterator p = individual_indices.begin();
- while (p != individual_indices.end())
- {
- unsigned int n = 0;
- std::set<unsigned int>::iterator q = p;
- ++q;
- while ((q != individual_indices.end())
- &&
- (*q == *p+n+1))
- {
- ++q;
- ++n;
- }
-
- if (n>0)
- {
- const unsigned int range_end = *q;
-
- // add the new range,
- // delete the elements of
- // the range from the set
- // of individual indices
- contiguous_ranges.insert (ContiguousRange(*p, *p+n+1));
- individual_indices.erase (p, q);
-
- // reset p to the element
- // past the last
- p = individual_indices.lower_bound (range_end);
- }
- else
- ++p;
- }
- }
-
-
- // next see if we can roll any of
- // the individual entries into the
- // contiguous ranges
- {
- std::set<ContiguousRange, RangeComparison>::iterator
- next_range = contiguous_ranges.begin();
- std::set<unsigned int>::iterator
- next_individual_index = individual_indices.begin();
-
- while ((next_range != contiguous_ranges.end())
- &&
- (next_individual_index != individual_indices.end()))
- {
- // if the next individual
- // index is beyond the upper
- // bound of the next range,
- // then we need to inspect
- // the next range
- if (*next_individual_index > next_range->second)
- {
- ++next_range;
- continue;
- }
-
- // if, on the other hand, the
- // next individual index is
- // below the lower bound of
- // the next range, then we
- // need to inspect the next
- // index
- if (*next_individual_index < next_range->first-1)
- {
- ++next_individual_index;
- continue;
- }
-
- // now we know that the
- // individual index is within
- // the next range, or
- // possibly one element
- // before, or one element
- // after. so they can be
- // merged. note that ranges
- // are half open, so in the
- // upper bound we have to
- // consider the next index+1
- ContiguousRange new_range (std::min (*next_individual_index,
- next_range->first),
- std::max (*next_individual_index+1,
- next_range->second));
-
- // erase old index and range,
- // and reset iterators
- //
- // note that the following
- // index can't possibly be
- // *next_index+1, since we
- // have merged contiguous
- // sets of individual indices
- // above. however, there may
- // be more individual indices
- // that lie within the
- // current range, so we'll
- // delete all of them
- const unsigned int old_index = *next_individual_index;
-
- {
- std::set<unsigned int>::iterator
- last_index = next_individual_index;
- ++last_index;
- while ((last_index != individual_indices.end())
- &&
- (*last_index < new_range.second))
- ++last_index;
-
- individual_indices.erase (next_individual_index,
- last_index);
- }
- next_individual_index = individual_indices.lower_bound (old_index);
-
- contiguous_ranges.erase (next_range);
- contiguous_ranges.insert (new_range);
-
- next_range = contiguous_ranges.lower_bound (new_range);
- }
- }
-
-
- // finally see if any of the
+ // see if any of the
// contiguous ranges can be
// merged. since they are sorted by
// their first index, determining
next = i;
++next;
- if (next != contiguous_ranges.end())
- if (next->first <= i->second)
- {
- const unsigned int first_index = i->first;
- const unsigned int last_index = next->second;
+ unsigned int first_index = i->first;
+ unsigned int last_index = i->second;
- // delete the two old
- // ranges and insert the
- // new range
- contiguous_ranges.erase (i, ++next);
- contiguous_ranges.insert (ContiguousRange(first_index,
- last_index));
+ // see if we can merge any of
+ // the following ranges
+ bool can_merge = false;
+ while (next != contiguous_ranges.end() &&
+ (next->first <= last_index))
+ {
+ last_index = next->second;
+ ++next;
+ can_merge = true;
+ }
- // then set iterator to
- // the same position as
- // before
- i = contiguous_ranges.lower_bound (ContiguousRange(first_index,
- last_index));
- }
+ if (can_merge == true)
+ {
+ // delete the old
+ // ranges and insert the
+ // new range
+ contiguous_ranges.erase (i, next);
+ contiguous_ranges.insert (ContiguousRange(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 = contiguous_ranges.lower_bound (ContiguousRange(first_index,
+ last_index));
+ }
}
}