From 5d397e50792460de45158e44894f15f5f9c17a2b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Carsten=20Gr=C3=A4ser?= <graeser@dune-project.org>
Date: Fri, 20 Nov 2009 23:07:22 +0000
Subject: [PATCH] Redesigned iterators: * Removed ugly ReferenceStorageIterator
 since   * it stored either a reference or a fake reference   * you could not
 use iterator->method   * you could not assign iterators * Introduce
 ContainerWrapperIterator   * always stores an assignable ContainerWrapper
 object   * allows iterator->method()   * can be used for any other sparse row
 type

[[Imported from SVN: r1127]]
---
 dune/istl/diagonalmatrix.hh | 259 +++++++++++++++++++++++-------------
 dune/istl/scaledidmatrix.hh |  28 ++--
 2 files changed, 179 insertions(+), 108 deletions(-)

diff --git a/dune/istl/diagonalmatrix.hh b/dune/istl/diagonalmatrix.hh
index b5f8ab140..2ca9f685a 100644
--- a/dune/istl/diagonalmatrix.hh
+++ b/dune/istl/diagonalmatrix.hh
@@ -1,7 +1,7 @@
 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 // vi: set et ts=4 sw=2 sts=2:
-#ifndef DUNE_DIAGONAL_MATRIX_HH
-#define DUNE_DIAGONAL_MATRIX_HH
+#ifndef DUNE_DIAGONAL_MATRIX_NEW_HH
+#define DUNE_DIAGONAL_MATRIX_NEW_HH
 
 /*! \file
    \brief  This file implements a quadratic matrix of fixed size which is diagonal.
@@ -11,6 +11,7 @@
 #include <cstddef>
 #include <complex>
 #include <iostream>
+#include <memory>
 #include <dune/common/exceptions.hh>
 #include <dune/common/fmatrix.hh>
 #include <dune/common/fvector.hh>
@@ -22,7 +23,8 @@ namespace Dune {
 
   template< class K, int n > class DiagonalRowVectorConst;
   template< class K, int n > class DiagonalRowVector;
-  template< class C, class T, class R, class S> class ReferenceStorageIterator;
+  template< class DiagonalMatrixType > class DiagonalMatrixWrapper;
+  template< class C, class T, class R> class ContainerWrapperIterator;
 
 
   /**
@@ -31,6 +33,7 @@ namespace Dune {
   template<class K, int n>
   class DiagonalMatrix
   {
+    typedef DiagonalMatrixWrapper< DiagonalMatrix<K,n> > WrapperType;
 
   public:
     //===== type definitions and constants
@@ -97,7 +100,7 @@ namespace Dune {
 
     //===== iterator interface to rows of the matrix
     //! Iterator class for sequential access
-    typedef ReferenceStorageIterator<DiagonalMatrix<K,n>,reference,reference,DiagonalMatrix<K,n>&> Iterator;
+    typedef ContainerWrapperIterator<const WrapperType, reference, reference> Iterator;
     //! typedef for stl compliant access
     typedef Iterator iterator;
     //! rename the iterators for easier access
@@ -108,30 +111,30 @@ namespace Dune {
     //! begin iterator
     Iterator begin ()
     {
-      return Iterator(*this,0);
+      return Iterator(WrapperType(this),0);
     }
 
     //! end iterator
     Iterator end ()
     {
-      return Iterator(*this,n);
+      return Iterator(WrapperType(this),n);
     }
 
     //! begin iterator
     Iterator rbegin ()
     {
-      return Iterator(*this,n-1);
+      return Iterator(WrapperType(this),n-1);
     }
 
     //! end iterator
     Iterator rend ()
     {
-      return Iterator(*this,-1);
+      return Iterator(WrapperType(this),-1);
     }
 
 
     //! Iterator class for sequential access
-    typedef ReferenceStorageIterator<const DiagonalMatrix<K,n>,const_reference,const_reference,const DiagonalMatrix<K,n>&> ConstIterator;
+    typedef ContainerWrapperIterator<const WrapperType, const_reference, const_reference> ConstIterator;
     //! typedef for stl compliant access
     typedef ConstIterator const_iterator;
     //! rename the iterators for easier access
@@ -142,25 +145,25 @@ namespace Dune {
     //! begin iterator
     ConstIterator begin () const
     {
-      return ConstIterator(*this,0);
+      return ConstIterator(WrapperType(this),0);
     }
 
     //! end iterator
     ConstIterator end () const
     {
-      return ConstIterator(*this,n);
+      return ConstIterator(WrapperType(this),n);
     }
 
     //! begin iterator
     ConstIterator rbegin () const
     {
-      return ConstIterator(*this,n-1);
+      return ConstIterator(WrapperType(this),n-1);
     }
 
     //! end iterator
     ConstIterator rend () const
     {
-      return ConstIterator(*this,-1);
+      return ConstIterator(WrapperType(this),-1);
     }
 
 
@@ -258,7 +261,7 @@ namespace Dune {
       if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
 #endif
       for (size_type i=0; i<n; i++)
-        y[i] += fm_ck(diag_[i])*x[i];
+        y[i] += conjugateComplex(diag_[i])*x[i];
     }
 
     //! y -= A x
@@ -293,9 +296,8 @@ namespace Dune {
       if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
       if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
 #endif
-
       for (size_type i=0; i<n; i++)
-        y[i] -= fm_ck(diag_[i])*x[i];
+        y[i] -= conjugateComplex(diag_[i])*x[i];
     }
 
     //! y += alpha A x
@@ -331,7 +333,7 @@ namespace Dune {
       if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
 #endif
       for (size_type i=0; i<n; i++)
-        y[i] += alpha * fm_ck(diag_[i]) * x[i];
+        y[i] += alpha * conjugateComplex(diag_[i]) * x[i];
     }
 
     //===== norms
@@ -474,12 +476,61 @@ namespace Dune {
   };
 
 
+  template<class DiagonalMatrixType>
+  class DiagonalMatrixWrapper
+  {
+    typedef typename DiagonalMatrixType::reference reference;
+    typedef typename DiagonalMatrixType::const_reference const_reference;
+    typedef typename DiagonalMatrixType::field_type K;
+    typedef DiagonalRowVector<K, DiagonalMatrixType::rows> row_type;
+    typedef std::size_t size_type;
+    typedef DiagonalMatrixWrapper< DiagonalMatrixType> MyType;
+
+    friend class ContainerWrapperIterator<const MyType, reference, reference>;
+    friend class ContainerWrapperIterator<const MyType, const_reference, const_reference>;
+
+  public:
+
+    DiagonalMatrixWrapper() :
+      mat_(0)
+    {}
+
+    DiagonalMatrixWrapper(const DiagonalMatrixType* mat) :
+      mat_(const_cast<DiagonalMatrixType*>(mat))
+    {}
+
+    size_type realIndex(int i) const
+    {
+      return i;
+    }
+
+    row_type* pointer(int i) const
+    {
+      row_ = row_type(&(mat_->diagonal(i)), i);
+      return &row_;
+    }
+
+    bool identical(const DiagonalMatrixWrapper& other) const
+    {
+      return mat_==other.mat_;
+    }
+
+  private:
+
+    mutable DiagonalMatrixType* mat_;
+    mutable row_type row_;
+  };
+
   /** \brief
    *
    */
   template< class K, int n >
   class DiagonalRowVectorConst
   {
+    template<class DiagonalMatrixType>
+    friend class DiagonalMatrixWrapper;
+    friend class ContainerWrapperIterator<DiagonalRowVectorConst<K,n>, const K, const K&>;
+
   public:
     // remember size of vector
     enum { dimension = n };
@@ -526,9 +577,10 @@ namespace Dune {
     //! same for read only access
     const K& operator[] (size_type i) const
     {
+#ifdef DUNE_FMatrix_WITH_CHECKING
       if (i!=row_)
-        DUNE_THROW(FMatrixError,"index is read only");
-      //            return ZERO<K>::Value;
+        DUNE_THROW(FMatrixError,"index is contained in pattern");
+#endif
       return *p_;
     }
 
@@ -540,51 +592,34 @@ namespace Dune {
     }
 
     //! ConstIterator class for sequential access
-    typedef ReferenceStorageIterator<DiagonalRowVectorConst<K,n>,const K,const K&,DiagonalRowVectorConst<K,n> > ConstIterator;
+    typedef ContainerWrapperIterator<DiagonalRowVectorConst<K,n>, const K, const K&> ConstIterator;
     //! typedef for stl compliant access
     typedef ConstIterator const_iterator;
 
     //! begin ConstIterator
     ConstIterator begin () const
     {
-      // the iterator gets this type as '[...]Const' and not as 'const [...]'
-      // thus we must remove constness
-      return ConstIterator(*const_cast<DiagonalRowVectorConst<K,n>*>(this),row_);
+      return ConstIterator(*this,0);
     }
 
     //! end ConstIterator
     ConstIterator end () const
     {
-      // the iterator gets this type as '[...]Const' and not as 'const [...]'
-      // thus we must remove constness
-      return ConstIterator(*const_cast<DiagonalRowVectorConst<K,n>*>(this),row_+1);
+      return ConstIterator(*this,1);
     }
 
     //! begin ConstIterator
     ConstIterator rbegin () const
     {
-      // the iterator gets this type as '[...]Const' and not as 'const [...]'
-      // thus we must remove constness
-      return ConstIterator(*const_cast<DiagonalRowVectorConst<K,n>*>(this),row_);
+      return ConstIterator(*this,0);
     }
 
     //! end ConstIterator
     ConstIterator rend () const
     {
-      // the iterator gets this type as '[...]Const' and not as 'const [...]'
-      // thus we must remove constness
-      return ConstIterator(*const_cast<DiagonalRowVectorConst<K,n>*>(this),-1);
+      return ConstIterator(*this,-1);
     }
 
-    //! return iterator to given element or end()
-    //    ConstIterator find (size_type i) const
-    //    {
-    //        if (i<n)
-    //            return ConstIterator(*this,i);
-    //        else
-    //            return ConstIterator(*this,n);
-    //    }
-
     //! Binary vector comparison
     bool operator== (const DiagonalRowVectorConst& y) const
     {
@@ -618,16 +653,34 @@ namespace Dune {
     }
 
   protected:
+
+    size_type realIndex(int i) const
+    {
+      return rowIndex();
+    }
+
+    K* pointer(size_type i) const
+    {
+      return const_cast<K*>(p_);
+    }
+
+    DiagonalRowVectorConst* operator&()
+    {
+      return this;
+    }
+
     // the data, very simply a pointer to the diagonal value and the row number
     K* p_;
     size_type row_;
-
-    void operator & ();
   };
 
   template< class K, int n >
   class DiagonalRowVector : public DiagonalRowVectorConst<K,n>
   {
+    template<class DiagonalMatrixType>
+    friend class DiagonalMatrixWrapper;
+    friend class ContainerWrapperIterator<DiagonalRowVector<K,n>, K, K&>;
+
   public:
     // standard constructor and everything is sufficient ...
 
@@ -663,52 +716,44 @@ namespace Dune {
     //! random access
     K& operator[] (size_type i)
     {
+#ifdef DUNE_FMatrix_WITH_CHECKING
       if (i!=row_)
-        DUNE_THROW(FMatrixError,"index is read only");
-      //            return ZERO<K>::Value;
+        DUNE_THROW(FMatrixError,"index is contained in pattern");
+#endif
       return *p_;
     }
 
     //! Iterator class for sequential access
-    typedef ReferenceStorageIterator<DiagonalRowVector<K,n>,K,K&,DiagonalRowVector<K,n> > Iterator;
+    typedef ContainerWrapperIterator<DiagonalRowVector<K,n>, K, K&> Iterator;
     //! typedef for stl compliant access
     typedef Iterator iterator;
 
     //! begin iterator
     Iterator begin ()
     {
-      return Iterator(*this,row_);
+      return Iterator(*this, 0);
     }
 
     //! end iterator
     Iterator end ()
     {
-      return Iterator(*this,row_+1);
+      return Iterator(*this, 1);
     }
 
     //! begin iterator
     Iterator rbegin ()
     {
-      return Iterator(*this,row_);
+      return Iterator(*this, 0);
     }
 
     //! end iterator
     Iterator rend ()
     {
-      return Iterator(*this,row_-1);
+      return Iterator(*this, -1);
     }
 
-    //! return iterator to given element or end()
-    //    Iterator find (size_type i)
-    //    {
-    //        if (i<n)
-    //            return Iterator(*this,i);
-    //        else
-    //            return Iterator(*this,n);
-    //    }
-
     //! ConstIterator class for sequential access
-    typedef ReferenceStorageIterator<DiagonalRowVectorConst<K,n>,const K,const K&,DiagonalRowVectorConst<K,n> > ConstIterator;
+    typedef ContainerWrapperIterator<DiagonalRowVectorConst<K,n>, const K, const K&> ConstIterator;
     //! typedef for stl compliant access
     typedef ConstIterator const_iterator;
 
@@ -724,11 +769,17 @@ namespace Dune {
     using DiagonalRowVectorConst<K,n>::rowIndex;
     using DiagonalRowVectorConst<K,n>::diagonal;
 
+  protected:
+
+    DiagonalRowVector* operator&()
+    {
+      return this;
+    }
+
   private:
+
     using DiagonalRowVectorConst<K,n>::p_;
     using DiagonalRowVectorConst<K,n>::row_;
-
-    void operator & ();
   };
 
 
@@ -758,53 +809,76 @@ namespace Dune {
   };
 
 
-  template<class C, class T, class R, class S>
-  class ReferenceStorageIterator : public BidirectionalIteratorFacade<ReferenceStorageIterator<C,T,R,S>,T, R, int>
+
+
+  template<class CW, class T, class R>
+  class ContainerWrapperIterator : public BidirectionalIteratorFacade<ContainerWrapperIterator<CW,T,R>,T, R, int>
   {
-    friend class ReferenceStorageIterator<typename mutable_reference<C>::type, typename mutable_reference<T>::type, typename mutable_reference<R>::type, typename mutable_reference<S>::type>;
-    friend class ReferenceStorageIterator<typename const_reference<C>::type, typename const_reference<T>::type, typename const_reference<R>::type, typename const_reference<S>::type>;
+    typedef typename remove_const<CW>::type NonConstCW;
 
-    typedef ReferenceStorageIterator<typename mutable_reference<C>::type, typename mutable_reference<T>::type, typename mutable_reference<R>::type, typename mutable_reference<S>::type> MyType;
-    typedef ReferenceStorageIterator<typename const_reference<C>::type, typename const_reference<T>::type, typename const_reference<R>::type, typename const_reference<S>::type> MyConstType;
+    friend class ContainerWrapperIterator<CW, typename mutable_reference<T>::type, typename mutable_reference<R>::type>;
+    friend class ContainerWrapperIterator<CW, typename const_reference<T>::type, typename const_reference<R>::type>;
+
+    typedef ContainerWrapperIterator<CW, typename mutable_reference<T>::type, typename mutable_reference<R>::type> MyType;
+    typedef ContainerWrapperIterator<CW, typename const_reference<T>::type, typename const_reference<R>::type> MyConstType;
 
   public:
 
     // Constructors needed by the facade iterators.
-    ReferenceStorageIterator() : container_(0), position_(0)
+    ContainerWrapperIterator() :
+      containerWrapper_(),
+      position_(0)
     {}
 
-    ReferenceStorageIterator(C& cont, int pos)
-      : container_(cont), position_(pos)
+    ContainerWrapperIterator(CW containerWrapper, int position) :
+      containerWrapper_(containerWrapper),
+      position_(position)
     {}
 
-    ReferenceStorageIterator(const MyType& other)
-      : container_(other.container_), position_(other.position_)
+    template<class OtherContainerWrapperIteratorType>
+    ContainerWrapperIterator(OtherContainerWrapperIteratorType& other) :
+      containerWrapper_(other.containerWrapper_),
+      position_(other.position_)
     {}
 
-    ReferenceStorageIterator(const MyConstType& other)
-      : container_(other.container_), position_(other.position_)
+    ContainerWrapperIterator(const MyType& other) :
+      containerWrapper_(other.containerWrapper_),
+      position_(other.position_)
     {}
 
+    ContainerWrapperIterator(const MyConstType& other) :
+      containerWrapper_(other.containerWrapper_),
+      position_(other.position_)
+    {}
+
+    template<class OtherContainerWrapperIteratorType>
+    ContainerWrapperIterator& operator=(OtherContainerWrapperIteratorType& other)
+    {
+      containerWrapper_ = other.containerWrapper_;
+      position_ = other.position_;
+    }
+
+    // This operator is needed since we can not get the address of the
+    // temporary object returned by dereference
+    T* operator->() const
+    {
+      return containerWrapper_.pointer(position_);
+    }
+
     // Methods needed by the forward iterator
     bool equals(const MyType& other) const
     {
-      // check for identity since we store references/objects
-      return position_ == other.position_ && container_.identical(other.container_);
+      return position_ == other.position_ && containerWrapper_.identical(other.containerWrapper_);
     }
 
-
     bool equals(const MyConstType& other) const
     {
-      // check for identity since we store references/objects
-      return position_ == other.position_ && container_.identical(other.container_);
+      return position_ == other.position_ && containerWrapper_.identical(other.containerWrapper_);
     }
 
     R dereference() const
     {
-      // iterator facedes cast to const
-      // thus this costness must be removed since the 'const'
-      // container is '[...]Const' and not 'const [...]'
-      return (const_cast< typename remove_const<C>::type& >(container_))[position_];
+      return *containerWrapper_.pointer(position_);
     }
 
     void increment()
@@ -821,7 +895,7 @@ namespace Dune {
     // Additional function needed by RandomAccessIterator
     R elementAt(int i) const
     {
-      return (const_cast< typename remove_const<C>::type& >(container_))[position_+i];
+      return *containerWrapper_.pointer(position_+i);
     }
 
     void advance(int n)
@@ -829,25 +903,20 @@ namespace Dune {
       position_=position_+n;
     }
 
-    std::ptrdiff_t distanceTo(const MyType& other) const
-    {
-      assert(container_.identical(other.container_));
-      return other.position_ - position_;
-    }
-
-    std::ptrdiff_t distanceTo(const MyConstType& other) const
+    template<class OtherContainerWrapperIteratorType>
+    std::ptrdiff_t distanceTo(OtherContainerWrapperIteratorType& other) const
     {
-      assert(container_.identical(other.container_));
+      assert(containerWrapper_.identical(other));
       return other.position_ - position_;
     }
 
     std::ptrdiff_t index() const
     {
-      return position_;
+      return containerWrapper_.realIndex(position_);
     }
 
   private:
-    S container_;
+    NonConstCW containerWrapper_;
     size_t position_;
   };
 
diff --git a/dune/istl/scaledidmatrix.hh b/dune/istl/scaledidmatrix.hh
index 5b3b44207..ed00d1b0f 100644
--- a/dune/istl/scaledidmatrix.hh
+++ b/dune/istl/scaledidmatrix.hh
@@ -25,6 +25,8 @@ namespace Dune {
   template<class K, int n>
   class ScaledIdentityMatrix
   {
+    typedef DiagonalMatrixWrapper< ScaledIdentityMatrix<K,n> > WrapperType;
+
   public:
     //===== type definitions and constants
 
@@ -83,7 +85,7 @@ namespace Dune {
 
     //===== iterator interface to rows of the matrix
     //! Iterator class for sequential access
-    typedef ReferenceStorageIterator<ScaledIdentityMatrix<K,n>,reference,reference,ScaledIdentityMatrix<K,n>&> Iterator;
+    typedef ContainerWrapperIterator<const WrapperType, reference, reference> Iterator;
     //! typedef for stl compliant access
     typedef Iterator iterator;
     //! rename the iterators for easier access
@@ -94,30 +96,30 @@ namespace Dune {
     //! begin iterator
     Iterator begin ()
     {
-      return Iterator(*this,0);
+      return Iterator(WrapperType(this),0);
     }
 
     //! end iterator
     Iterator end ()
     {
-      return Iterator(*this,n);
+      return Iterator(WrapperType(this),n);
     }
 
     //! begin iterator
     Iterator rbegin ()
     {
-      return Iterator(*this,n-1);
+      return Iterator(WrapperType(this),n-1);
     }
 
     //! end iterator
     Iterator rend ()
     {
-      return Iterator(*this,-1);
+      return Iterator(WrapperType(this),-1);
     }
 
 
     //! Iterator class for sequential access
-    typedef ReferenceStorageIterator<const ScaledIdentityMatrix<K,n>,const_reference,const_reference,const ScaledIdentityMatrix<K,n>&> ConstIterator;
+    typedef ContainerWrapperIterator<const WrapperType, const_reference, const_reference> ConstIterator;
     //! typedef for stl compliant access
     typedef ConstIterator const_iterator;
     //! rename the iterators for easier access
@@ -128,25 +130,25 @@ namespace Dune {
     //! begin iterator
     ConstIterator begin () const
     {
-      return ConstIterator(*this,0);
+      return ConstIterator(WrapperType(this),0);
     }
 
     //! end iterator
     ConstIterator end () const
     {
-      return ConstIterator(*this,n);
+      return ConstIterator(WrapperType(this),n);
     }
 
     //! begin iterator
     ConstIterator rbegin () const
     {
-      return ConstIterator(*this,n-1);
+      return ConstIterator(WrapperType(this),n-1);
     }
 
     //! end iterator
     ConstIterator rend () const
     {
-      return ConstIterator(*this,-1);
+      return ConstIterator(WrapperType(this),-1);
     }
 
     //===== vector space arithmetic
@@ -239,7 +241,7 @@ namespace Dune {
       if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
 #endif
       for (size_type i=0; i<n; i++)
-        y[i] += fm_ck(p_)*x[i];
+        y[i] += conjugateComplex(p_)*x[i];
     }
 
     //! y -= A x
@@ -275,7 +277,7 @@ namespace Dune {
       if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
 #endif
       for (size_type i=0; i<n; i++)
-        y[i] -= fm_ck(p_)*x[i];
+        y[i] -= conjugateComplex(p_)*x[i];
     }
 
     //! y += alpha A x
@@ -311,7 +313,7 @@ namespace Dune {
       if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
 #endif
       for (size_type i=0; i<n; i++)
-        y[i] += alpha * fm_ck(p_) * x[i];
+        y[i] += alpha * conjugateComplex(p_) * x[i];
     }
 
     //===== norms
-- 
GitLab