From 32586f02dc2e5e4e611c6cd332f7a1a2b7211ee6 Mon Sep 17 00:00:00 2001 From: wolf Date: Fri, 28 Sep 2001 17:49:28 +0000 Subject: [PATCH] BlockVectors now have iterators. git-svn-id: https://svn.dealii.org/trunk@5120 0785d39b-7218-0410-832d-ea1e28bc413d --- deal.II/doc/news/2001/c-3-2.html | 8 + deal.II/lac/include/lac/block_vector.h | 1212 ++++++++++++++--- .../lac/include/lac/block_vector.templates.h | 375 ++--- deal.II/lac/source/block_vector.cc | 10 + tests/lac/Makefile | 29 +- tests/lac/block_vector_iterator.cc | 352 +++++ tests/lac/block_vector_iterator.checked | 20 + 7 files changed, 1559 insertions(+), 447 deletions(-) create mode 100644 tests/lac/block_vector_iterator.cc create mode 100644 tests/lac/block_vector_iterator.checked diff --git a/deal.II/doc/news/2001/c-3-2.html b/deal.II/doc/news/2001/c-3-2.html index b8b45241e1..9848e739f7 100644 --- a/deal.II/doc/news/2001/c-3-2.html +++ b/deal.II/doc/news/2001/c-3-2.html @@ -44,6 +44,14 @@ documentation, etc.

lac

    +
  1. + New: The BlockVector now has a + full-fledged random access iterator type, working in exactly + the same way as the iterators of the C++ standard containers. +
    + (WB 2001/09/28) +

    +
  2. New: Vector::operator * is now templatized, allowing for scalar products of vectors with diff --git a/deal.II/lac/include/lac/block_vector.h b/deal.II/lac/include/lac/block_vector.h index 0d0f39a057..7a4a8651c0 100644 --- a/deal.II/lac/include/lac/block_vector.h +++ b/deal.II/lac/include/lac/block_vector.h @@ -19,12 +19,560 @@ #include #include #include +#include + + +// forward declaration +template +class BlockVector; + + +/** + * Namespace in which iterators in block vectors are implemented. + * + * @author Wolfgang Bangerth, 2001 + */ +namespace BlockVectorIterators +{ + /** + * Declaration of the general + * template of a structure which is + * used to determine some types + * based on the template arguments + * of other classes. + */ + template + struct Types + {}; + + + + /** + * Declaration of a specialized + * template of a structure which is + * used to determine some types + * based on the template arguments + * of other classes. + * + * This is for the use of non-const + * iterators. + */ + template + struct Types + { + /** + * Type of the vector + * underlying the block vector + * used in non-const + * iterators. There, the + * vector must not be constant. + */ + typedef Vector Vector; + + /** + * Type of the block vector + * used in non-const + * iterators. There, the block + * vector must not be constant. + */ + typedef BlockVector BlockVector; + + /** + * Type of the numbers we point + * to. Here, they are not + * constant. + */ + typedef number NumberType; + }; + + + + /** + * Declaration of a specialized + * template of a structure which is + * used to determine some types + * based on the template arguments + * of other classes. + * + * This is for the use of + * @p{const_iterator}s. + */ + template + struct Types + { + /** + * Type of the vector + * underlying the block vector + * used in + * @p{const_iterators}. There, + * the vector must be + * constant. + */ + typedef const Vector Vector; + + /** + * Type of the block vector + * used in + * @p{const_iterator}s. There, + * the block vector must be + * constant. + */ + typedef const BlockVector BlockVector; + + /** + * Type of the numbers we point + * to. Here, they are constant + * since the block vector we + * use is constant. + */ + typedef const number NumberType; + }; + + + /** + * General random-access iterator + * class for block vectors. Since + * we do not want to have two + * classes for non-const + * @p{iterator}s and + * @p{const_iterator}s, we take a + * second template argument which + * denotes whether the vector we + * point into is a constant object + * or not. The first template + * argument is always the number + * type of the block vector in use. + * + * This class satisfies all + * requirements of random access + * iterators defined in the C++ + * standard. Operations on these + * iterators are constant in the + * number of elements in the block + * vector. However, they are + * sometimes linear in the number + * of blocks in the vector, but + * since that does rarely change + * dynamically within an + * application, this is a constant + * and we again have that the + * iterator satisfies the + * requirements of a random access + * iterator. + * + * The implementation of this class + * has to work around some problems + * in compilers and standard + * libraries. One of these requires + * us to write all comparison + * operators twice, once comparison + * with iterators of the same type + * and once with iterators pointing + * to numbers of opposite constness + * specification. The reason is + * that if we would have written + * the comparison operators as a + * template on the constness of the + * right hand side, then gcc2.95 + * signals an error that these + * operators ambiguate operators + * declared somewhere within the + * standard library. Likewise, we + * have to work around some + * problems with granting other + * iterators friendship. This makes + * the implementation somewhat + * non-optimal at places, but at + * least everything works. + * + * @author Wolfgang Bangerth, 2001 + */ + template + class Iterator : +#ifdef HAVE_STD_ITERATOR_CLASS + public std::iterator::NumberType> +#else + random_access_iterator::NumberType,int> +#endif + { + private: + /** + * Typedef an iterator with + * opposite constness + * requirements on the elements + * it points to. + */ + typedef Iterator InverseConstnessIterator; + + public: + /** + * Declare some typedefs which + * are standard for iterators + * and are used by algorithms + * to enquire about the + * specifics of the iterators + * they work on. + */ + typedef std::random_access_iterator_tag iterator_type; + typedef typename Types::NumberType value_type; + typedef ptrdiff_t difference_type; + typedef value_type &reference; + typedef value_type *pointer; + + /** + * Typedef the type of the + * block vector (which differs + * in constness, depending on + * the second template + * parameter). + */ + typedef typename Types::BlockVector BlockVectorType; + + /** + * Type of the number this + * iterator points + * to. Depending on the value + * of the second template + * parameter, this is either a + * constant or non-const + * number. + */ + typedef typename Types::NumberType NumberType; + + /** + * Construct an iterator from + * a vector to which we point + * and the global index of + * the element pointed to. + * + * Depending on the value of + * the @p{constness} template + * argument of this class, + * the first argument of this + * constructor is either is a + * @p{const} or non-@p{const} + * reference. + */ + Iterator (BlockVectorType &parent, + const unsigned int global_index); + + /** + * Copy constructor. + */ + Iterator (const Iterator &c); + + /** + * Copy constructor for + * conversion between iterators + * with different constness + * requirements. This + * constructor throws an error + * if an attempt is made at + * converting a constant to a + * non-constant iterator. + */ + template + Iterator (const Iterator &c); + + private: + /** + * Constructor used internally + * in this class. The arguments + * match exactly the values of + * the respective member + * variables. + */ + Iterator (BlockVectorType &parent, + const unsigned int global_index, + const unsigned int current_block, + const unsigned int index_within_block, + const unsigned int next_break_forward, + const unsigned int next_break_backward); + + public: + + /** + * Copy operator. + */ + Iterator & operator = (const Iterator &c); + + /** + * Dereferencing operator. If + * the template argument + * @p{constness} is @p{true}, + * then no writing to the + * result is possible, making + * this a @p{const_iterator}. + */ + reference operator * () const; + + /** + * Dereferencing operator. If + * the template argument + * @p{constness} is @p{true}, + * then no writing to the + * result is possible, making + * this a @p{const_iterator}. + */ + pointer operator -> () const; + + /** + * Random access operator, + * grant access to arbitrary + * elements relative to the one + * presently pointed to. + */ + reference operator [] (const difference_type d) 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; + + /** + * Same, but compare with an + * iterator of different + * constness. + */ + bool operator == (const InverseConstnessIterator &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; + + /** + * Same, but compare with an + * iterator of different + * constness. + */ + bool operator != (const InverseConstnessIterator &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; + + /** + * Same, but compare with an + * iterator of different + * constness. + */ + bool operator < (const InverseConstnessIterator &i) const; + + /** + * Comparison operator alike + * to the one above. + */ + bool operator <= (const Iterator &i) const; + + /** + * Same, but compare with an + * iterator of different + * constness. + */ + bool operator <= (const InverseConstnessIterator &i) const; + + /** + * Comparison operator alike + * to the one above. + */ + bool operator > (const Iterator &i) const; + + /** + * Same, but compare with an + * iterator of different + * constness. + */ + bool operator > (const InverseConstnessIterator &i) const; + + /** + * Comparison operator alike + * to the one above. + */ + bool operator >= (const Iterator &i) const; + + /** + * Same, but compare with an + * iterator of different + * constness. + */ + bool operator >= (const InverseConstnessIterator &i) const; + + /** + * Return the distance between + * the two iterators, in + * elements. + */ + difference_type operator - (const Iterator &i) const; + + /** + * Same, but for iterators of + * opposite constness. + */ + difference_type operator - (const InverseConstnessIterator &i) const; + + /** + * Return an iterator which is + * the given number of elements + * in front of the present one. + */ + Iterator operator + (const difference_type &d) const; + + /** + * Return an iterator which is + * the given number of elements + * behind the present one. + */ + Iterator operator - (const difference_type &d) const; + + /** + * Move the iterator @p{d} + * elements forward at once, + * and return the result. + */ + Iterator & operator += (const difference_type &d); + + /** + * Move the iterator @p{d} + * elements backward at once, + * and return the result. + */ + Iterator & operator -= (const difference_type &d); + + /** + * Exception. + */ + DeclException0 (ExcPointerToDifferentVectors); + /** + * Exception. + */ + DeclException0 (ExcCastingAwayConstness); + + private: + /** + * Pointer to the block + * vector object to which + * this iterator + * points. Depending on the + * value of the @p{constness} + * template argument of this + * class, this is a @p{const} + * or non-@p{const} pointer. + */ + BlockVectorType *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 (); + + friend class InverseConstnessIterator; + }; +}; + /** - * Several vectors of data. + * A vector composed of several blocks each representing a vector of + * its own. * - * The BlockVector is a collection of normal LAC-@p{Vector}s. Each of + * The @p{BlockVector} is a collection of normal LAC-@p{Vector}s. Each of * the vectors inside can have a different size. The special case of a * block vector with constant block size is supported by constructor * and reinit functions. @@ -50,187 +598,6 @@ 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 @@ -247,8 +614,8 @@ class BlockVector typedef Number value_type; typedef value_type *pointer; typedef const value_type *const_pointer; - typedef Iterator iterator; - typedef Iterator const_iterator; + typedef BlockVectorIterators::Iterator iterator; + typedef BlockVectorIterators::Iterator const_iterator; typedef value_type &reference; typedef const value_type &const_reference; typedef size_t size_type; @@ -428,7 +795,7 @@ class BlockVector /** * Access to a single block. */ - Vector& block (const unsigned int i); + Vector & block (const unsigned int i); /** * Read-only access to a single block. @@ -552,6 +919,18 @@ class BlockVector */ const_iterator begin () const; + /** + * Return an iterator pointing to + * the element past the end. + */ + iterator end (); + + /** + * Return an iterator pointing to + * the element past the end of a + * constant block vector. + */ + const_iterator end () const; //@} @@ -748,7 +1127,8 @@ class BlockVector * Make the iterator class a * friend. */ - template friend class Iterator; + friend class iterator; + friend class const_iterator; }; @@ -861,6 +1241,464 @@ BlockVector::get_block_indices () const } +namespace BlockVectorIterators +{ + + template + inline + 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 + inline + 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) + { + Assert (! ((constness==false) && (constness2==true)), + ExcCastingAwayConstness()); + }; + + + + template + inline + Iterator:: + Iterator (BlockVectorType &parent, + const unsigned int global_index, + const unsigned int current_block, + const unsigned int index_within_block, + const unsigned int next_break_forward, + const unsigned int next_break_backward) + : + parent (&parent), + global_index (global_index), + current_block (current_block), + index_within_block (index_within_block), + next_break_forward (next_break_forward), + next_break_backward (next_break_backward) + { + }; + + + + template + inline + Iterator & + 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 + inline + typename Iterator::reference + Iterator::operator * () const + { + // we might want to return the + // following directly, but if we do + // that we run into a gcc bug where + // it complains that we return a + // reference to a temporary + const reference p = parent->block(current_block)(index_within_block); + return p; + }; + + + + template + inline + typename Iterator::pointer + Iterator::operator -> () const + { + // we might want to return the + // following directly, but if we do + // that we run into a gcc bug where + // it complains that we return a + // reference to a temporary + const reference p = parent->block(current_block)(index_within_block); + return &p; + }; + + + + template + inline + typename Iterator::reference + Iterator::operator [] (const difference_type d) const + { + // if the index pointed to is + // still within the block we + // currently point into, then we + // can save the computation of + // the block + if ((global_index+d >= next_break_backward) && + (global_index+d <= next_break_forward)) + { + const reference p = parent->block(current_block)(index_within_block + d); + return p; + }; + + + // if the index is not within the + // block of the block vector into + // which we presently point, then + // there is no way: we have to + // search for the block. this can + // be done through the parent + // class as well. + const reference p = (*parent)(global_index+d); + return p; + }; + + + + template + inline + Iterator & + Iterator::operator ++ () + { + move_forward (); + return *this; + }; + + + + template + inline + Iterator + Iterator::operator ++ (int) + { + const Iterator old_value = *this; + move_forward (); + return old_value; + }; + + + + template + inline + Iterator & + Iterator::operator -- () + { + move_backward (); + return *this; + }; + + + + template + inline + Iterator + Iterator::operator -- (int) + { + const Iterator old_value = *this; + move_backward (); + return old_value; + }; + + + + template + inline + bool + Iterator::operator == (const Iterator &i) const + { + Assert (parent == i.parent, ExcPointerToDifferentVectors()); + + return (global_index == i.global_index); + }; + + + + template + inline + bool + Iterator::operator == (const InverseConstnessIterator &i) const + { + Assert (parent == i.parent, ExcPointerToDifferentVectors()); + + return (global_index == i.global_index); + }; + + + + template + inline + bool + Iterator::operator != (const Iterator &i) const + { + Assert (parent == i.parent, ExcPointerToDifferentVectors()); + + return (global_index != i.global_index); + }; + + + + template + inline + bool + Iterator::operator != (const InverseConstnessIterator &i) const + { + Assert (parent == i.parent, ExcPointerToDifferentVectors()); + + return (global_index != i.global_index); + }; + + + + template + inline + bool + Iterator::operator < (const Iterator &i) const + { + Assert (parent == i.parent, ExcPointerToDifferentVectors()); + + return (global_index < i.global_index); + }; + + + + template + inline + bool + Iterator::operator < (const InverseConstnessIterator &i) const + { + Assert (parent == i.parent, ExcPointerToDifferentVectors()); + + return (global_index < i.global_index); + }; + + + + template + inline + bool + Iterator::operator <= (const Iterator &i) const + { + Assert (parent == i.parent, ExcPointerToDifferentVectors()); + + return (global_index <= i.global_index); + }; + + + + template + inline + bool + Iterator::operator <= (const InverseConstnessIterator &i) const + { + Assert (parent == i.parent, ExcPointerToDifferentVectors()); + + return (global_index <= i.global_index); + }; + + + + template + inline + bool + Iterator::operator > (const Iterator &i) const + { + Assert (parent == i.parent, ExcPointerToDifferentVectors()); + + return (global_index > i.global_index); + }; + + + + template + inline + bool + Iterator::operator > (const InverseConstnessIterator &i) const + { + Assert (parent == i.parent, ExcPointerToDifferentVectors()); + + return (global_index > i.global_index); + }; + + + + template + inline + bool + Iterator::operator >= (const Iterator &i) const + { + Assert (parent == i.parent, ExcPointerToDifferentVectors()); + + return (global_index >= i.global_index); + }; + + + + template + inline + bool + Iterator::operator >= (const InverseConstnessIterator &i) const + { + Assert (parent == i.parent, ExcPointerToDifferentVectors()); + + return (global_index >= i.global_index); + }; + + + + template + inline + typename Iterator::difference_type + Iterator::operator - (const Iterator &i) const + { + Assert (parent == i.parent, ExcPointerToDifferentVectors()); + + return (static_cast(global_index) - + static_cast(i.global_index)); + }; + + + + template + inline + typename Iterator::difference_type + Iterator::operator - (const InverseConstnessIterator &i) const + { + Assert (parent == i.parent, ExcPointerToDifferentVectors()); + + return (static_cast(global_index) - + static_cast(i.global_index)); + }; + + + + template + inline + Iterator + Iterator::operator + (const difference_type &d) const + { + // if the index pointed to is + // still within the block we + // currently point into, then we + // can save the computation of + // the block + if ((global_index+d >= next_break_backward) && + (global_index+d <= next_break_forward)) + return Iterator (*parent, global_index+d, current_block, + index_within_block+d, + next_break_forward, next_break_backward); + else + // outside present block, so + // have to seek new block + // anyway + return Iterator (*parent, global_index+d); + }; + + + + template + inline + Iterator + Iterator::operator - (const difference_type &d) const + { + // if the index pointed to is + // still within the block we + // currently point into, then we + // can save the computation of + // the block + if ((global_index-d >= next_break_backward) && + (global_index-d <= next_break_forward)) + return Iterator (*parent, global_index-d, current_block, + index_within_block-d, + next_break_forward, next_break_backward); + else + // outside present block, so + // have to seek new block + // anyway + return Iterator (*parent, global_index-d); + }; + + + + template + inline + Iterator & + Iterator::operator += (const difference_type &d) + { + // if the index pointed to is + // still within the block we + // currently point into, then we + // can save the computation of + // the block + if ((global_index+d >= next_break_backward) && + (global_index+d <= next_break_forward)) + { + global_index += d; + index_within_block += d; + } + else + // outside present block, so + // have to seek new block + // anyway + *this = Iterator (*parent, global_index+d); + + return *this; + }; + + + + template + inline + Iterator & + Iterator::operator -= (const difference_type &d) + { + // if the index pointed to is + // still within the block we + // currently point into, then we + // can save the computation of + // the block + if ((global_index-d >= next_break_backward) && + (global_index-d <= next_break_forward)) + { + global_index -= d; + index_within_block -= d; + } + else + // outside present block, so + // have to seek new block + // anyway + *this = Iterator (*parent, global_index-d); + + return *this; + }; + +}; + + /** * Global function @p{swap} which overloads the default implementation * of the C++ standard library which uses a temporary object. The diff --git a/deal.II/lac/include/lac/block_vector.templates.h b/deal.II/lac/include/lac/block_vector.templates.h index d151449c5b..897daf363d 100644 --- a/deal.II/lac/include/lac/block_vector.templates.h +++ b/deal.II/lac/include/lac/block_vector.templates.h @@ -179,11 +179,28 @@ template typename BlockVector::const_iterator BlockVector::begin() const { - Assert (false, ExcNotImplemented()); - return const_iterator(*const_cast(this), 0U); + return const_iterator(*this, 0U); }; +template +typename BlockVector::iterator +BlockVector::end() +{ + return iterator(*this, size()); +}; + + + +template +typename BlockVector::const_iterator +BlockVector::end() const +{ + return const_iterator(*this, size()); +}; + + + template Number BlockVector::norm_sqr () const { @@ -196,6 +213,7 @@ Number BlockVector::norm_sqr () const }; + template Number BlockVector::mean_value () const { @@ -208,6 +226,7 @@ Number BlockVector::mean_value () const } + template Number BlockVector::l1_norm () const { @@ -220,6 +239,7 @@ Number BlockVector::l1_norm () const } + template Number BlockVector::l2_norm () const { @@ -227,6 +247,7 @@ Number BlockVector::l2_norm () const } + template Number BlockVector::linfty_norm () const { @@ -241,6 +262,7 @@ Number BlockVector::linfty_norm () const } + template BlockVector& BlockVector::operator += (const BlockVector& v) @@ -250,6 +272,7 @@ BlockVector::operator += (const BlockVector& v) } + template BlockVector& BlockVector::operator -= (const BlockVector& v) @@ -265,6 +288,7 @@ BlockVector::operator -= (const BlockVector& v) } + template void BlockVector::add (const Number a) { @@ -275,6 +299,7 @@ void BlockVector::add (const Number a) } + template void BlockVector::add (const BlockVector& v) { @@ -288,6 +313,7 @@ void BlockVector::add (const BlockVector& v) } + template void BlockVector::add (const Number a, const BlockVector& v) @@ -302,6 +328,7 @@ void BlockVector::add (const Number a, } + template void BlockVector::add (const Number a, const BlockVector& v, @@ -321,6 +348,7 @@ void BlockVector::add (const Number a, } + template void BlockVector::sadd (const Number x, const BlockVector& v) @@ -335,6 +363,7 @@ void BlockVector::sadd (const Number x, } + template void BlockVector::sadd (const Number x, const Number a, const BlockVector& v) @@ -349,6 +378,7 @@ void BlockVector::sadd (const Number x, const Number a, } + template void BlockVector::sadd (const Number x, const Number a, const BlockVector& v, @@ -367,6 +397,7 @@ void BlockVector::sadd (const Number x, const Number a, } + template void BlockVector::sadd (const Number x, const Number a, const BlockVector& v, @@ -526,268 +557,120 @@ 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 () +namespace BlockVectorIterators { - 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) + template + Iterator:: + Iterator (BlockVectorType &parent, + const unsigned global_index) + : + parent (&parent), + global_index (global_index) + { + // find which block we are + // in. for this, take into + // account that it happens at + // times that people want to + // initialize iterators + // past-the-end + if (global_index < parent.size()) { - // ok, we traverse a boundary - // between blocks: - --current_block; - index_within_block = parent->block_indices.block_size(current_block)-1; + const std::pair + indices = parent.block_indices.global_to_local(global_index); + current_block = indices.first; + index_within_block = indices.second; - // 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); + = parent.block_indices.local_to_global (current_block, 0); + next_break_forward + = (parent.block_indices.local_to_global (current_block, 0) + +parent.block_indices.block_size(current_block)-1); } else - // current block was 0, we now - // get into unspecified terrain + // past the end. only have one + // value for this { - --current_block; - index_within_block = static_cast(-1); - next_break_forward = 0; - next_break_backward = 0; + this->global_index = parent.size (); + current_block = parent.n_blocks(); + index_within_block = 0; + next_break_backward = global_index; + next_break_forward = static_cast(-1); }; - - --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()); + template + void + 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; - return (global_index > i.global_index); -}; + // 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.block_size(current_block); + 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 -bool -BlockVector::Iterator::operator >= (const Iterator &i) const -{ - Assert (parent == i.parent, ExcPointerToDifferentVectors()); - return (global_index >= i.global_index); + template + void + 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.block_size (current_block); + } + 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; + }; }; - - #endif diff --git a/deal.II/lac/source/block_vector.cc b/deal.II/lac/source/block_vector.cc index a085184bb6..601deb685b 100644 --- a/deal.II/lac/source/block_vector.cc +++ b/deal.II/lac/source/block_vector.cc @@ -16,3 +16,13 @@ // explicit instantiations template class BlockVector; template class BlockVector; + +namespace BlockVectorIterators +{ + template class Iterator; + template class Iterator; + + template class Iterator; + template class Iterator; +}; + diff --git a/tests/lac/Makefile b/tests/lac/Makefile index 03e38372a4..19ab30819a 100644 --- a/tests/lac/Makefile +++ b/tests/lac/Makefile @@ -20,20 +20,21 @@ default: run-tests ############################################################ -block_matrices.exe : block_matrices.go $(libraries) -block_vector.exe : block_vector.go abort.go $(libraries) -full_matrix.exe : full_matrix.go $(libraries) -matrix_out.exe : matrix_out.go $(libraries) -solver.exe : solver.go testmatrix.go $(libraries) -sparsity_pattern.exe: sparsity_pattern.go testmatrix.go $(libraries) -sparse_ilu.exe : sparse_ilu.go testmatrix.go $(libraries) -vector-vector.exe : vector-vector.go $(libraries) -#mgbase.exe : mgbase.go $(libraries) -#mg.exe : mg.go testmatrix.go $(libraries) - - -tests = block_matrices block_vector full_matrix matrix_out solver \ - sparsity_pattern sparse_ilu vector-vector +block_matrices.exe : block_matrices.go $(libraries) +block_vector.exe : block_vector.go abort.go $(libraries) +block_vector_iterator.exe : block_vector_iterator.go $(libraries) +full_matrix.exe : full_matrix.go $(libraries) +matrix_out.exe : matrix_out.go $(libraries) +solver.exe : solver.go testmatrix.go $(libraries) +sparsity_pattern.exe : sparsity_pattern.go testmatrix.go $(libraries) +sparse_ilu.exe : sparse_ilu.go testmatrix.go $(libraries) +vector-vector.exe : vector-vector.go $(libraries) +#mgbase.exe : mgbase.go $(libraries) +#mg.exe : mg.go testmatrix.go $(libraries) + + +tests = block_matrices block_vector block_vector_iterator full_matrix \ + matrix_out solver sparsity_pattern sparse_ilu vector-vector ############################################################ diff --git a/tests/lac/block_vector_iterator.cc b/tests/lac/block_vector_iterator.cc new file mode 100644 index 0000000000..4c6c03a874 --- /dev/null +++ b/tests/lac/block_vector_iterator.cc @@ -0,0 +1,352 @@ +//-------------------------------------------------------------------- +// $Id$ +// Version: $Name$ +// +// Copyright (C) 2000, 2001 by the deal.II authors +// +// This file is subject to QPL and may not be distributed +// without copyright and license information. Please refer +// to the file deal.II/doc/license.html for the text and +// further information on this license. +// +//-------------------------------------------------------------------- + + +#include +#include +#include +#include +#include +#include +#include + +template +bool operator == (const BlockVector &v1, + const BlockVector &v2) +{ + if (v1.size() != v2.size()) + return false; + for (unsigned int i=0; i ivector(4); + ivector[0] = 2; + ivector[1] = 4; + ivector[2] = 3; + ivector[3] = 5; + + // Check 1: initialization via + // iterators + if (true) + { + BlockVector v1(ivector); + BlockVector v2(ivector); + + // initialize first vector with + // simple loop + for (unsigned int i=0; i::iterator p2 = v2.begin(); + for (unsigned int i=0; i v1(ivector); + + // initialize first vector with + // simple loop + for (unsigned int i=0; i v2(ivector, v1.begin(), v1.end()); + // check that the two vectors are equal + deallog << "Check 2: " << (v1==v2 ? "true" : "false") << std::endl; + }; + + // Check 3: loop forward and back + // and check that things are the + // same + if (true) + { + BlockVector v1(ivector); + // initialize first vector with + // simple loop + for (unsigned int i=0; i::iterator p1 = v1.begin(); + for (unsigned int i=0; i v1(ivector); + // initialize first vector with + // simple loop + for (unsigned int i=0; i::const_iterator p1 = v1.begin(); + for (unsigned int i=0; i v1(ivector); + // initialize first vector with + // simple loop + for (unsigned int i=0; i(v1.size()) ? + "true" : "false") + << std::endl; + + // check std::copy + BlockVector v2(ivector); + std::copy (v1.begin(), v1.end(), v2.begin()); + deallog << "Check 6: " << (v1 == v2 ? "true" : "false") << std::endl; + + // check std::transform + std::transform (v1.begin(), v1.end(), v2.begin(), + std::bind2nd (std::multiplies(), + 2.0)); + v2.scale (1./2.); + deallog << "Check 7: " << (v1 == v2 ? "true" : "false") << std::endl; + + + // check operators +/-, +=/-= + deallog << "Check 8: " + << (std::distance(v1.begin(), v1.begin()+3) == 3 ? + "true" : "false") + << std::endl; + deallog << "Check 9: " + << (std::distance(v1.end()-6, v1.end()) == 6 ? + "true" : "false") + << std::endl; + deallog << "Check 10: " + << (std::distance(v1.begin(), v1.end()) == (signed)v1.size() ? + "true" : "false") + << std::endl; + deallog << "Check 11: " + << (std::distance(v1.begin(), (v1.begin()+=7)) == 7 ? + "true" : "false") + << std::endl; + deallog << "Check 12: " + << (std::distance((v1.end()-=4), v1.end()) == 4 ? + "true" : "false") + << std::endl; + + // check advance + BlockVector::iterator p2 = v1.begin(); + std::advance (p2, v1.size()); + deallog << "Check 13: " << (p2 == v1.end() ? "true" : "false") << std::endl; + + BlockVector::const_iterator p3 = v1.begin(); + std::advance (p3, v1.size()); + deallog << "Check 14: " << (p3 == v1.end() ? "true" : "false") << std::endl; + }; + + // Check 15: initialization through + // iterators + if (true) + { + BlockVector v1(ivector); + // initialize first vector with + // simple loop + for (unsigned int i=0; i v2(v1.begin(), v1.end()); + + // and reverse way + BlockVector v3(ivector, v2.begin(), v2.end()); + deallog << "Check 15: " << (v1==v3 ? "true" : "false") << std::endl; + }; + + // Check 16: initialization through + // iterators. variant with one + // constant object + if (true) + { + BlockVector v1(ivector); + // initialize first vector with + // simple loop + for (unsigned int i=0; i v2(v1.begin(), v1.end()); + + // and reverse way + BlockVector v3(ivector, v2.begin(), v2.end()); + deallog << "Check 16: " << (v1==v3 ? "true" : "false") << std::endl; + }; + + // Check 17: initialization through + // iterators. variant with two + // constant object + if (true) + { + BlockVector v1(ivector); + // initialize first vector with + // simple loop + for (unsigned int i=0; i v2(v1.begin(), v1.end()); + + // and reverse way + const BlockVector v3(ivector, v2.begin(), v2.end()); + deallog << "Check 17: " << (v1==v3 ? "true" : "false") << std::endl; + }; + + // Check 18: initialization through + // iterators. variant with three + // constant object + if (true) + { + BlockVector v0(ivector); + // initialize first vector with + // simple loop + for (unsigned int i=0; i v1 = v0; + + // initialize a normal vector + // from it + const Vector v2(v1.begin(), v1.end()); + + // and reverse way + const BlockVector v3(ivector, v2.begin(), v2.end()); + deallog << "Check 18: " << (v1==v3 ? "true" : "false") << std::endl; + }; + + // Check 19: operator[] + if (true) + { + BlockVector v1(ivector); + for (unsigned int i=0; i::iterator p = (v1.begin()+i); + for (unsigned int j=0; j