From 85e67d84df3d8937f65fafa2794ee5deb6a6df48 Mon Sep 17 00:00:00 2001 From: Guido Kanschat Date: Mon, 20 Feb 2006 17:15:59 +0000 Subject: [PATCH] new generalized iterator for block matrices git-svn-id: https://svn.dealii.org/trunk@12429 0785d39b-7218-0410-832d-ea1e28bc413d --- deal.II/lac/include/lac/block_matrix_base.h | 1229 +++++++++++-------- deal.II/lac/include/lac/matrix_iterator.h | 236 ++++ 2 files changed, 981 insertions(+), 484 deletions(-) create mode 100644 deal.II/lac/include/lac/matrix_iterator.h diff --git a/deal.II/lac/include/lac/block_matrix_base.h b/deal.II/lac/include/lac/block_matrix_base.h index 2beb4499b3..a99a311a8f 100644 --- a/deal.II/lac/include/lac/block_matrix_base.h +++ b/deal.II/lac/include/lac/block_matrix_base.h @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -28,198 +29,261 @@ *@{ */ - /** - * @cond internal - */ -namespace internal -{ - /** * Namespace in which iterators in block matrices are implemented. * * @author Wolfgang Bangerth, 2004 */ - namespace BlockMatrixIterators +namespace BlockMatrixIterators +{ + /** + * Base class for block matrix + * accessors, implementing the + * stepping through a matrix. + */ + template + class AccessorBase { - template class ConstIterator; - - /** - * Accessor class for iterators - */ - template - class Accessor - { - public: - /** - * Typedef the value type of the - * matrix we point into. - */ - typedef typename BlockMatrix::value_type value_type; - - /** - * Constructor. Since we use - * accessors only for read - * access, a const matrix - * pointer is sufficient. - * - * Place the iterator at the - * beginning of the given row of the - * matrix, or create the end pointer - * if @p row equals the total number - * of rows in the matrix. - */ - Accessor (const BlockMatrix *m, - const unsigned int row); - - /** - * Row number of the element - * represented by this - * object. - */ - unsigned int row() const; - - /** - * Column number of the - * element represented by - * this object. - */ - unsigned int column() const; - - /** - * Value of this matrix entry. - */ - value_type value() const; - - /** - * Block row of the - * element represented by - * this object. - */ - unsigned int block_row() const; - - /** - * Block column of the - * element represented by - * this object. - */ - unsigned int block_column() const; - - protected: - /** - * The matrix accessed. - */ - const BlockMatrix * matrix; - - /** - * Iterator of the underlying matrix - * class. - */ - typename BlockMatrix::BlockType::const_iterator base_iterator; - - /** - * Block row into which we presently - * point. - */ - unsigned int row_block; - - /** - * Block column into which we - * presently point. - */ - unsigned int col_block; - - /** - * Move ahead one element. - */ - void advance (); - - /** - * Compare this accessor with another - * one for equality. - */ - bool operator == (const Accessor &a) const; - - /** - * Let the iterator class be a - * friend. - */ - template - friend class ConstIterator; - }; - - /** - * STL conforming iterator. - */ - template - class ConstIterator - { - public: - /** - * Constructor. - * - * Place the iterator at the - * beginning of the given row of the - * matrix, or create the end pointer - * if @p row equals the total number - * of rows in the matrix. - */ - ConstIterator(const BlockMatrix *matrix, - const unsigned int row); - - /** - * Prefix increment. - */ - ConstIterator& operator++ (); - - /** - * Postfix increment. - */ - ConstIterator& operator++ (int); - - /** - * Dereferencing operator. - */ - const Accessor & operator* () const; - - /** - * Dereferencing operator. - */ - const Accessor * operator-> () const; - - /** - * Comparison. True, if - * both iterators point to - * the same matrix - * position. - */ - bool operator == (const ConstIterator&) const; - /** - * Inverse of operator==(). - */ - bool operator != (const ConstIterator&) const; - - /** - * Comparison - * operator. Result is true - * if either the first row - * number is smaller or if - * the row numbers are - * equal and the first - * index is smaller. - */ - bool operator < (const ConstIterator&) const; - - private: - /** - * The accessor with which we work. - */ - Accessor accessor; - }; - } + public: + /** + * Typedef the value type of the + * matrix we point into. + */ + typedef typename BlockMatrix::value_type value_type; + + /** + * Initialize data fields to + * default values. + */ + AccessorBase (); + + /** + * Block row of the + * element represented by + * this object. + */ + unsigned int block_row() const; + + /** + * Block column of the + * element represented by + * this object. + */ + unsigned int block_column() const; + + protected: + /** + * Block row into which we presently + * point. + */ + unsigned int row_block; + + /** + * Block column into which we + * presently point. + */ + unsigned int col_block; + + /** + * Let the iterator class be a + * friend. + */ + template + friend class MatrixIterator; + }; + /** + * Accessor classes in + * block matrices. + */ + template + class Accessor; + + /** + * Block matrix accessor for non + * const matrices. + */ + template + class Accessor + : + public AccessorBase + { + public: + /** + * Type of the matrix used in + * this accessor. + */ + typedef BlockMatrix MatrixType; + + /** + * Typedef the value type of the + * matrix we point into. + */ + typedef typename BlockMatrix::value_type value_type; + + /** + * Constructor. Since we use + * accessors only for read + * access, a const matrix + * pointer is sufficient. + * + * Place the iterator at the + * beginning of the given row of the + * matrix, or create the end pointer + * if @p row equals the total number + * of rows in the matrix. + */ + Accessor (BlockMatrix* m, + const unsigned int row, + const unsigned int col); + + /** + * Row number of the element + * represented by this + * object. + */ + unsigned int row() const; + + /** + * Column number of the + * element represented by + * this object. + */ + unsigned int column() const; + + /** + * Value of the entry at the + * current position. + */ + value_type value() const; + + /** + * Set new value. + */ + void set_value(value_type newval) const; + + protected: + /** + * The matrix accessed. + */ + BlockMatrix * matrix; + + /** + * Iterator of the underlying matrix + * class. + */ + typename BlockMatrix::BlockType::iterator base_iterator; + + /** + * Move ahead one element. + */ + void advance (); + + /** + * Compare this accessor with another + * one for equality. + */ + bool operator == (const Accessor &a) const; + + template friend class MatrixIterator; + friend class Accessor; + }; + + /** + * Block matrix accessor for + * constant matrices, implementing + * the stepping through a matrix. + */ + template + class Accessor + : + public AccessorBase + { + public: + /** + * Thype of the matrix used in + * this accessor. + */ + typedef const BlockMatrix MatrixType; + + /** + * Typedef the value type of the + * matrix we point into. + */ + typedef typename BlockMatrix::value_type value_type; + + /** + * Constructor. Since we use + * accessors only for read + * access, a const matrix + * pointer is sufficient. + * + * Place the iterator at the + * beginning of the given row of the + * matrix, or create the end pointer + * if @p row equals the total number + * of rows in the matrix. + */ + Accessor (const BlockMatrix* m, + const unsigned int row, + const unsigned int col); + + /** + * Initalize const accessor + * from non const accessor. + */ + Accessor(const Accessor&); + + /** + * Row number of the element + * represented by this + * object. + */ + unsigned int row() const; + + /** + * Column number of the + * element represented by + * this object. + */ + unsigned int column() const; + + /** + * Value of the entry at the + * current position. + */ + value_type value() const; + protected: + /** + * The matrix accessed. + */ + const BlockMatrix * matrix; + + /** + * Iterator of the underlying matrix + * class. + */ + typename BlockMatrix::BlockType::const_iterator base_iterator; + + /** + * Move ahead one element. + */ + void advance (); + + /** + * Compare this accessor with another + * one for equality. + */ + bool operator == (const Accessor &a) const; + + /** + * Let the iterator class be a + * friend. + */ + template + friend class MatrixIterator; + }; } - /** - * @endcond - */ + /** @@ -302,11 +366,11 @@ class BlockMatrixBase : public Subscriptor typedef size_t size_type; typedef - internal::BlockMatrixIterators::ConstIterator + MatrixIterator > iterator; typedef - internal::BlockMatrixIterators::ConstIterator + MatrixIterator > const_iterator; @@ -604,6 +668,27 @@ class BlockMatrixBase : public Subscriptor const BlockVectorType &x, const BlockVectorType &b) const; + /** + * STL-like iterator with the + * first entry. + */ + iterator begin (); + + /** + * Final iterator. + */ + iterator end (); + + /** + * STL-like iterator with the + * first entry of row r. + */ + iterator begin (const unsigned int r); + + /** + * Final iterator of row r. + */ + iterator end (const unsigned int r); /** * STL-like iterator with the * first entry. @@ -900,14 +985,15 @@ class BlockMatrixBase : public Subscriptor * a compiler bug here again. */ #ifndef DEAL_II_NAMESP_TEMPL_FRIEND_BUG - template - friend class internal::BlockMatrixIterators::Accessor; + template + friend class BlockMatrixIterators::Accessor; template - friend class internal::BlockMatrixIterators::ConstIterator; + friend class MatrixIterator; #else - typedef internal::BlockMatrixIterators::Accessor Accessor; - friend class Accessor; + typedef BlockMatrixIterators::Accessor ConstAccessor; + typedef BlockMatrixIterators::Accessor Accessor; + friend class ConstAccessor; friend class const_iterator; #endif @@ -920,316 +1006,449 @@ class BlockMatrixBase : public Subscriptor /* ------------------------- Template functions ---------------------- */ -namespace internal +namespace BlockMatrixIterators { - namespace BlockMatrixIterators - { - template - inline - Accessor:: - Accessor (const BlockMatrix *matrix, - const unsigned int row) - : - matrix(matrix), - base_iterator(matrix->block(0,0).begin()), - row_block(0), - col_block(0) - { - // check if this is a regular row or - // the end of the matrix - if (row < matrix->m()) - { - const std::pair indices - = matrix->row_block_indices.global_to_local(row); - - // find the first block that does - // have an entry in this row - for (unsigned int bc=0; bcn_block_cols(); ++bc) - { - base_iterator - = matrix->block(indices.first, bc).begin(indices.second); - if (base_iterator != - matrix->block(indices.first, bc).end(indices.second)) - { - row_block = indices.first; - col_block = bc; - return; - } - } - - // hm, there is no block that has - // an entry in this column. we need - // to take the next entry then, - // which may be the first entry of - // the next row, or recursively the - // next row, or so on - *this = Accessor (matrix, row+1); - } - else - { - // we were asked to create the end - // iterator for this matrix - row_block = deal_II_numbers::invalid_unsigned_int; - col_block = deal_II_numbers::invalid_unsigned_int; - } - } - - - template - inline - unsigned int - Accessor::row() const - { - Assert (row_block != deal_II_numbers::invalid_unsigned_int, - ExcIteratorPastEnd()); - - return (matrix->row_block_indices.local_to_global(row_block, 0) + - base_iterator->row()); - } - - - template - inline - unsigned int - Accessor::column() const - { - Assert (col_block != deal_II_numbers::invalid_unsigned_int, - ExcIteratorPastEnd()); - - return (matrix->column_block_indices.local_to_global(col_block,0) + - base_iterator->column()); - } - - - template - inline - unsigned int - Accessor::block_row() const - { - Assert (row_block != deal_II_numbers::invalid_unsigned_int, - ExcIteratorPastEnd()); - - return row_block; - } - - - template - inline - unsigned int - Accessor::block_column() const - { - Assert (col_block != deal_II_numbers::invalid_unsigned_int, - ExcIteratorPastEnd()); - - return col_block; - } - - - template - inline - typename Accessor::value_type - Accessor::value () const - { - Assert (row_block != deal_II_numbers::invalid_unsigned_int, - ExcIteratorPastEnd()); - Assert (col_block != deal_II_numbers::invalid_unsigned_int, - ExcIteratorPastEnd()); - - return base_iterator->value(); - } - + template + inline + AccessorBase::AccessorBase() + : + row_block(0), + col_block(0) + {} + + template + inline + unsigned int + AccessorBase::block_row() const + { + Assert (row_block != deal_II_numbers::invalid_unsigned_int, + ExcIteratorPastEnd()); + + return row_block; + } + + + template + inline + unsigned int + AccessorBase::block_column() const + { + Assert (col_block != deal_II_numbers::invalid_unsigned_int, + ExcIteratorPastEnd()); + + return col_block; + } + + + template + inline + Accessor::Accessor ( + const BlockMatrix *matrix, + const unsigned int row, + const unsigned int col) + : + matrix(matrix), + base_iterator(matrix->block(0,0).begin()) + { + Assert(col==0, ExcNotImplemented()); + + // check if this is a regular row or + // the end of the matrix + if (row < matrix->m()) + { + const std::pair indices + = matrix->row_block_indices.global_to_local(row); + + // find the first block that does + // have an entry in this row + for (unsigned int bc=0; bcn_block_cols(); ++bc) + { + base_iterator + = matrix->block(indices.first, bc).begin(indices.second); + if (base_iterator != + matrix->block(indices.first, bc).end(indices.second)) + { + this->row_block = indices.first; + this->col_block = bc; + return; + } + } + + // hm, there is no block that has + // an entry in this column. we need + // to take the next entry then, + // which may be the first entry of + // the next row, or recursively the + // next row, or so on + *this = Accessor (matrix, row+1, 0); + } + else + { + // we were asked to create the end + // iterator for this matrix + this->row_block = deal_II_numbers::invalid_unsigned_int; + this->col_block = deal_II_numbers::invalid_unsigned_int; + } + } + - template - inline - void - Accessor::advance () - { - Assert (row_block != deal_II_numbers::invalid_unsigned_int, - ExcIteratorPastEnd()); - Assert (col_block != deal_II_numbers::invalid_unsigned_int, - ExcIteratorPastEnd()); +// template +// inline +// Accessor::Accessor (const Accessor& other) +// : +// matrix(other.matrix), +// base_iterator(other.base_iterator) +// { +// this->row_block = other.row_block; +// this->col_block = other.col_block; +// } + - // Remember current row inside block - unsigned int local_row = base_iterator->row(); + template + inline + Accessor::Accessor (const Accessor& other) + : + matrix(other.matrix), + base_iterator(other.base_iterator) + { + this->row_block = other.row_block; + this->col_block = other.col_block; + } + - // Advance one element inside the - // current block - ++base_iterator; + template + inline + unsigned int + Accessor::row() const + { + Assert (this->row_block != deal_II_numbers::invalid_unsigned_int, + ExcIteratorPastEnd()); + + return (matrix->row_block_indices.local_to_global(this->row_block, 0) + + base_iterator->row()); + } - // while we hit the end of the row of a - // block (which may happen multiple - // times if rows inside a block are - // empty), we have to jump to the next - // block and take the - while (base_iterator == - matrix->block(row_block, - col_block).end(local_row)) - { - // jump to next block in this block - // row, if possible, otherwise go - // to next row - if (col_block < matrix->n_block_cols()-1) - { - ++col_block; - base_iterator - = matrix->block(row_block, col_block).begin(local_row); - } - else - { - // jump back to next row in - // first block column - col_block = 0; - ++local_row; - - // see if this has brought us - // past the number of rows in - // this block. if so see - // whether we've just fallen - // off the end of the whole - // matrix - if (local_row == matrix->block(row_block, col_block).m()) - { - local_row = 0; - ++row_block; - if (row_block == matrix->n_block_rows()) - { - row_block = deal_II_numbers::invalid_unsigned_int; - col_block = deal_II_numbers::invalid_unsigned_int; - return; - } - } + + template + inline + unsigned int + Accessor::column() const + { + Assert (this->col_block != deal_II_numbers::invalid_unsigned_int, + ExcIteratorPastEnd()); + + return (matrix->column_block_indices.local_to_global(this->col_block,0) + + base_iterator->column()); + } + + + template + inline + typename Accessor::value_type + Accessor::value () const + { + Assert (this->row_block != deal_II_numbers::invalid_unsigned_int, + ExcIteratorPastEnd()); + Assert (this->col_block != deal_II_numbers::invalid_unsigned_int, + ExcIteratorPastEnd()); + + return base_iterator->value(); + } + + + + template + inline + void + Accessor::advance () + { + Assert (this->row_block != deal_II_numbers::invalid_unsigned_int, + ExcIteratorPastEnd()); + Assert (this->col_block != deal_II_numbers::invalid_unsigned_int, + ExcIteratorPastEnd()); + + // Remember current row inside block + unsigned int local_row = base_iterator->row(); + + // Advance one element inside the + // current block + ++base_iterator; + + // while we hit the end of the row of a + // block (which may happen multiple + // times if rows inside a block are + // empty), we have to jump to the next + // block and take the + while (base_iterator == + matrix->block(this->row_block, this->col_block).end(local_row)) + { + // jump to next block in this block + // row, if possible, otherwise go + // to next row + if (this->col_block < matrix->n_block_cols()-1) + { + ++this->col_block; + base_iterator + = matrix->block(this->row_block, this->col_block).begin(local_row); + } + else + { + // jump back to next row in + // first block column + this->col_block = 0; + ++local_row; + + // see if this has brought us + // past the number of rows in + // this block. if so see + // whether we've just fallen + // off the end of the whole + // matrix + if (local_row == matrix->block(this->row_block, this->col_block).m()) + { + local_row = 0; + ++this->row_block; + if (this->row_block == matrix->n_block_rows()) + { + this->row_block = deal_II_numbers::invalid_unsigned_int; + this->col_block = deal_II_numbers::invalid_unsigned_int; + return; + } + } - base_iterator - = matrix->block(row_block, col_block).begin(local_row); - } - } - } + base_iterator + = matrix->block(this->row_block, this->col_block).begin(local_row); + } + } + } - - - template - inline - bool - Accessor::operator == (const Accessor &a) const - { - if (matrix != a.matrix) - return false; - - if (row_block == a.row_block - && col_block == a.col_block) - // end iterators do not necessarily - // have to have the same - // base_iterator representation, but - // valid iterators have to - return (((row_block == deal_II_numbers::invalid_unsigned_int) - && - (col_block == deal_II_numbers::invalid_unsigned_int)) - || - (base_iterator == a.base_iterator)); + template + inline + bool + Accessor::operator == (const Accessor &a) const + { + if (matrix != a.matrix) return false; - } - - -//--------------------------------------------------------------------------- - - - template - inline - ConstIterator:: - ConstIterator (const BlockMatrix *m, - const unsigned int r) - : - accessor (m, r) - {} - - - - template - inline - ConstIterator & - ConstIterator::operator++ () - { - accessor.advance (); - return *this; - } - - - -// template -// inline -// const_iterator& -// ConstIterator::operator++ (int) -// { -// Assert (false, ExcNotImplemented()); -// } - - - - - template - inline - const Accessor & - ConstIterator::operator* () const - { - return accessor; - } - - - template - inline - const Accessor * - ConstIterator::operator-> () const - { - return &accessor; - } - - - - template - inline - bool - ConstIterator:: - operator == (const ConstIterator& i) const - { - return (accessor == i.accessor); - } - - - - template - inline - bool - ConstIterator:: - operator != (const ConstIterator& i) const - { - return !(*this == i); - } + if (this->row_block == a.row_block + && this->col_block == a.col_block) + // end iterators do not necessarily + // have to have the same + // base_iterator representation, but + // valid iterators have to + return (((this->row_block == deal_II_numbers::invalid_unsigned_int) + && + (this->col_block == deal_II_numbers::invalid_unsigned_int)) + || + (base_iterator == a.base_iterator)); + + return false; + } + +//----------------------------------------------------------------------// + + template + inline + Accessor::Accessor ( + BlockMatrix *matrix, + const unsigned int row, + const unsigned int col) + : + matrix(matrix), + base_iterator(matrix->block(0,0).begin()) + { + Assert(col==0, ExcNotImplemented()); + // check if this is a regular row or + // the end of the matrix + if (row < matrix->m()) + { + const std::pair indices + = matrix->row_block_indices.global_to_local(row); + + // find the first block that does + // have an entry in this row + for (unsigned int bc=0; bcn_block_cols(); ++bc) + { + base_iterator + = matrix->block(indices.first, bc).begin(indices.second); + if (base_iterator != + matrix->block(indices.first, bc).end(indices.second)) + { + this->row_block = indices.first; + this->col_block = bc; + return; + } + } + + // hm, there is no block that has + // an entry in this column. we need + // to take the next entry then, + // which may be the first entry of + // the next row, or recursively the + // next row, or so on + *this = Accessor (matrix, row+1, 0); + } + else + { + // we were asked to create the end + // iterator for this matrix + this->row_block = deal_II_numbers::invalid_unsigned_int; + this->col_block = deal_II_numbers::invalid_unsigned_int; + } + } + + + template + inline + unsigned int + Accessor::row() const + { + Assert (this->row_block != deal_II_numbers::invalid_unsigned_int, + ExcIteratorPastEnd()); + + return (matrix->row_block_indices.local_to_global(this->row_block, 0) + + base_iterator->row()); + } + + + template + inline + unsigned int + Accessor::column() const + { + Assert (this->col_block != deal_II_numbers::invalid_unsigned_int, + ExcIteratorPastEnd()); + + return (matrix->column_block_indices.local_to_global(this->col_block,0) + + base_iterator->column()); + } + + + template + inline + typename Accessor::value_type + Accessor::value () const + { + Assert (this->row_block != deal_II_numbers::invalid_unsigned_int, + ExcIteratorPastEnd()); + Assert (this->col_block != deal_II_numbers::invalid_unsigned_int, + ExcIteratorPastEnd()); + + return base_iterator->value(); + } + + + + template + inline + void + Accessor::set_value (typename Accessor::value_type newval) const + { + Assert (this->row_block != deal_II_numbers::invalid_unsigned_int, + ExcIteratorPastEnd()); + Assert (this->col_block != deal_II_numbers::invalid_unsigned_int, + ExcIteratorPastEnd()); + + base_iterator->value() = newval; + } + + + + template + inline + void + Accessor::advance () + { + Assert (this->row_block != deal_II_numbers::invalid_unsigned_int, + ExcIteratorPastEnd()); + Assert (this->col_block != deal_II_numbers::invalid_unsigned_int, + ExcIteratorPastEnd()); + + // Remember current row inside block + unsigned int local_row = base_iterator->row(); + + // Advance one element inside the + // current block + ++base_iterator; + + // while we hit the end of the row of a + // block (which may happen multiple + // times if rows inside a block are + // empty), we have to jump to the next + // block and take the + while (base_iterator == + matrix->block(this->row_block, this->col_block).end(local_row)) + { + // jump to next block in this block + // row, if possible, otherwise go + // to next row + if (this->col_block < matrix->n_block_cols()-1) + { + ++this->col_block; + base_iterator + = matrix->block(this->row_block, this->col_block).begin(local_row); + } + else + { + // jump back to next row in + // first block column + this->col_block = 0; + ++local_row; + + // see if this has brought us + // past the number of rows in + // this block. if so see + // whether we've just fallen + // off the end of the whole + // matrix + if (local_row == matrix->block(this->row_block, this->col_block).m()) + { + local_row = 0; + ++this->row_block; + if (this->row_block == matrix->n_block_rows()) + { + this->row_block = deal_II_numbers::invalid_unsigned_int; + this->col_block = deal_II_numbers::invalid_unsigned_int; + return; + } + } + + base_iterator + = matrix->block(this->row_block, this->col_block).begin(local_row); + } + } + } + + - template - inline - bool - ConstIterator:: - operator < (const ConstIterator& i) const - { - if (accessor.row_block < i.accessor.row_block) - return true; - if (accessor.row_block == i.accessor.row_block) - { - if (accessor.base_iterator->row() < i.accessor.base_iterator->row()) - return true; - if (accessor.base_iterator->row() == i.accessor.base_iterator->row()) - return (accessor.base_iterator < i.accessor.base_iterator); - } + template + inline + bool + Accessor::operator == (const Accessor &a) const + { + if (matrix != a.matrix) return false; - } + if (this->row_block == a.row_block + && this->col_block == a.col_block) + // end iterators do not necessarily + // have to have the same + // base_iterator representation, but + // valid iterators have to + return (((this->row_block == deal_II_numbers::invalid_unsigned_int) + && + (this->col_block == deal_II_numbers::invalid_unsigned_int)) + || + (base_iterator == a.base_iterator)); + + return false; } } + //--------------------------------------------------------------------------- @@ -1843,6 +2062,48 @@ BlockMatrixBase::end (const unsigned int r) const +template +inline +typename BlockMatrixBase::iterator +BlockMatrixBase::begin () +{ + return iterator(this, 0); +} + + + +template +inline +typename BlockMatrixBase::iterator +BlockMatrixBase::end () +{ + return iterator(this, m()); +} + + + +template +inline +typename BlockMatrixBase::iterator +BlockMatrixBase::begin (const unsigned int r) +{ + Assert (r +inline +typename BlockMatrixBase::iterator +BlockMatrixBase::end (const unsigned int r) +{ + Assert (r void BlockMatrixBase::collect_sizes () diff --git a/deal.II/lac/include/lac/matrix_iterator.h b/deal.II/lac/include/lac/matrix_iterator.h new file mode 100644 index 0000000000..55a43e1966 --- /dev/null +++ b/deal.II/lac/include/lac/matrix_iterator.h @@ -0,0 +1,236 @@ +//--------------------------------------------------------------------------- +// $Id$ +// Version: $Name$ +// +// Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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. +// +//--------------------------------------------------------------------------- +#ifndef __deal2__matrix_iterator_h +#define __deal2__matrix_iterator_h + + +#include + + /** + * STL conforming iterator for constant + * and non-constant matrices. + * + * This iterator is abstracted from + * the actual matrix type and can be + * used for any matrix having the + * required ACCESSOR type. + * + * @author Guido Kanschat, 2006, based on previous a implementation + */ +template +class MatrixIterator +{ + public: + /** + * Typedef for the matrix type + * (including constness) we are to + * operate on. + */ + typedef typename ACCESSOR::MatrixType MatrixType; + + /** + * Constructor. Create an + * iterator into the matrix + * matrix for the given + * row and the + * index within it. + */ + MatrixIterator (MatrixType *matrix, + const unsigned int row = 0, + const unsigned int index = 0); + + /** + * Copy from another matrix + * iterator. Mostly implemented + * to allow initialization of a + * constant iterator from a non + * constant, this function only + * requires that a conversion + * from the other iterator's + * accessor to this accessor + * object is possible. + */ + template + MatrixIterator(const MatrixIterator& other); + + /** + * Prefix increment. + */ + MatrixIterator & operator++ (); + + /** + * Postfix increment. + */ + MatrixIterator operator++ (int); + + /** + * Dereferencing operator. + */ + const ACCESSOR & operator* () const; + + /** + * Dereferencing operator. + */ + const ACCESSOR * operator-> () const; + + /** + * Comparison. True, if + * both accessors are equal. + */ + bool operator == (const MatrixIterator &) const; + + /** + * Inverse of ==. + */ + bool operator != (const MatrixIterator &) const; + + /** + * Comparison operator. Result is + * true if either the first row + * number is smaller or if the row + * numbers are equal and the first + * index is smaller. + * + * This function is only valid if + * both iterators point into the same + * matrix. + */ + bool operator < (const MatrixIterator &) const; + + /** + * Comparison operator. Works in the + * same way as above operator, just + * the other way round. + */ + bool operator > (const MatrixIterator &) const; + + private: + /** + * Store an object of the + * accessor class. + */ + ACCESSOR accessor; + + /** + * Allow other iterators access + * to private data. + */ + template friend class MatrixIterator; +}; + + +//----------------------------------------------------------------------// + +template +inline +MatrixIterator:: +MatrixIterator (MatrixType *matrix, + const unsigned int r, + const unsigned int i) + : + accessor(matrix, r, i) +{} + + +template +template +inline +MatrixIterator:: +MatrixIterator (const MatrixIterator& other) + : + accessor(other.accessor) +{} + + +template +inline +MatrixIterator & +MatrixIterator::operator++ () +{ + accessor.advance (); + return *this; +} + + +template +inline +MatrixIterator +MatrixIterator::operator++ (int) +{ + const MatrixIterator iter = *this; + accessor.advance (); + return iter; +} + + +template +inline +const ACCESSOR & +MatrixIterator::operator* () const +{ + return accessor; +} + + +template +inline +const ACCESSOR * +MatrixIterator::operator-> () const +{ + return &accessor; +} + + +template +inline +bool +MatrixIterator:: +operator == (const MatrixIterator& other) const +{ + return (accessor == other.accessor); +} + + +template +inline +bool +MatrixIterator:: +operator != (const MatrixIterator& other) const +{ + return ! (*this == other); +} + + +template +inline +bool +MatrixIterator:: +operator < (const MatrixIterator& other) const +{ + Assert (&accessor.get_matrix() == &other.accessor.get_matrix(), + ExcInternalError()); + + return (accessor < other.accessor); +} + + +template +inline +bool +MatrixIterator:: +operator > (const MatrixIterator& other) const +{ + return (other < *this); +} + +#endif -- 2.39.5