From: Wolfgang Bangerth Date: Thu, 27 Sep 2001 15:35:50 +0000 (+0000) Subject: Mostly implement iterators for block vectors. Some parts still missing though. X-Git-Tag: v8.0.0~18704 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7cb908daedbe87d53554d64e6fb89ef216eec12f;p=dealii.git Mostly implement iterators for block vectors. Some parts still missing though. git-svn-id: https://svn.dealii.org/trunk@5112 0785d39b-7218-0410-832d-ea1e28bc413d --- diff --git a/deal.II/lac/include/lac/block_vector.h b/deal.II/lac/include/lac/block_vector.h index 20c75c26cf..0d0f39a057 100644 --- a/deal.II/lac/include/lac/block_vector.h +++ b/deal.II/lac/include/lac/block_vector.h @@ -50,6 +50,187 @@ template class BlockVector { + template + class Iterator + { + public: + /** + * Construct an iterator from + * a vector to which we point + * and the global index of + * the element pointed to. + */ + Iterator (BlockVector &parent, + const unsigned global_index); + + /** + * Copy constructor. + */ + Iterator (const Iterator &c); + + /** + * Copy operator. + */ + Iterator & operator = (const Iterator &c); + + /** + * Dereferencing operator. If + * the template argument + * @p{Pointee} has a + * @p{const} specification, + * then no writing to the + * result is possible, making + * this a @p{const_iterator}. + */ + Pointee & operator * () const; + + /** + * Prefix @p{++} operator: + * @p{++i}. This operator + * advances the iterator to + * the next element and + * returns a reference to + * @p{*this}. + */ + Iterator & operator ++ (); + + /** + * Postfix @p{++} operator: + * @p{i++}. This operator + * advances the iterator to + * the next element and + * returns a copy of the old + * value of this iterator. + */ + Iterator operator ++ (int); + + /** + * Prefix @p{--} operator: + * @p{--i}. This operator + * retracts the iterator to + * the previous element and + * returns a reference to + * @p{*this}. + */ + Iterator & operator -- (); + + /** + * Postfix @p{--} operator: + * @p{i--}. This operator + * retracts the iterator to + * the previous element and + * returns a copy of the old + * value of this iterator. + */ + Iterator operator -- (int); + + /** + * Compare for equality of + * iterators. This operator + * checks whether the vectors + * pointed to are the same, + * and if not it throws an + * exception. + */ + bool operator == (const Iterator &i) const; + + /** + * Compare for inequality of + * iterators. This operator + * checks whether the vectors + * pointed to are the same, + * and if not it throws an + * exception. + */ + bool operator != (const Iterator &i) const; + + /** + * Check whether this + * iterators points to an + * element previous to the + * one pointed to by the + * given argument. This + * operator checks whether + * the vectors pointed to are + * the same, and if not it + * throws an exception. + */ + bool operator < (const Iterator &i) const; + + /** + * Comparison operator alike + * to the one above. + */ + bool operator <= (const Iterator &i) const; + + /** + * Comparison operator alike + * to the one above. + */ + bool operator > (const Iterator &i) const; + + /** + * Comparison operator alike + * to the one above. + */ + bool operator >= (const Iterator &i) const; + + /** + * Exception. + */ + DeclException0 (ExcPointerToDifferentVectors); + + + private: + /** + * Pointer to the block + * vector object to which + * this iterator points. + */ + BlockVector *parent; + + /** + * Global index of the + * element to which we + * presently point. + */ + unsigned int global_index; + + /** + * Current block and index + * within this block of the + * element presently pointed + * to. + */ + unsigned int current_block; + unsigned int index_within_block; + + /** + * Indices of the global + * element address at which + * we have to move on to + * another block when moving + * forward and + * backward. These indices + * are kept as a cache since + * this is much more + * efficient than always + * asking the parent object. + */ + unsigned int next_break_forward; + unsigned int next_break_backward; + + /** + * Move forward one element. + */ + void move_forward (); + + /** + * Move backward one element. + */ + void move_backward (); + }; + public: /** * Declare standard types used in @@ -63,12 +244,14 @@ class BlockVector * implemented that cycle through * the individual sub-vectors. */ - typedef Number value_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef size_t size_type; + typedef Number value_type; + typedef value_type *pointer; + typedef const value_type *const_pointer; + typedef Iterator iterator; + typedef Iterator const_iterator; + typedef value_type &reference; + typedef const value_type &const_reference; + typedef size_t size_type; /** * Constructor. There are three @@ -355,6 +538,20 @@ class BlockVector * as a writeable reference. */ Number& operator() (const unsigned int i); + + /** + * Return an iterator pointing to + * the first element. + */ + iterator begin (); + + /** + * Return an iterator pointing to + * the first element of a + * constant block vector. + */ + const_iterator begin () const; + //@} @@ -546,6 +743,12 @@ class BlockVector * here for convenience. */ unsigned int num_blocks; + + /** + * Make the iterator class a + * friend. + */ + template friend class Iterator; }; diff --git a/deal.II/lac/include/lac/block_vector.templates.h b/deal.II/lac/include/lac/block_vector.templates.h index 68af1979db..d151449c5b 100644 --- a/deal.II/lac/include/lac/block_vector.templates.h +++ b/deal.II/lac/include/lac/block_vector.templates.h @@ -150,6 +150,7 @@ bool BlockVector::all_zero () const } + template Number BlockVector::operator * (const BlockVector& v) const { @@ -165,6 +166,24 @@ Number BlockVector::operator * (const BlockVector& v) const } +template +typename BlockVector::iterator +BlockVector::begin() +{ + return iterator(*this, 0U); +}; + + + +template +typename BlockVector::const_iterator +BlockVector::begin() const +{ + Assert (false, ExcNotImplemented()); + return const_iterator(*const_cast(this), 0U); +}; + + template Number BlockVector::norm_sqr () const { @@ -507,6 +526,268 @@ BlockVector::memory_consumption () const +template +template +BlockVector::Iterator:: +Iterator (BlockVector &parent, + const unsigned global_index) + : + parent (&parent), + global_index (global_index) +{ + // find which block we are in + const std::pair + indices = parent.block_indices.global_to_local(global_index); + current_block = indices.first; + index_within_block = indices.second; + + next_break_backward = parent.block_indices.local_to_global (current_block, 0); + next_break_forward + = parent.block_indices.local_to_global (current_block, + next_break_backward + + parent.block_indices + .block_size(current_block)-1); +}; + + + + +template +template +BlockVector::Iterator:: +Iterator (const Iterator &c) + : + parent (c.parent), + global_index (c.global_index), + current_block (c.current_block), + index_within_block (c.index_within_block), + next_break_forward (c.next_break_forward), + next_break_backward (c.next_break_backward) +{}; + + + +template +template +typename BlockVector::Iterator & +BlockVector::Iterator:: +operator = (const Iterator &c) +{ + parent = c.parent; + global_index = c.global_index; + index_within_block = c.index_within_block; + current_block = c.current_block; + next_break_forward = c.next_break_forward; + next_break_backward = c.next_break_backward; + + return *this; +}; + + + +template +template +void +BlockVector::Iterator::move_forward () +{ + if (global_index != next_break_forward) + ++index_within_block; + else + { + // ok, we traverse a boundary + // between blocks: + index_within_block = 0; + ++current_block; + + // break backwards is now old + // break forward + next_break_backward = next_break_forward+1; + + // compute new break forward + if (current_block < parent->block_indices.size()) + next_break_forward + = parent->block_indices.local_to_global (current_block, + next_break_backward + + parent->block_indices + .block_size(current_block)-1); + else + // if we are beyond the end, + // then move the next + // boundary arbitrarily far + // away + next_break_forward = static_cast(-1); + }; + + ++global_index; +}; + + + +template +template +void +BlockVector::Iterator::move_backward () +{ + if (global_index != next_break_backward) + --index_within_block; + else + if (current_block != 0) + { + // ok, we traverse a boundary + // between blocks: + --current_block; + index_within_block = parent->block_indices.block_size(current_block)-1; + + // break forwards is now old + // break backward + next_break_forward = next_break_backward-1; + + // compute new break forward + next_break_backward + = parent->block_indices.local_to_global (current_block, 0); + } + else + // current block was 0, we now + // get into unspecified terrain + { + --current_block; + index_within_block = static_cast(-1); + next_break_forward = 0; + next_break_backward = 0; + }; + + --global_index; +}; + + + +template +template +Pointee & +BlockVector::Iterator::operator * () const +{ + return parent->block(current_block)(index_within_block); +}; + + + +template +template +typename BlockVector::Iterator & +BlockVector::Iterator::operator ++ () +{ + move_forward (); + return *this; +}; + + + +template +template +typename BlockVector::Iterator +BlockVector::Iterator::operator ++ (int) +{ + const Iterator old_value = *this; + move_forward (); + return old_value; +}; + + + +template +template +typename BlockVector::Iterator & +BlockVector::Iterator::operator -- () +{ + move_backward (); + return *this; +}; + + + +template +template +typename BlockVector::Iterator +BlockVector::Iterator::operator -- (int) +{ + const Iterator old_value = *this; + move_backward (); + return old_value; +}; + + + +template +template +bool +BlockVector::Iterator::operator == (const Iterator &i) const +{ + Assert (parent == i.parent, ExcPointerToDifferentVectors()); + + return (global_index == i.global_index); +}; + + + +template +template +bool +BlockVector::Iterator::operator != (const Iterator &i) const +{ + Assert (parent == i.parent, ExcPointerToDifferentVectors()); + + return (global_index != i.global_index); +}; + + + +template +template +bool +BlockVector::Iterator::operator < (const Iterator &i) const +{ + Assert (parent == i.parent, ExcPointerToDifferentVectors()); + + return (global_index < i.global_index); +}; + + + +template +template +bool +BlockVector::Iterator::operator <= (const Iterator &i) const +{ + Assert (parent == i.parent, ExcPointerToDifferentVectors()); + + return (global_index <= i.global_index); +}; + + + +template +template +bool +BlockVector::Iterator::operator > (const Iterator &i) const +{ + Assert (parent == i.parent, ExcPointerToDifferentVectors()); + + return (global_index > i.global_index); +}; + + + +template +template +bool +BlockVector::Iterator::operator >= (const Iterator &i) const +{ + Assert (parent == i.parent, ExcPointerToDifferentVectors()); + + return (global_index >= i.global_index); +}; + + #endif