#include <base/exceptions.h>
#include <cstdio>
#include <vector>
+#include <iterator>
+
+
+// forward declaration
+template <typename Number>
+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 <typename number, bool constness>
+ 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 <typename number>
+ struct Types<number,false>
+ {
+ /**
+ * Type of the vector
+ * underlying the block vector
+ * used in non-const
+ * iterators. There, the
+ * vector must not be constant.
+ */
+ typedef Vector<number> Vector;
+
+ /**
+ * Type of the block vector
+ * used in non-const
+ * iterators. There, the block
+ * vector must not be constant.
+ */
+ typedef BlockVector<number> 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 <typename number>
+ struct Types<number,true>
+ {
+ /**
+ * Type of the vector
+ * underlying the block vector
+ * used in
+ * @p{const_iterators}. There,
+ * the vector must be
+ * constant.
+ */
+ typedef const Vector<number> Vector;
+
+ /**
+ * Type of the block vector
+ * used in
+ * @p{const_iterator}s. There,
+ * the block vector must be
+ * constant.
+ */
+ typedef const BlockVector<number> 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 <typename number, bool constness>
+ class Iterator :
+#ifdef HAVE_STD_ITERATOR_CLASS
+ public std::iterator<std::random_access_iterator_tag,
+ typename Types<number,constness>::NumberType>
+#else
+ random_access_iterator<typename Types<number,constness>::NumberType,int>
+#endif
+ {
+ private:
+ /**
+ * Typedef an iterator with
+ * opposite constness
+ * requirements on the elements
+ * it points to.
+ */
+ typedef Iterator<number,!constness> 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<number,constness>::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<number,constness>::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<number,constness>::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<number,constness> &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 <bool constness2>
+ Iterator (const Iterator<number,constness2> &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.
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
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 BlockVectorIterators::Iterator<Number,false> iterator;
+ typedef BlockVectorIterators::Iterator<Number,true> const_iterator;
typedef value_type &reference;
typedef const value_type &const_reference;
typedef size_t size_type;
/**
* Access to a single block.
*/
- Vector<Number>& block (const unsigned int i);
+ Vector<Number> & block (const unsigned int i);
/**
* Read-only access to a single block.
*/
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;
//@}
* Make the iterator class a
* friend.
*/
- template <typename Pointee> friend class Iterator;
+ friend class iterator;
+ friend class const_iterator;
};
}
+namespace BlockVectorIterators
+{
+
+ template <typename number, bool constness>
+ inline
+ Iterator<number,constness>::
+ Iterator (const Iterator<number,constness> &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, bool constness>
+ template <bool constness2>
+ inline
+ Iterator<number,constness>::
+ Iterator (const Iterator<number,constness2> &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 <typename number, bool constness>
+ inline
+ Iterator<number,constness>::
+ 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 <typename number, bool constness>
+ inline
+ Iterator<number,constness> &
+ Iterator<number,constness>::
+ 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, bool constness>
+ inline
+ typename Iterator<number,constness>::reference
+ Iterator<number,constness>::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 <typename number, bool constness>
+ inline
+ typename Iterator<number,constness>::pointer
+ Iterator<number,constness>::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 <typename number, bool constness>
+ inline
+ typename Iterator<number,constness>::reference
+ Iterator<number,constness>::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 <typename number, bool constness>
+ inline
+ Iterator<number,constness> &
+ Iterator<number,constness>::operator ++ ()
+ {
+ move_forward ();
+ return *this;
+ };
+
+
+
+ template <typename number, bool constness>
+ inline
+ Iterator<number,constness>
+ Iterator<number,constness>::operator ++ (int)
+ {
+ const Iterator old_value = *this;
+ move_forward ();
+ return old_value;
+ };
+
+
+
+ template <typename number, bool constness>
+ inline
+ Iterator<number,constness> &
+ Iterator<number,constness>::operator -- ()
+ {
+ move_backward ();
+ return *this;
+ };
+
+
+
+ template <typename number, bool constness>
+ inline
+ Iterator<number,constness>
+ Iterator<number,constness>::operator -- (int)
+ {
+ const Iterator old_value = *this;
+ move_backward ();
+ return old_value;
+ };
+
+
+
+ template <typename number, bool constness>
+ inline
+ bool
+ Iterator<number,constness>::operator == (const Iterator &i) const
+ {
+ Assert (parent == i.parent, ExcPointerToDifferentVectors());
+
+ return (global_index == i.global_index);
+ };
+
+
+
+ template <typename number, bool constness>
+ inline
+ bool
+ Iterator<number,constness>::operator == (const InverseConstnessIterator &i) const
+ {
+ Assert (parent == i.parent, ExcPointerToDifferentVectors());
+
+ return (global_index == i.global_index);
+ };
+
+
+
+ template <typename number, bool constness>
+ inline
+ bool
+ Iterator<number,constness>::operator != (const Iterator &i) const
+ {
+ Assert (parent == i.parent, ExcPointerToDifferentVectors());
+
+ return (global_index != i.global_index);
+ };
+
+
+
+ template <typename number, bool constness>
+ inline
+ bool
+ Iterator<number,constness>::operator != (const InverseConstnessIterator &i) const
+ {
+ Assert (parent == i.parent, ExcPointerToDifferentVectors());
+
+ return (global_index != i.global_index);
+ };
+
+
+
+ template <typename number, bool constness>
+ inline
+ bool
+ Iterator<number,constness>::operator < (const Iterator &i) const
+ {
+ Assert (parent == i.parent, ExcPointerToDifferentVectors());
+
+ return (global_index < i.global_index);
+ };
+
+
+
+ template <typename number, bool constness>
+ inline
+ bool
+ Iterator<number,constness>::operator < (const InverseConstnessIterator &i) const
+ {
+ Assert (parent == i.parent, ExcPointerToDifferentVectors());
+
+ return (global_index < i.global_index);
+ };
+
+
+
+ template <typename number, bool constness>
+ inline
+ bool
+ Iterator<number,constness>::operator <= (const Iterator &i) const
+ {
+ Assert (parent == i.parent, ExcPointerToDifferentVectors());
+
+ return (global_index <= i.global_index);
+ };
+
+
+
+ template <typename number, bool constness>
+ inline
+ bool
+ Iterator<number,constness>::operator <= (const InverseConstnessIterator &i) const
+ {
+ Assert (parent == i.parent, ExcPointerToDifferentVectors());
+
+ return (global_index <= i.global_index);
+ };
+
+
+
+ template <typename number, bool constness>
+ inline
+ bool
+ Iterator<number,constness>::operator > (const Iterator &i) const
+ {
+ Assert (parent == i.parent, ExcPointerToDifferentVectors());
+
+ return (global_index > i.global_index);
+ };
+
+
+
+ template <typename number, bool constness>
+ inline
+ bool
+ Iterator<number,constness>::operator > (const InverseConstnessIterator &i) const
+ {
+ Assert (parent == i.parent, ExcPointerToDifferentVectors());
+
+ return (global_index > i.global_index);
+ };
+
+
+
+ template <typename number, bool constness>
+ inline
+ bool
+ Iterator<number,constness>::operator >= (const Iterator &i) const
+ {
+ Assert (parent == i.parent, ExcPointerToDifferentVectors());
+
+ return (global_index >= i.global_index);
+ };
+
+
+
+ template <typename number, bool constness>
+ inline
+ bool
+ Iterator<number,constness>::operator >= (const InverseConstnessIterator &i) const
+ {
+ Assert (parent == i.parent, ExcPointerToDifferentVectors());
+
+ return (global_index >= i.global_index);
+ };
+
+
+
+ template <typename number, bool constness>
+ inline
+ typename Iterator<number,constness>::difference_type
+ Iterator<number,constness>::operator - (const Iterator &i) const
+ {
+ Assert (parent == i.parent, ExcPointerToDifferentVectors());
+
+ return (static_cast<signed int>(global_index) -
+ static_cast<signed int>(i.global_index));
+ };
+
+
+
+ template <typename number, bool constness>
+ inline
+ typename Iterator<number,constness>::difference_type
+ Iterator<number,constness>::operator - (const InverseConstnessIterator &i) const
+ {
+ Assert (parent == i.parent, ExcPointerToDifferentVectors());
+
+ return (static_cast<signed int>(global_index) -
+ static_cast<signed int>(i.global_index));
+ };
+
+
+
+ template <typename number, bool constness>
+ inline
+ Iterator<number,constness>
+ Iterator<number,constness>::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 <typename number, bool constness>
+ inline
+ Iterator<number,constness>
+ Iterator<number,constness>::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 <typename number, bool constness>
+ inline
+ Iterator<number,constness> &
+ Iterator<number,constness>::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 <typename number, bool constness>
+ inline
+ Iterator<number,constness> &
+ Iterator<number,constness>::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
typename BlockVector<Number>::const_iterator
BlockVector<Number>::begin() const
{
- Assert (false, ExcNotImplemented());
- return const_iterator(*const_cast<BlockVector*>(this), 0U);
+ return const_iterator(*this, 0U);
};
+template <typename Number>
+typename BlockVector<Number>::iterator
+BlockVector<Number>::end()
+{
+ return iterator(*this, size());
+};
+
+
+
+template <typename Number>
+typename BlockVector<Number>::const_iterator
+BlockVector<Number>::end() const
+{
+ return const_iterator(*this, size());
+};
+
+
+
template <typename Number>
Number BlockVector<Number>::norm_sqr () const
{
};
+
template <typename Number>
Number BlockVector<Number>::mean_value () const
{
}
+
template <typename Number>
Number BlockVector<Number>::l1_norm () const
{
}
+
template <typename Number>
Number BlockVector<Number>::l2_norm () const
{
}
+
template <typename Number>
Number BlockVector<Number>::linfty_norm () const
{
}
+
template <typename Number>
BlockVector<Number>&
BlockVector<Number>::operator += (const BlockVector<Number>& v)
}
+
template <typename Number>
BlockVector<Number>&
BlockVector<Number>::operator -= (const BlockVector<Number>& v)
}
+
template <typename Number>
void BlockVector<Number>::add (const Number a)
{
}
+
template <typename Number>
void BlockVector<Number>::add (const BlockVector<Number>& v)
{
}
+
template <typename Number>
void BlockVector<Number>::add (const Number a,
const BlockVector<Number>& v)
}
+
template <typename Number>
void BlockVector<Number>::add (const Number a,
const BlockVector<Number>& v,
}
+
template <typename Number>
void BlockVector<Number>::sadd (const Number x,
const BlockVector<Number>& v)
}
+
template <typename Number>
void BlockVector<Number>::sadd (const Number x, const Number a,
const BlockVector<Number>& v)
}
+
template <typename Number>
void BlockVector<Number>::sadd (const Number x, const Number a,
const BlockVector<Number>& v,
}
+
template <typename Number>
void BlockVector<Number>::sadd (const Number x, const Number a,
const BlockVector<Number>& v,
-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 ()
+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<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)
+ template <typename number, bool constness>
+ Iterator<number,constness>::
+ 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<unsigned int, unsigned int>
+ 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<unsigned int>(-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<unsigned int>(-1);
};
-
- --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());
+ template <typename number, bool constness>
+ void
+ Iterator<number,constness>::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<unsigned int>(-1);
+ };
+
+ ++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, bool constness>
+ void
+ Iterator<number,constness>::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<unsigned int>(-1);
+ next_break_forward = 0;
+ next_break_backward = 0;
+ };
+
+ --global_index;
+ };
};
-
-
#endif
--- /dev/null
+//--------------------------------------------------------------------
+// $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 <base/logstream.h>
+#include <lac/block_vector.h>
+#include <fstream>
+#include <vector>
+#include <algorithm>
+#include <numeric>
+#include <utility>
+
+template <typename number>
+bool operator == (const BlockVector<number> &v1,
+ const BlockVector<number> &v2)
+{
+ if (v1.size() != v2.size())
+ return false;
+ for (unsigned int i=0; i<v1.size(); ++i)
+ if (v1(i) != v2(i))
+ return false;
+ return true;
+};
+
+
+void test ()
+{
+ std::vector<unsigned int> ivector(4);
+ ivector[0] = 2;
+ ivector[1] = 4;
+ ivector[2] = 3;
+ ivector[3] = 5;
+
+ // Check 1: initialization via
+ // iterators
+ if (true)
+ {
+ BlockVector<double> v1(ivector);
+ BlockVector<double> v2(ivector);
+
+ // initialize first vector with
+ // simple loop
+ for (unsigned int i=0; i<v1.size(); ++i)
+ v1(i) = i;
+ // initialize other vector
+ // through iterators
+ BlockVector<double>::iterator p2 = v2.begin();
+ for (unsigned int i=0; i<v1.size(); ++i, ++p2)
+ *p2 = i;
+ Assert (p2==v2.end(), ExcInternalError());
+
+ // check that the two vectors are equal
+ deallog << "Check 1: " << (v1==v2 ? "true" : "false") << std::endl;
+ };
+
+ // Check 1: initialization via
+ // iterators
+ if (true)
+ {
+ BlockVector<double> v1(ivector);
+
+ // initialize first vector with
+ // simple loop
+ for (unsigned int i=0; i<v1.size(); ++i)
+ v1(i) = i;
+ // initialize other vector
+ // through iterators into first
+ // vector
+ BlockVector<double> 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<double> v1(ivector);
+ // initialize first vector with
+ // simple loop
+ for (unsigned int i=0; i<v1.size(); ++i)
+ v1(i) = i;
+
+ BlockVector<double>::iterator p1 = v1.begin();
+ for (unsigned int i=0; i<v1.size(); ++i, ++p1)
+ Assert (*p1 == i, ExcInternalError());
+
+ Assert (p1 == v1.end(), ExcInternalError());
+
+ // move back into allowable
+ // region
+ --p1;
+
+ // check backwards
+ for (unsigned int i=0; i<v1.size(); ++i, --p1)
+ Assert (*p1 == v1.size()-i-1, ExcInternalError());
+
+ // if we came thus far,
+ // everything is alright
+ deallog << "Check 3: true" << std::endl;
+ };
+
+
+ // Check 4: same, but this time
+ // with const iterators
+ if (true)
+ {
+ BlockVector<double> v1(ivector);
+ // initialize first vector with
+ // simple loop
+ for (unsigned int i=0; i<v1.size(); ++i)
+ v1(i) = i;
+
+ BlockVector<double>::const_iterator p1 = v1.begin();
+ for (unsigned int i=0; i<v1.size(); ++i, ++p1)
+ Assert (*p1 == i, ExcInternalError());
+
+ Assert (p1 == v1.end(), ExcInternalError());
+
+ // move back into allowable
+ // region
+ --p1;
+
+ // check backwards
+ for (unsigned int i=0; i<v1.size(); ++i, --p1)
+ Assert (*p1 == v1.size()-i-1, ExcInternalError());
+
+ // if we came thus far,
+ // everything is alright
+ deallog << "Check 4: true" << std::endl;
+ };
+
+ // Checks 5-14: use some standard
+ // algorithms
+ if (true)
+ {
+ BlockVector<double> v1(ivector);
+ // initialize first vector with
+ // simple loop
+ for (unsigned int i=0; i<v1.size(); ++i)
+ v1(i) = i;
+
+ // check std::distance
+ // algorithm
+ deallog << "Check 5: "
+ << (std::distance (v1.begin(), v1.end()) ==
+ static_cast<signed int>(v1.size()) ?
+ "true" : "false")
+ << std::endl;
+
+ // check std::copy
+ BlockVector<double> 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<double>(),
+ 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<double>::iterator p2 = v1.begin();
+ std::advance (p2, v1.size());
+ deallog << "Check 13: " << (p2 == v1.end() ? "true" : "false") << std::endl;
+
+ BlockVector<double>::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<double> v1(ivector);
+ // initialize first vector with
+ // simple loop
+ for (unsigned int i=0; i<v1.size(); ++i)
+ v1(i) = i;
+
+ // initialize a normal vector
+ // from it
+ Vector<double> v2(v1.begin(), v1.end());
+
+ // and reverse way
+ BlockVector<double> 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<double> v1(ivector);
+ // initialize first vector with
+ // simple loop
+ for (unsigned int i=0; i<v1.size(); ++i)
+ v1(i) = i;
+
+ // initialize a normal vector
+ // from it
+ const Vector<double> v2(v1.begin(), v1.end());
+
+ // and reverse way
+ BlockVector<double> 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<double> v1(ivector);
+ // initialize first vector with
+ // simple loop
+ for (unsigned int i=0; i<v1.size(); ++i)
+ v1(i) = i;
+
+ // initialize a normal vector
+ // from it
+ const Vector<double> v2(v1.begin(), v1.end());
+
+ // and reverse way
+ const BlockVector<double> 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<double> v0(ivector);
+ // initialize first vector with
+ // simple loop
+ for (unsigned int i=0; i<v0.size(); ++i)
+ v0(i) = i;
+
+ const BlockVector<double> v1 = v0;
+
+ // initialize a normal vector
+ // from it
+ const Vector<double> v2(v1.begin(), v1.end());
+
+ // and reverse way
+ const BlockVector<double> v3(ivector, v2.begin(), v2.end());
+ deallog << "Check 18: " << (v1==v3 ? "true" : "false") << std::endl;
+ };
+
+ // Check 19: operator[]
+ if (true)
+ {
+ BlockVector<double> v1(ivector);
+ for (unsigned int i=0; i<v1.size(); ++i)
+ v1(i) = i;
+
+ for (unsigned int i=0; i<v1.size(); ++i)
+ {
+ const BlockVector<double>::iterator p = (v1.begin()+i);
+ for (unsigned int j=0; j<v1.size(); ++j)
+ Assert (p[(signed)j-(signed)i] == j, ExcInternalError());
+ };
+
+ // if we came thus far,
+ // everything is alright
+ deallog << "Check 19: true" << std::endl;
+ };
+};
+
+
+
+
+
+int main ()
+{
+ std::ofstream logfile("block_vector_iterator.output");
+ logfile.setf(std::ios::fixed);
+ logfile.precision(3);
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+
+ try
+ {
+ test ();
+ }
+ catch (std::exception &e)
+ {
+ std::cerr << std::endl << std::endl
+ << "----------------------------------------------------"
+ << std::endl;
+ std::cerr << "Exception on processing: " << e.what() << std::endl
+ << "Aborting!" << std::endl
+ << "----------------------------------------------------"
+ << std::endl;
+ // abort
+ return 2;
+ }
+ catch (...)
+ {
+ std::cerr << std::endl << std::endl
+ << "----------------------------------------------------"
+ << std::endl;
+ std::cerr << "Unknown exception!" << std::endl
+ << "Aborting!" << std::endl
+ << "----------------------------------------------------"
+ << std::endl;
+ // abort
+ return 3;
+ };
+
+
+ return 0;
+};
+