template <typename Number>
class BlockVector
{
+ template <typename Pointee>
+ class Iterator
+ {
+ public:
+ /**
+ * Construct an iterator from
+ * a vector to which we point
+ * and the global index of
+ * the element pointed to.
+ */
+ Iterator (BlockVector<Number> &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<Number> *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
* 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<Number> iterator;
+ typedef Iterator<const Number> const_iterator;
+ typedef value_type &reference;
+ typedef const value_type &const_reference;
+ typedef size_t size_type;
/**
* Constructor. There are three
* 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;
+
//@}
* here for convenience.
*/
unsigned int num_blocks;
+
+ /**
+ * Make the iterator class a
+ * friend.
+ */
+ template <typename Pointee> friend class Iterator;
};
}
+
template <typename Number>
Number BlockVector<Number>::operator * (const BlockVector<Number>& v) const
{
}
+template <typename Number>
+typename BlockVector<Number>::iterator
+BlockVector<Number>::begin()
+{
+ return iterator(*this, 0U);
+};
+
+
+
+template <typename Number>
+typename BlockVector<Number>::const_iterator
+BlockVector<Number>::begin() const
+{
+ Assert (false, ExcNotImplemented());
+ return const_iterator(*const_cast<BlockVector*>(this), 0U);
+};
+
+
template <typename Number>
Number BlockVector<Number>::norm_sqr () const
{
+template <typename Number>
+template <typename Pointee>
+BlockVector<Number>::Iterator<Pointee>::
+Iterator (BlockVector<Number> &parent,
+ const unsigned global_index)
+ :
+ parent (&parent),
+ global_index (global_index)
+{
+ // find which block we are in
+ const std::pair<unsigned int, unsigned int>
+ 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 <typename Number>
+template <typename Pointee>
+BlockVector<Number>::Iterator<Pointee>::
+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 <typename Number>
+template <typename Pointee>
+typename BlockVector<Number>::Iterator<Pointee> &
+BlockVector<Number>::Iterator<Pointee>::
+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 <typename Number>
+template <typename Pointee>
+void
+BlockVector<Number>::Iterator<Pointee>::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<unsigned int>(-1);
+ };
+
+ ++global_index;
+};
+
+
+
+template <typename Number>
+template <typename Pointee>
+void
+BlockVector<Number>::Iterator<Pointee>::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<unsigned int>(-1);
+ next_break_forward = 0;
+ next_break_backward = 0;
+ };
+
+ --global_index;
+};
+
+
+
+template <typename Number>
+template <typename Pointee>
+Pointee &
+BlockVector<Number>::Iterator<Pointee>::operator * () const
+{
+ return parent->block(current_block)(index_within_block);
+};
+
+
+
+template <typename Number>
+template <typename Pointee>
+typename BlockVector<Number>::Iterator<Pointee> &
+BlockVector<Number>::Iterator<Pointee>::operator ++ ()
+{
+ move_forward ();
+ return *this;
+};
+
+
+
+template <typename Number>
+template <typename Pointee>
+typename BlockVector<Number>::Iterator<Pointee>
+BlockVector<Number>::Iterator<Pointee>::operator ++ (int)
+{
+ const Iterator old_value = *this;
+ move_forward ();
+ return old_value;
+};
+
+
+
+template <typename Number>
+template <typename Pointee>
+typename BlockVector<Number>::Iterator<Pointee> &
+BlockVector<Number>::Iterator<Pointee>::operator -- ()
+{
+ move_backward ();
+ return *this;
+};
+
+
+
+template <typename Number>
+template <typename Pointee>
+typename BlockVector<Number>::Iterator<Pointee>
+BlockVector<Number>::Iterator<Pointee>::operator -- (int)
+{
+ const Iterator old_value = *this;
+ move_backward ();
+ return old_value;
+};
+
+
+
+template <typename Number>
+template <typename Pointee>
+bool
+BlockVector<Number>::Iterator<Pointee>::operator == (const Iterator &i) const
+{
+ Assert (parent == i.parent, ExcPointerToDifferentVectors());
+
+ return (global_index == i.global_index);
+};
+
+
+
+template <typename Number>
+template <typename Pointee>
+bool
+BlockVector<Number>::Iterator<Pointee>::operator != (const Iterator &i) const
+{
+ Assert (parent == i.parent, ExcPointerToDifferentVectors());
+
+ return (global_index != i.global_index);
+};
+
+
+
+template <typename Number>
+template <typename Pointee>
+bool
+BlockVector<Number>::Iterator<Pointee>::operator < (const Iterator &i) const
+{
+ Assert (parent == i.parent, ExcPointerToDifferentVectors());
+
+ return (global_index < i.global_index);
+};
+
+
+
+template <typename Number>
+template <typename Pointee>
+bool
+BlockVector<Number>::Iterator<Pointee>::operator <= (const Iterator &i) const
+{
+ Assert (parent == i.parent, ExcPointerToDifferentVectors());
+
+ return (global_index <= i.global_index);
+};
+
+
+
+template <typename Number>
+template <typename Pointee>
+bool
+BlockVector<Number>::Iterator<Pointee>::operator > (const Iterator &i) const
+{
+ Assert (parent == i.parent, ExcPointerToDifferentVectors());
+
+ return (global_index > i.global_index);
+};
+
+
+
+template <typename Number>
+template <typename Pointee>
+bool
+BlockVector<Number>::Iterator<Pointee>::operator >= (const Iterator &i) const
+{
+ Assert (parent == i.parent, ExcPointerToDifferentVectors());
+
+ return (global_index >= i.global_index);
+};
+
+
#endif