From ec55c88ed0aca80c1fce9ffa80cda6ee723297e7 Mon Sep 17 00:00:00 2001 From: Timo Heister Date: Sat, 11 Jul 2015 17:02:08 -0400 Subject: [PATCH] new IndexSet iterators Add ElementIterator and IntervalIterator to iterate over the contents of IndexSet. --- doc/news/changes.h | 5 + include/deal.II/base/index_set.h | 744 +++++++++++++++++++++++-- source/base/index_set.cc | 33 +- tests/base/index_set_iterate_01.cc | 166 ++++++ tests/base/index_set_iterate_01.output | 11 + 5 files changed, 903 insertions(+), 56 deletions(-) create mode 100644 tests/base/index_set_iterate_01.cc create mode 100644 tests/base/index_set_iterate_01.output diff --git a/doc/news/changes.h b/doc/news/changes.h index b7c586e92d..67e6a9058b 100644 --- a/doc/news/changes.h +++ b/doc/news/changes.h @@ -50,6 +50,11 @@ inconvenience this causes.
    +
  1. New: IndexSet now implements iterators. +
    + (Timo Heister, 2015/07/12) +
  2. +
diff --git a/include/deal.II/base/index_set.h b/include/deal.II/base/index_set.h index b8dd4bd236..ec16a1ad0c 100644 --- a/include/deal.II/base/index_set.h +++ b/include/deal.II/base/index_set.h @@ -50,6 +50,11 @@ DEAL_II_NAMESPACE_OPEN * the size of the index space $[0,\text{size})$ of which objects of this * class are a subset. * + * There are two ways to iterate over the IndexSets: First, begin() and end() + * allow iteration over individual indices in the set. Second, begin_interval() + * and end_interval() allow iteration over the half-open ranges as described + * above. + * * The data structures used in this class along with a rationale can be found * in the * @ref distributed_paper "Distributed Computing paper". @@ -59,6 +64,16 @@ DEAL_II_NAMESPACE_OPEN class IndexSet { public: + // forward declarations: + class ElementIterator; + class IntervalIterator; + + /** + * @p size_type is the type used for storing the size and the individual + * entries in the IndexSet. + */ + typedef types::global_dof_index size_type; + /** * One can see an IndexSet as a container of size size(), where the elements * of the containers are bool values that are either false or true, @@ -78,6 +93,7 @@ public: */ typedef signed int value_type; + /** * Default constructor. */ @@ -86,7 +102,7 @@ public: /** * Constructor that also sets the overall size of the index range. */ - explicit IndexSet (const types::global_dof_index size); + explicit IndexSet (const size_type size); /** * Remove all indices from this index set. The index set retains its size, @@ -100,7 +116,7 @@ public: * This function can only be called if the index set does not yet contain * any elements. This can be achieved by calling clear(), for example. */ - void set_size (const types::global_dof_index size); + void set_size (const size_type size); /** * Return the size of the index space of which this index set is a subset @@ -109,19 +125,19 @@ public: * Note that the result is not equal to the number of indices within this * set. The latter information is returned by n_elements(). */ - types::global_dof_index size () const; + size_type size () const; /** * Add the half-open range $[\text{begin},\text{end})$ to the set of indices * represented by this class. */ - void add_range (const types::global_dof_index begin, - const types::global_dof_index end); + void add_range (const size_type begin, + const size_type end); /** * Add an individual index to the set of indices. */ - void add_index (const types::global_dof_index index); + void add_index (const size_type index); /** * Add a whole set of indices described by dereferencing every element of @@ -152,7 +168,7 @@ public: /** * Return whether the specified index is an element of the index set. */ - bool is_element (const types::global_dof_index index) const; + bool is_element (const size_type index) const; /** * Return whether the index set stored by this object defines a contiguous @@ -163,14 +179,14 @@ public: /** * Return the number of elements stored in this index set. */ - types::global_dof_index n_elements () const; + size_type n_elements () const; /** * Return the global index of the local index with number @p local_index * stored in this index set. @p local_index obviously needs to be less than * n_elements(). */ - types::global_dof_index nth_index_in_set (const unsigned int local_index) const; + size_type nth_index_in_set (const unsigned int local_index) const; /** * Return the how-manyth element of this set (counted in ascending order) @p @@ -178,7 +194,7 @@ public: * function throws an exception if the index @p global_index is not actually * a member of this index set, i.e. if is_element(global_index) is false. */ - types::global_dof_index index_within_set (const types::global_dof_index global_index) const; + size_type index_within_set (const size_type global_index) const; /** * Each index set can be represented as the union of a number of contiguous @@ -231,8 +247,8 @@ public: * interval [begin, end) is a window through which we see * the set represented by the current object. */ - IndexSet get_view (const types::global_dof_index begin, - const types::global_dof_index end) const; + IndexSet get_view (const size_type begin, + const size_type end) const; /** @@ -246,7 +262,7 @@ public: /** * Fills the given vector with all indices contained in this IndexSet. */ - void fill_index_vector(std::vector &indices) const; + void fill_index_vector(std::vector &indices) const; /** * Fill the given vector with either zero or one elements, providing a @@ -334,7 +350,7 @@ public: */ std::size_t memory_consumption () const; - DeclException1 (ExcIndexNotPresent, types::global_dof_index, + DeclException1 (ExcIndexNotPresent, size_type, << "The global index " << arg1 << " is not an element of this set."); @@ -345,6 +361,288 @@ public: template void serialize (Archive &ar, const unsigned int version); + + /** + * @name Iterators + * @{ + */ + + /** + * Dereferencing an IntervalIterator will return a reference to an object of + * this type. It allows access to a contiguous interval $[a,b[$ (also called + * a range) of the IndexSet being iterated over. + */ + class IntervalAccessor + { + public: + /** + * Construct a valid accessor given an Indexset and the index @p range_idx + * of the range to point to. + */ + IntervalAccessor(const IndexSet *idxset, const size_type range_idx); + + /** + * Construct an invalid accessor for the Indexset. + */ + explicit IntervalAccessor(const IndexSet *idxset); + + /** + * Number of elements in this interval. + */ + size_type n_elements() const; + + /** + * If true, we are pointing at a valid interval in the IndexSet. + */ + bool is_valid() const; + + /** + * Return an iterator pointing at the first index in this interval. + */ + ElementIterator begin() const; + + /** + * Return an iterator pointing directly after the last index in this + * interval. + */ + ElementIterator end() const; + + /** + * Return the index of the last index in this interval. + */ + size_type last() const; + + private: + /** + * Private copy constructor. + */ + IntervalAccessor(const IntervalAccessor &other); + /** + * Private copy operator. + */ + IntervalAccessor &operator = (const IntervalAccessor &other); + + /** + * Test for equality, used by IntervalIterator. + */ + bool operator == (const IntervalAccessor &other) const; + /** + * Smaller-than operator, used by IntervalIterator. + */ + bool operator < (const IntervalAccessor &other) const; + /** + * Advance this accessor to point to the next interval in the @p + * index_set. + */ + void advance (); + /** + * Reference to the IndexSet. + */ + const IndexSet *index_set; + + /** + * Index into index_set.ranges[]. Set to numbers::invalid_dof_index if + * invalid or the end iterator. + */ + size_type range_idx; + + friend class IntervalIterator; + }; + + /** + * Class that represents an iterator pointing to a contiguous interval + * $[a,b[$ as returned by IndexSet::begin_interval(). + */ + class IntervalIterator + { + public: + /** + * Construct a valid iterator pointing to the interval with index @p + * range_idx. + */ + IntervalIterator(const IndexSet *idxset, const size_type range_idx); + + /** + * Construct an invalid iterator (used as end()). + */ + explicit IntervalIterator(const IndexSet *idxset); + + /** + * Construct an empty iterator. + */ + IntervalIterator(); + + /** + * Copy constructor from @p other iterator. + */ + IntervalIterator(const IntervalIterator &other); + + /** + * Assignment of another iterator. + */ + IntervalIterator &operator = (const IntervalIterator &other); + + /** + * Prefix increment. + */ + IntervalIterator &operator++ (); + + /** + * Postfix increment. + */ + IntervalIterator operator++ (int); + + /** + * Dereferencing operator, returns an IntervalAccessor. + */ + const IntervalAccessor &operator* () const; + + /** + * Dereferencing operator, returns a pointer to an IntervalAccessor. + */ + const IntervalAccessor *operator-> () const; + + /** + * Comparison. + */ + bool operator == (const IntervalIterator &) const; + + /** + * Inverse of ==. + */ + bool operator != (const IntervalIterator &) const; + + /** + * Comparison operator. + */ + bool operator < (const IntervalIterator &) const; + + /** + * Return the distance between the current iterator and the argument. The + * distance is given by how many times one has to apply operator++ to the + * current iterator to get the argument (for a positive return value), or + * operator-- (for a negative return value). + */ + int operator - (const IntervalIterator &p) const; + + private: + /** + * Accessor that contains what IndexSet and interval we are pointing at. + */ + IntervalAccessor accessor; + }; + + /** + * Class that represents an iterator pointing to a single element in the + * IndexSet as returned by IndexSet::begin(). + */ + class ElementIterator + { + public: + /** + * Construct an iterator pointing to the global index @p index in the + * interval @p range_idx + */ + ElementIterator(const IndexSet *idxset, const size_type range_idx, const size_type index); + + /** + * Construct an iterator pointing to the end of the IndexSet. + */ + explicit ElementIterator(const IndexSet *idxset); + + /** + * Dereferencing operator. The returned value is the index of the element + * inside the IndexSet. + */ + size_type operator* () const; + + /** + * Does this iterator point to an existing element? + */ + bool is_valid () const; + + /** + * Prefix increment. + */ + ElementIterator &operator++ (); + + /** + * Postfix increment. + */ + ElementIterator operator++ (int); + + /** + * Comparison. + */ + bool operator == (const ElementIterator &) const; + + /** + * Inverse of ==. + */ + bool operator != (const ElementIterator &) const; + + /** + * Comparison operator. + */ + bool operator < (const ElementIterator &) const; + + /** + * Return the distance between the current iterator and the argument. In + * the expression it_left-it_right the distance is given by + * how many times one has to apply operator++ to the right operand @p + * it_right to get the left operand @p it_left (for a positive return + * value), or to @p it_left to get the @p it_right (for a negative return + * value). + */ + std::ptrdiff_t operator - (const ElementIterator &p) const; + + private: + /** + * Advance iterator by one. + */ + void advance (); + + /** + * The parent IndexSet. + */ + const IndexSet *index_set; + /** + * Index into index_set.ranges. + */ + size_type range_idx; + /** + * The global index this iterator is pointing at. + */ + size_type idx; + }; + + /** + * Return an iterator that points at the first index that is contained in + * this IndexSet. + */ + ElementIterator begin() const; + + /** + * Return an iterator that points one after the last index that is contained + * in this IndexSet. + */ + ElementIterator end() const; + + /** + * Return an Iterator that points at the first interval of this IndexSet. + */ + IntervalIterator begin_intervals() const; + + /** + * Return an Iterator that points one after the last interval of this + * IndexSet. + */ + IntervalIterator end_intervals() const; + + /** + * @} + */ + private: /** * A type that denotes the half open index range [begin,end). @@ -356,10 +654,10 @@ private: */ struct Range { - types::global_dof_index begin; - types::global_dof_index end; + size_type begin; + size_type end; - types::global_dof_index nth_index_in_set; + size_type nth_index_in_set; /** * Default constructor. Since there is no useful choice for a default @@ -378,8 +676,8 @@ private: * @param i2 First index greater than the last index of the indicated * range. */ - Range (const types::global_dof_index i1, - const types::global_dof_index i2); + Range (const size_type i1, + const size_type i2); friend inline bool operator< (const Range &range_1, @@ -450,7 +748,7 @@ private: * The overall size of the index range. Elements of this index set have to * have a smaller number than this value. */ - types::global_dof_index index_space_size; + size_type index_space_size; /** * This integer caches the index of the largest range in @p ranges. This @@ -461,7 +759,7 @@ private: * locally owned range), whereas there are only a few other elements * (ghosts). */ - mutable types::global_dof_index largest_range; + mutable size_type largest_range; /** * Actually perform the compress() operation. @@ -497,6 +795,333 @@ IndexSet complete_index_set (const unsigned int N) /* ------------------ inline functions ------------------ */ + +/* IntervalAccessor */ + +inline +IndexSet::IntervalAccessor::IntervalAccessor(const IndexSet *idxset, const IndexSet::size_type range_idx) + : index_set(idxset), range_idx(range_idx) +{ + Assert(range_idx < idxset->n_intervals(), ExcInternalError("Invalid range index")); +} + +inline +IndexSet::IntervalAccessor::IntervalAccessor(const IndexSet *idxset) + : index_set(idxset), range_idx(numbers::invalid_dof_index) +{} + +inline +IndexSet::size_type IndexSet::IntervalAccessor::n_elements() const +{ + Assert(is_valid(), ExcMessage("invalid iterator")); + return index_set->ranges[range_idx].end - index_set->ranges[range_idx].begin; +} + +inline +bool IndexSet::IntervalAccessor::is_valid() const +{ + return index_set != NULL && range_idx < index_set->n_intervals(); +} + +inline +IndexSet::ElementIterator IndexSet::IntervalAccessor::begin() const +{ + Assert(is_valid(), ExcMessage("invalid iterator")); + return IndexSet::ElementIterator(index_set, range_idx, index_set->ranges[range_idx].begin); +} + +inline +IndexSet::ElementIterator IndexSet::IntervalAccessor::end() const +{ + Assert(is_valid(), ExcMessage("invalid iterator")); + + // point to first index in next interval unless we are the last interval. + if (range_idx < index_set->ranges.size()-1) + return IndexSet::ElementIterator(index_set, range_idx+1, index_set->ranges[range_idx+1].begin); + else + return index_set->end(); +} + +inline +IndexSet::size_type +IndexSet::IntervalAccessor::last() const +{ + Assert(is_valid(), ExcMessage("invalid iterator")); + + return index_set->ranges[range_idx].end-1; +} + +inline +IndexSet::IntervalAccessor::IntervalAccessor(const IndexSet::IntervalAccessor &other) + : index_set (other.index_set), range_idx(other.range_idx) +{ + Assert( range_idx == numbers::invalid_dof_index || is_valid(), ExcMessage("invalid iterator")); +} + +inline +IndexSet::IntervalAccessor & +IndexSet::IntervalAccessor::operator = (const IndexSet::IntervalAccessor &other) +{ + index_set = other.index_set; + range_idx = other.range_idx; + Assert( range_idx == numbers::invalid_dof_index || is_valid(), ExcMessage("invalid iterator")); + return *this; +} + +inline +bool IndexSet::IntervalAccessor::operator == (const IndexSet::IntervalAccessor &other) const +{ + Assert (index_set == other.index_set, ExcMessage("Can not compare accessors pointing to different IndexSets")); + return range_idx == other.range_idx; +} + +inline +bool IndexSet::IntervalAccessor::operator < (const IndexSet::IntervalAccessor &other) const +{ + Assert (index_set == other.index_set, ExcMessage("Can not compare accessors pointing to different IndexSets")); + return range_idx < other.range_idx; +} + +inline +void IndexSet::IntervalAccessor::advance () +{ + Assert(is_valid(), ExcMessage("Impossible to advance an IndexSet::IntervalIterator that is invalid")); + ++range_idx; + + // set ourselves to invalid if we walk off the end + if (range_idx>=index_set->ranges.size()) + range_idx = numbers::invalid_dof_index; +} + +/* IntervalIterator */ + +inline +IndexSet::IntervalIterator::IntervalIterator(const IndexSet *idxset, const IndexSet::size_type range_idx) + : accessor(idxset, range_idx) +{} + +inline +IndexSet::IntervalIterator::IntervalIterator() + : accessor(NULL) +{} + +inline +IndexSet::IntervalIterator::IntervalIterator(const IndexSet *idxset) + : accessor(idxset) +{} + +inline +IndexSet::IntervalIterator::IntervalIterator(const IndexSet::IntervalIterator &other) + : accessor(other.accessor) +{} + +inline +IndexSet::IntervalIterator & +IndexSet::IntervalIterator::operator = (const IntervalIterator &other) +{ + accessor = other.accessor; + return *this; +} + + +inline +IndexSet::IntervalIterator & +IndexSet::IntervalIterator::operator++ () +{ + accessor.advance(); + return *this; +} + +inline +IndexSet::IntervalIterator +IndexSet::IntervalIterator::operator++ (int) +{ + const IndexSet::IntervalIterator iter = *this; + accessor.advance (); + return iter; +} + +inline +const IndexSet::IntervalAccessor & +IndexSet::IntervalIterator::operator* () const +{ + return accessor; +} + +inline +const IndexSet::IntervalAccessor * +IndexSet::IntervalIterator::operator-> () const +{ + return &accessor; +} + +inline +bool IndexSet::IntervalIterator::operator == (const IndexSet::IntervalIterator &other) const +{ + return accessor == other.accessor; +} + +inline +bool IndexSet::IntervalIterator::operator != (const IndexSet::IntervalIterator &other) const +{ + return !(*this == other); +} + +inline +bool IndexSet::IntervalIterator::operator < (const IndexSet::IntervalIterator &other) const +{ + return accessor < other.accessor; +} + +inline +int IndexSet::IntervalIterator::operator - (const IndexSet::IntervalIterator &other) const +{ + Assert (accessor.index_set == other.accessor.index_set, ExcMessage("Can not compare iterators belonging to different IndexSets")); + + const size_type lhs = (accessor.range_idx == numbers::invalid_dof_index) ? accessor.index_set->ranges.size() : accessor.range_idx; + const size_type rhs = (other.accessor.range_idx == numbers::invalid_dof_index) ? accessor.index_set->ranges.size() : other.accessor.range_idx; + + if (lhs > rhs) + return static_cast(lhs - rhs); + else + return -static_cast(rhs - lhs); +} + + +/* ElementIterator */ + +inline +bool IndexSet::ElementIterator::is_valid() const +{ + Assert( + (range_idx == numbers::invalid_dof_index && idx == numbers::invalid_dof_index) + || + (range_idx < index_set->ranges.size() && idxranges[range_idx].end) + , ExcInternalError("Invalid ElementIterator state.")); + + return range_idx < index_set->ranges.size() && idxranges[range_idx].end; +} + +inline +IndexSet::ElementIterator::ElementIterator(const IndexSet *idxset, const IndexSet::size_type range_idx, const IndexSet::size_type index) + : index_set(idxset), range_idx(range_idx), idx(index) +{ + Assert(range_idx < index_set->ranges.size(), + ExcMessage("Invalid range index for IndexSet::ElementIterator constructor.")); + Assert(idx >= index_set->ranges[range_idx].begin + && + idx < index_set->ranges[range_idx].end, + ExcInternalError("Invalid index argument for IndexSet::ElementIterator constructor.")); +} + +inline +IndexSet::ElementIterator::ElementIterator(const IndexSet *idxset) + : index_set(idxset), range_idx(numbers::invalid_dof_index), idx(numbers::invalid_dof_index) +{} + +inline +IndexSet::size_type +IndexSet::ElementIterator::operator* () const +{ + Assert(is_valid(), ExcMessage("Impossible to dereference an IndexSet::ElementIterator that is invalid")); + return idx; +} + +inline +bool IndexSet::ElementIterator::operator == (const IndexSet::ElementIterator &other) const +{ + Assert (index_set == other.index_set, ExcMessage("Can not compare iterators belonging to different IndexSets")); + return range_idx == other.range_idx && idx==other.idx; +} + +inline +void IndexSet::ElementIterator::advance () +{ + Assert(is_valid(), ExcMessage("Impossible to advance an IndexSet::ElementIterator that is invalid")); + if (idx < index_set->ranges[range_idx].end) + ++idx; + // end of this range? + if (idx == index_set->ranges[range_idx].end) + { + // point to first element in next interval if possible + if (range_idx < index_set->ranges.size()-1) + { + ++range_idx; + idx = index_set->ranges[range_idx].begin; + } + else + { + // we just fell off the end, set to invalid: + range_idx = numbers::invalid_dof_index; + idx = numbers::invalid_dof_index; + } + } +} + +inline +IndexSet::ElementIterator & +IndexSet::ElementIterator::operator++ () +{ + advance(); + return *this; +} + +inline +IndexSet::ElementIterator +IndexSet::ElementIterator::operator++ (int) +{ + IndexSet::ElementIterator it = *this; + advance(); + return it; +} + +inline +bool IndexSet::ElementIterator::operator != (const IndexSet::ElementIterator &other) const +{ + return !(*this == other); +} + +inline +bool IndexSet::ElementIterator::operator < (const IndexSet::ElementIterator &other) const +{ + Assert (index_set == other.index_set, ExcMessage("Can not compare iterators belonging to different IndexSets")); + return range_idx < other.range_idx || (range_idx == other.range_idx && idxranges[range_idx].end-idx; + + // now walk in steps of ranges (need to start one behind our current one): + for (size_type range=range_idx+1; rangeranges.size() && range<=other.range_idx; ++range) + c += index_set->ranges[range].end-index_set->ranges[range].begin; + + Assert(other.range_idx < index_set->ranges.size() || other.range_idx == numbers::invalid_dof_index, + ExcMessage("Inconsistent iterator state. Did you invalidate iterators by modifying the IndexSet?")); + + // We might have walked too far because we went until the end of other.range_idx, so walk backwards to other.idx: + if (other.range_idx != numbers::invalid_dof_index) + c -= index_set->ranges[other.range_idx].end - other.idx; + + return -c; +} + + +/* Range */ + inline IndexSet::Range::Range () : @@ -506,14 +1131,53 @@ IndexSet::Range::Range () inline -IndexSet::Range::Range (const types::global_dof_index i1, - const types::global_dof_index i2) +IndexSet::Range::Range (const size_type i1, + const size_type i2) : begin(i1), end(i2) {} +/* IndexSet itself */ + +inline +IndexSet::ElementIterator IndexSet::begin() const +{ + compress(); + if (ranges.size()>0) + return IndexSet::ElementIterator(this, 0, ranges[0].begin); + else + return end(); +} + +inline +IndexSet::ElementIterator IndexSet::end() const +{ + compress(); + return IndexSet::ElementIterator(this); +} + + +inline +IndexSet::IntervalIterator IndexSet::begin_intervals() const +{ + compress(); + if (ranges.size()>0) + return IndexSet::IntervalIterator(this, 0); + else + return end_intervals(); +} + +inline +IndexSet::IntervalIterator IndexSet::end_intervals() const +{ + compress(); + return IndexSet::IntervalIterator(this); +} + + + inline IndexSet::IndexSet () : @@ -525,7 +1189,7 @@ IndexSet::IndexSet () inline -IndexSet::IndexSet (const types::global_dof_index size) +IndexSet::IndexSet (const size_type size) : is_compressed (true), index_space_size (size), @@ -546,7 +1210,7 @@ IndexSet::clear () inline void -IndexSet::set_size (const types::global_dof_index sz) +IndexSet::set_size (const size_type sz) { Assert (ranges.empty(), ExcMessage ("This function can only be called if the current " @@ -558,7 +1222,7 @@ IndexSet::set_size (const types::global_dof_index sz) inline -types::global_dof_index +IndexSet::size_type IndexSet::size () const { return index_space_size; @@ -580,10 +1244,10 @@ IndexSet::compress () const inline void -IndexSet::add_index (const types::global_dof_index index) +IndexSet::add_index (const size_type index) { Assert (index < index_space_size, - ExcIndexRangeType (index, 0, index_space_size)); + ExcIndexRangeType (index, 0, index_space_size)); const Range new_range(index, index+1); if (ranges.size() == 0 || index > ranges.back().end) @@ -610,8 +1274,8 @@ IndexSet::add_indices (const ForwardIterator &begin, // consecutive, merge them to a range for (ForwardIterator p=begin; p!=end;) { - const types::global_dof_index begin_index = *p; - types::global_dof_index end_index = begin_index + 1; + const size_type begin_index = *p; + size_type end_index = begin_index + 1; ForwardIterator q = p; ++q; while ((q != end) && (*q == end_index)) @@ -629,7 +1293,7 @@ IndexSet::add_indices (const ForwardIterator &begin, inline bool -IndexSet::is_element (const types::global_dof_index index) const +IndexSet::is_element (const size_type index) const { if (ranges.empty() == false) { @@ -691,13 +1355,13 @@ IndexSet::is_contiguous () const inline -types::global_dof_index +IndexSet::size_type IndexSet::n_elements () const { // make sure we have non-overlapping ranges compress (); - types::global_dof_index v = 0; + size_type v = 0; if (!ranges.empty()) { Range &r = ranges.back(); @@ -705,7 +1369,7 @@ IndexSet::n_elements () const } #ifdef DEBUG - types::global_dof_index s = 0; + size_type s = 0; for (std::vector::iterator range = ranges.begin(); range != ranges.end(); ++range) @@ -729,13 +1393,13 @@ IndexSet::n_intervals () const inline -types::global_dof_index +IndexSet::size_type IndexSet::nth_index_in_set (const unsigned int n) const { // to make this call thread-safe, compress() must not be called through this // function Assert (is_compressed == true, ExcMessage ("IndexSet must be compressed.")); - Assert (n < n_elements(), ExcIndexRangeType (n, 0, n_elements())); + Assert (n < n_elements(), ExcIndexRangeType (n, 0, n_elements())); // first check whether the index is in the largest range Assert (largest_range < ranges.size(), ExcInternalError()); @@ -772,14 +1436,14 @@ IndexSet::nth_index_in_set (const unsigned int n) const inline -types::global_dof_index -IndexSet::index_within_set (const types::global_dof_index n) const +IndexSet::size_type +IndexSet::index_within_set (const size_type n) const { // to make this call thread-safe, compress() must not be called through this // function Assert (is_compressed == true, ExcMessage ("IndexSet must be compressed.")); Assert (is_element(n) == true, ExcIndexNotPresent (n)); - Assert (n < size(), ExcIndexRangeType (n, 0, size())); + Assert (n < size(), ExcIndexRangeType (n, 0, size())); // check whether the index is in the largest range. use the result to // perform a one-sided binary search afterward @@ -859,7 +1523,7 @@ IndexSet::fill_binary_vector (Vector &vector) const for (std::vector::iterator it = ranges.begin(); it != ranges.end(); ++it) - for (types::global_dof_index i=it->begin; iend; ++i) + for (size_type i=it->begin; iend; ++i) vector[i] = 1; } diff --git a/source/base/index_set.cc b/source/base/index_set.cc index 16f67cf684..92cdab2660 100644 --- a/source/base/index_set.cc +++ b/source/base/index_set.cc @@ -28,18 +28,19 @@ DEAL_II_NAMESPACE_OPEN + void -IndexSet::add_range (const types::global_dof_index begin, - const types::global_dof_index end) +IndexSet::add_range (const size_type begin, + const size_type end) { Assert ((begin < index_space_size) || ((begin == index_space_size) && (end == index_space_size)), - ExcIndexRangeType (begin, 0, index_space_size)); + ExcIndexRangeType (begin, 0, index_space_size)); Assert (end <= index_space_size, - ExcIndexRangeType (end, 0, index_space_size+1)); + ExcIndexRangeType (end, 0, index_space_size+1)); Assert (begin <= end, - ExcIndexRangeType (begin, 0, end)); + ExcIndexRangeType (begin, 0, end)); if (begin != end) { @@ -75,8 +76,8 @@ IndexSet::do_compress () const next = i; ++next; - types::global_dof_index first_index = i->begin; - types::global_dof_index last_index = i->end; + size_type first_index = i->begin; + size_type last_index = i->end; // see if we can merge any of the following ranges while (next != ranges.end() && @@ -99,7 +100,7 @@ IndexSet::do_compress () const } // now compute indices within set and the range with most elements - types::global_dof_index next_index = 0, largest_range_size = 0; + size_type next_index = 0, largest_range_size = 0; for (std::vector::iterator i = ranges.begin(); i != ranges.end(); ++i) { @@ -178,8 +179,8 @@ IndexSet::operator & (const IndexSet &is) const IndexSet -IndexSet::get_view (const types::global_dof_index begin, - const types::global_dof_index end) const +IndexSet::get_view (const size_type begin, + const size_type end) const { Assert (begin <= end, ExcMessage ("End index needs to be larger or equal to begin index!")); @@ -354,7 +355,7 @@ IndexSet::write(std::ostream &out) const void IndexSet::read(std::istream &in) { - types::global_dof_index s; + size_type s; unsigned int numranges; in >> s >> numranges; @@ -362,7 +363,7 @@ IndexSet::read(std::istream &in) set_size(s); for (unsigned int i=0; i> b >> e; add_range(b,e); } @@ -387,7 +388,7 @@ IndexSet::block_write(std::ostream &out) const void IndexSet::block_read(std::istream &in) { - types::global_dof_index size; + size_type size; size_t n_ranges; in.read(reinterpret_cast(&size), sizeof(size)); in.read(reinterpret_cast(&n_ranges), sizeof(n_ranges)); @@ -404,7 +405,7 @@ IndexSet::block_read(std::istream &in) -void IndexSet::fill_index_vector(std::vector &indices) const +void IndexSet::fill_index_vector(std::vector &indices) const { compress(); @@ -414,7 +415,7 @@ void IndexSet::fill_index_vector(std::vector &indices) for (std::vector::iterator it = ranges.begin(); it != ranges.end(); ++it) - for (types::global_dof_index i=it->begin; iend; ++i) + for (size_type i=it->begin; iend; ++i) indices.push_back (i); Assert (indices.size() == n_elements(), ExcInternalError()); @@ -467,7 +468,7 @@ IndexSet::make_trilinos_map (const MPI_Comm &communicator, #endif else { - std::vector indices; + std::vector indices; fill_index_vector(indices); return Epetra_Map (TrilinosWrappers::types::int_type(-1), diff --git a/tests/base/index_set_iterate_01.cc b/tests/base/index_set_iterate_01.cc new file mode 100644 index 0000000000..c8ca84a10a --- /dev/null +++ b/tests/base/index_set_iterate_01.cc @@ -0,0 +1,166 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2015 by the deal.II authors +// +// This file is part of the deal.II library. +// +// The deal.II library is free software; you can use it, redistribute +// it, and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// The full text of the license can be found in the file LICENSE at +// the top level of the deal.II distribution. +// +// --------------------------------------------------------------------- + + +// test IndexSet iterators + +#include "../tests.h" +#include +#include +#include +#include + +#include + +void test (IndexSet &index_set) +{ + index_set.print(deallog); + + Assert((int)index_set.n_intervals() == index_set.end_intervals()-index_set.begin_intervals(), + ExcInternalError()); + + IndexSet::IntervalIterator endit = index_set.end_intervals(); + Assert(!endit->is_valid(), ExcInternalError()); + + // print intervals + for (IndexSet::IntervalIterator it = index_set.begin_intervals(); it != endit; ++it) + { + if (it->n_elements()==1) + deallog << *(it->begin()) << " "; + else + deallog << "[" << *(it->begin()) << "," << it->last() << "] "; + } + deallog << std::endl; + + // print entries + { + for (IndexSet::ElementIterator it = index_set.begin(); it != index_set.end(); ++it) + deallog << *it << " "; + deallog << std::endl; + } + + // check comparison, distance, and n_elements: + unsigned int c = 0; + for (IndexSet::IntervalIterator it = index_set.begin_intervals(); it != endit; ++it, ++c) + { + IndexSet::IntervalIterator it2 = it; + Assert(it == it2, ExcInternalError()); + Assert(it-it2 == 0, ExcInternalError()); + Assert(endit != it, ExcInternalError()); + Assert(it != endit, ExcInternalError()); + + IndexSet::IntervalIterator it3 = it2++; + Assert(it == it3, ExcInternalError()); + Assert(it2-it3 == 1, ExcInternalError()); + Assert(it3 < it2, ExcInternalError()); + Assert(++it3 == it2, ExcInternalError()); + + Assert(it->is_valid(), ExcInternalError()); + + Assert(it < endit, ExcInternalError()); + Assert(!(it < it), ExcInternalError()); + + Assert((it-index_set.begin_intervals()) == (int)c, ExcInternalError()); + Assert((index_set.begin_intervals()-it) == -(int)c, ExcInternalError()); + + deallog << c << ": n_el: " << it->n_elements() << std::endl; + } + + // ElementIterator checks + { + IndexSet::ElementIterator it = index_set.begin(); + + unsigned int c = 0; + for (; it != index_set.end(); ++it, ++c) + { + Assert(it < index_set.end(), ExcInternalError()); + + IndexSet::ElementIterator it2 = it; + Assert(it == it2, ExcInternalError()); + Assert(!(it < it2), ExcInternalError()); + IndexSet::ElementIterator it3 = it2++; + Assert(it == it3, ExcInternalError()); + Assert(it < it2, ExcInternalError()); + Assert(it != it2, ExcInternalError()); + + Assert((it - index_set.begin()) == c, ExcInternalError()); + Assert((index_set.begin() - it) == -(int)c, ExcInternalError()); + } + } + + + // pre vs post increment + { + IndexSet::ElementIterator it = index_set.begin(); + IndexSet::ElementIterator it2 = index_set.begin(); + + for (; it != index_set.end(); ++it, it2++) + Assert(it == it2, ExcInternalError()); + } + + // pre vs post increment, part 2 + { + IndexSet::IntervalIterator it = index_set.begin_intervals(); + IndexSet::IntervalIterator it2 = index_set.begin_intervals(); + + for (; it != index_set.end_intervals(); ++it, it2++) + Assert(it == it2, ExcInternalError()); + } + + // Assignment + { + IndexSet::IntervalIterator it = index_set.begin_intervals(); + Assert(it->is_valid() || index_set.n_elements()==0, ExcInternalError()); + it = index_set.end_intervals(); + Assert(!it->is_valid(), ExcInternalError()); + } + + // Construct empty iterator + { + IndexSet::IntervalIterator it; + Assert(!it->is_valid(), ExcInternalError()); + it = index_set.begin_intervals(); + Assert(it->is_valid() || index_set.n_elements()==0, ExcInternalError()); + } +} + +void test() +{ + IndexSet index_set (20); + index_set.add_range (2,4); + index_set.add_range (12,18); + index_set.add_index (6); + index_set.add_index (8); + index_set.add_index (9); + index_set.add_index (16); + + test(index_set); + + IndexSet empty (42); + test(empty); +} + + + + +int main() +{ + std::ofstream logfile("output"); + deallog.attach(logfile); + deallog.depth_console(0); + deallog.threshold_double(1.e-10); + + test (); +} diff --git a/tests/base/index_set_iterate_01.output b/tests/base/index_set_iterate_01.output new file mode 100644 index 0000000000..178f472dcb --- /dev/null +++ b/tests/base/index_set_iterate_01.output @@ -0,0 +1,11 @@ + +DEAL::{[2,3], 6, [8,9], [12,17]} +DEAL::[2,3] 6 [8,9] [12,17] +DEAL::2 3 6 8 9 12 13 14 15 16 17 +DEAL::0: n_el: 2 +DEAL::1: n_el: 1 +DEAL::2: n_el: 2 +DEAL::3: n_el: 6 +DEAL::{} +DEAL:: +DEAL:: -- 2.39.5